@raster-app/react 0.1.0-canary-623b3d3 → 0.1.0-canary-32ca74d

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.
@@ -14,6 +14,15 @@ export declare function Empty({ glyph, title, text, children, }: {
14
14
  text: string;
15
15
  children?: ReactNode;
16
16
  }): import("react").JSX.Element;
17
+ /** Raster's columns for a grid this wide: its window holds a 266px sidebar and 30px padding too. */
18
+ export declare function gridColumns(width: number): number;
19
+ /**
20
+ * Tiles in Raster's grid, a row at a time as the Raster app draws them: only the rows in view,
21
+ * and five either side, are mounted, however many have loaded.
22
+ */
23
+ export declare function TileGrid({ children }: {
24
+ children: ReactNode;
25
+ }): import("react").JSX.Element;
17
26
  /**
18
27
  * Raster's grid tile: the picture over its blurred fill, or a checkerboard where it has alpha,
19
28
  * with a pill for a badge on the left and one for an action on the right.
@@ -32,7 +41,7 @@ export declare function Tile({ asset, onOpen, selected, badge, action, }: {
32
41
  */
33
42
  export declare function Detail({ item, busy, onPick, }: {
34
43
  item: Asset | SearchHit | AssetVariant;
35
- /** While the asset is read in full for the host. */
44
+ /** While the asset is read in full for the host, or a promote has yet to land. */
36
45
  busy: boolean;
37
46
  onPick?: () => void;
38
47
  }): import("react").JSX.Element;
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from 'react';
2
+ import { useVirtualizer } from '@tanstack/react-virtual';
3
+ import { Children, useEffect, useLayoutEffect, useRef, useState } from 'react';
3
4
  import { formatDateLong, formatFileSize, formatRelativeTime, getBlurhashPlaceholder, getPreviewUrl, getThumbUrl, isReady, toUserMessage, } from '@raster-app/sdk';
4
5
  import { useRasterClient } from './context.js';
5
6
  import { Icon } from './icons.js';
@@ -20,6 +21,54 @@ export function ErrorCard({ error, onError }) {
20
21
  export function Empty({ glyph, title, text, children, }) {
21
22
  return (_jsxs("div", { className: "rs-empty", children: [_jsx("div", { className: "rs-empty-glyph", children: glyph === 'grid' ? _jsx(Icon, { shape: "grid" }) : glyph }), _jsx("h2", { className: "rs-heading", children: title }), _jsx("p", { className: "rs-muted rs-small", children: text }), children] }));
22
23
  }
24
+ /** Raster's tile height (`.rs-asset-thumb`) and the gap between its rows. */
25
+ const ROW_HEIGHT = 210 + 30;
26
+ /** The Raster app's columns from its window's width (`calculateGridColumns`). */
27
+ const BREAKPOINTS = [
28
+ [2180, 7],
29
+ [1920, 6],
30
+ [1536, 5],
31
+ [1280, 4],
32
+ [1024, 3],
33
+ [768, 2],
34
+ ];
35
+ /** Raster's columns for a grid this wide: its window holds a 266px sidebar and 30px padding too. */
36
+ export function gridColumns(width) {
37
+ const viewport = width + 266 + 2 * 30;
38
+ return BREAKPOINTS.find(([min]) => viewport >= min)?.[1] ?? 1;
39
+ }
40
+ /**
41
+ * Tiles in Raster's grid, a row at a time as the Raster app draws them: only the rows in view,
42
+ * and five either side, are mounted, however many have loaded.
43
+ */
44
+ export function TileGrid({ children }) {
45
+ const tiles = Children.toArray(children);
46
+ const grid = useRef(null);
47
+ const [width, setWidth] = useState(0);
48
+ useLayoutEffect(() => {
49
+ const node = grid.current;
50
+ if (node === null)
51
+ return;
52
+ setWidth(node.clientWidth);
53
+ if (typeof ResizeObserver === 'undefined')
54
+ return;
55
+ const observer = new ResizeObserver(() => setWidth(node.clientWidth));
56
+ observer.observe(node);
57
+ return () => observer.disconnect();
58
+ }, []);
59
+ const columns = gridColumns(width);
60
+ const rows = useVirtualizer({
61
+ count: Math.ceil(tiles.length / columns),
62
+ getScrollElement: () => grid.current?.closest('.rs-content') ?? null,
63
+ estimateSize: () => ROW_HEIGHT,
64
+ overscan: 5,
65
+ scrollMargin: grid.current?.offsetTop ?? 0,
66
+ });
67
+ return (_jsx("div", { ref: grid, className: "rs-tile-grid", style: { height: rows.getTotalSize() }, children: rows.getVirtualItems().map((row) => (_jsx("div", { className: "rs-grid", style: {
68
+ top: row.start - rows.options.scrollMargin,
69
+ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
70
+ }, children: tiles.slice(row.index * columns, (row.index + 1) * columns) }, row.key))) }));
71
+ }
23
72
  /**
24
73
  * Raster's grid tile: the picture over its blurred fill, or a checkerboard where it has alpha,
25
74
  * with a pill for a badge on the left and one for an action on the right.
@@ -28,7 +77,7 @@ export function Tile({ asset, onOpen, selected, badge, action, }) {
28
77
  const [loaded, setLoaded] = useState(false);
29
78
  const ready = isReady(asset);
30
79
  const thumb = getThumbUrl(asset);
31
- const fill = ('blurhash' in asset ? getBlurhashPlaceholder(asset) : null) ?? thumb;
80
+ const fill = 'blurhash' in asset ? getBlurhashPlaceholder(asset) : null;
32
81
  const transparent = 'contentType' in asset && /png|svg|webp|gif/.test(asset.contentType ?? '');
33
82
  const size = 'size' in asset ? formatFileSize(asset.size) : '';
34
83
  const updated = 'updated' in asset ? formatRelativeTime(asset.updated) : '';
@@ -56,7 +105,7 @@ export function Detail({ item, busy, onPick, }) {
56
105
  }
57
106
  /** A file on its way into Raster, as the grid shows it until Raster has processed it. */
58
107
  export function PendingTile({ name, preview, status, }) {
59
- return (_jsx("div", { className: "rs-tile", children: _jsxs("div", { className: "rs-asset-thumb", "data-loaded": true, "aria-busy": "true", children: [_jsx("img", { className: "rs-thumb-blur", src: preview, alt: "" }), _jsx("div", { className: "rs-thumb-preview", children: _jsx("img", { src: preview, alt: "" }) }), _jsxs("div", { className: "rs-thumb-meta", children: [_jsx("span", { className: "rs-thumb-title", children: name }), _jsxs("span", { className: "rs-thumb-subtitle", children: [_jsx("span", { className: "rs-spinner" }), status] })] })] }) }));
108
+ return (_jsx("div", { className: "rs-tile", children: _jsxs("div", { className: "rs-asset-thumb", "data-loaded": true, "aria-busy": "true", children: [_jsx("div", { className: "rs-thumb-preview", children: _jsx("img", { src: preview, alt: "" }) }), _jsxs("div", { className: "rs-thumb-meta", children: [_jsx("span", { className: "rs-thumb-title", children: name }), _jsxs("span", { className: "rs-thumb-subtitle", children: [_jsx("span", { className: "rs-spinner" }), status] })] })] }) }));
60
109
  }
61
110
  /** A control that opens the file chooser, drawn as whatever `className` makes it. */
62
111
  export function FilePicker({ className, disabled, focusable = true, onFile, children, }) {
@@ -100,8 +149,12 @@ export function OrganizationSwitcher({ organizations, current, onIntent, onSelec
100
149
  return;
101
150
  const close = (event) => {
102
151
  const outside = event.target instanceof Node && !root.current?.contains(event.target);
103
- if (event instanceof KeyboardEvent ? event.key === 'Escape' : outside)
104
- setOpen(false);
152
+ if (event instanceof KeyboardEvent ? event.key !== 'Escape' : !outside)
153
+ return;
154
+ // Stopped here, so a host dialog that closes on Escape stays open.
155
+ if (event instanceof KeyboardEvent)
156
+ event.stopPropagation();
157
+ setOpen(false);
105
158
  };
106
159
  document.addEventListener('mousedown', close);
107
160
  document.addEventListener('keydown', close);
@@ -1 +1 @@
1
- {"version":3,"file":"picker-parts.js","sourceRoot":"","sources":["../src/picker-parts.tsx"],"names":[],"mappings":"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","sourcesContent":["import { type ReactNode, useEffect, useRef, useState } from 'react'\n\nimport {\n\ttype Asset,\n\ttype AssetVariant,\n\ttype Organization,\n\ttype RasterApiError,\n\ttype SearchHit,\n\tformatDateLong,\n\tformatFileSize,\n\tformatRelativeTime,\n\tgetBlurhashPlaceholder,\n\tgetPreviewUrl,\n\tgetThumbUrl,\n\tisReady,\n\ttoUserMessage,\n} from '@raster-app/sdk'\n\nimport { useRasterClient } from './context.js'\nimport { Icon } from './icons.js'\nimport type { PromoteState } from './use-promote-variant.js'\nimport type { UploadState } from './use-asset-upload.js'\n\nexport type ReportError = ((error: RasterApiError) => void) | undefined\n\nexport function Brand() {\n\treturn (\n\t\t<div className=\"rs-brand\">\n\t\t\t<Icon shape=\"raster\" solid width={18} />\n\t\t\tRaster\n\t\t</div>\n\t)\n}\n\n// Strict Mode runs an effect twice in development; the host hears of each error once.\nconst reported = new WeakSet<RasterApiError>()\n\nexport function ErrorCard({ error, onError }: { error: RasterApiError; onError: ReportError }) {\n\tuseEffect(() => {\n\t\tif (reported.has(error)) return\n\t\treported.add(error)\n\t\tonError?.(error)\n\t}, [error, onError])\n\treturn (\n\t\t<p role=\"alert\" className=\"rs-card\">\n\t\t\t{toUserMessage(error)}\n\t\t</p>\n\t)\n}\n\nexport function Empty({\n\tglyph,\n\ttitle,\n\ttext,\n\tchildren,\n}: {\n\tglyph: 'grid' | '∅'\n\ttitle: string\n\ttext: string\n\tchildren?: ReactNode\n}) {\n\treturn (\n\t\t<div className=\"rs-empty\">\n\t\t\t<div className=\"rs-empty-glyph\">{glyph === 'grid' ? <Icon shape=\"grid\" /> : glyph}</div>\n\t\t\t<h2 className=\"rs-heading\">{title}</h2>\n\t\t\t<p className=\"rs-muted rs-small\">{text}</p>\n\t\t\t{children}\n\t\t</div>\n\t)\n}\n\n/**\n * Raster's grid tile: the picture over its blurred fill, or a checkerboard where it has alpha,\n * with a pill for a badge on the left and one for an action on the right.\n */\nexport function Tile({\n\tasset,\n\tonOpen,\n\tselected,\n\tbadge,\n\taction,\n}: {\n\tasset: Asset | SearchHit | AssetVariant\n\tonOpen: () => void\n\t/** Whether this is the version shown large, among an asset's versions. */\n\tselected?: boolean\n\tbadge?: ReactNode\n\taction?: ReactNode\n}) {\n\tconst [loaded, setLoaded] = useState(false)\n\tconst ready = isReady(asset)\n\tconst thumb = getThumbUrl(asset)\n\tconst fill = ('blurhash' in asset ? getBlurhashPlaceholder(asset) : null) ?? thumb\n\tconst transparent = 'contentType' in asset && /png|svg|webp|gif/.test(asset.contentType ?? '')\n\tconst size = 'size' in asset ? formatFileSize(asset.size) : ''\n\tconst updated = 'updated' in asset ? formatRelativeTime(asset.updated) : ''\n\n\treturn (\n\t\t<div className=\"rs-tile\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"rs-asset-thumb\"\n\t\t\t\tdata-loaded={loaded || undefined}\n\t\t\t\tdisabled={!ready}\n\t\t\t\taria-pressed={selected}\n\t\t\t\ttitle={\n\t\t\t\t\t'created' in asset && asset.created\n\t\t\t\t\t\t? `Created ${formatDateLong(asset.created)}`\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tonClick={onOpen}\n\t\t\t>\n\t\t\t\t{transparent ? (\n\t\t\t\t\t<div className=\"rs-transparent\" />\n\t\t\t\t) : (\n\t\t\t\t\tfill && <img className=\"rs-thumb-blur\" src={fill} alt=\"\" />\n\t\t\t\t)}\n\t\t\t\t<div className=\"rs-thumb-preview\">\n\t\t\t\t\t{thumb && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={thumb}\n\t\t\t\t\t\t\tsrc={thumb}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\tdecoding=\"async\"\n\t\t\t\t\t\t\tonLoad={() => setLoaded(true)}\n\t\t\t\t\t\t\tonError={() => setLoaded(true)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"rs-thumb-meta\">\n\t\t\t\t\t<span className=\"rs-thumb-title\">{asset.name}</span>\n\t\t\t\t\t<span className=\"rs-thumb-subtitle\">\n\t\t\t\t\t\t{!ready && <span>Not ready</span>}\n\t\t\t\t\t\t{ready && size && <span>{size}</span>}\n\t\t\t\t\t\t{ready && updated && <span>{updated}</span>}\n\t\t\t\t\t\t{ready && !size && !updated && asset.width && asset.height && (\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t{asset.width} × {asset.height}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</button>\n\t\t\t{badge}\n\t\t\t{action}\n\t\t</div>\n\t)\n}\n\n/**\n * An opened asset or variant: the image large, its facts, and what the host can do with it.\n * Raster opens through the host, which reaches the browser from a Figma plugin too.\n */\nexport function Detail({\n\titem,\n\tbusy,\n\tonPick,\n}: {\n\titem: Asset | SearchHit | AssetVariant\n\t/** While the asset is read in full for the host. */\n\tbusy: boolean\n\tonPick?: () => void\n}) {\n\tconst { host } = useRasterClient()\n\tconst image = getPreviewUrl(item)\n\tconst appUrl = item.appUrl\n\tconst facts = [\n\t\titem.width && item.height ? `${item.width} × ${item.height}` : '',\n\t\t'size' in item ? formatFileSize(item.size) : '',\n\t\t'created' in item && item.created ? `Created ${formatDateLong(item.created)}` : '',\n\t].filter((fact) => fact !== '')\n\n\treturn (\n\t\t<div className=\"rs-detail\">\n\t\t\t<div className=\"rs-detail-image\">{image && <img key={image} src={image} alt=\"\" />}</div>\n\t\t\t<div className=\"rs-detail-info\">\n\t\t\t\t<h2 className=\"rs-heading\">{item.name}</h2>\n\t\t\t\t{facts.length > 0 && <p className=\"rs-muted rs-small\">{facts.join(' · ')}</p>}\n\t\t\t\t{onPick && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"rs-button rs-button-primary\"\n\t\t\t\t\t\tdisabled={!isReady(item) || busy}\n\t\t\t\t\t\tonClick={onPick}\n\t\t\t\t\t>\n\t\t\t\t\t\tPick asset\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t{appUrl && (\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName=\"rs-button rs-button-secondary\"\n\t\t\t\t\t\thref={appUrl}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\t\t\thost.openExternal(appUrl)\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon shape=\"link\" width={12.25} />\n\t\t\t\t\t\tOpen in Raster\n\t\t\t\t\t</a>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/** A file on its way into Raster, as the grid shows it until Raster has processed it. */\nexport function PendingTile({\n\tname,\n\tpreview,\n\tstatus,\n}: {\n\tname: string\n\tpreview: string\n\tstatus: string\n}) {\n\treturn (\n\t\t<div className=\"rs-tile\">\n\t\t\t<div className=\"rs-asset-thumb\" data-loaded aria-busy=\"true\">\n\t\t\t\t<img className=\"rs-thumb-blur\" src={preview} alt=\"\" />\n\t\t\t\t<div className=\"rs-thumb-preview\">\n\t\t\t\t\t<img src={preview} alt=\"\" />\n\t\t\t\t</div>\n\t\t\t\t<div className=\"rs-thumb-meta\">\n\t\t\t\t\t<span className=\"rs-thumb-title\">{name}</span>\n\t\t\t\t\t<span className=\"rs-thumb-subtitle\">\n\t\t\t\t\t\t<span className=\"rs-spinner\" />\n\t\t\t\t\t\t{status}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/** A control that opens the file chooser, drawn as whatever `className` makes it. */\nexport function FilePicker({\n\tclassName,\n\tdisabled,\n\tfocusable = true,\n\tonFile,\n\tchildren,\n}: {\n\tclassName: string\n\tdisabled: boolean\n\tfocusable?: boolean\n\tonFile: (file: File) => void\n\tchildren: ReactNode\n}) {\n\treturn (\n\t\t<label className={className}>\n\t\t\t{children}\n\t\t\t<input\n\t\t\t\tclassName=\"rs-visually-hidden\"\n\t\t\t\ttype=\"file\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\ttabIndex={focusable ? 0 : -1}\n\t\t\t\tonChange={(event) => {\n\t\t\t\t\tconst file = event.target.files?.[0]\n\t\t\t\t\t// Cleared, so picking the same file again uploads it again.\n\t\t\t\t\tevent.target.value = ''\n\t\t\t\t\tif (file) onFile(file)\n\t\t\t\t}}\n\t\t\t/>\n\t\t</label>\n\t)\n}\n\nconst UPLOADS = {\n\tuploading: 'Uploading',\n\tprocessing: 'Processing',\n\tdone: 'Uploaded',\n\t'timed-out': 'Still processing',\n} as const\nconst PROMOTES = {\n\tpromoting: 'Setting as default',\n\tdone: 'Default set',\n\t'timed-out': 'Still setting as default',\n} as const\n\n/** Where an upload and a promote stand, beside the header; each failure shows as an error. */\nexport function Progress({ upload, promote }: { upload: UploadState; promote: PromoteState }) {\n\treturn (\n\t\t<>\n\t\t\t{upload.status !== 'idle' && upload.status !== 'error' && (\n\t\t\t\t<Status status={upload.status} text={UPLOADS[upload.status]} />\n\t\t\t)}\n\t\t\t{promote.status !== 'idle' && promote.status !== 'error' && (\n\t\t\t\t<Status status={promote.status} text={PROMOTES[promote.status]} />\n\t\t\t)}\n\t\t</>\n\t)\n}\n\nfunction Status({ status, text }: { status: string; text: string }) {\n\tlet glyph = <span className=\"rs-spinner\" />\n\tif (status === 'done') glyph = <Icon shape=\"check\" />\n\tif (status === 'timed-out') glyph = <Icon shape=\"info-circle\" />\n\treturn (\n\t\t<span className=\"rs-status\" data-status={status}>\n\t\t\t{glyph}\n\t\t\t{text}\n\t\t</span>\n\t)\n}\n\n/** Raster's organization switcher: the current organization, over a menu of every one. */\nexport function OrganizationSwitcher({\n\torganizations,\n\tcurrent,\n\tonIntent,\n\tonSelect,\n}: {\n\torganizations: Array<Organization>\n\tcurrent: Organization | undefined\n\tonIntent: (organization: Organization) => void\n\tonSelect: (organizationId: string) => void\n}) {\n\tconst [open, setOpen] = useState(false)\n\tconst root = useRef<HTMLDivElement>(null)\n\n\tuseEffect(() => {\n\t\tif (!open) return\n\t\tconst close = (event: MouseEvent | KeyboardEvent) => {\n\t\t\tconst outside = event.target instanceof Node && !root.current?.contains(event.target)\n\t\t\tif (event instanceof KeyboardEvent ? event.key === 'Escape' : outside) setOpen(false)\n\t\t}\n\t\tdocument.addEventListener('mousedown', close)\n\t\tdocument.addEventListener('keydown', close)\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('mousedown', close)\n\t\t\tdocument.removeEventListener('keydown', close)\n\t\t}\n\t}, [open])\n\n\treturn (\n\t\t<div className=\"rs-org\" ref={root}>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"rs-sidebar-item rs-org-trigger\"\n\t\t\t\taria-expanded={open}\n\t\t\t\tonClick={() => setOpen(!open)}\n\t\t\t>\n\t\t\t\t<Avatar name={current?.name ?? current?.id ?? ''} />\n\t\t\t\t<span className=\"rs-library-name\">{current?.name ?? current?.id}</span>\n\t\t\t\t<Icon shape=\"chevron-up-down\" />\n\t\t\t</button>\n\t\t\t{open && (\n\t\t\t\t<div className=\"rs-menu\">\n\t\t\t\t\t<div className=\"rs-menu-heading\">Organizations</div>\n\t\t\t\t\t{organizations.map((organization) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={organization.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\torganization.id === current?.id ? 'rs-sidebar-item is-active' : 'rs-sidebar-item'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonMouseEnter={() => onIntent(organization)}\n\t\t\t\t\t\t\tonFocus={() => onIntent(organization)}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tsetOpen(false)\n\t\t\t\t\t\t\t\tonSelect(organization.id)\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Avatar name={organization.name ?? organization.id} />\n\t\t\t\t\t\t\t<span className=\"rs-library-name\">{organization.name ?? organization.id}</span>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n/** Raster's letter avatar, on a gradient hued from the name as the app hues it. */\nfunction Avatar({ name }: { name: string }) {\n\tif (name === '') return null\n\tlet hex = ''\n\tfor (let index = 0; index < Math.min(name.length, 10); index++) {\n\t\thex += `000${name.charCodeAt(index).toString(16)}`.slice(-4)\n\t}\n\tconst hue = Number.parseInt(hex, 16) % 360\n\treturn (\n\t\t<span\n\t\t\tclassName=\"rs-avatar\"\n\t\t\tstyle={{\n\t\t\t\tbackgroundImage: `linear-gradient(45deg, hsl(${hue}, 70%, 50%), hsl(${(hue + 60) % 360}, 70%, 50%))`,\n\t\t\t}}\n\t\t>\n\t\t\t{name.charAt(0).toUpperCase()}\n\t\t</span>\n\t)\n}\n\n/**\n * The spinner at the end of the grid, which asks for the next page once it is within two rows\n * of view. Keyed by the item count, so it looks again after each page lands.\n */\nexport function Sentinel({ onVisible }: { onVisible: () => void }) {\n\tconst spinner = useRef<HTMLSpanElement>(null)\n\n\tuseEffect(() => {\n\t\tconst node = spinner.current\n\t\tif (node === null || typeof IntersectionObserver === 'undefined') return\n\t\tconst observer = new IntersectionObserver(\n\t\t\t(entries) => {\n\t\t\t\tif (entries.some((entry) => entry.isIntersecting)) onVisible()\n\t\t\t},\n\t\t\t{ root: node.closest('.rs-content'), rootMargin: '0px 0px 360px 0px' }\n\t\t)\n\t\tobserver.observe(node)\n\t\treturn () => observer.disconnect()\n\t}, [onVisible])\n\n\treturn <span ref={spinner} className=\"rs-spinner\" />\n}\n"]}
1
+ {"version":3,"file":"picker-parts.js","sourceRoot":"","sources":["../src/picker-parts.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useVirtualizer } from '@tanstack/react-virtual'\nimport { Children, type ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react'\n\nimport {\n\ttype Asset,\n\ttype AssetVariant,\n\ttype Organization,\n\ttype RasterApiError,\n\ttype SearchHit,\n\tformatDateLong,\n\tformatFileSize,\n\tformatRelativeTime,\n\tgetBlurhashPlaceholder,\n\tgetPreviewUrl,\n\tgetThumbUrl,\n\tisReady,\n\ttoUserMessage,\n} from '@raster-app/sdk'\n\nimport { useRasterClient } from './context.js'\nimport { Icon } from './icons.js'\nimport type { PromoteState } from './use-promote-variant.js'\nimport type { UploadState } from './use-asset-upload.js'\n\nexport type ReportError = ((error: RasterApiError) => void) | undefined\n\nexport function Brand() {\n\treturn (\n\t\t<div className=\"rs-brand\">\n\t\t\t<Icon shape=\"raster\" solid width={18} />\n\t\t\tRaster\n\t\t</div>\n\t)\n}\n\n// Strict Mode runs an effect twice in development; the host hears of each error once.\nconst reported = new WeakSet<RasterApiError>()\n\nexport function ErrorCard({ error, onError }: { error: RasterApiError; onError: ReportError }) {\n\tuseEffect(() => {\n\t\tif (reported.has(error)) return\n\t\treported.add(error)\n\t\tonError?.(error)\n\t}, [error, onError])\n\treturn (\n\t\t<p role=\"alert\" className=\"rs-card\">\n\t\t\t{toUserMessage(error)}\n\t\t</p>\n\t)\n}\n\nexport function Empty({\n\tglyph,\n\ttitle,\n\ttext,\n\tchildren,\n}: {\n\tglyph: 'grid' | '∅'\n\ttitle: string\n\ttext: string\n\tchildren?: ReactNode\n}) {\n\treturn (\n\t\t<div className=\"rs-empty\">\n\t\t\t<div className=\"rs-empty-glyph\">{glyph === 'grid' ? <Icon shape=\"grid\" /> : glyph}</div>\n\t\t\t<h2 className=\"rs-heading\">{title}</h2>\n\t\t\t<p className=\"rs-muted rs-small\">{text}</p>\n\t\t\t{children}\n\t\t</div>\n\t)\n}\n\n/** Raster's tile height (`.rs-asset-thumb`) and the gap between its rows. */\nconst ROW_HEIGHT = 210 + 30\n\n/** The Raster app's columns from its window's width (`calculateGridColumns`). */\nconst BREAKPOINTS: Array<[number, number]> = [\n\t[2180, 7],\n\t[1920, 6],\n\t[1536, 5],\n\t[1280, 4],\n\t[1024, 3],\n\t[768, 2],\n]\n\n/** Raster's columns for a grid this wide: its window holds a 266px sidebar and 30px padding too. */\nexport function gridColumns(width: number): number {\n\tconst viewport = width + 266 + 2 * 30\n\treturn BREAKPOINTS.find(([min]) => viewport >= min)?.[1] ?? 1\n}\n\n/**\n * Tiles in Raster's grid, a row at a time as the Raster app draws them: only the rows in view,\n * and five either side, are mounted, however many have loaded.\n */\nexport function TileGrid({ children }: { children: ReactNode }) {\n\tconst tiles = Children.toArray(children)\n\tconst grid = useRef<HTMLDivElement>(null)\n\tconst [width, setWidth] = useState(0)\n\n\tuseLayoutEffect(() => {\n\t\tconst node = grid.current\n\t\tif (node === null) return\n\t\tsetWidth(node.clientWidth)\n\t\tif (typeof ResizeObserver === 'undefined') return\n\t\tconst observer = new ResizeObserver(() => setWidth(node.clientWidth))\n\t\tobserver.observe(node)\n\t\treturn () => observer.disconnect()\n\t}, [])\n\n\tconst columns = gridColumns(width)\n\tconst rows = useVirtualizer({\n\t\tcount: Math.ceil(tiles.length / columns),\n\t\tgetScrollElement: () => grid.current?.closest('.rs-content') ?? null,\n\t\testimateSize: () => ROW_HEIGHT,\n\t\toverscan: 5,\n\t\tscrollMargin: grid.current?.offsetTop ?? 0,\n\t})\n\n\treturn (\n\t\t<div ref={grid} className=\"rs-tile-grid\" style={{ height: rows.getTotalSize() }}>\n\t\t\t{rows.getVirtualItems().map((row) => (\n\t\t\t\t<div\n\t\t\t\t\tkey={row.key}\n\t\t\t\t\tclassName=\"rs-grid\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\ttop: row.start - rows.options.scrollMargin,\n\t\t\t\t\t\tgridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{tiles.slice(row.index * columns, (row.index + 1) * columns)}\n\t\t\t\t</div>\n\t\t\t))}\n\t\t</div>\n\t)\n}\n\n/**\n * Raster's grid tile: the picture over its blurred fill, or a checkerboard where it has alpha,\n * with a pill for a badge on the left and one for an action on the right.\n */\nexport function Tile({\n\tasset,\n\tonOpen,\n\tselected,\n\tbadge,\n\taction,\n}: {\n\tasset: Asset | SearchHit | AssetVariant\n\tonOpen: () => void\n\t/** Whether this is the version shown large, among an asset's versions. */\n\tselected?: boolean\n\tbadge?: ReactNode\n\taction?: ReactNode\n}) {\n\tconst [loaded, setLoaded] = useState(false)\n\tconst ready = isReady(asset)\n\tconst thumb = getThumbUrl(asset)\n\tconst fill = 'blurhash' in asset ? getBlurhashPlaceholder(asset) : null\n\tconst transparent = 'contentType' in asset && /png|svg|webp|gif/.test(asset.contentType ?? '')\n\tconst size = 'size' in asset ? formatFileSize(asset.size) : ''\n\tconst updated = 'updated' in asset ? formatRelativeTime(asset.updated) : ''\n\n\treturn (\n\t\t<div className=\"rs-tile\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"rs-asset-thumb\"\n\t\t\t\tdata-loaded={loaded || undefined}\n\t\t\t\tdisabled={!ready}\n\t\t\t\taria-pressed={selected}\n\t\t\t\ttitle={\n\t\t\t\t\t'created' in asset && asset.created\n\t\t\t\t\t\t? `Created ${formatDateLong(asset.created)}`\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tonClick={onOpen}\n\t\t\t>\n\t\t\t\t{transparent ? (\n\t\t\t\t\t<div className=\"rs-transparent\" />\n\t\t\t\t) : (\n\t\t\t\t\tfill && <img className=\"rs-thumb-blur\" src={fill} alt=\"\" />\n\t\t\t\t)}\n\t\t\t\t<div className=\"rs-thumb-preview\">\n\t\t\t\t\t{thumb && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={thumb}\n\t\t\t\t\t\t\tsrc={thumb}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\tdecoding=\"async\"\n\t\t\t\t\t\t\tonLoad={() => setLoaded(true)}\n\t\t\t\t\t\t\tonError={() => setLoaded(true)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"rs-thumb-meta\">\n\t\t\t\t\t<span className=\"rs-thumb-title\">{asset.name}</span>\n\t\t\t\t\t<span className=\"rs-thumb-subtitle\">\n\t\t\t\t\t\t{!ready && <span>Not ready</span>}\n\t\t\t\t\t\t{ready && size && <span>{size}</span>}\n\t\t\t\t\t\t{ready && updated && <span>{updated}</span>}\n\t\t\t\t\t\t{ready && !size && !updated && asset.width && asset.height && (\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t{asset.width} × {asset.height}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</button>\n\t\t\t{badge}\n\t\t\t{action}\n\t\t</div>\n\t)\n}\n\n/**\n * An opened asset or variant: the image large, its facts, and what the host can do with it.\n * Raster opens through the host, which reaches the browser from a Figma plugin too.\n */\nexport function Detail({\n\titem,\n\tbusy,\n\tonPick,\n}: {\n\titem: Asset | SearchHit | AssetVariant\n\t/** While the asset is read in full for the host, or a promote has yet to land. */\n\tbusy: boolean\n\tonPick?: () => void\n}) {\n\tconst { host } = useRasterClient()\n\tconst image = getPreviewUrl(item)\n\tconst appUrl = item.appUrl\n\tconst facts = [\n\t\titem.width && item.height ? `${item.width} × ${item.height}` : '',\n\t\t'size' in item ? formatFileSize(item.size) : '',\n\t\t'created' in item && item.created ? `Created ${formatDateLong(item.created)}` : '',\n\t].filter((fact) => fact !== '')\n\n\treturn (\n\t\t<div className=\"rs-detail\">\n\t\t\t<div className=\"rs-detail-image\">{image && <img key={image} src={image} alt=\"\" />}</div>\n\t\t\t<div className=\"rs-detail-info\">\n\t\t\t\t<h2 className=\"rs-heading\">{item.name}</h2>\n\t\t\t\t{facts.length > 0 && <p className=\"rs-muted rs-small\">{facts.join(' · ')}</p>}\n\t\t\t\t{onPick && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"rs-button rs-button-primary\"\n\t\t\t\t\t\tdisabled={!isReady(item) || busy}\n\t\t\t\t\t\tonClick={onPick}\n\t\t\t\t\t>\n\t\t\t\t\t\tPick asset\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t{appUrl && (\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName=\"rs-button rs-button-secondary\"\n\t\t\t\t\t\thref={appUrl}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\t\t\thost.openExternal(appUrl)\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon shape=\"link\" width={12.25} />\n\t\t\t\t\t\tOpen in Raster\n\t\t\t\t\t</a>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/** A file on its way into Raster, as the grid shows it until Raster has processed it. */\nexport function PendingTile({\n\tname,\n\tpreview,\n\tstatus,\n}: {\n\tname: string\n\tpreview: string\n\tstatus: string\n}) {\n\treturn (\n\t\t<div className=\"rs-tile\">\n\t\t\t<div className=\"rs-asset-thumb\" data-loaded aria-busy=\"true\">\n\t\t\t\t<div className=\"rs-thumb-preview\">\n\t\t\t\t\t<img src={preview} alt=\"\" />\n\t\t\t\t</div>\n\t\t\t\t<div className=\"rs-thumb-meta\">\n\t\t\t\t\t<span className=\"rs-thumb-title\">{name}</span>\n\t\t\t\t\t<span className=\"rs-thumb-subtitle\">\n\t\t\t\t\t\t<span className=\"rs-spinner\" />\n\t\t\t\t\t\t{status}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/** A control that opens the file chooser, drawn as whatever `className` makes it. */\nexport function FilePicker({\n\tclassName,\n\tdisabled,\n\tfocusable = true,\n\tonFile,\n\tchildren,\n}: {\n\tclassName: string\n\tdisabled: boolean\n\tfocusable?: boolean\n\tonFile: (file: File) => void\n\tchildren: ReactNode\n}) {\n\treturn (\n\t\t<label className={className}>\n\t\t\t{children}\n\t\t\t<input\n\t\t\t\tclassName=\"rs-visually-hidden\"\n\t\t\t\ttype=\"file\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\ttabIndex={focusable ? 0 : -1}\n\t\t\t\tonChange={(event) => {\n\t\t\t\t\tconst file = event.target.files?.[0]\n\t\t\t\t\t// Cleared, so picking the same file again uploads it again.\n\t\t\t\t\tevent.target.value = ''\n\t\t\t\t\tif (file) onFile(file)\n\t\t\t\t}}\n\t\t\t/>\n\t\t</label>\n\t)\n}\n\nconst UPLOADS = {\n\tuploading: 'Uploading',\n\tprocessing: 'Processing',\n\tdone: 'Uploaded',\n\t'timed-out': 'Still processing',\n} as const\nconst PROMOTES = {\n\tpromoting: 'Setting as default',\n\tdone: 'Default set',\n\t'timed-out': 'Still setting as default',\n} as const\n\n/** Where an upload and a promote stand, beside the header; each failure shows as an error. */\nexport function Progress({ upload, promote }: { upload: UploadState; promote: PromoteState }) {\n\treturn (\n\t\t<>\n\t\t\t{upload.status !== 'idle' && upload.status !== 'error' && (\n\t\t\t\t<Status status={upload.status} text={UPLOADS[upload.status]} />\n\t\t\t)}\n\t\t\t{promote.status !== 'idle' && promote.status !== 'error' && (\n\t\t\t\t<Status status={promote.status} text={PROMOTES[promote.status]} />\n\t\t\t)}\n\t\t</>\n\t)\n}\n\nfunction Status({ status, text }: { status: string; text: string }) {\n\tlet glyph = <span className=\"rs-spinner\" />\n\tif (status === 'done') glyph = <Icon shape=\"check\" />\n\tif (status === 'timed-out') glyph = <Icon shape=\"info-circle\" />\n\treturn (\n\t\t<span className=\"rs-status\" data-status={status}>\n\t\t\t{glyph}\n\t\t\t{text}\n\t\t</span>\n\t)\n}\n\n/** Raster's organization switcher: the current organization, over a menu of every one. */\nexport function OrganizationSwitcher({\n\torganizations,\n\tcurrent,\n\tonIntent,\n\tonSelect,\n}: {\n\torganizations: Array<Organization>\n\tcurrent: Organization | undefined\n\tonIntent: (organization: Organization) => void\n\tonSelect: (organizationId: string) => void\n}) {\n\tconst [open, setOpen] = useState(false)\n\tconst root = useRef<HTMLDivElement>(null)\n\n\tuseEffect(() => {\n\t\tif (!open) return\n\t\tconst close = (event: MouseEvent | KeyboardEvent) => {\n\t\t\tconst outside = event.target instanceof Node && !root.current?.contains(event.target)\n\t\t\tif (event instanceof KeyboardEvent ? event.key !== 'Escape' : !outside) return\n\t\t\t// Stopped here, so a host dialog that closes on Escape stays open.\n\t\t\tif (event instanceof KeyboardEvent) event.stopPropagation()\n\t\t\tsetOpen(false)\n\t\t}\n\t\tdocument.addEventListener('mousedown', close)\n\t\tdocument.addEventListener('keydown', close)\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('mousedown', close)\n\t\t\tdocument.removeEventListener('keydown', close)\n\t\t}\n\t}, [open])\n\n\treturn (\n\t\t<div className=\"rs-org\" ref={root}>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"rs-sidebar-item rs-org-trigger\"\n\t\t\t\taria-expanded={open}\n\t\t\t\tonClick={() => setOpen(!open)}\n\t\t\t>\n\t\t\t\t<Avatar name={current?.name ?? current?.id ?? ''} />\n\t\t\t\t<span className=\"rs-library-name\">{current?.name ?? current?.id}</span>\n\t\t\t\t<Icon shape=\"chevron-up-down\" />\n\t\t\t</button>\n\t\t\t{open && (\n\t\t\t\t<div className=\"rs-menu\">\n\t\t\t\t\t<div className=\"rs-menu-heading\">Organizations</div>\n\t\t\t\t\t{organizations.map((organization) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={organization.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\torganization.id === current?.id ? 'rs-sidebar-item is-active' : 'rs-sidebar-item'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonMouseEnter={() => onIntent(organization)}\n\t\t\t\t\t\t\tonFocus={() => onIntent(organization)}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tsetOpen(false)\n\t\t\t\t\t\t\t\tonSelect(organization.id)\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Avatar name={organization.name ?? organization.id} />\n\t\t\t\t\t\t\t<span className=\"rs-library-name\">{organization.name ?? organization.id}</span>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n/** Raster's letter avatar, on a gradient hued from the name as the app hues it. */\nfunction Avatar({ name }: { name: string }) {\n\tif (name === '') return null\n\tlet hex = ''\n\tfor (let index = 0; index < Math.min(name.length, 10); index++) {\n\t\thex += `000${name.charCodeAt(index).toString(16)}`.slice(-4)\n\t}\n\tconst hue = Number.parseInt(hex, 16) % 360\n\treturn (\n\t\t<span\n\t\t\tclassName=\"rs-avatar\"\n\t\t\tstyle={{\n\t\t\t\tbackgroundImage: `linear-gradient(45deg, hsl(${hue}, 70%, 50%), hsl(${(hue + 60) % 360}, 70%, 50%))`,\n\t\t\t}}\n\t\t>\n\t\t\t{name.charAt(0).toUpperCase()}\n\t\t</span>\n\t)\n}\n\n/**\n * The spinner at the end of the grid, which asks for the next page once it is within two rows\n * of view. Keyed by the item count, so it looks again after each page lands.\n */\nexport function Sentinel({ onVisible }: { onVisible: () => void }) {\n\tconst spinner = useRef<HTMLSpanElement>(null)\n\n\tuseEffect(() => {\n\t\tconst node = spinner.current\n\t\tif (node === null || typeof IntersectionObserver === 'undefined') return\n\t\tconst observer = new IntersectionObserver(\n\t\t\t(entries) => {\n\t\t\t\tif (entries.some((entry) => entry.isIntersecting)) onVisible()\n\t\t\t},\n\t\t\t{ root: node.closest('.rs-content'), rootMargin: '0px 0px 360px 0px' }\n\t\t)\n\t\tobserver.observe(node)\n\t\treturn () => observer.disconnect()\n\t}, [onVisible])\n\n\treturn <span ref={spinner} className=\"rs-spinner\" />\n}\n"]}
@@ -4,7 +4,7 @@ import { useRef, useState } from 'react';
4
4
  import { isReady, } from '@raster-app/sdk';
5
5
  import { useRasterClient } from './context.js';
6
6
  import { Icon } from './icons.js';
7
- import { Brand, Detail, Empty, ErrorCard, FilePicker, OrganizationSwitcher, PendingTile, Progress, Sentinel, Tile, } from './picker-parts.js';
7
+ import { Brand, Detail, Empty, ErrorCard, FilePicker, OrganizationSwitcher, PendingTile, Progress, Sentinel, Tile, TileGrid, } from './picker-parts.js';
8
8
  import { SignIn } from './picker-sign-in.js';
9
9
  import { useAssetSearch } from './use-asset-search.js';
10
10
  import { useAssetUpload } from './use-asset-upload.js';
@@ -69,6 +69,8 @@ function Browser({ onPick, onError, }) {
69
69
  const shown = search.active ? search : library === null ? null : assets;
70
70
  const items = search.active ? search.hits : assets.assets;
71
71
  const hit = search.active ? (search.hits?.find((entry) => entry.id === focusId) ?? null) : null;
72
+ // Until a promote lands, the cached asset is still the previous default.
73
+ const busy = read.isPending || promote.state.status === 'promoting';
72
74
  /** Hand the host the whole asset: a search hit or a variant carries less, so it is read first. */
73
75
  function pick(item) {
74
76
  if (organizationId === null || onPick === undefined)
@@ -86,14 +88,14 @@ function Browser({ onPick, onError, }) {
86
88
  }
87
89
  /** Upload one file into the open library, or as a variant of `parentId`. */
88
90
  async function send(file, parentId) {
89
- if (organizationId === null || library === null || !writable)
91
+ // A second upload would cancel the one in flight.
92
+ if (organizationId === null || library === null || !writable || pending !== null)
90
93
  return;
91
94
  const preview = URL.createObjectURL(file);
92
95
  setPending({ name: file.name, preview, parentId });
93
96
  await upload.upload({ organizationId, libraryId: library.id, parentId, source: file });
94
97
  URL.revokeObjectURL(preview);
95
- // A later upload may have taken the placeholder over by now.
96
- setPending((current) => (current?.preview === preview ? null : current));
98
+ setPending(null);
97
99
  }
98
100
  /** The first press asks to confirm; the second promotes. */
99
101
  function setDefault(variant) {
@@ -124,23 +126,23 @@ function Browser({ onPick, onError, }) {
124
126
  if (versions) {
125
127
  const focused = [opened, ...variants].find((entry) => entry.id === focusId) ?? opened;
126
128
  heading = (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "rs-crumb", onClick: () => navigation.openAsset(null), children: library?.name }), _jsx("span", { className: "rs-muted", children: "/" }), _jsx("h1", { className: "rs-heading", children: opened.name }), _jsxs("span", { className: "rs-sidebar-count is-active", children: [variants.length + 1, " versions"] })] }));
127
- content = (_jsxs(_Fragment, { children: [_jsx(Detail, { item: focused, busy: read.isPending, onPick: onPick && (() => pick(focused)) }), _jsxs("div", { className: "rs-grid", children: [_jsx(Tile, { asset: opened, selected: focused.id === opened.id, onOpen: () => setFocus({ scope, id: opened.id }), badge: _jsxs("span", { className: "rs-pill rs-tile-badge", children: [_jsx(Icon, { shape: "star", solid: true, width: 10.5 }), "Default"] }) }), variants.map((variant) => (_jsx(Tile, { asset: variant, selected: focused.id === variant.id, onOpen: () => setFocus({ scope, id: variant.id }), action: writable &&
129
+ content = (_jsxs(_Fragment, { children: [_jsx(Detail, { item: focused, busy: busy, onPick: onPick && (() => pick(focused)) }), _jsxs(TileGrid, { children: [_jsx(Tile, { asset: opened, selected: focused.id === opened.id, onOpen: () => setFocus({ scope, id: opened.id }), badge: _jsxs("span", { className: "rs-pill rs-tile-badge", children: [_jsx(Icon, { shape: "star", solid: true, width: 10.5 }), "Default"] }) }), variants.map((variant) => (_jsx(Tile, { asset: variant, selected: focused.id === variant.id, onOpen: () => setFocus({ scope, id: variant.id }), action: writable &&
128
130
  isReady(variant) && (_jsxs("button", { type: "button", className: confirming === variant.id
129
131
  ? 'rs-pill rs-tile-action is-confirming'
130
132
  : 'rs-pill rs-tile-action', disabled: promote.state.status === 'promoting', onClick: () => setDefault(variant), children: [_jsx(Icon, { shape: "star", width: 10.5 }), confirming === variant.id ? 'Confirm' : 'Set as default'] })) }, variant.id))), pendingTile] })] }));
131
133
  }
132
134
  else if (hit) {
133
135
  heading = (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "rs-crumb", onClick: () => setFocus(null), children: "Search" }), _jsx("span", { className: "rs-muted", children: "/" }), _jsx("h1", { className: "rs-heading", children: hit.name })] }));
134
- content = _jsx(Detail, { item: hit, busy: read.isPending, onPick: onPick && (() => pick(hit)) });
136
+ content = _jsx(Detail, { item: hit, busy: busy, onPick: onPick && (() => pick(hit)) });
135
137
  }
136
138
  else if (shown === null ? organizations.isLoading || libraries.isLoading : items === null) {
137
139
  content = shown?.error ? null : (_jsx("div", { className: "rs-center", children: _jsx("span", { className: "rs-spinner" }) }));
138
140
  }
139
141
  else if (shown !== null && items?.length === 0 && !pendingTile) {
140
- content = search.active ? (_jsx(Empty, { glyph: "\u2205", title: "No results", text: `Nothing matches “${search.query}”.` })) : (_jsx(Empty, { glyph: "\u2205", title: "No assets", text: "This library is empty.", children: writable && library !== null && (_jsx(FilePicker, { className: "rs-button rs-button-primary rs-button-sm", disabled: false, onFile: (file) => void send(file, null), children: "Upload files" })) }));
142
+ content = search.active ? (_jsx(Empty, { glyph: "\u2205", title: "No results", text: `Nothing matches “${search.query}”.` })) : (_jsx(Empty, { glyph: "\u2205", title: "No assets", text: "This library is empty.", children: writable && library !== null && (_jsx(FilePicker, { className: "rs-button rs-button-primary rs-button-sm", disabled: pending !== null, onFile: (file) => void send(file, null), children: "Upload files" })) }));
141
143
  }
142
144
  else if (shown !== null && items) {
143
- content = (_jsxs(_Fragment, { children: [_jsxs("div", { className: "rs-grid", children: [pendingTile, search.active
145
+ content = (_jsxs(_Fragment, { children: [_jsxs(TileGrid, { children: [pendingTile, search.active
144
146
  ? search.hits?.map((entry) => (_jsx(Tile, { asset: entry, onOpen: () => setFocus({ scope, id: entry.id }) }, entry.id)))
145
147
  : assets.assets?.map((asset) => {
146
148
  const count = asset.variants?.filter(Boolean).length ?? 0;
@@ -160,12 +162,12 @@ function Browser({ onPick, onError, }) {
160
162
  };
161
163
  return (_jsxs("div", { className: open ? 'rs-library is-expanded' : 'rs-library', children: [_jsxs("button", { type: "button", className: "rs-sidebar-item rs-library-row", disabled: entry.access === null, onMouseEnter: warm, onFocus: warm, onClick: () => navigation.openLibrary(entry), children: [_jsx(Icon, { shape: "grid" }), _jsx("span", { className: "rs-library-name", children: entry.name }), _jsx("span", { className: open ? 'rs-sidebar-count is-active' : 'rs-sidebar-count', children: COUNT.format(entry.assetsCount ?? 0) })] }), _jsx("div", { className: open ? 'rs-library-menu is-expanded' : 'rs-library-menu', "aria-hidden": !open, children: _jsxs("div", { children: [_jsxs("button", { type: "button", tabIndex: open ? 0 : -1, className: open && !search.active && opened === null
162
164
  ? 'rs-sidebar-item is-active'
163
- : 'rs-sidebar-item', onClick: toGrid, children: [_jsx(Icon, { shape: "circle" }), "All Assets"] }), _jsxs(FilePicker, { className: "rs-sidebar-item", disabled: !open || entry.access !== 'write', focusable: open, onFile: (file) => {
165
+ : 'rs-sidebar-item', onClick: toGrid, children: [_jsx(Icon, { shape: "circle" }), "All Assets"] }), _jsxs(FilePicker, { className: "rs-sidebar-item", disabled: !open || entry.access !== 'write' || pending !== null, focusable: open, onFile: (file) => {
164
166
  toGrid();
165
167
  void send(file, null);
166
168
  }, children: [_jsx(Icon, { shape: "upload" }), "Upload"] })] }) })] }, entry.id));
167
169
  })] }), _jsxs("div", { className: "rs-sidebar-footer", children: [_jsx("span", { className: "rs-sidebar-item rs-muted", children: session.isSignedIn ? (session.userName ?? 'Signed in') : 'API key' }), _jsx("button", { type: "button", className: "rs-sidebar-item", onClick: () => void session.signOut(), children: "Sign out" })] })] }), _jsxs("section", { className: "rs-main", "aria-label": "Assets", onDragEnter: (event) => {
168
- if (!dropTarget || !event.dataTransfer.types.includes('Files'))
170
+ if (!dropTarget || pending !== null || !event.dataTransfer.types.includes('Files'))
169
171
  return;
170
172
  dragDepth.current += 1;
171
173
  setDragging(true);
@@ -183,6 +185,6 @@ function Browser({ onPick, onError, }) {
183
185
  const file = event.dataTransfer.files[0];
184
186
  if (file && dropTarget)
185
187
  void send(file, versions ? opened.id : null);
186
- }, children: [_jsxs("header", { className: "rs-header", children: [heading, _jsx("span", { className: "rs-muted rs-small", children: status }), _jsx(Progress, { upload: upload.state, promote: promote.state }), _jsxs("div", { className: "rs-search", children: [_jsx(Icon, { shape: "search", width: 12.25 }), _jsx("input", { ref: searchInput, className: "rs-input", "aria-label": "Search Raster", placeholder: library === null ? 'Search every library…' : `Search ${library.name}…`, value: query, onChange: (event) => navigation.setQuery(event.target.value) }), query !== '' && (_jsx("button", { type: "button", className: "rs-icon-button", "aria-label": "Clear search", onClick: () => navigation.setQuery(''), children: _jsx(Icon, { shape: "x", width: 10.5 }) }))] }), versions && writable && (_jsxs(FilePicker, { className: "rs-button rs-button-sm", disabled: false, onFile: (file) => void send(file, opened.id), children: [_jsx(Icon, { shape: "upload", width: 12.25 }), "Upload variant"] })), _jsx("button", { type: "button", className: "rs-button rs-button-sm", onClick: navigation.refresh, children: "Refresh" })] }), _jsxs("div", { className: "rs-content rs-scroll", children: [organizations.error && _jsx(ErrorCard, { error: organizations.error, onError: onError }), libraries.error && _jsx(ErrorCard, { error: libraries.error, onError: onError }), shown?.error && _jsx(ErrorCard, { error: shown.error, onError: onError }), read.error && _jsx(ErrorCard, { error: read.error, onError: onError }), upload.state.status === 'error' && (_jsx(ErrorCard, { error: upload.state.error, onError: onError })), promote.state.status === 'error' && (_jsx(ErrorCard, { error: promote.state.error, onError: onError })), content] }), _jsx("div", { className: dragging ? 'rs-drop is-active' : 'rs-drop' })] })] }));
188
+ }, children: [_jsxs("header", { className: "rs-header", children: [heading, _jsx("span", { className: "rs-muted rs-small", children: status }), _jsx(Progress, { upload: upload.state, promote: promote.state }), _jsxs("div", { className: "rs-search", children: [_jsx(Icon, { shape: "search", width: 12.25 }), _jsx("input", { ref: searchInput, className: "rs-input", "aria-label": "Search Raster", placeholder: library === null ? 'Search every library…' : `Search ${library.name}…`, value: query, onChange: (event) => navigation.setQuery(event.target.value) }), query !== '' && (_jsx("button", { type: "button", className: "rs-icon-button", "aria-label": "Clear search", onClick: () => navigation.setQuery(''), children: _jsx(Icon, { shape: "x", width: 10.5 }) }))] }), versions && writable && (_jsxs(FilePicker, { className: "rs-button rs-button-sm", disabled: pending !== null, onFile: (file) => void send(file, opened.id), children: [_jsx(Icon, { shape: "upload", width: 12.25 }), "Upload variant"] })), _jsx("button", { type: "button", className: "rs-button rs-button-sm", onClick: navigation.refresh, children: "Refresh" })] }), _jsxs("div", { className: "rs-content", children: [organizations.error && _jsx(ErrorCard, { error: organizations.error, onError: onError }), libraries.error && _jsx(ErrorCard, { error: libraries.error, onError: onError }), shown?.error && _jsx(ErrorCard, { error: shown.error, onError: onError }), read.error && _jsx(ErrorCard, { error: read.error, onError: onError }), upload.state.status === 'error' && (_jsx(ErrorCard, { error: upload.state.error, onError: onError })), promote.state.status === 'error' && (_jsx(ErrorCard, { error: promote.state.error, onError: onError })), content] }), _jsx("div", { className: dragging ? 'rs-drop is-active' : 'rs-drop' })] })] }));
187
189
  }
188
190
  //# sourceMappingURL=raster-picker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"raster-picker.js","sourceRoot":"","sources":["../src/raster-picker.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMutation } from '@tanstack/react-query'\nimport { type ReactNode, useRef, useState } from 'react'\n\nimport {\n\ttype Asset,\n\ttype AssetVariant,\n\ttype RasterApiError,\n\ttype SearchHit,\n\tisReady,\n} from '@raster-app/sdk'\n\nimport { useRasterClient } from './context.js'\nimport { Icon } from './icons.js'\nimport {\n\tBrand,\n\tDetail,\n\tEmpty,\n\tErrorCard,\n\tFilePicker,\n\tOrganizationSwitcher,\n\tPendingTile,\n\tProgress,\n\ttype ReportError,\n\tSentinel,\n\tTile,\n} from './picker-parts.js'\nimport { SignIn } from './picker-sign-in.js'\nimport { useAssetSearch } from './use-asset-search.js'\nimport { useAssetUpload } from './use-asset-upload.js'\nimport { useAssets, usePrefetchAssets } from './use-assets.js'\nimport { useLibraries, usePrefetchLibraries } from './use-libraries.js'\nimport { useRasterNavigation } from './use-navigation.js'\nimport { useOrganizations } from './use-organizations.js'\nimport { usePromoteVariant } from './use-promote-variant.js'\nimport { useSession } from './use-session.js'\n\nexport type RasterPickerProps = {\n\t/**\n\t * The picked asset, whole whether it came from a library, a search or an asset's versions, and\n\t * its organization. `getFullSizeUrl(asset)` is the image. Without it, the picker only browses,\n\t * with no Pick asset button.\n\t */\n\tonPick?: (asset: Asset, organizationId: string) => void\n\t/** Binds the device sign-in to this organization; any other grant fails. */\n\torganizationId?: string\n\t/** The consent the device sign-in asks for: `org` when `organizationId` is set, else `user`. */\n\tscope?: 'user' | 'org'\n\t/** Each failure the picker shows, once, for the host to log. */\n\tonError?: (error: RasterApiError) => void\n\t/** Follows the system's color scheme when unset. */\n\ttheme?: 'light' | 'dark'\n}\n\nconst COUNT = new Intl.NumberFormat('en-US', { notation: 'compact' })\n\n/** A file on its way in, which the grid shows until Raster has processed it. */\ntype Pending = { name: string; preview: string; parentId: string | null }\n\n/**\n * Raster's asset picker, drawn as Raster draws it (`@raster-app/react/styles.css`): sign-in, the\n * organization's libraries, search and uploads. A tile opens its asset large, to pick or open in\n * Raster, over its versions with the default to set. It fills its container, inside a\n * `RasterProvider`.\n */\nexport function RasterPicker({ onPick, organizationId, scope, onError, theme }: RasterPickerProps) {\n\tconst { credentials, isConfigured } = useSession()\n\n\tlet body = (\n\t\t<div className=\"rs-center\">\n\t\t\t<span className=\"rs-spinner\" />\n\t\t</div>\n\t)\n\tif (credentials !== undefined && !isConfigured) {\n\t\tbody = (\n\t\t\t<SignIn\n\t\t\t\torganizationId={organizationId}\n\t\t\t\tscope={scope ?? (organizationId === undefined ? 'user' : 'org')}\n\t\t\t\tonError={onError}\n\t\t\t/>\n\t\t)\n\t} else if (isConfigured) {\n\t\tbody = <Browser onPick={onPick} onError={onError} />\n\t}\n\treturn (\n\t\t<div className=\"rs rs-picker\" data-theme={theme}>\n\t\t\t{body}\n\t\t</div>\n\t)\n}\n\nfunction Browser({\n\tonPick,\n\tonError,\n}: {\n\tonPick: RasterPickerProps['onPick']\n\tonError: ReportError\n}) {\n\tconst client = useRasterClient()\n\tconst session = useSession()\n\tconst organizations = useOrganizations()\n\tconst navigation = useRasterNavigation({ organizations: organizations.data ?? null })\n\tconst { organizationId, library, query } = navigation\n\tconst organization = organizations.data?.find((entry) => entry.id === organizationId)\n\tconst libraries = useLibraries({ organizationId, organizationName: organization?.name ?? null })\n\tconst assets = useAssets({ organizationId, libraryId: library?.id ?? null })\n\tconst search = useAssetSearch(\n\t\torganizationId === null ? null : { organizationId, libraryId: library?.id ?? null },\n\t\tquery\n\t)\n\tconst upload = useAssetUpload()\n\tconst promote = usePromoteVariant()\n\tconst read = useMutation<Asset, RasterApiError, Parameters<typeof client.assets.get>[0]>({\n\t\tmutationFn: (options) => client.assets.get(options),\n\t})\n\tconst prefetchAssets = usePrefetchAssets()\n\tconst prefetchLibraries = usePrefetchLibraries()\n\tconst searchInput = useRef<HTMLInputElement>(null)\n\tconst [pending, setPending] = useState<Pending | null>(null)\n\tconst [confirming, setConfirming] = useState<string | null>(null)\n\tconst [dragging, setDragging] = useState(false)\n\tconst dragDepth = useRef(0)\n\t// The version shown large, or the search hit opened, for the scope it was chosen in.\n\tconst [focus, setFocus] = useState<{ scope: string; id: string } | null>(null)\n\tconst scope = [organizationId, library?.id, navigation.asset?.id, query].join('/')\n\tconst focusId = focus?.scope === scope ? focus.id : null\n\n\tconst access = libraries.data?.find((entry) => entry.id === library?.id)?.access ?? null\n\tconst writable = access === 'write'\n\t// The asset as the list last read it, which refetches after an upload or a promote.\n\tconst opened =\n\t\tnavigation.asset === null\n\t\t\t? null\n\t\t\t: (assets.assets?.find((entry) => entry.id === navigation.asset?.id) ?? navigation.asset)\n\tconst versions = !search.active && opened !== null\n\tconst variants = (opened?.variants ?? []).filter(\n\t\t(variant): variant is AssetVariant => variant !== null\n\t)\n\tconst shown = search.active ? search : library === null ? null : assets\n\tconst items = search.active ? search.hits : assets.assets\n\tconst hit = search.active ? (search.hits?.find((entry) => entry.id === focusId) ?? null) : null\n\n\t/** Hand the host the whole asset: a search hit or a variant carries less, so it is read first. */\n\tfunction pick(item: Asset | SearchHit | AssetVariant) {\n\t\tif (organizationId === null || onPick === undefined) return\n\t\tconst loaded = assets.assets?.find((entry) => entry.id === item.id)\n\t\tif (loaded) {\n\t\t\tonPick(loaded, organizationId)\n\t\t\treturn\n\t\t}\n\t\t// A variant lives in its original's library, which is the open one.\n\t\tconst libraryId = ('libraryId' in item ? item.libraryId : null) ?? library?.id\n\t\tif (!libraryId) return\n\t\tread.mutate(\n\t\t\t{ organizationId, libraryId, assetId: item.id },\n\t\t\t{ onSuccess: (asset) => onPick(asset, organizationId) }\n\t\t)\n\t}\n\n\t/** Upload one file into the open library, or as a variant of `parentId`. */\n\tasync function send(file: File, parentId: string | null) {\n\t\tif (organizationId === null || library === null || !writable) return\n\t\tconst preview = URL.createObjectURL(file)\n\t\tsetPending({ name: file.name, preview, parentId })\n\t\tawait upload.upload({ organizationId, libraryId: library.id, parentId, source: file })\n\t\tURL.revokeObjectURL(preview)\n\t\t// A later upload may have taken the placeholder over by now.\n\t\tsetPending((current) => (current?.preview === preview ? null : current))\n\t}\n\n\t/** The first press asks to confirm; the second promotes. */\n\tfunction setDefault(variant: AssetVariant) {\n\t\tif (confirming !== variant.id) {\n\t\t\tsetConfirming(variant.id)\n\t\t\treturn\n\t\t}\n\t\tsetConfirming(null)\n\t\tif (organizationId === null || library === null || opened === null) return\n\t\tvoid promote.promote({\n\t\t\torganizationId,\n\t\t\tlibraryId: library.id,\n\t\t\tassetId: opened.id,\n\t\t\tvariantId: variant.id,\n\t\t})\n\t}\n\n\tconst pendingTile = pending !== null &&\n\t\t!search.active &&\n\t\tpending.parentId === (opened?.id ?? null) && (\n\t\t\t<PendingTile\n\t\t\t\tname={pending.name}\n\t\t\t\tpreview={pending.preview}\n\t\t\t\tstatus={upload.state.status === 'uploading' ? 'Uploading' : 'Processing'}\n\t\t\t/>\n\t\t)\n\n\tlet status = ''\n\tif (search.active) status = search.isSearching ? 'Searching' : `${search.found} found`\n\telse if (library !== null && !versions) status = `${assets.assets?.length ?? 0} loaded`\n\n\tlet heading: ReactNode = (\n\t\t<>\n\t\t\t<h1 className=\"rs-heading\">{search.active ? 'Search' : (library?.name ?? 'Libraries')}</h1>\n\t\t\t{!search.active && library !== null && (\n\t\t\t\t<span className=\"rs-sidebar-count is-active\">{access ?? 'no access'}</span>\n\t\t\t)}\n\t\t</>\n\t)\n\tlet content: ReactNode = (\n\t\t<Empty glyph=\"grid\" title=\"Choose a library\" text=\"Or search every library.\" />\n\t)\n\tif (versions) {\n\t\tconst focused = [opened, ...variants].find((entry) => entry.id === focusId) ?? opened\n\t\theading = (\n\t\t\t<>\n\t\t\t\t<button type=\"button\" className=\"rs-crumb\" onClick={() => navigation.openAsset(null)}>\n\t\t\t\t\t{library?.name}\n\t\t\t\t</button>\n\t\t\t\t<span className=\"rs-muted\">/</span>\n\t\t\t\t<h1 className=\"rs-heading\">{opened.name}</h1>\n\t\t\t\t<span className=\"rs-sidebar-count is-active\">{variants.length + 1} versions</span>\n\t\t\t</>\n\t\t)\n\t\tcontent = (\n\t\t\t<>\n\t\t\t\t<Detail item={focused} busy={read.isPending} onPick={onPick && (() => pick(focused))} />\n\t\t\t\t<div className=\"rs-grid\">\n\t\t\t\t\t<Tile\n\t\t\t\t\t\tasset={opened}\n\t\t\t\t\t\tselected={focused.id === opened.id}\n\t\t\t\t\t\tonOpen={() => setFocus({ scope, id: opened.id })}\n\t\t\t\t\t\tbadge={\n\t\t\t\t\t\t\t<span className=\"rs-pill rs-tile-badge\">\n\t\t\t\t\t\t\t\t<Icon shape=\"star\" solid width={10.5} />\n\t\t\t\t\t\t\t\tDefault\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t\t{variants.map((variant) => (\n\t\t\t\t\t\t<Tile\n\t\t\t\t\t\t\tkey={variant.id}\n\t\t\t\t\t\t\tasset={variant}\n\t\t\t\t\t\t\tselected={focused.id === variant.id}\n\t\t\t\t\t\t\tonOpen={() => setFocus({ scope, id: variant.id })}\n\t\t\t\t\t\t\taction={\n\t\t\t\t\t\t\t\twritable &&\n\t\t\t\t\t\t\t\tisReady(variant) && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\t\t\t\tconfirming === variant.id\n\t\t\t\t\t\t\t\t\t\t\t\t? 'rs-pill rs-tile-action is-confirming'\n\t\t\t\t\t\t\t\t\t\t\t\t: 'rs-pill rs-tile-action'\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tdisabled={promote.state.status === 'promoting'}\n\t\t\t\t\t\t\t\t\t\tonClick={() => setDefault(variant)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Icon shape=\"star\" width={10.5} />\n\t\t\t\t\t\t\t\t\t\t{confirming === variant.id ? 'Confirm' : 'Set as default'}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t\t{pendingTile}\n\t\t\t\t</div>\n\t\t\t</>\n\t\t)\n\t} else if (hit) {\n\t\theading = (\n\t\t\t<>\n\t\t\t\t<button type=\"button\" className=\"rs-crumb\" onClick={() => setFocus(null)}>\n\t\t\t\t\tSearch\n\t\t\t\t</button>\n\t\t\t\t<span className=\"rs-muted\">/</span>\n\t\t\t\t<h1 className=\"rs-heading\">{hit.name}</h1>\n\t\t\t</>\n\t\t)\n\t\tcontent = <Detail item={hit} busy={read.isPending} onPick={onPick && (() => pick(hit))} />\n\t} else if (shown === null ? organizations.isLoading || libraries.isLoading : items === null) {\n\t\tcontent = shown?.error ? null : (\n\t\t\t<div className=\"rs-center\">\n\t\t\t\t<span className=\"rs-spinner\" />\n\t\t\t</div>\n\t\t)\n\t} else if (shown !== null && items?.length === 0 && !pendingTile) {\n\t\tcontent = search.active ? (\n\t\t\t<Empty glyph=\"∅\" title=\"No results\" text={`Nothing matches “${search.query}”.`} />\n\t\t) : (\n\t\t\t<Empty glyph=\"∅\" title=\"No assets\" text=\"This library is empty.\">\n\t\t\t\t{writable && library !== null && (\n\t\t\t\t\t<FilePicker\n\t\t\t\t\t\tclassName=\"rs-button rs-button-primary rs-button-sm\"\n\t\t\t\t\t\tdisabled={false}\n\t\t\t\t\t\tonFile={(file) => void send(file, null)}\n\t\t\t\t\t>\n\t\t\t\t\t\tUpload files\n\t\t\t\t\t</FilePicker>\n\t\t\t\t)}\n\t\t\t</Empty>\n\t\t)\n\t} else if (shown !== null && items) {\n\t\tcontent = (\n\t\t\t<>\n\t\t\t\t<div className=\"rs-grid\">\n\t\t\t\t\t{pendingTile}\n\t\t\t\t\t{search.active\n\t\t\t\t\t\t? search.hits?.map((entry) => (\n\t\t\t\t\t\t\t\t<Tile\n\t\t\t\t\t\t\t\t\tkey={entry.id}\n\t\t\t\t\t\t\t\t\tasset={entry}\n\t\t\t\t\t\t\t\t\tonOpen={() => setFocus({ scope, id: entry.id })}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t: assets.assets?.map((asset) => {\n\t\t\t\t\t\t\t\tconst count = asset.variants?.filter(Boolean).length ?? 0\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<Tile\n\t\t\t\t\t\t\t\t\t\tkey={asset.id}\n\t\t\t\t\t\t\t\t\t\tasset={asset}\n\t\t\t\t\t\t\t\t\t\tonOpen={() => {\n\t\t\t\t\t\t\t\t\t\t\tsetConfirming(null)\n\t\t\t\t\t\t\t\t\t\t\tnavigation.openAsset(asset)\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tbadge={\n\t\t\t\t\t\t\t\t\t\t\tcount > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"rs-pill rs-tile-badge\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Icon shape=\"layers\" width={10.5} />\n\t\t\t\t\t\t\t\t\t\t\t\t\t{count + 1} versions\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t\t{shown.hasMore && (\n\t\t\t\t\t<div className=\"rs-center\">\n\t\t\t\t\t\t<Sentinel key={items.length} onVisible={shown.loadMore} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</>\n\t\t)\n\t}\n\n\tconst dropTarget = writable && library !== null && !search.active\n\n\treturn (\n\t\t<>\n\t\t\t<aside className=\"rs-sidebar\">\n\t\t\t\t<Brand />\n\t\t\t\t<OrganizationSwitcher\n\t\t\t\t\torganizations={organizations.data ?? []}\n\t\t\t\t\tcurrent={organization}\n\t\t\t\t\tonIntent={(entry) =>\n\t\t\t\t\t\tentry.id !== organizationId && prefetchLibraries(entry.id, entry.name)\n\t\t\t\t\t}\n\t\t\t\t\tonSelect={navigation.selectOrganization}\n\t\t\t\t/>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={search.active ? 'rs-sidebar-item is-active' : 'rs-sidebar-item'}\n\t\t\t\t\tonClick={() => searchInput.current?.focus()}\n\t\t\t\t>\n\t\t\t\t\t<Icon shape=\"search\" />\n\t\t\t\t\tSearch\n\t\t\t\t</button>\n\t\t\t\t<nav className=\"rs-scroll\">\n\t\t\t\t\t<h2 className=\"rs-sidebar-heading\">Libraries</h2>\n\t\t\t\t\t{libraries.data?.map((entry) => {\n\t\t\t\t\t\tconst open = entry.id === library?.id\n\t\t\t\t\t\tconst warm = () => organizationId !== null && prefetchAssets(organizationId, entry.id)\n\t\t\t\t\t\tconst toGrid = () => {\n\t\t\t\t\t\t\tnavigation.setQuery('')\n\t\t\t\t\t\t\tnavigation.openAsset(null)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div key={entry.id} className={open ? 'rs-library is-expanded' : 'rs-library'}>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"rs-sidebar-item rs-library-row\"\n\t\t\t\t\t\t\t\t\tdisabled={entry.access === null}\n\t\t\t\t\t\t\t\t\tonMouseEnter={warm}\n\t\t\t\t\t\t\t\t\tonFocus={warm}\n\t\t\t\t\t\t\t\t\tonClick={() => navigation.openLibrary(entry)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon shape=\"grid\" />\n\t\t\t\t\t\t\t\t\t<span className=\"rs-library-name\">{entry.name}</span>\n\t\t\t\t\t\t\t\t\t<span className={open ? 'rs-sidebar-count is-active' : 'rs-sidebar-count'}>\n\t\t\t\t\t\t\t\t\t\t{COUNT.format(entry.assetsCount ?? 0)}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName={open ? 'rs-library-menu is-expanded' : 'rs-library-menu'}\n\t\t\t\t\t\t\t\t\taria-hidden={!open}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\ttabIndex={open ? 0 : -1}\n\t\t\t\t\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\t\t\t\t\topen && !search.active && opened === null\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'rs-sidebar-item is-active'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'rs-sidebar-item'\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tonClick={toGrid}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Icon shape=\"circle\" />\n\t\t\t\t\t\t\t\t\t\t\tAll Assets\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t<FilePicker\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"rs-sidebar-item\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={!open || entry.access !== 'write'}\n\t\t\t\t\t\t\t\t\t\t\tfocusable={open}\n\t\t\t\t\t\t\t\t\t\t\tonFile={(file) => {\n\t\t\t\t\t\t\t\t\t\t\t\ttoGrid()\n\t\t\t\t\t\t\t\t\t\t\t\tvoid send(file, null)\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Icon shape=\"upload\" />\n\t\t\t\t\t\t\t\t\t\t\tUpload\n\t\t\t\t\t\t\t\t\t\t</FilePicker>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t</nav>\n\t\t\t\t<div className=\"rs-sidebar-footer\">\n\t\t\t\t\t<span className=\"rs-sidebar-item rs-muted\">\n\t\t\t\t\t\t{session.isSignedIn ? (session.userName ?? 'Signed in') : 'API key'}\n\t\t\t\t\t</span>\n\t\t\t\t\t<button type=\"button\" className=\"rs-sidebar-item\" onClick={() => void session.signOut()}>\n\t\t\t\t\t\tSign out\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</aside>\n\t\t\t<section\n\t\t\t\tclassName=\"rs-main\"\n\t\t\t\taria-label=\"Assets\"\n\t\t\t\tonDragEnter={(event) => {\n\t\t\t\t\tif (!dropTarget || !event.dataTransfer.types.includes('Files')) return\n\t\t\t\t\tdragDepth.current += 1\n\t\t\t\t\tsetDragging(true)\n\t\t\t\t}}\n\t\t\t\tonDragOver={(event) => {\n\t\t\t\t\tif (dropTarget) event.preventDefault()\n\t\t\t\t}}\n\t\t\t\tonDragLeave={() => {\n\t\t\t\t\tdragDepth.current = Math.max(0, dragDepth.current - 1)\n\t\t\t\t\tif (dragDepth.current === 0) setDragging(false)\n\t\t\t\t}}\n\t\t\t\tonDrop={(event) => {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tdragDepth.current = 0\n\t\t\t\t\tsetDragging(false)\n\t\t\t\t\tconst file = event.dataTransfer.files[0]\n\t\t\t\t\tif (file && dropTarget) void send(file, versions ? opened.id : null)\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<header className=\"rs-header\">\n\t\t\t\t\t{heading}\n\t\t\t\t\t<span className=\"rs-muted rs-small\">{status}</span>\n\t\t\t\t\t<Progress upload={upload.state} promote={promote.state} />\n\t\t\t\t\t<div className=\"rs-search\">\n\t\t\t\t\t\t<Icon shape=\"search\" width={12.25} />\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tref={searchInput}\n\t\t\t\t\t\t\tclassName=\"rs-input\"\n\t\t\t\t\t\t\taria-label=\"Search Raster\"\n\t\t\t\t\t\t\tplaceholder={library === null ? 'Search every library…' : `Search ${library.name}…`}\n\t\t\t\t\t\t\tvalue={query}\n\t\t\t\t\t\t\tonChange={(event) => navigation.setQuery(event.target.value)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{query !== '' && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"rs-icon-button\"\n\t\t\t\t\t\t\t\taria-label=\"Clear search\"\n\t\t\t\t\t\t\t\tonClick={() => navigation.setQuery('')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon shape=\"x\" width={10.5} />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t{versions && writable && (\n\t\t\t\t\t\t<FilePicker\n\t\t\t\t\t\t\tclassName=\"rs-button rs-button-sm\"\n\t\t\t\t\t\t\tdisabled={false}\n\t\t\t\t\t\t\tonFile={(file) => void send(file, opened.id)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon shape=\"upload\" width={12.25} />\n\t\t\t\t\t\t\tUpload variant\n\t\t\t\t\t\t</FilePicker>\n\t\t\t\t\t)}\n\t\t\t\t\t<button type=\"button\" className=\"rs-button rs-button-sm\" onClick={navigation.refresh}>\n\t\t\t\t\t\tRefresh\n\t\t\t\t\t</button>\n\t\t\t\t</header>\n\t\t\t\t<div className=\"rs-content rs-scroll\">\n\t\t\t\t\t{organizations.error && <ErrorCard error={organizations.error} onError={onError} />}\n\t\t\t\t\t{libraries.error && <ErrorCard error={libraries.error} onError={onError} />}\n\t\t\t\t\t{shown?.error && <ErrorCard error={shown.error} onError={onError} />}\n\t\t\t\t\t{read.error && <ErrorCard error={read.error} onError={onError} />}\n\t\t\t\t\t{upload.state.status === 'error' && (\n\t\t\t\t\t\t<ErrorCard error={upload.state.error} onError={onError} />\n\t\t\t\t\t)}\n\t\t\t\t\t{promote.state.status === 'error' && (\n\t\t\t\t\t\t<ErrorCard error={promote.state.error} onError={onError} />\n\t\t\t\t\t)}\n\t\t\t\t\t{content}\n\t\t\t\t</div>\n\t\t\t\t<div className={dragging ? 'rs-drop is-active' : 'rs-drop'} />\n\t\t\t</section>\n\t\t</>\n\t)\n}\n"]}
1
+ {"version":3,"file":"raster-picker.js","sourceRoot":"","sources":["../src/raster-picker.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMutation } from '@tanstack/react-query'\nimport { type ReactNode, useRef, useState } from 'react'\n\nimport {\n\ttype Asset,\n\ttype AssetVariant,\n\ttype RasterApiError,\n\ttype SearchHit,\n\tisReady,\n} from '@raster-app/sdk'\n\nimport { useRasterClient } from './context.js'\nimport { Icon } from './icons.js'\nimport {\n\tBrand,\n\tDetail,\n\tEmpty,\n\tErrorCard,\n\tFilePicker,\n\tOrganizationSwitcher,\n\tPendingTile,\n\tProgress,\n\ttype ReportError,\n\tSentinel,\n\tTile,\n\tTileGrid,\n} from './picker-parts.js'\nimport { SignIn } from './picker-sign-in.js'\nimport { useAssetSearch } from './use-asset-search.js'\nimport { useAssetUpload } from './use-asset-upload.js'\nimport { useAssets, usePrefetchAssets } from './use-assets.js'\nimport { useLibraries, usePrefetchLibraries } from './use-libraries.js'\nimport { useRasterNavigation } from './use-navigation.js'\nimport { useOrganizations } from './use-organizations.js'\nimport { usePromoteVariant } from './use-promote-variant.js'\nimport { useSession } from './use-session.js'\n\nexport type RasterPickerProps = {\n\t/**\n\t * The picked asset, whole whether it came from a library, a search or an asset's versions, and\n\t * its organization. `getFullSizeUrl(asset)` is the image. Without it, the picker only browses,\n\t * with no Pick asset button.\n\t */\n\tonPick?: (asset: Asset, organizationId: string) => void\n\t/** Binds the device sign-in to this organization; any other grant fails. */\n\torganizationId?: string\n\t/** The consent the device sign-in asks for: `org` when `organizationId` is set, else `user`. */\n\tscope?: 'user' | 'org'\n\t/** Each failure the picker shows, once, for the host to log. */\n\tonError?: (error: RasterApiError) => void\n\t/** Follows the system's color scheme when unset. */\n\ttheme?: 'light' | 'dark'\n}\n\nconst COUNT = new Intl.NumberFormat('en-US', { notation: 'compact' })\n\n/** A file on its way in, which the grid shows until Raster has processed it. */\ntype Pending = { name: string; preview: string; parentId: string | null }\n\n/**\n * Raster's asset picker, drawn as Raster draws it (`@raster-app/react/styles.css`): sign-in, the\n * organization's libraries, search and uploads. A tile opens its asset large, to pick or open in\n * Raster, over its versions with the default to set. It fills its container, inside a\n * `RasterProvider`.\n */\nexport function RasterPicker({ onPick, organizationId, scope, onError, theme }: RasterPickerProps) {\n\tconst { credentials, isConfigured } = useSession()\n\n\tlet body = (\n\t\t<div className=\"rs-center\">\n\t\t\t<span className=\"rs-spinner\" />\n\t\t</div>\n\t)\n\tif (credentials !== undefined && !isConfigured) {\n\t\tbody = (\n\t\t\t<SignIn\n\t\t\t\torganizationId={organizationId}\n\t\t\t\tscope={scope ?? (organizationId === undefined ? 'user' : 'org')}\n\t\t\t\tonError={onError}\n\t\t\t/>\n\t\t)\n\t} else if (isConfigured) {\n\t\tbody = <Browser onPick={onPick} onError={onError} />\n\t}\n\treturn (\n\t\t<div className=\"rs rs-picker\" data-theme={theme}>\n\t\t\t{body}\n\t\t</div>\n\t)\n}\n\nfunction Browser({\n\tonPick,\n\tonError,\n}: {\n\tonPick: RasterPickerProps['onPick']\n\tonError: ReportError\n}) {\n\tconst client = useRasterClient()\n\tconst session = useSession()\n\tconst organizations = useOrganizations()\n\tconst navigation = useRasterNavigation({ organizations: organizations.data ?? null })\n\tconst { organizationId, library, query } = navigation\n\tconst organization = organizations.data?.find((entry) => entry.id === organizationId)\n\tconst libraries = useLibraries({ organizationId, organizationName: organization?.name ?? null })\n\tconst assets = useAssets({ organizationId, libraryId: library?.id ?? null })\n\tconst search = useAssetSearch(\n\t\torganizationId === null ? null : { organizationId, libraryId: library?.id ?? null },\n\t\tquery\n\t)\n\tconst upload = useAssetUpload()\n\tconst promote = usePromoteVariant()\n\tconst read = useMutation<Asset, RasterApiError, Parameters<typeof client.assets.get>[0]>({\n\t\tmutationFn: (options) => client.assets.get(options),\n\t})\n\tconst prefetchAssets = usePrefetchAssets()\n\tconst prefetchLibraries = usePrefetchLibraries()\n\tconst searchInput = useRef<HTMLInputElement>(null)\n\tconst [pending, setPending] = useState<Pending | null>(null)\n\tconst [confirming, setConfirming] = useState<string | null>(null)\n\tconst [dragging, setDragging] = useState(false)\n\tconst dragDepth = useRef(0)\n\t// The version shown large, or the search hit opened, for the scope it was chosen in.\n\tconst [focus, setFocus] = useState<{ scope: string; id: string } | null>(null)\n\tconst scope = [organizationId, library?.id, navigation.asset?.id, query].join('/')\n\tconst focusId = focus?.scope === scope ? focus.id : null\n\n\tconst access = libraries.data?.find((entry) => entry.id === library?.id)?.access ?? null\n\tconst writable = access === 'write'\n\t// The asset as the list last read it, which refetches after an upload or a promote.\n\tconst opened =\n\t\tnavigation.asset === null\n\t\t\t? null\n\t\t\t: (assets.assets?.find((entry) => entry.id === navigation.asset?.id) ?? navigation.asset)\n\tconst versions = !search.active && opened !== null\n\tconst variants = (opened?.variants ?? []).filter(\n\t\t(variant): variant is AssetVariant => variant !== null\n\t)\n\tconst shown = search.active ? search : library === null ? null : assets\n\tconst items = search.active ? search.hits : assets.assets\n\tconst hit = search.active ? (search.hits?.find((entry) => entry.id === focusId) ?? null) : null\n\t// Until a promote lands, the cached asset is still the previous default.\n\tconst busy = read.isPending || promote.state.status === 'promoting'\n\n\t/** Hand the host the whole asset: a search hit or a variant carries less, so it is read first. */\n\tfunction pick(item: Asset | SearchHit | AssetVariant) {\n\t\tif (organizationId === null || onPick === undefined) return\n\t\tconst loaded = assets.assets?.find((entry) => entry.id === item.id)\n\t\tif (loaded) {\n\t\t\tonPick(loaded, organizationId)\n\t\t\treturn\n\t\t}\n\t\t// A variant lives in its original's library, which is the open one.\n\t\tconst libraryId = ('libraryId' in item ? item.libraryId : null) ?? library?.id\n\t\tif (!libraryId) return\n\t\tread.mutate(\n\t\t\t{ organizationId, libraryId, assetId: item.id },\n\t\t\t{ onSuccess: (asset) => onPick(asset, organizationId) }\n\t\t)\n\t}\n\n\t/** Upload one file into the open library, or as a variant of `parentId`. */\n\tasync function send(file: File, parentId: string | null) {\n\t\t// A second upload would cancel the one in flight.\n\t\tif (organizationId === null || library === null || !writable || pending !== null) return\n\t\tconst preview = URL.createObjectURL(file)\n\t\tsetPending({ name: file.name, preview, parentId })\n\t\tawait upload.upload({ organizationId, libraryId: library.id, parentId, source: file })\n\t\tURL.revokeObjectURL(preview)\n\t\tsetPending(null)\n\t}\n\n\t/** The first press asks to confirm; the second promotes. */\n\tfunction setDefault(variant: AssetVariant) {\n\t\tif (confirming !== variant.id) {\n\t\t\tsetConfirming(variant.id)\n\t\t\treturn\n\t\t}\n\t\tsetConfirming(null)\n\t\tif (organizationId === null || library === null || opened === null) return\n\t\tvoid promote.promote({\n\t\t\torganizationId,\n\t\t\tlibraryId: library.id,\n\t\t\tassetId: opened.id,\n\t\t\tvariantId: variant.id,\n\t\t})\n\t}\n\n\tconst pendingTile = pending !== null &&\n\t\t!search.active &&\n\t\tpending.parentId === (opened?.id ?? null) && (\n\t\t\t<PendingTile\n\t\t\t\tname={pending.name}\n\t\t\t\tpreview={pending.preview}\n\t\t\t\tstatus={upload.state.status === 'uploading' ? 'Uploading' : 'Processing'}\n\t\t\t/>\n\t\t)\n\n\tlet status = ''\n\tif (search.active) status = search.isSearching ? 'Searching' : `${search.found} found`\n\telse if (library !== null && !versions) status = `${assets.assets?.length ?? 0} loaded`\n\n\tlet heading: ReactNode = (\n\t\t<>\n\t\t\t<h1 className=\"rs-heading\">{search.active ? 'Search' : (library?.name ?? 'Libraries')}</h1>\n\t\t\t{!search.active && library !== null && (\n\t\t\t\t<span className=\"rs-sidebar-count is-active\">{access ?? 'no access'}</span>\n\t\t\t)}\n\t\t</>\n\t)\n\tlet content: ReactNode = (\n\t\t<Empty glyph=\"grid\" title=\"Choose a library\" text=\"Or search every library.\" />\n\t)\n\tif (versions) {\n\t\tconst focused = [opened, ...variants].find((entry) => entry.id === focusId) ?? opened\n\t\theading = (\n\t\t\t<>\n\t\t\t\t<button type=\"button\" className=\"rs-crumb\" onClick={() => navigation.openAsset(null)}>\n\t\t\t\t\t{library?.name}\n\t\t\t\t</button>\n\t\t\t\t<span className=\"rs-muted\">/</span>\n\t\t\t\t<h1 className=\"rs-heading\">{opened.name}</h1>\n\t\t\t\t<span className=\"rs-sidebar-count is-active\">{variants.length + 1} versions</span>\n\t\t\t</>\n\t\t)\n\t\tcontent = (\n\t\t\t<>\n\t\t\t\t<Detail item={focused} busy={busy} onPick={onPick && (() => pick(focused))} />\n\t\t\t\t<TileGrid>\n\t\t\t\t\t<Tile\n\t\t\t\t\t\tasset={opened}\n\t\t\t\t\t\tselected={focused.id === opened.id}\n\t\t\t\t\t\tonOpen={() => setFocus({ scope, id: opened.id })}\n\t\t\t\t\t\tbadge={\n\t\t\t\t\t\t\t<span className=\"rs-pill rs-tile-badge\">\n\t\t\t\t\t\t\t\t<Icon shape=\"star\" solid width={10.5} />\n\t\t\t\t\t\t\t\tDefault\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t\t{variants.map((variant) => (\n\t\t\t\t\t\t<Tile\n\t\t\t\t\t\t\tkey={variant.id}\n\t\t\t\t\t\t\tasset={variant}\n\t\t\t\t\t\t\tselected={focused.id === variant.id}\n\t\t\t\t\t\t\tonOpen={() => setFocus({ scope, id: variant.id })}\n\t\t\t\t\t\t\taction={\n\t\t\t\t\t\t\t\twritable &&\n\t\t\t\t\t\t\t\tisReady(variant) && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\t\t\t\tconfirming === variant.id\n\t\t\t\t\t\t\t\t\t\t\t\t? 'rs-pill rs-tile-action is-confirming'\n\t\t\t\t\t\t\t\t\t\t\t\t: 'rs-pill rs-tile-action'\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tdisabled={promote.state.status === 'promoting'}\n\t\t\t\t\t\t\t\t\t\tonClick={() => setDefault(variant)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Icon shape=\"star\" width={10.5} />\n\t\t\t\t\t\t\t\t\t\t{confirming === variant.id ? 'Confirm' : 'Set as default'}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t\t{pendingTile}\n\t\t\t\t</TileGrid>\n\t\t\t</>\n\t\t)\n\t} else if (hit) {\n\t\theading = (\n\t\t\t<>\n\t\t\t\t<button type=\"button\" className=\"rs-crumb\" onClick={() => setFocus(null)}>\n\t\t\t\t\tSearch\n\t\t\t\t</button>\n\t\t\t\t<span className=\"rs-muted\">/</span>\n\t\t\t\t<h1 className=\"rs-heading\">{hit.name}</h1>\n\t\t\t</>\n\t\t)\n\t\tcontent = <Detail item={hit} busy={busy} onPick={onPick && (() => pick(hit))} />\n\t} else if (shown === null ? organizations.isLoading || libraries.isLoading : items === null) {\n\t\tcontent = shown?.error ? null : (\n\t\t\t<div className=\"rs-center\">\n\t\t\t\t<span className=\"rs-spinner\" />\n\t\t\t</div>\n\t\t)\n\t} else if (shown !== null && items?.length === 0 && !pendingTile) {\n\t\tcontent = search.active ? (\n\t\t\t<Empty glyph=\"∅\" title=\"No results\" text={`Nothing matches “${search.query}”.`} />\n\t\t) : (\n\t\t\t<Empty glyph=\"∅\" title=\"No assets\" text=\"This library is empty.\">\n\t\t\t\t{writable && library !== null && (\n\t\t\t\t\t<FilePicker\n\t\t\t\t\t\tclassName=\"rs-button rs-button-primary rs-button-sm\"\n\t\t\t\t\t\tdisabled={pending !== null}\n\t\t\t\t\t\tonFile={(file) => void send(file, null)}\n\t\t\t\t\t>\n\t\t\t\t\t\tUpload files\n\t\t\t\t\t</FilePicker>\n\t\t\t\t)}\n\t\t\t</Empty>\n\t\t)\n\t} else if (shown !== null && items) {\n\t\tcontent = (\n\t\t\t<>\n\t\t\t\t<TileGrid>\n\t\t\t\t\t{pendingTile}\n\t\t\t\t\t{search.active\n\t\t\t\t\t\t? search.hits?.map((entry) => (\n\t\t\t\t\t\t\t\t<Tile\n\t\t\t\t\t\t\t\t\tkey={entry.id}\n\t\t\t\t\t\t\t\t\tasset={entry}\n\t\t\t\t\t\t\t\t\tonOpen={() => setFocus({ scope, id: entry.id })}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t: assets.assets?.map((asset) => {\n\t\t\t\t\t\t\t\tconst count = asset.variants?.filter(Boolean).length ?? 0\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<Tile\n\t\t\t\t\t\t\t\t\t\tkey={asset.id}\n\t\t\t\t\t\t\t\t\t\tasset={asset}\n\t\t\t\t\t\t\t\t\t\tonOpen={() => {\n\t\t\t\t\t\t\t\t\t\t\tsetConfirming(null)\n\t\t\t\t\t\t\t\t\t\t\tnavigation.openAsset(asset)\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tbadge={\n\t\t\t\t\t\t\t\t\t\t\tcount > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"rs-pill rs-tile-badge\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Icon shape=\"layers\" width={10.5} />\n\t\t\t\t\t\t\t\t\t\t\t\t\t{count + 1} versions\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t})}\n\t\t\t\t</TileGrid>\n\t\t\t\t{shown.hasMore && (\n\t\t\t\t\t<div className=\"rs-center\">\n\t\t\t\t\t\t<Sentinel key={items.length} onVisible={shown.loadMore} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</>\n\t\t)\n\t}\n\n\tconst dropTarget = writable && library !== null && !search.active\n\n\treturn (\n\t\t<>\n\t\t\t<aside className=\"rs-sidebar\">\n\t\t\t\t<Brand />\n\t\t\t\t<OrganizationSwitcher\n\t\t\t\t\torganizations={organizations.data ?? []}\n\t\t\t\t\tcurrent={organization}\n\t\t\t\t\tonIntent={(entry) =>\n\t\t\t\t\t\tentry.id !== organizationId && prefetchLibraries(entry.id, entry.name)\n\t\t\t\t\t}\n\t\t\t\t\tonSelect={navigation.selectOrganization}\n\t\t\t\t/>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={search.active ? 'rs-sidebar-item is-active' : 'rs-sidebar-item'}\n\t\t\t\t\tonClick={() => searchInput.current?.focus()}\n\t\t\t\t>\n\t\t\t\t\t<Icon shape=\"search\" />\n\t\t\t\t\tSearch\n\t\t\t\t</button>\n\t\t\t\t<nav className=\"rs-scroll\">\n\t\t\t\t\t<h2 className=\"rs-sidebar-heading\">Libraries</h2>\n\t\t\t\t\t{libraries.data?.map((entry) => {\n\t\t\t\t\t\tconst open = entry.id === library?.id\n\t\t\t\t\t\tconst warm = () => organizationId !== null && prefetchAssets(organizationId, entry.id)\n\t\t\t\t\t\tconst toGrid = () => {\n\t\t\t\t\t\t\tnavigation.setQuery('')\n\t\t\t\t\t\t\tnavigation.openAsset(null)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div key={entry.id} className={open ? 'rs-library is-expanded' : 'rs-library'}>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"rs-sidebar-item rs-library-row\"\n\t\t\t\t\t\t\t\t\tdisabled={entry.access === null}\n\t\t\t\t\t\t\t\t\tonMouseEnter={warm}\n\t\t\t\t\t\t\t\t\tonFocus={warm}\n\t\t\t\t\t\t\t\t\tonClick={() => navigation.openLibrary(entry)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon shape=\"grid\" />\n\t\t\t\t\t\t\t\t\t<span className=\"rs-library-name\">{entry.name}</span>\n\t\t\t\t\t\t\t\t\t<span className={open ? 'rs-sidebar-count is-active' : 'rs-sidebar-count'}>\n\t\t\t\t\t\t\t\t\t\t{COUNT.format(entry.assetsCount ?? 0)}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName={open ? 'rs-library-menu is-expanded' : 'rs-library-menu'}\n\t\t\t\t\t\t\t\t\taria-hidden={!open}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\ttabIndex={open ? 0 : -1}\n\t\t\t\t\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\t\t\t\t\topen && !search.active && opened === null\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'rs-sidebar-item is-active'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'rs-sidebar-item'\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tonClick={toGrid}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Icon shape=\"circle\" />\n\t\t\t\t\t\t\t\t\t\t\tAll Assets\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t<FilePicker\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"rs-sidebar-item\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={!open || entry.access !== 'write' || pending !== null}\n\t\t\t\t\t\t\t\t\t\t\tfocusable={open}\n\t\t\t\t\t\t\t\t\t\t\tonFile={(file) => {\n\t\t\t\t\t\t\t\t\t\t\t\ttoGrid()\n\t\t\t\t\t\t\t\t\t\t\t\tvoid send(file, null)\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Icon shape=\"upload\" />\n\t\t\t\t\t\t\t\t\t\t\tUpload\n\t\t\t\t\t\t\t\t\t\t</FilePicker>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t</nav>\n\t\t\t\t<div className=\"rs-sidebar-footer\">\n\t\t\t\t\t<span className=\"rs-sidebar-item rs-muted\">\n\t\t\t\t\t\t{session.isSignedIn ? (session.userName ?? 'Signed in') : 'API key'}\n\t\t\t\t\t</span>\n\t\t\t\t\t<button type=\"button\" className=\"rs-sidebar-item\" onClick={() => void session.signOut()}>\n\t\t\t\t\t\tSign out\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</aside>\n\t\t\t<section\n\t\t\t\tclassName=\"rs-main\"\n\t\t\t\taria-label=\"Assets\"\n\t\t\t\tonDragEnter={(event) => {\n\t\t\t\t\tif (!dropTarget || pending !== null || !event.dataTransfer.types.includes('Files')) return\n\t\t\t\t\tdragDepth.current += 1\n\t\t\t\t\tsetDragging(true)\n\t\t\t\t}}\n\t\t\t\tonDragOver={(event) => {\n\t\t\t\t\tif (dropTarget) event.preventDefault()\n\t\t\t\t}}\n\t\t\t\tonDragLeave={() => {\n\t\t\t\t\tdragDepth.current = Math.max(0, dragDepth.current - 1)\n\t\t\t\t\tif (dragDepth.current === 0) setDragging(false)\n\t\t\t\t}}\n\t\t\t\tonDrop={(event) => {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tdragDepth.current = 0\n\t\t\t\t\tsetDragging(false)\n\t\t\t\t\tconst file = event.dataTransfer.files[0]\n\t\t\t\t\tif (file && dropTarget) void send(file, versions ? opened.id : null)\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<header className=\"rs-header\">\n\t\t\t\t\t{heading}\n\t\t\t\t\t<span className=\"rs-muted rs-small\">{status}</span>\n\t\t\t\t\t<Progress upload={upload.state} promote={promote.state} />\n\t\t\t\t\t<div className=\"rs-search\">\n\t\t\t\t\t\t<Icon shape=\"search\" width={12.25} />\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tref={searchInput}\n\t\t\t\t\t\t\tclassName=\"rs-input\"\n\t\t\t\t\t\t\taria-label=\"Search Raster\"\n\t\t\t\t\t\t\tplaceholder={library === null ? 'Search every library…' : `Search ${library.name}…`}\n\t\t\t\t\t\t\tvalue={query}\n\t\t\t\t\t\t\tonChange={(event) => navigation.setQuery(event.target.value)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{query !== '' && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"rs-icon-button\"\n\t\t\t\t\t\t\t\taria-label=\"Clear search\"\n\t\t\t\t\t\t\t\tonClick={() => navigation.setQuery('')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon shape=\"x\" width={10.5} />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t{versions && writable && (\n\t\t\t\t\t\t<FilePicker\n\t\t\t\t\t\t\tclassName=\"rs-button rs-button-sm\"\n\t\t\t\t\t\t\tdisabled={pending !== null}\n\t\t\t\t\t\t\tonFile={(file) => void send(file, opened.id)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon shape=\"upload\" width={12.25} />\n\t\t\t\t\t\t\tUpload variant\n\t\t\t\t\t\t</FilePicker>\n\t\t\t\t\t)}\n\t\t\t\t\t<button type=\"button\" className=\"rs-button rs-button-sm\" onClick={navigation.refresh}>\n\t\t\t\t\t\tRefresh\n\t\t\t\t\t</button>\n\t\t\t\t</header>\n\t\t\t\t<div className=\"rs-content\">\n\t\t\t\t\t{organizations.error && <ErrorCard error={organizations.error} onError={onError} />}\n\t\t\t\t\t{libraries.error && <ErrorCard error={libraries.error} onError={onError} />}\n\t\t\t\t\t{shown?.error && <ErrorCard error={shown.error} onError={onError} />}\n\t\t\t\t\t{read.error && <ErrorCard error={read.error} onError={onError} />}\n\t\t\t\t\t{upload.state.status === 'error' && (\n\t\t\t\t\t\t<ErrorCard error={upload.state.error} onError={onError} />\n\t\t\t\t\t)}\n\t\t\t\t\t{promote.state.status === 'error' && (\n\t\t\t\t\t\t<ErrorCard error={promote.state.error} onError={onError} />\n\t\t\t\t\t)}\n\t\t\t\t\t{content}\n\t\t\t\t</div>\n\t\t\t\t<div className={dragging ? 'rs-drop is-active' : 'rs-drop'} />\n\t\t\t</section>\n\t\t</>\n\t)\n}\n"]}
package/dist/styles.css CHANGED
@@ -102,7 +102,7 @@
102
102
  }
103
103
 
104
104
  .rs-picker > .rs-sidebar {
105
- width: 208px;
105
+ width: 266px;
106
106
  flex-shrink: 0;
107
107
  }
108
108
 
@@ -119,7 +119,7 @@
119
119
  flex-shrink: 0;
120
120
  align-items: center;
121
121
  gap: 10.5px;
122
- padding: 10.5px 10.5px 0 16px;
122
+ padding: 10.5px 10.5px 0 30px;
123
123
  }
124
124
 
125
125
  /* The title and search give way first, so no button's label is cut. */
@@ -127,10 +127,16 @@
127
127
  flex-shrink: 0;
128
128
  }
129
129
 
130
+ /*
131
+ * Positioned, so a grid's `offsetTop` counts from the top of the scroll. Its scrollbar is the
132
+ * system's, as Raster's grid has, so it takes none of the grid's width.
133
+ */
130
134
  .rs-content {
135
+ position: relative;
131
136
  flex: 1;
132
137
  min-height: 0;
133
- padding: 16px;
138
+ overflow-y: auto;
139
+ padding: 30px;
134
140
  }
135
141
 
136
142
  .rs-content > * + * {
@@ -622,10 +628,20 @@
622
628
 
623
629
  /* ---- asset tiles ---- */
624
630
 
631
+ /* A row of tiles, with its columns from `gridColumns`, placed where the scroll puts it. */
625
632
  .rs-grid {
626
633
  display: grid;
627
- grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
628
- gap: 16px;
634
+ gap: 30px;
635
+ }
636
+
637
+ .rs-tile-grid {
638
+ position: relative;
639
+ }
640
+
641
+ .rs-tile-grid > .rs-grid {
642
+ position: absolute;
643
+ right: 0;
644
+ left: 0;
629
645
  }
630
646
 
631
647
  .rs-asset-thumb {
@@ -635,7 +651,7 @@
635
651
  flex-direction: column;
636
652
  justify-content: space-between;
637
653
  width: 100%;
638
- height: 164px;
654
+ height: 210px;
639
655
  overflow: hidden;
640
656
  padding: 0;
641
657
  border: 0;
@@ -667,16 +683,15 @@
667
683
  opacity: 0.6;
668
684
  }
669
685
 
686
+ /* The blurhash is blurred already, so it is stretched over the tile with no filter to composite. */
670
687
  .rs-thumb-blur {
671
688
  position: absolute;
672
- inset: -56px;
689
+ inset: 0;
673
690
  z-index: 10;
674
- width: calc(100% + 112px);
675
- height: calc(100% + 112px);
691
+ width: 100%;
692
+ height: 100%;
676
693
  object-fit: cover;
677
- filter: blur(40px);
678
694
  opacity: 0.75;
679
- transform: translateZ(0);
680
695
  }
681
696
 
682
697
  .rs-thumb-preview {
@@ -706,11 +721,9 @@
706
721
  flex-direction: column;
707
722
  justify-content: center;
708
723
  flex-shrink: 0;
709
- height: 44px;
724
+ height: 54px;
710
725
  padding: 7px 10.5px;
711
726
  background: var(--rs-thumb-meta);
712
- -webkit-backdrop-filter: blur(12px);
713
- backdrop-filter: blur(12px);
714
727
  }
715
728
 
716
729
  .rs-thumb-title {
@@ -800,7 +813,7 @@
800
813
  /* The transparency checkerboard, behind a format that carries alpha. */
801
814
  .rs-transparent {
802
815
  position: absolute;
803
- inset: 0 0 44px 0;
816
+ inset: 0 0 54px 0;
804
817
  z-index: 10;
805
818
  background-color: var(--rs-thumb-bg);
806
819
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raster-app/react",
3
- "version": "0.1.0-canary-623b3d3",
3
+ "version": "0.1.0-canary-32ca74d",
4
4
  "description": "React provider and hooks for the Raster SDK: session, organizations, libraries, assets, search and uploads.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://raster.app/docs/api/sdk",
@@ -40,8 +40,9 @@
40
40
  "test": "bun test"
41
41
  },
42
42
  "dependencies": {
43
- "@raster-app/sdk": "0.1.0-canary-623b3d3",
44
- "@tanstack/react-query": "^5.103.1"
43
+ "@raster-app/sdk": "0.1.0-canary-32ca74d",
44
+ "@tanstack/react-query": "^5.103.1",
45
+ "@tanstack/react-virtual": "^3.14.13"
45
46
  },
46
47
  "peerDependencies": {
47
48
  "react": "^18 || ^19"