@misoto22/folio 0.17.1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/Accordion.md +1 -1
- package/dist/agent/Actions.md +1 -1
- package/dist/agent/Alert.md +1 -1
- package/dist/agent/AppShell.md +1 -1
- package/dist/agent/ArchitectureFigure.md +1 -1
- package/dist/agent/AreaChart.md +1 -1
- package/dist/agent/Article.md +1 -1
- package/dist/agent/AspectRatio.md +1 -1
- package/dist/agent/Avatar.md +1 -1
- package/dist/agent/Badge.md +1 -1
- package/dist/agent/BarChart.md +1 -1
- package/dist/agent/BarList.md +1 -1
- package/dist/agent/BigNumber.md +1 -1
- package/dist/agent/BoxPlot.md +1 -1
- package/dist/agent/Breadcrumb.md +1 -1
- package/dist/agent/BulletChart.md +1 -1
- package/dist/agent/Button.md +1 -1
- package/dist/agent/Calendar.md +1 -1
- package/dist/agent/CalendarHeatmap.md +1 -1
- package/dist/agent/Card.md +1 -1
- package/dist/agent/Checkbox.md +1 -1
- package/dist/agent/Code.md +1 -1
- package/dist/agent/CodeBlock.md +1 -1
- package/dist/agent/Collapsible.md +1 -1
- package/dist/agent/Collection.md +1 -1
- package/dist/agent/ColorPicker.md +1 -1
- package/dist/agent/Combobox.md +1 -1
- package/dist/agent/Command.md +2 -1
- package/dist/agent/ComposedChart.md +1 -1
- package/dist/agent/Contact.md +1 -1
- package/dist/agent/Content.md +1 -1
- package/dist/agent/ContextMenu.md +1 -1
- package/dist/agent/Conversation.md +1 -1
- package/dist/agent/DataflowFigure.md +1 -1
- package/dist/agent/DatePicker.md +1 -1
- package/dist/agent/DescriptionList.md +1 -1
- package/dist/agent/Diagram.md +1 -1
- package/dist/agent/DiagramCanvas.md +1 -1
- package/dist/agent/DiagramExportMenu.md +1 -1
- package/dist/agent/DiagramInspector.md +1 -1
- package/dist/agent/DiagramLegend.md +1 -1
- package/dist/agent/DiagramMinimap.md +1 -1
- package/dist/agent/DiagramToolbar.md +1 -1
- package/dist/agent/Dialog.md +1 -1
- package/dist/agent/DropdownMenu.md +1 -1
- package/dist/agent/EmptyState.md +1 -1
- package/dist/agent/ErrorState.md +1 -1
- package/dist/agent/Evidence.md +1 -1
- package/dist/agent/Facet.md +1 -1
- package/dist/agent/Field.md +1 -1
- package/dist/agent/FigureBand.md +1 -1
- package/dist/agent/FloatingIconButton.md +1 -1
- package/dist/agent/FunnelChart.md +1 -1
- package/dist/agent/Heading.md +1 -1
- package/dist/agent/Heatmap.md +1 -1
- package/dist/agent/Histogram.md +1 -1
- package/dist/agent/Input.md +1 -1
- package/dist/agent/Kbd.md +1 -1
- package/dist/agent/LifecycleFigure.md +1 -1
- package/dist/agent/LineChart.md +1 -1
- package/dist/agent/LinkArrow.md +1 -1
- package/dist/agent/Markdown.md +1 -1
- package/dist/agent/Media.md +1 -1
- package/dist/agent/Metric.md +1 -1
- package/dist/agent/Metrics.md +1 -1
- package/dist/agent/Music.md +1 -1
- package/dist/agent/NativeSelect.md +1 -1
- package/dist/agent/NavItem.md +1 -1
- package/dist/agent/NumberField.md +1 -1
- package/dist/agent/PageHeader.md +1 -1
- package/dist/agent/Pagination.md +1 -1
- package/dist/agent/PieChart.md +1 -1
- package/dist/agent/Popover.md +1 -1
- package/dist/agent/Portfolio.md +1 -1
- package/dist/agent/PortfolioIndex.md +1 -1
- package/dist/agent/Progress.md +1 -1
- package/dist/agent/RadarChart.md +1 -1
- package/dist/agent/RadialChart.md +1 -1
- package/dist/agent/RadioGroup.md +1 -1
- package/dist/agent/Reading.md +10 -1
- package/dist/agent/Recovery.md +3 -3
- package/dist/agent/SankeyChart.md +1 -1
- package/dist/agent/ScatterChart.md +1 -1
- package/dist/agent/ScrollArea.md +1 -1
- package/dist/agent/SearchPalette.md +1 -1
- package/dist/agent/SearchableMenu.md +1 -1
- package/dist/agent/Select.md +1 -1
- package/dist/agent/Separator.md +1 -1
- package/dist/agent/SequenceFigure.md +1 -1
- package/dist/agent/Sheet.md +1 -1
- package/dist/agent/Sidebar.md +1 -1
- package/dist/agent/SiteNavigation.md +1 -1
- package/dist/agent/SiteShell.md +1 -1
- package/dist/agent/Skeleton.md +1 -1
- package/dist/agent/Slider.md +1 -1
- package/dist/agent/Sparkline.md +1 -1
- package/dist/agent/Spinner.md +1 -1
- package/dist/agent/StatusDot.md +1 -1
- package/dist/agent/StatusPill.md +1 -1
- package/dist/agent/Steps.md +1 -1
- package/dist/agent/Switch.md +1 -1
- package/dist/agent/Table.md +1 -1
- package/dist/agent/Tabs.md +1 -1
- package/dist/agent/Tag.md +1 -1
- package/dist/agent/Text.md +1 -1
- package/dist/agent/Textarea.md +1 -1
- package/dist/agent/Timeline.md +6 -2
- package/dist/agent/Timestamp.md +1 -1
- package/dist/agent/Toast.md +1 -1
- package/dist/agent/ToggleGroup.md +1 -1
- package/dist/agent/Toolbar.md +1 -1
- package/dist/agent/Tooltip.md +1 -1
- package/dist/agent/TreemapChart.md +1 -1
- package/dist/agent/WaterfallChart.md +1 -1
- package/dist/agent/Workbench.md +1 -1
- package/dist/agent/WorkflowFigure.md +1 -1
- package/dist/agent/catalog.json +10 -1
- package/dist/agent/index.md +2 -1
- package/dist/components/Button/Button.js +1 -1
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Command/Command.d.ts +3 -1
- package/dist/components/Command/Command.js +3 -2
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/keyframes.css +22 -0
- package/dist/styles.css +1 -1
- package/dist/themes.css +11 -0
- package/dist/tokens.css +14 -0
- package/dist/tokens.d.ts +4 -0
- package/dist/tokens.js +21 -0
- package/dist/tokens.json +21 -0
- package/dist/website/Media/Media.js +2 -2
- package/dist/website/Media/Media.js.map +1 -1
- package/dist/website/Reading/Reading.d.ts +7 -1
- package/dist/website/Reading/Reading.js +4 -0
- package/dist/website/Reading/Reading.js.map +1 -1
- package/dist/website/Recovery/Recovery.d.ts +10 -2
- package/dist/website/Recovery/Recovery.js +36 -2
- package/dist/website/Recovery/Recovery.js.map +1 -1
- package/dist/website/SearchPalette/SearchPalette.js +2 -0
- package/dist/website/SearchPalette/SearchPalette.js.map +1 -1
- package/dist/website/Timeline/Timeline.d.ts +11 -2
- package/dist/website/Timeline/Timeline.js +7 -1
- package/dist/website/Timeline/Timeline.js.map +1 -1
- package/dist/website/Workbench/theme.d.ts +2 -1
- package/dist/website/Workbench/theme.js +2 -1
- package/dist/website/Workbench/theme.js.map +1 -1
- package/dist/website/index.d.ts +2 -2
- package/dist/website-media.css +10 -4
- package/dist/website-reading.css +15 -4
- package/dist/website-recovery.css +8 -0
- package/dist/website-search.css +28 -14
- package/dist/website-timeline.css +6 -0
- package/package.json +1 -1
- package/skills/folio-design/rules/tokens.md +1 -0
package/dist/tokens.json
CHANGED
|
@@ -300,6 +300,21 @@
|
|
|
300
300
|
"category": "space",
|
|
301
301
|
"light": "52px"
|
|
302
302
|
},
|
|
303
|
+
"device-bezel": {
|
|
304
|
+
"layer": "tokens",
|
|
305
|
+
"category": "colour",
|
|
306
|
+
"light": "#1d1d1f"
|
|
307
|
+
},
|
|
308
|
+
"device-rim": {
|
|
309
|
+
"layer": "tokens",
|
|
310
|
+
"category": "colour",
|
|
311
|
+
"light": "#4a4a4d"
|
|
312
|
+
},
|
|
313
|
+
"device-island": {
|
|
314
|
+
"layer": "tokens",
|
|
315
|
+
"category": "colour",
|
|
316
|
+
"light": "#000"
|
|
317
|
+
},
|
|
303
318
|
"display-scale": {
|
|
304
319
|
"layer": "tokens",
|
|
305
320
|
"category": "other",
|
|
@@ -417,6 +432,12 @@
|
|
|
417
432
|
"light": "calc(999px * var(--radius-factor))",
|
|
418
433
|
"comment": "capsules and counters"
|
|
419
434
|
},
|
|
435
|
+
"radius-control": {
|
|
436
|
+
"layer": "tokens",
|
|
437
|
+
"category": "radius",
|
|
438
|
+
"light": "var(--radius)",
|
|
439
|
+
"comment": "The corner every pressable control shares — a button, an icon button, a launcher. A role rather than a step, so a theme can make controls capsules without re-shaping the inputs and plates that also sit on `--radius`. The `data-controls` axis in themes.css is the only thing that moves it."
|
|
440
|
+
},
|
|
420
441
|
"radius-row": {
|
|
421
442
|
"layer": "tokens",
|
|
422
443
|
"category": "radius",
|
|
@@ -52,7 +52,7 @@ function MediaGalleryItem({ children, title, index, location, orientation, class
|
|
|
52
52
|
] }) });
|
|
53
53
|
}
|
|
54
54
|
function MediaGallerySkeleton({ label, count = 6 }) {
|
|
55
|
-
return /* @__PURE__ */ jsxs(SkeletonPage, { label, "aria-label": label, children: [
|
|
55
|
+
return /* @__PURE__ */ jsx("div", { className: "folio-loading-page", children: /* @__PURE__ */ jsxs(SkeletonPage, { label, "aria-label": label, children: [
|
|
56
56
|
/* @__PURE__ */ jsxs("header", { className: "folio-media-masthead", children: [
|
|
57
57
|
/* @__PURE__ */ jsx(SkeletonLine, { className: "w-24" }),
|
|
58
58
|
/* @__PURE__ */ jsx(SkeletonBlock, { className: "mt-4 h-9 w-[min(560px,90%)]" }),
|
|
@@ -63,7 +63,7 @@ function MediaGallerySkeleton({ label, count = 6 }) {
|
|
|
63
63
|
/* @__PURE__ */ jsx(SkeletonBlock, { className: "folio-media-gallery-mount" }),
|
|
64
64
|
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-3 w-3/4" })
|
|
65
65
|
] }, index)) }) })
|
|
66
|
-
] });
|
|
66
|
+
] }) });
|
|
67
67
|
}
|
|
68
68
|
function MediaDetailLayout({ title, titleId, headingLevel = 1, category, notesLabel, orientation, backLink, index, media, light, actions, metadata, location, pager, related, className, ...rest }) {
|
|
69
69
|
const Heading = `h${headingLevel}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/website/Media/Media.tsx"],"sourcesContent":["import { Slot } from '@radix-ui/react-slot'\nimport { RiAddLine, RiSubtractLine } from '@remixicon/react'\nimport type { ComponentPropsWithRef, HTMLAttributes, ReactElement, ReactNode } from 'react'\nimport { Badge } from '../../components/Badge/Badge'\nimport { Button, type ButtonProps } from '../../components/Button/Button'\nimport { DescriptionList, type DescriptionListItem } from '../../components/DescriptionList/DescriptionList'\nimport { EmptyState } from '../../components/EmptyState/EmptyState'\nimport { SkeletonBlock, SkeletonLine, SkeletonPage } from '../../components/Skeleton/Skeleton'\nimport { cn } from '../../lib/cn'\nimport { replaceSlotContent } from '../../lib/slot-content'\n\nexport interface MediaMastheadProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n eyebrow?: ReactNode\n title: ReactNode\n description?: ReactNode\n /** The title level when this page composition sits inside another document. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6\n}\n\n/** The quiet opening to an image collection, before its controls and prints. */\nexport function MediaMasthead({ eyebrow, title, description, headingLevel = 1, className, ...rest }: MediaMastheadProps) {\n const Heading = `h${headingLevel}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\n return (\n <header className={cn('folio-media-masthead', className)} {...rest}>\n {eyebrow && <p className=\"folio-media-eyebrow\">{eyebrow}</p>}\n <Heading className=\"folio-media-masthead-title\">{title}</Heading>\n {description && <p className=\"folio-media-description\">{description}</p>}\n </header>\n )\n}\n\nexport interface PhotographFeatureProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n image: ReactNode\n title: ReactNode\n eyebrow?: ReactNode\n description?: ReactNode\n caption?: ReactNode\n action?: ReactNode\n}\n\n/** A photograph and an editorial introduction, with the original image ratio. */\nexport function PhotographFeature({ image, title, eyebrow, description, caption, action, className, ...rest }: PhotographFeatureProps) {\n return (\n <section className={cn('folio-photograph-feature', className)} {...rest}>\n <div className=\"folio-photograph-feature-copy\">\n {eyebrow && <p className=\"folio-media-eyebrow\">{eyebrow}</p>}\n <h2 className=\"folio-photograph-feature-title\">{title}</h2>\n {description && <div className=\"folio-media-description\">{description}</div>}\n {action && <div className=\"folio-photograph-feature-action\">{action}</div>}\n </div>\n <figure className=\"folio-photograph-feature-figure\">\n <div className=\"folio-photograph-feature-image\">{image}</div>\n {caption && <figcaption className=\"folio-photograph-feature-caption\">{caption}</figcaption>}\n </figure>\n </section>\n )\n}\n\nexport interface MediaCollectionProps extends HTMLAttributes<HTMLDivElement> {\n masthead: ReactNode\n controls?: ReactNode\n collectionId?: string\n footer?: ReactNode\n}\n\n/** Page-level gallery composition; the host owns its filters and collection. */\nexport function MediaCollection({ masthead, controls, collectionId, footer, children, className, ...rest }: MediaCollectionProps) {\n return (\n <div className={cn('folio-media-gallery-page', className)} {...rest}>\n {masthead}\n {controls && <div className=\"folio-media-container\">{controls}</div>}\n <section id={collectionId} className=\"folio-media-gallery-content\">{children}</section>\n {footer}\n </div>\n )\n}\n\nexport interface MediaGalleryProps extends HTMLAttributes<HTMLUListElement> {\n children?: ReactNode\n /** Supply localized empty copy when the collection may have no children. */\n emptyTitle?: ReactNode\n emptyAction?: ReactNode\n}\n\n/** Level mounts keep unlike aspect ratios aligned without cropping the prints. */\nexport function MediaGallery({ children, emptyTitle, emptyAction, className, ...rest }: MediaGalleryProps) {\n return (\n <div className=\"folio-media-container\">\n {emptyTitle ? <EmptyState title={emptyTitle} action={emptyAction} /> : (\n <ul role=\"list\" className={cn('folio-media-gallery', className)} {...rest}>{children}</ul>\n )}\n </div>\n )\n}\n\nexport interface MediaGalleryItemProps extends Omit<HTMLAttributes<HTMLLIElement>, 'title'> {\n /** A host link containing its image. The package supplies the print layout. */\n children: ReactElement\n title: ReactNode\n index?: ReactNode\n location?: ReactNode\n orientation?: 'portrait' | 'landscape' | 'square'\n}\n\nexport function MediaGalleryItem({ children, title, index, location, orientation, className, ...rest }: MediaGalleryItemProps) {\n return (\n <li className={cn('folio-media-gallery-item', className)} {...rest}>\n <figure>\n <Slot className=\"folio-media-gallery-link\" data-photo-orientation={orientation}>{children}</Slot>\n <figcaption className=\"folio-media-gallery-caption\">\n {index != null && <span className=\"folio-media-gallery-index\" aria-hidden=\"true\">{index}</span>}\n <span className=\"folio-media-gallery-title\">{title}</span>\n {location && <span className=\"folio-media-gallery-location\">{location}</span>}\n </figcaption>\n </figure>\n </li>\n )\n}\n\nexport interface MediaGallerySkeletonProps {\n label: string\n count?: number\n}\n\nexport function MediaGallerySkeleton({ label, count = 6 }: MediaGallerySkeletonProps) {\n return (\n <SkeletonPage label={label} aria-label={label}>\n <header className=\"folio-media-masthead\">\n <SkeletonLine className=\"w-24\" />\n <SkeletonBlock className=\"mt-4 h-9 w-[min(560px,90%)]\" />\n <SkeletonBlock className=\"mt-2.5 h-9 w-[min(380px,70%)]\" />\n </header>\n <div className=\"folio-media-container\"><SkeletonLine className=\"h-11 w-full\" /></div>\n <section data-loading-content className=\"folio-media-gallery-content\">\n <MediaGallery>\n {Array.from({ length: count }, (_, index) => (\n <li key={index}>\n <SkeletonBlock className=\"folio-media-gallery-mount\" />\n <SkeletonLine className=\"mt-3 w-3/4\" />\n </li>\n ))}\n </MediaGallery>\n </section>\n </SkeletonPage>\n )\n}\n\nexport interface MediaDetailLayoutProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n title: ReactNode\n titleId: string\n /** The title level when this page composition sits inside another document. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6\n category?: ReactNode\n notesLabel: string\n orientation: 'portrait' | 'landscape' | 'square'\n backLink: ReactElement\n index?: ReactNode\n media: ReactNode\n light?: ReactNode\n actions?: ReactNode\n metadata?: ReactNode\n location?: ReactNode\n pager?: ReactNode\n related?: ReactNode\n}\n\n/** Portraits share a spread with their notes; landscapes lead a full-width spread. */\nexport function MediaDetailLayout({ title, titleId, headingLevel = 1, category, notesLabel, orientation, backLink, index, media, light, actions, metadata, location, pager, related, className, ...rest }: MediaDetailLayoutProps) {\n const Heading = `h${headingLevel}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\n return (\n <div className=\"folio-media-detail-page\">\n <article className={cn('folio-media-detail', className)} aria-labelledby={titleId} data-photo-detail {...rest}>\n <header className=\"folio-media-index-bar\">\n <Button asChild variant=\"ghost\">{backLink}</Button>\n {index && <span className=\"folio-media-index\">{index}</span>}\n </header>\n <div className=\"folio-media-spread\" data-photo-spread={orientation === 'landscape' ? 'wide' : 'tall'}>\n <div className=\"folio-media-well\" data-photo-media>{media}</div>\n <aside className=\"folio-media-ledger\" aria-label={notesLabel} data-photo-ledger>\n <div className=\"folio-media-ledger-narrative\">\n <div className=\"folio-media-ledger-lead\">\n {category && <p className=\"folio-media-eyebrow\">{category}</p>}\n <Heading id={titleId} className=\"folio-media-detail-title\">{title}</Heading>\n </div>\n {light}\n {actions && <div className=\"folio-media-actions\" data-photo-actions>{actions}</div>}\n </div>\n <div className=\"folio-media-ledger-data\">{metadata}{location}</div>\n </aside>\n </div>\n {pager}\n {related}\n </article>\n </div>\n )\n}\n\nexport interface MediaMetadataProps extends HTMLAttributes<HTMLDListElement> {\n items: DescriptionListItem[]\n}\n\nexport function MediaMetadata({ items, className, ...rest }: MediaMetadataProps) {\n return <DescriptionList items={items} className={cn('folio-media-metadata', className)} data-photo-specs {...rest} />\n}\n\nexport interface MediaPagerProps extends HTMLAttributes<HTMLElement> {\n label: string\n previous?: ReactNode\n next?: ReactNode\n}\n\nexport function MediaPager({ label, previous, next, className, ...rest }: MediaPagerProps) {\n if (!previous && !next) return null\n return <nav aria-label={label} className={cn('folio-media-pager', className)} data-photo-pager {...rest}>{previous || <span />}{next || <span />}</nav>\n}\n\nexport interface MediaPagerItemProps {\n link: ReactElement\n direction: 'previous' | 'next'\n label: ReactNode\n title: ReactNode\n image?: ReactNode\n}\n\nexport function MediaPagerItem({ link, direction, label, title, image }: MediaPagerItemProps) {\n return (\n <Slot className=\"folio-media-pager-link\" data-direction={direction}>\n {/** Slot composes the host link while retaining its routing behavior. */}\n {replaceSlotContent(link, <>\n {image && direction === 'previous' && <span className=\"folio-media-pager-image\">{image}</span>}\n <span className=\"folio-media-pager-copy\">\n <span className=\"folio-media-pager-label\">{label}</span>{' '}\n <strong className=\"folio-media-pager-title\">{title}</strong>\n </span>\n {image && direction === 'next' && <span className=\"folio-media-pager-image\">{image}</span>}\n </>)}\n </Slot>\n )\n}\n\nexport interface MediaThumbnailStripProps extends HTMLAttributes<HTMLElement> {\n heading: ReactNode\n}\n\nexport function MediaThumbnailStrip({ heading, children, className, ...rest }: MediaThumbnailStripProps) {\n return <section className={cn('folio-media-thumbnails', className)} data-photo-related {...rest}><h2>{heading}</h2><div className=\"folio-media-thumbnail-list\">{children}</div></section>\n}\n\nexport interface MediaThumbnailProps {\n children: ReactElement\n}\n\nexport function MediaThumbnail({ children }: MediaThumbnailProps) {\n return <Slot className=\"folio-media-thumbnail\">{children}</Slot>\n}\n\nexport interface MediaLightNoteLine {\n id: string\n icon?: ReactNode\n text: ReactNode\n detail?: ReactNode\n}\n\nexport interface MediaLightNoteProps {\n label: ReactNode\n lines: MediaLightNoteLine[]\n}\n\n/** The host supplies observations and formatted labels; this is presentation only. */\nexport function MediaLightNote({ label, lines }: MediaLightNoteProps) {\n return <div className=\"folio-media-light\"><Badge tone=\"outline\">{label}</Badge>{lines.map((line) => <div className=\"folio-media-light-line\" key={line.id}>{line.icon}<span>{line.text}</span>{line.detail && <span className=\"folio-media-light-detail\">{line.detail}</span>}</div>)}</div>\n}\n\nexport interface MediaMapSectionProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n title: ReactNode\n hint?: ReactNode\n /** An optional legacy anchor, owned and named by the host. */\n aliasId?: string\n map: ReactNode\n preview: ReactNode\n}\n\nexport function MediaMapSection({ title, hint, aliasId, map, preview, className, ...rest }: MediaMapSectionProps) {\n return <section className={cn('folio-media-map-section', className)} {...rest}><div className=\"folio-media-container\">{aliasId && <span id={aliasId} className=\"folio-media-anchor\" aria-hidden=\"true\" />}<header><h2>{title}</h2>{hint && <p>{hint}</p>}</header><div className=\"folio-media-map-grid\">{map}{preview}</div></div></section>\n}\n\nexport interface MediaMapFrameProps extends HTMLAttributes<HTMLDivElement> {\n label?: ReactNode\n hint?: ReactNode\n navigation?: ReactNode\n compact?: boolean\n}\n\nexport function MediaMapFrame({ label, hint, navigation, compact = false, children, className, ...rest }: MediaMapFrameProps) {\n return <div className={cn('folio-media-map-frame', compact && 'folio-media-map-frame-compact', className)} {...rest}>{label && <span className=\"folio-media-map-label\">{label}</span>}<div className=\"folio-media-map-stage\">{children}{hint && <div className=\"folio-media-map-hint\">{hint}</div>}{navigation && <div className=\"folio-media-map-navigation\">{navigation}</div>}</div></div>\n}\n\nexport interface MediaMapNavigationProps {\n zoomInLabel: string\n zoomOutLabel: string\n onZoomIn: () => void\n onZoomOut: () => void\n}\n\nexport function MediaMapNavigation({ zoomInLabel, zoomOutLabel, onZoomIn, onZoomOut }: MediaMapNavigationProps) {\n return <><Button variant=\"secondary\" iconOnly aria-label={zoomInLabel} onClick={onZoomIn}><RiAddLine size={18} aria-hidden=\"true\" /></Button><Button variant=\"secondary\" iconOnly aria-label={zoomOutLabel} onClick={onZoomOut}><RiSubtractLine size={18} aria-hidden=\"true\" /></Button></>\n}\n\nexport type MediaMapCanvasProps = ComponentPropsWithRef<'div'>\n\n/** A sized provider container. Map creation, themes and geographic math stay in the host. */\nexport function MediaMapCanvas({ className, ...rest }: MediaMapCanvasProps) {\n return <div className={cn('folio-media-map-canvas', className)} {...rest} />\n}\n\nexport interface MediaMapPreviewProps {\n title: ReactNode\n image?: ReactNode\n action?: ReactNode\n place?: ReactNode\n coordinates?: ReactNode\n children?: ReactNode\n}\n\nexport function MediaMapPreview({ title, image, action, place, coordinates, children }: MediaMapPreviewProps) {\n return <aside className=\"folio-media-map-preview\"><div className=\"folio-media-map-preview-image\">{image}{action && <div className=\"folio-media-map-preview-action\">{action}</div>}</div><div className=\"folio-media-map-preview-copy\"><h3>{title}</h3>{place && <p className=\"folio-media-map-place\">{place}</p>}{coordinates && <div className=\"folio-media-map-coordinates\">{coordinates}</div>}{children}</div></aside>\n}\n\nexport interface MediaMapArea {\n id: string\n label: ReactNode\n count: ReactNode\n}\n\nexport interface MediaMapAreaListProps {\n items: MediaMapArea[]\n value?: string\n onValueChange: (value: string) => void\n}\n\nexport function MediaMapAreaList({ items, value, onValueChange }: MediaMapAreaListProps) {\n return (\n <div className=\"folio-media-map-areas\">\n {items.map((item) => (\n <Button key={item.id} variant=\"ghost\" aria-pressed={value === item.id} onClick={() => onValueChange(item.id)} className=\"folio-media-map-area\">\n <span className=\"folio-media-map-area-name\"><span aria-hidden=\"true\" />{item.label}</span>{' '}\n <span className=\"folio-media-map-area-count\">{item.count}</span>\n </Button>\n ))}\n </div>\n )\n}\n\nexport interface MediaMapMarkerProps extends Omit<Extract<ButtonProps, { href?: undefined }>, 'children' | 'iconOnly'> {\n label: string\n active?: boolean\n}\n\n/** A keyboard-operable 44px marker for a host's map-provider portal. */\nexport function MediaMapMarker({ label, active = false, className, ...rest }: MediaMapMarkerProps) {\n return <Button {...rest} variant=\"ghost\" iconOnly aria-label={label} aria-pressed={active} className={cn('folio-media-map-marker', className)} style={{ width: 44, height: 44, ...rest.style }}><MediaMapPin active={active} /></Button>\n}\n\nexport interface MediaMapPinProps {\n active?: boolean\n}\n\nexport function MediaMapPin({ active = false }: MediaMapPinProps) {\n return <span className=\"folio-media-map-pin\" data-active={active || undefined} aria-hidden=\"true\"><span /></span>\n}\n\nexport function MediaMapSkeleton() {\n return <div className=\"folio-media-map-skeleton folio-media-container\" aria-hidden=\"true\"><SkeletonBlock className=\"folio-media-map-canvas\" /></div>\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/website/Media/Media.tsx"],"sourcesContent":["import { Slot } from '@radix-ui/react-slot'\nimport { RiAddLine, RiSubtractLine } from '@remixicon/react'\nimport type { ComponentPropsWithRef, HTMLAttributes, ReactElement, ReactNode } from 'react'\nimport { Badge } from '../../components/Badge/Badge'\nimport { Button, type ButtonProps } from '../../components/Button/Button'\nimport { DescriptionList, type DescriptionListItem } from '../../components/DescriptionList/DescriptionList'\nimport { EmptyState } from '../../components/EmptyState/EmptyState'\nimport { SkeletonBlock, SkeletonLine, SkeletonPage } from '../../components/Skeleton/Skeleton'\nimport { cn } from '../../lib/cn'\nimport { replaceSlotContent } from '../../lib/slot-content'\n\nexport interface MediaMastheadProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n eyebrow?: ReactNode\n title: ReactNode\n description?: ReactNode\n /** The title level when this page composition sits inside another document. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6\n}\n\n/** The quiet opening to an image collection, before its controls and prints. */\nexport function MediaMasthead({ eyebrow, title, description, headingLevel = 1, className, ...rest }: MediaMastheadProps) {\n const Heading = `h${headingLevel}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\n return (\n <header className={cn('folio-media-masthead', className)} {...rest}>\n {eyebrow && <p className=\"folio-media-eyebrow\">{eyebrow}</p>}\n <Heading className=\"folio-media-masthead-title\">{title}</Heading>\n {description && <p className=\"folio-media-description\">{description}</p>}\n </header>\n )\n}\n\nexport interface PhotographFeatureProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n image: ReactNode\n title: ReactNode\n eyebrow?: ReactNode\n description?: ReactNode\n caption?: ReactNode\n action?: ReactNode\n}\n\n/** A photograph and an editorial introduction, with the original image ratio. */\nexport function PhotographFeature({ image, title, eyebrow, description, caption, action, className, ...rest }: PhotographFeatureProps) {\n return (\n <section className={cn('folio-photograph-feature', className)} {...rest}>\n <div className=\"folio-photograph-feature-copy\">\n {eyebrow && <p className=\"folio-media-eyebrow\">{eyebrow}</p>}\n <h2 className=\"folio-photograph-feature-title\">{title}</h2>\n {description && <div className=\"folio-media-description\">{description}</div>}\n {action && <div className=\"folio-photograph-feature-action\">{action}</div>}\n </div>\n <figure className=\"folio-photograph-feature-figure\">\n <div className=\"folio-photograph-feature-image\">{image}</div>\n {caption && <figcaption className=\"folio-photograph-feature-caption\">{caption}</figcaption>}\n </figure>\n </section>\n )\n}\n\nexport interface MediaCollectionProps extends HTMLAttributes<HTMLDivElement> {\n masthead: ReactNode\n controls?: ReactNode\n collectionId?: string\n footer?: ReactNode\n}\n\n/** Page-level gallery composition; the host owns its filters and collection. */\nexport function MediaCollection({ masthead, controls, collectionId, footer, children, className, ...rest }: MediaCollectionProps) {\n return (\n <div className={cn('folio-media-gallery-page', className)} {...rest}>\n {masthead}\n {controls && <div className=\"folio-media-container\">{controls}</div>}\n <section id={collectionId} className=\"folio-media-gallery-content\">{children}</section>\n {footer}\n </div>\n )\n}\n\nexport interface MediaGalleryProps extends HTMLAttributes<HTMLUListElement> {\n children?: ReactNode\n /** Supply localized empty copy when the collection may have no children. */\n emptyTitle?: ReactNode\n emptyAction?: ReactNode\n}\n\n/** Level mounts keep unlike aspect ratios aligned without cropping the prints. */\nexport function MediaGallery({ children, emptyTitle, emptyAction, className, ...rest }: MediaGalleryProps) {\n return (\n <div className=\"folio-media-container\">\n {emptyTitle ? <EmptyState title={emptyTitle} action={emptyAction} /> : (\n <ul role=\"list\" className={cn('folio-media-gallery', className)} {...rest}>{children}</ul>\n )}\n </div>\n )\n}\n\nexport interface MediaGalleryItemProps extends Omit<HTMLAttributes<HTMLLIElement>, 'title'> {\n /** A host link containing its image. The package supplies the print layout. */\n children: ReactElement\n title: ReactNode\n index?: ReactNode\n location?: ReactNode\n orientation?: 'portrait' | 'landscape' | 'square'\n}\n\nexport function MediaGalleryItem({ children, title, index, location, orientation, className, ...rest }: MediaGalleryItemProps) {\n return (\n <li className={cn('folio-media-gallery-item', className)} {...rest}>\n <figure>\n <Slot className=\"folio-media-gallery-link\" data-photo-orientation={orientation}>{children}</Slot>\n <figcaption className=\"folio-media-gallery-caption\">\n {index != null && <span className=\"folio-media-gallery-index\" aria-hidden=\"true\">{index}</span>}\n <span className=\"folio-media-gallery-title\">{title}</span>\n {location && <span className=\"folio-media-gallery-location\">{location}</span>}\n </figcaption>\n </figure>\n </li>\n )\n}\n\nexport interface MediaGallerySkeletonProps {\n label: string\n count?: number\n}\n\nexport function MediaGallerySkeleton({ label, count = 6 }: MediaGallerySkeletonProps) {\n return (\n <div className=\"folio-loading-page\">\n <SkeletonPage label={label} aria-label={label}>\n <header className=\"folio-media-masthead\">\n <SkeletonLine className=\"w-24\" />\n <SkeletonBlock className=\"mt-4 h-9 w-[min(560px,90%)]\" />\n <SkeletonBlock className=\"mt-2.5 h-9 w-[min(380px,70%)]\" />\n </header>\n <div className=\"folio-media-container\"><SkeletonLine className=\"h-11 w-full\" /></div>\n <section data-loading-content className=\"folio-media-gallery-content\">\n <MediaGallery>\n {Array.from({ length: count }, (_, index) => (\n <li key={index}>\n <SkeletonBlock className=\"folio-media-gallery-mount\" />\n <SkeletonLine className=\"mt-3 w-3/4\" />\n </li>\n ))}\n </MediaGallery>\n </section>\n </SkeletonPage>\n </div>\n )\n}\n\nexport interface MediaDetailLayoutProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n title: ReactNode\n titleId: string\n /** The title level when this page composition sits inside another document. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6\n category?: ReactNode\n notesLabel: string\n orientation: 'portrait' | 'landscape' | 'square'\n backLink: ReactElement\n index?: ReactNode\n media: ReactNode\n light?: ReactNode\n actions?: ReactNode\n metadata?: ReactNode\n location?: ReactNode\n pager?: ReactNode\n related?: ReactNode\n}\n\n/** Portraits share a spread with their notes; landscapes lead a full-width spread. */\nexport function MediaDetailLayout({ title, titleId, headingLevel = 1, category, notesLabel, orientation, backLink, index, media, light, actions, metadata, location, pager, related, className, ...rest }: MediaDetailLayoutProps) {\n const Heading = `h${headingLevel}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\n return (\n <div className=\"folio-media-detail-page\">\n <article className={cn('folio-media-detail', className)} aria-labelledby={titleId} data-photo-detail {...rest}>\n <header className=\"folio-media-index-bar\">\n <Button asChild variant=\"ghost\">{backLink}</Button>\n {index && <span className=\"folio-media-index\">{index}</span>}\n </header>\n <div className=\"folio-media-spread\" data-photo-spread={orientation === 'landscape' ? 'wide' : 'tall'}>\n <div className=\"folio-media-well\" data-photo-media>{media}</div>\n <aside className=\"folio-media-ledger\" aria-label={notesLabel} data-photo-ledger>\n <div className=\"folio-media-ledger-narrative\">\n <div className=\"folio-media-ledger-lead\">\n {category && <p className=\"folio-media-eyebrow\">{category}</p>}\n <Heading id={titleId} className=\"folio-media-detail-title\">{title}</Heading>\n </div>\n {light}\n {actions && <div className=\"folio-media-actions\" data-photo-actions>{actions}</div>}\n </div>\n <div className=\"folio-media-ledger-data\">{metadata}{location}</div>\n </aside>\n </div>\n {pager}\n {related}\n </article>\n </div>\n )\n}\n\nexport interface MediaMetadataProps extends HTMLAttributes<HTMLDListElement> {\n items: DescriptionListItem[]\n}\n\nexport function MediaMetadata({ items, className, ...rest }: MediaMetadataProps) {\n return <DescriptionList items={items} className={cn('folio-media-metadata', className)} data-photo-specs {...rest} />\n}\n\nexport interface MediaPagerProps extends HTMLAttributes<HTMLElement> {\n label: string\n previous?: ReactNode\n next?: ReactNode\n}\n\nexport function MediaPager({ label, previous, next, className, ...rest }: MediaPagerProps) {\n if (!previous && !next) return null\n return <nav aria-label={label} className={cn('folio-media-pager', className)} data-photo-pager {...rest}>{previous || <span />}{next || <span />}</nav>\n}\n\nexport interface MediaPagerItemProps {\n link: ReactElement\n direction: 'previous' | 'next'\n label: ReactNode\n title: ReactNode\n image?: ReactNode\n}\n\nexport function MediaPagerItem({ link, direction, label, title, image }: MediaPagerItemProps) {\n return (\n <Slot className=\"folio-media-pager-link\" data-direction={direction}>\n {/** Slot composes the host link while retaining its routing behavior. */}\n {replaceSlotContent(link, <>\n {image && direction === 'previous' && <span className=\"folio-media-pager-image\">{image}</span>}\n <span className=\"folio-media-pager-copy\">\n <span className=\"folio-media-pager-label\">{label}</span>{' '}\n <strong className=\"folio-media-pager-title\">{title}</strong>\n </span>\n {image && direction === 'next' && <span className=\"folio-media-pager-image\">{image}</span>}\n </>)}\n </Slot>\n )\n}\n\nexport interface MediaThumbnailStripProps extends HTMLAttributes<HTMLElement> {\n heading: ReactNode\n}\n\nexport function MediaThumbnailStrip({ heading, children, className, ...rest }: MediaThumbnailStripProps) {\n return <section className={cn('folio-media-thumbnails', className)} data-photo-related {...rest}><h2>{heading}</h2><div className=\"folio-media-thumbnail-list\">{children}</div></section>\n}\n\nexport interface MediaThumbnailProps {\n children: ReactElement\n}\n\nexport function MediaThumbnail({ children }: MediaThumbnailProps) {\n return <Slot className=\"folio-media-thumbnail\">{children}</Slot>\n}\n\nexport interface MediaLightNoteLine {\n id: string\n icon?: ReactNode\n text: ReactNode\n detail?: ReactNode\n}\n\nexport interface MediaLightNoteProps {\n label: ReactNode\n lines: MediaLightNoteLine[]\n}\n\n/** The host supplies observations and formatted labels; this is presentation only. */\nexport function MediaLightNote({ label, lines }: MediaLightNoteProps) {\n return <div className=\"folio-media-light\"><Badge tone=\"outline\">{label}</Badge>{lines.map((line) => <div className=\"folio-media-light-line\" key={line.id}>{line.icon}<span>{line.text}</span>{line.detail && <span className=\"folio-media-light-detail\">{line.detail}</span>}</div>)}</div>\n}\n\nexport interface MediaMapSectionProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n title: ReactNode\n hint?: ReactNode\n /** An optional legacy anchor, owned and named by the host. */\n aliasId?: string\n map: ReactNode\n preview: ReactNode\n}\n\nexport function MediaMapSection({ title, hint, aliasId, map, preview, className, ...rest }: MediaMapSectionProps) {\n return <section className={cn('folio-media-map-section', className)} {...rest}><div className=\"folio-media-container\">{aliasId && <span id={aliasId} className=\"folio-media-anchor\" aria-hidden=\"true\" />}<header><h2>{title}</h2>{hint && <p>{hint}</p>}</header><div className=\"folio-media-map-grid\">{map}{preview}</div></div></section>\n}\n\nexport interface MediaMapFrameProps extends HTMLAttributes<HTMLDivElement> {\n label?: ReactNode\n hint?: ReactNode\n navigation?: ReactNode\n compact?: boolean\n}\n\nexport function MediaMapFrame({ label, hint, navigation, compact = false, children, className, ...rest }: MediaMapFrameProps) {\n return <div className={cn('folio-media-map-frame', compact && 'folio-media-map-frame-compact', className)} {...rest}>{label && <span className=\"folio-media-map-label\">{label}</span>}<div className=\"folio-media-map-stage\">{children}{hint && <div className=\"folio-media-map-hint\">{hint}</div>}{navigation && <div className=\"folio-media-map-navigation\">{navigation}</div>}</div></div>\n}\n\nexport interface MediaMapNavigationProps {\n zoomInLabel: string\n zoomOutLabel: string\n onZoomIn: () => void\n onZoomOut: () => void\n}\n\nexport function MediaMapNavigation({ zoomInLabel, zoomOutLabel, onZoomIn, onZoomOut }: MediaMapNavigationProps) {\n return <><Button variant=\"secondary\" iconOnly aria-label={zoomInLabel} onClick={onZoomIn}><RiAddLine size={18} aria-hidden=\"true\" /></Button><Button variant=\"secondary\" iconOnly aria-label={zoomOutLabel} onClick={onZoomOut}><RiSubtractLine size={18} aria-hidden=\"true\" /></Button></>\n}\n\nexport type MediaMapCanvasProps = ComponentPropsWithRef<'div'>\n\n/** A sized provider container. Map creation, themes and geographic math stay in the host. */\nexport function MediaMapCanvas({ className, ...rest }: MediaMapCanvasProps) {\n return <div className={cn('folio-media-map-canvas', className)} {...rest} />\n}\n\nexport interface MediaMapPreviewProps {\n title: ReactNode\n image?: ReactNode\n action?: ReactNode\n place?: ReactNode\n coordinates?: ReactNode\n children?: ReactNode\n}\n\nexport function MediaMapPreview({ title, image, action, place, coordinates, children }: MediaMapPreviewProps) {\n return <aside className=\"folio-media-map-preview\"><div className=\"folio-media-map-preview-image\">{image}{action && <div className=\"folio-media-map-preview-action\">{action}</div>}</div><div className=\"folio-media-map-preview-copy\"><h3>{title}</h3>{place && <p className=\"folio-media-map-place\">{place}</p>}{coordinates && <div className=\"folio-media-map-coordinates\">{coordinates}</div>}{children}</div></aside>\n}\n\nexport interface MediaMapArea {\n id: string\n label: ReactNode\n count: ReactNode\n}\n\nexport interface MediaMapAreaListProps {\n items: MediaMapArea[]\n value?: string\n onValueChange: (value: string) => void\n}\n\nexport function MediaMapAreaList({ items, value, onValueChange }: MediaMapAreaListProps) {\n return (\n <div className=\"folio-media-map-areas\">\n {items.map((item) => (\n <Button key={item.id} variant=\"ghost\" aria-pressed={value === item.id} onClick={() => onValueChange(item.id)} className=\"folio-media-map-area\">\n <span className=\"folio-media-map-area-name\"><span aria-hidden=\"true\" />{item.label}</span>{' '}\n <span className=\"folio-media-map-area-count\">{item.count}</span>\n </Button>\n ))}\n </div>\n )\n}\n\nexport interface MediaMapMarkerProps extends Omit<Extract<ButtonProps, { href?: undefined }>, 'children' | 'iconOnly'> {\n label: string\n active?: boolean\n}\n\n/** A keyboard-operable 44px marker for a host's map-provider portal. */\nexport function MediaMapMarker({ label, active = false, className, ...rest }: MediaMapMarkerProps) {\n return <Button {...rest} variant=\"ghost\" iconOnly aria-label={label} aria-pressed={active} className={cn('folio-media-map-marker', className)} style={{ width: 44, height: 44, ...rest.style }}><MediaMapPin active={active} /></Button>\n}\n\nexport interface MediaMapPinProps {\n active?: boolean\n}\n\nexport function MediaMapPin({ active = false }: MediaMapPinProps) {\n return <span className=\"folio-media-map-pin\" data-active={active || undefined} aria-hidden=\"true\"><span /></span>\n}\n\nexport function MediaMapSkeleton() {\n return <div className=\"folio-media-map-skeleton folio-media-container\" aria-hidden=\"true\"><SkeletonBlock className=\"folio-media-map-canvas\" /></div>\n}\n"],"mappings":"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","names":[]}
|
|
@@ -128,6 +128,12 @@ interface PreviewPairProps {
|
|
|
128
128
|
desktop: ReactNode;
|
|
129
129
|
mobile?: ReactNode;
|
|
130
130
|
}
|
|
131
|
+
interface DeviceRowProps {
|
|
132
|
+
children: ReactNode;
|
|
133
|
+
label?: string;
|
|
134
|
+
}
|
|
135
|
+
/** Two or three phones side by side, the middle one raised a step, wrapping to a column on a narrow screen. */
|
|
136
|
+
declare function DeviceRow({ children, label }: DeviceRowProps): react.JSX.Element;
|
|
131
137
|
declare function PreviewPair({ desktop, mobile }: PreviewPairProps): react.JSX.Element;
|
|
132
138
|
interface CommandTab {
|
|
133
139
|
id: string;
|
|
@@ -200,4 +206,4 @@ interface CommandSnippetProps {
|
|
|
200
206
|
}
|
|
201
207
|
declare function CommandSnippet({ code, pieces, copyLabel, copiedLabel, className }: CommandSnippetProps): react.JSX.Element;
|
|
202
208
|
|
|
203
|
-
export { ActionBand, type ActionBandProps, type ArchitectureColumnNode, ArchitectureColumns, type ArchitectureColumnsProps, AuthorPanel, type AuthorPanelProps, type CommandPiece, CommandSnippet, type CommandSnippetProps, type CommandTab, CommandTabs, type CommandTabsProps, ContentFigure, type ContentFigureProps, DetailMasthead, type DetailMastheadProps, DevicePreview, type DevicePreviewProps, FeaturePairs, type FeaturePairsProps, MediaPlayback, type MediaPlaybackProps, MobileOutline, type MobileOutlineProps, type OutlineItem, PreviewPair, type PreviewPairProps, ReadingFigure, type ReadingFigureProps, ReadingForm, type ReadingFormProps, ReadingLayout, type ReadingLayoutProps, ReadingLead, type ReadingLeadProps, type ReadingMetadataItem, ReadingPage, type ReadingPageProps, type ReadingPagerItem, ReadingProgress, ReadingSection, type ReadingSectionProps, ReadingSurface, type ReadingSurfaceProps, RecordPager, type RecordPagerProps, TableOfContents, type TableOfContentsProps, TokenLine, type TokenLineProps, isSelfNumbered, numberToc };
|
|
209
|
+
export { ActionBand, type ActionBandProps, type ArchitectureColumnNode, ArchitectureColumns, type ArchitectureColumnsProps, AuthorPanel, type AuthorPanelProps, type CommandPiece, CommandSnippet, type CommandSnippetProps, type CommandTab, CommandTabs, type CommandTabsProps, ContentFigure, type ContentFigureProps, DetailMasthead, type DetailMastheadProps, DevicePreview, type DevicePreviewProps, DeviceRow, type DeviceRowProps, FeaturePairs, type FeaturePairsProps, MediaPlayback, type MediaPlaybackProps, MobileOutline, type MobileOutlineProps, type OutlineItem, PreviewPair, type PreviewPairProps, ReadingFigure, type ReadingFigureProps, ReadingForm, type ReadingFormProps, ReadingLayout, type ReadingLayoutProps, ReadingLead, type ReadingLeadProps, type ReadingMetadataItem, ReadingPage, type ReadingPageProps, type ReadingPagerItem, ReadingProgress, ReadingSection, type ReadingSectionProps, ReadingSurface, type ReadingSurfaceProps, RecordPager, type RecordPagerProps, TableOfContents, type TableOfContentsProps, TokenLine, type TokenLineProps, isSelfNumbered, numberToc };
|
|
@@ -259,6 +259,9 @@ function DevicePreview({ kind, label, media, caption }) {
|
|
|
259
259
|
caption && /* @__PURE__ */ jsx("figcaption", { children: caption })
|
|
260
260
|
] });
|
|
261
261
|
}
|
|
262
|
+
function DeviceRow({ children, label }) {
|
|
263
|
+
return /* @__PURE__ */ jsx("div", { className: "folio-device-row", role: label ? "group" : void 0, "aria-label": label, children });
|
|
264
|
+
}
|
|
262
265
|
function PreviewPair({ desktop, mobile }) {
|
|
263
266
|
return /* @__PURE__ */ jsxs("div", { className: "folio-preview-pair", "data-mobile": Boolean(mobile) || void 0, children: [
|
|
264
267
|
desktop,
|
|
@@ -336,6 +339,7 @@ export {
|
|
|
336
339
|
ContentFigure,
|
|
337
340
|
DetailMasthead,
|
|
338
341
|
DevicePreview,
|
|
342
|
+
DeviceRow,
|
|
339
343
|
FeaturePairs,
|
|
340
344
|
MediaPlayback,
|
|
341
345
|
MobileOutline,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/website/Reading/Reading.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useRef, useState, type HTMLAttributes, type ReactNode } from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { RiListUnordered, RiPlayFill, RiPauseFill } from '@remixicon/react'\nimport { Button } from '../../components/Button/Button'\nimport { StatusDot } from '../../components/StatusDot/StatusDot'\nimport { Sheet, SheetContent, SheetTrigger } from '../../components/Sheet/Sheet'\nimport { CodeBlock } from '../../components/CodeBlock/CodeBlock'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../../components/Tabs/Tabs'\nimport { cn } from '../../lib/cn'\nimport { replaceSlotContent } from '../../lib/slot-content'\nimport type { CollectionLink } from '../Collection/Collection'\n\nexport interface ReadingMetadataItem { label: string; value: ReactNode; live?: boolean; dateTime?: string }\nexport interface DetailMastheadProps { backLink?: ReactNode; title: string; dek?: ReactNode; context?: ReactNode; aside?: ReactNode; actions?: ReactNode; metadata?: ReadingMetadataItem[]; width?: 'page' | 'fill' }\nexport function DetailMasthead({ backLink, title, dek, context, aside, actions, metadata = [], width = 'page' }: DetailMastheadProps) {\n const stacked = title.length <= 28 || typeof dek !== 'string' || dek.length > 280 || Boolean(aside)\n return <header className=\"folio-detail-masthead\" data-width={width} data-stacked={stacked || undefined} data-display={title.length <= 16 || undefined}>\n {backLink && <div className=\"folio-detail-back\">{backLink}</div>}{context && <p className=\"folio-detail-context\">{context}</p>}\n <div className=\"folio-detail-opening\" data-aside={Boolean(aside) || undefined} data-stacked={stacked || undefined}>{aside ? <div className=\"folio-detail-copy\"><h1>{title}</h1>{dek && <p className=\"folio-detail-dek\">{dek}</p>}</div> : <><h1>{title}</h1>{dek && <p className=\"folio-detail-dek\">{dek}</p>}</>}{aside && <aside>{aside}</aside>}</div>\n {(metadata.length > 0 || actions) && <div className=\"folio-detail-metabar\"><dl>{metadata.map((item) => <div key={item.label}><dt>{item.label}</dt><dd>{item.live && <StatusDot size=\"sm\" pulse={false} />}{item.dateTime ? <time dateTime={item.dateTime}>{item.value}</time> : item.value}</dd></div>)}</dl>{actions && <div className=\"folio-detail-actions\">{actions}</div>}</div>}\n </header>\n}\nexport interface ReadingLayoutProps extends HTMLAttributes<HTMLDivElement> { outline?: ReactNode }\nexport function ReadingLayout({ children, outline, className, ...rest }: ReadingLayoutProps) { return <div className={cn('folio-reading-layout', className)} {...rest}><div className=\"folio-reading-body\">{children}</div>{outline}</div> }\nexport interface ReadingSectionProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> { title?: ReactNode; caption?: ReactNode; lead?: ReactNode; compact?: boolean; seamless?: boolean }\n/** `seamless` lets a structured child continue directly from the section rule without drawing a second seam. */\nexport function ReadingSection({ title, caption, lead, compact, seamless, children, className, ...rest }: ReadingSectionProps) {\n return <section className={cn('folio-reading-section', className)} data-compact={compact || undefined} data-seamless={seamless || undefined} {...rest}>{(title || caption) && <div className=\"folio-reading-heading\"><h2>{title}</h2>{caption && <span>{caption}</span>}</div>}{lead && <p className=\"folio-reading-lead\">{lead}</p>}{children}</section>\n}\nexport interface ReadingLeadProps { children: ReactNode; muted?: ReactNode; description?: ReactNode }\nexport function ReadingLead({ children, muted, description }: ReadingLeadProps) { return <div className=\"folio-reading-lede\"><p>{children}{muted && <span> {muted}</span>}</p>{description && <p>{description}</p>}</div> }\nexport interface ReadingPagerItem { link: CollectionLink; direction: ReactNode; title: ReactNode; media?: ReactNode }\nexport interface RecordPagerProps { label: string; previous?: ReadingPagerItem; next?: ReadingPagerItem }\nexport function RecordPager({ label, previous, next }: RecordPagerProps) {\n if (!previous && !next) return null\n const cell = (item: ReadingPagerItem | undefined, direction: 'prev' | 'next') => item ? <Slot className=\"folio-record-pager-link\" data-direction={direction}>{replaceSlotContent(item.link, <>{item.media && <span className=\"folio-record-pager-media\">{item.media}</span>}<span><span className=\"folio-record-pager-direction\">{item.direction}</span>{' '}<strong>{item.title}</strong></span></>)}</Slot> : <span />\n return <nav className=\"folio-record-pager\" aria-label={label}>{cell(previous, 'prev')}{cell(next, 'next')}</nav>\n}\nexport interface OutlineItem { id: string; label: string; level: number }\nconst SELF_NUMBERED = /^\\s*\\d+[a-z]?\\s*[.)]\\s+/i\nexport function isSelfNumbered(items: OutlineItem[]): boolean {\n if (!items.length) return false\n const top = Math.min(...items.map((item) => item.level))\n const headings = items.filter((item) => item.level === top)\n return headings.length >= 2 && headings.filter((item) => SELF_NUMBERED.test(item.label)).length * 2 > headings.length\n}\nexport function numberToc(items: OutlineItem[]): string[] {\n const top = items.length ? Math.min(...items.map((item) => item.level)) : 0\n let major = 0; let minor = 0\n return items.map((item) => item.level <= top ? (minor = 0, String(++major)) : `${major}.${++minor}`)\n}\nexport interface TableOfContentsProps { items: OutlineItem[]; label: string; numbering?: 'auto' | 'none'; onNavigate?: (id: string) => void; expanded?: boolean }\nexport function TableOfContents({ items, label, numbering = 'auto', onNavigate, expanded = false }: TableOfContentsProps) {\n const [activeId, setActiveId] = useState(items[0]?.id ?? '')\n const pinnedId = useRef<string | null>(null)\n const releaseTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const numbers = numberToc(items)\n const showNumbers = numbering === 'auto' && !isSelfNumbered(items)\n const top = items.length ? Math.min(...items.map((item) => item.level)) : 0\n useEffect(() => () => clearTimeout(releaseTimer.current), [])\n useEffect(() => {\n const sections = items.map((item) => document.getElementById(item.id)).filter((item): item is HTMLElement => Boolean(item))\n const first = sections[0]\n if (!first) return\n const update = () => {\n let current = first\n for (const section of sections) if (section.getBoundingClientRect().top <= window.innerHeight * .28) current = section\n if (pinnedId.current && current.id !== pinnedId.current) return\n pinnedId.current = null\n setActiveId(current.id)\n }\n window.addEventListener('scroll', update, { passive: true }); window.addEventListener('resize', update); update()\n return () => { window.removeEventListener('scroll', update); window.removeEventListener('resize', update) }\n }, [items])\n const groups: { item: OutlineItem; index: number; subs: { item: OutlineItem; index: number }[] }[] = []\n items.forEach((item, index) => { const last = groups.at(-1); if (item.level <= top || !last) groups.push({ item, index, subs: [] }); else last.subs.push({ item, index }) })\n if (!items.length) return null\n const link = (item: OutlineItem, index: number, isOpen?: boolean) => <a href={`#${item.id}`} data-toc-id={item.id} aria-current={activeId === item.id ? 'true' : undefined} aria-expanded={isOpen} onClick={(event) => {\n pinnedId.current = item.id; clearTimeout(releaseTimer.current); releaseTimer.current = setTimeout(() => { pinnedId.current = null }, 1200); setActiveId(item.id)\n if (onNavigate) { event.preventDefault(); onNavigate(item.id) }\n }}>{showNumbers && <span aria-hidden>{numbers[index]}</span>}{item.label}</a>\n return <nav className=\"folio-toc\" aria-label={label}><div><p>{label}</p><ul>{groups.map((group) => {\n const open = expanded || group.item.id === activeId || group.subs.some(({ item }) => item.id === activeId)\n return <li key={group.item.id}>{link(group.item, group.index, group.subs.length ? open : undefined)}{group.subs.length > 0 && open && <ul>{group.subs.map(({ item, index }) => <li key={item.id}>{link(item, index)}</li>)}</ul>}</li>\n })}</ul></div></nav>\n}\nexport interface MobileOutlineProps { items: OutlineItem[]; title: string; openLabel: string; closeLabel: string }\nexport function MobileOutline({ items, title, openLabel, closeLabel }: MobileOutlineProps) {\n const [open, setOpen] = useState(false)\n if (!items.length) return null\n return <Sheet open={open} onOpenChange={setOpen}><SheetTrigger asChild><Button variant=\"secondary\" iconOnly aria-label={openLabel} className=\"folio-outline-trigger\"><RiListUnordered size={18} aria-hidden=\"true\" /></Button></SheetTrigger><SheetContent title={title} closeLabel={closeLabel} side=\"bottom\" className=\"folio-outline-sheet\" aria-describedby={undefined}><TableOfContents items={items} label={title} expanded onNavigate={(id) => {\n setOpen(false)\n requestAnimationFrame(() => { const target = document.getElementById(id); if (target) { target.scrollIntoView({ behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth', block: 'start' }); window.history.replaceState(null, '', `#${id}`) } })\n }} /></SheetContent></Sheet>\n}\nexport function ReadingProgress() {\n const [progress, setProgress] = useState(0)\n useEffect(() => {\n const update = () => { const doc = document.documentElement; const max = doc.scrollHeight - doc.clientHeight; setProgress(max > 0 ? Math.min(100, Math.max(0, doc.scrollTop / max * 100)) : 0) }\n update(); window.addEventListener('scroll', update, { passive: true }); window.addEventListener('resize', update)\n return () => { window.removeEventListener('scroll', update); window.removeEventListener('resize', update) }\n }, [])\n return <div className=\"folio-reading-progress\" aria-hidden><div style={{ width: `${progress}%` }} /></div>\n}\nexport interface AuthorPanelProps { avatar?: ReactNode; name: string; role?: ReactNode; bio?: ReactNode; links?: ReactNode }\nexport function AuthorPanel({ avatar, name, role, bio, links }: AuthorPanelProps) { return <aside className=\"folio-author-panel\">{avatar && <div className=\"folio-author-avatar\" aria-hidden>{avatar}</div>}<div><h2>{name}</h2>{role && <div className=\"folio-author-role\">{role}</div>}{bio && <p>{bio}</p>}{links && <div className=\"folio-author-links\">{links}</div>}</div></aside> }\nexport interface ReadingFigureProps { media: ReactNode; captionStart?: ReactNode; captionEnd?: ReactNode; width?: 'page' | 'fill'; ratio?: string; fit?: 'cover' | 'contain' }\n/** A reading image can preserve its source framing with `fit=\"contain\"`, rather than silently cropping it to a house ratio. */\nexport function ReadingFigure({ media, captionStart, captionEnd, width = 'page', ratio = '16 / 8', fit = 'cover' }: ReadingFigureProps) { return <figure className=\"folio-reading-figure\" data-width={width} data-fit={fit}><div style={{ aspectRatio: ratio }}>{media}</div>{(captionStart || captionEnd) && <figcaption><span>{captionStart}</span><span>{captionEnd}</span></figcaption>}</figure> }\nexport interface MediaPlaybackProps { src: string; poster?: string; label: string; playLabel: string; pauseLabel: string; fallback: ReactNode }\nexport function MediaPlayback({ src, poster, label, playLabel, pauseLabel, fallback }: MediaPlaybackProps) {\n const [reduceMotion, setReduceMotion] = useState(true)\n const [playing, setPlaying] = useState(false)\n const ref = useRef<HTMLVideoElement>(null)\n useEffect(() => { if (typeof window.matchMedia !== 'function') return; const query = window.matchMedia('(prefers-reduced-motion: reduce)'); const update = () => setReduceMotion(query.matches); update(); query.addEventListener('change', update); return () => query.removeEventListener('change', update) }, [])\n if (reduceMotion) return fallback\n return <div className=\"folio-media-playback\"><video ref={ref} src={src} poster={poster} aria-label={label} autoPlay muted loop playsInline preload=\"metadata\" onPlay={() => setPlaying(true)} onPause={() => setPlaying(false)} /><Button type=\"button\" variant=\"secondary\" iconOnly aria-label={playing ? pauseLabel : playLabel} onClick={() => { if (playing) ref.current?.pause(); else void ref.current?.play().catch(() => {}) }}>{playing ? <RiPauseFill size={18} aria-hidden /> : <RiPlayFill size={18} aria-hidden />}</Button></div>\n}\nexport interface ActionBandProps { title: ReactNode; description?: ReactNode; actions?: ReactNode; eyebrow?: ReactNode }\n/** A terminal project invitation with one strong entry action and quieter supporting actions. */\nexport function ActionBand({ title, description, actions, eyebrow }: ActionBandProps) { return <section className=\"folio-action-band\">{eyebrow && <span className=\"folio-action-band__eyebrow\">{eyebrow}</span>}<div className=\"folio-action-band__copy\"><h2>{title}</h2>{description && <p>{description}</p>}</div>{actions && <div className=\"folio-action-band__actions\">{actions}</div>}</section> }\nexport interface FeaturePairsProps { items: { id?: string; label?: ReactNode; title?: ReactNode; description: ReactNode }[] }\nexport function FeaturePairs({ items }: FeaturePairsProps) { return <div className=\"folio-feature-pairs\">{items.map((item, index) => <div key={item.id ?? index}>{item.label && <span>{item.label}</span>}{item.title && <h3>{item.title}</h3>}<div className=\"folio-feature-description\">{item.description}</div></div>)}</div> }\nexport interface DevicePreviewProps { kind: 'browser' | 'phone'; label?: string; media: ReactNode; caption?: ReactNode }\nexport function DevicePreview({ kind, label, media, caption }: DevicePreviewProps) { return <figure className=\"folio-device-preview\" data-kind={kind}><div>{kind === 'browser' && <div className=\"folio-browser-bar\"><span aria-hidden>● ● ●</span><span>{label}</span></div>}<div className=\"folio-device-screen\">{media}</div></div>{caption && <figcaption>{caption}</figcaption>}</figure> }\nexport interface PreviewPairProps { desktop: ReactNode; mobile?: ReactNode }\nexport function PreviewPair({ desktop, mobile }: PreviewPairProps) { return <div className=\"folio-preview-pair\" data-mobile={Boolean(mobile) || undefined}>{desktop}{mobile}</div> }\nexport interface CommandTab { id: string; name: string; commands: string[]; then?: ReactNode; note?: ReactNode; link?: ReactNode }\nexport interface CommandTabsProps { label: string; tabs: CommandTab[]; copyLabel: string; copiedLabel: string; footer?: ReactNode }\nexport function CommandTabs({ label, tabs, copyLabel, copiedLabel, footer }: CommandTabsProps) {\n const first = tabs[0]\n if (!first) return null\n return <div className=\"folio-command-tabs\"><Tabs defaultValue={first.id}><TabsList aria-label={label}>{tabs.map((tab) => <TabsTrigger value={tab.id} key={tab.id}>{tab.name}</TabsTrigger>)}</TabsList>{tabs.map((tab) => <TabsContent value={tab.id} key={tab.id}>{tab.commands.map((command) => <CodeBlock key={command} code={command} copyLabel={copyLabel} copiedLabel={copiedLabel} />)}{tab.then && <p>{tab.then}</p>}{tab.note && <p>{tab.note}</p>}{tab.link}</TabsContent>)}</Tabs>{footer && <div className=\"folio-command-footer\">{footer}</div>}</div>\n}\nexport interface ReadingSurfaceProps extends HTMLAttributes<HTMLDivElement> { numbered?: boolean }\nexport function ReadingSurface({ numbered, children, className, ...rest }: ReadingSurfaceProps) { return <div className={cn('folio-reading-surface', className)} data-folio-article data-numbered={numbered || undefined} {...rest}>{children}</div> }\nexport interface ReadingFormProps extends React.FormHTMLAttributes<HTMLFormElement> { inline?: boolean }\nexport function ReadingForm({ inline, className, ...props }: ReadingFormProps) { return <form className={cn('folio-reading-form', className)} data-inline={inline || undefined} {...props} /> }\nexport interface ArchitectureColumnNode { id: string; title: string; description?: string }\nexport interface ArchitectureColumnsProps { columns: { title: string; connected?: boolean; nodes: ArchitectureColumnNode[] }[]; foundation?: ArchitectureColumnNode[] }\nexport function ArchitectureColumns({ columns, foundation }: ArchitectureColumnsProps) {\n return <div className=\"folio-architecture-columns\"><div>{columns.map((column, index) => <div key={index} data-connected={Boolean(foundation?.length && column.connected) || undefined}><h3>{column.title}</h3>{column.nodes.map((node) => <div className=\"folio-architecture-node\" key={node.id}><strong>{node.title}</strong>{node.description && <span>{node.description}</span>}</div>)}</div>)}</div>{foundation && foundation.length > 0 && <div className=\"folio-architecture-foundation\">{foundation.map((node) => <div key={node.id}><strong>{node.title}</strong>{node.description && <span>{node.description}</span>}</div>)}</div>}</div>\n}\nexport interface TokenLineProps { items: { label: ReactNode; strong?: boolean; icon?: ReactNode }[]; label?: ReactNode; separator?: string }\nexport function TokenLine({ items, label, separator = '·' }: TokenLineProps) {\n return <div className=\"folio-token-line\" data-flow={separator !== '·' || undefined}>\n {label && <span>{label}</span>}\n <ul role=\"list\" aria-label={typeof label === 'string' ? label : undefined}>\n {items.map((item, index) => <li key={index}>\n {index > 0 && <span aria-hidden className=\"folio-token-separator\">{separator}</span>}\n {item.icon && <span className=\"folio-token-icon\" aria-hidden>{item.icon}</span>}{item.strong ? <strong>{item.label}</strong> : item.label}\n </li>)}\n </ul>\n </div>\n}\nexport interface ContentFigureProps { children: ReactNode; caption?: ReactNode; wide?: boolean }\nexport function ContentFigure({ children, caption, wide }: ContentFigureProps) { return <figure className=\"folio-content-figure\" data-wide={wide || undefined}>{children}{caption && <figcaption>{caption}</figcaption>}</figure> }\nexport interface ReadingPageProps extends HTMLAttributes<HTMLElement> { children: ReactNode }\nexport function ReadingPage({ children, className, ...props }: ReadingPageProps) { return <section className={cn('folio-reading-page', className)} {...props}>{children}</section> }\nexport interface CommandPiece { text: string; emphasis?: 'strong' | 'normal' | 'muted' }\nexport interface CommandSnippetProps { code: string; pieces?: CommandPiece[]; copyLabel: string; copiedLabel: string; className?: string }\nexport function CommandSnippet({ code, pieces, copyLabel, copiedLabel, className }: CommandSnippetProps) {\n const escape = (value: string) => value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''')\n // Only use the highlighting when it describes the exact source being copied.\n const highlighted = pieces?.map((piece) => piece.text).join('') === code ? pieces : undefined\n const html = highlighted ? `<pre><code>${highlighted.map((piece) => `<span class=\"folio-command-${piece.emphasis ?? 'normal'}\">${escape(piece.text)}</span>`).join('')}</code></pre>` : undefined\n return <div className={cn('folio-command-snippet', className)}><CodeBlock code={code} html={html} copyLabel={copyLabel} copiedLabel={copiedLabel} /></div>\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/website/Reading/Reading.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useRef, useState, type HTMLAttributes, type ReactNode } from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { RiListUnordered, RiPlayFill, RiPauseFill } from '@remixicon/react'\nimport { Button } from '../../components/Button/Button'\nimport { StatusDot } from '../../components/StatusDot/StatusDot'\nimport { Sheet, SheetContent, SheetTrigger } from '../../components/Sheet/Sheet'\nimport { CodeBlock } from '../../components/CodeBlock/CodeBlock'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '../../components/Tabs/Tabs'\nimport { cn } from '../../lib/cn'\nimport { replaceSlotContent } from '../../lib/slot-content'\nimport type { CollectionLink } from '../Collection/Collection'\n\nexport interface ReadingMetadataItem { label: string; value: ReactNode; live?: boolean; dateTime?: string }\nexport interface DetailMastheadProps { backLink?: ReactNode; title: string; dek?: ReactNode; context?: ReactNode; aside?: ReactNode; actions?: ReactNode; metadata?: ReadingMetadataItem[]; width?: 'page' | 'fill' }\nexport function DetailMasthead({ backLink, title, dek, context, aside, actions, metadata = [], width = 'page' }: DetailMastheadProps) {\n const stacked = title.length <= 28 || typeof dek !== 'string' || dek.length > 280 || Boolean(aside)\n return <header className=\"folio-detail-masthead\" data-width={width} data-stacked={stacked || undefined} data-display={title.length <= 16 || undefined}>\n {backLink && <div className=\"folio-detail-back\">{backLink}</div>}{context && <p className=\"folio-detail-context\">{context}</p>}\n <div className=\"folio-detail-opening\" data-aside={Boolean(aside) || undefined} data-stacked={stacked || undefined}>{aside ? <div className=\"folio-detail-copy\"><h1>{title}</h1>{dek && <p className=\"folio-detail-dek\">{dek}</p>}</div> : <><h1>{title}</h1>{dek && <p className=\"folio-detail-dek\">{dek}</p>}</>}{aside && <aside>{aside}</aside>}</div>\n {(metadata.length > 0 || actions) && <div className=\"folio-detail-metabar\"><dl>{metadata.map((item) => <div key={item.label}><dt>{item.label}</dt><dd>{item.live && <StatusDot size=\"sm\" pulse={false} />}{item.dateTime ? <time dateTime={item.dateTime}>{item.value}</time> : item.value}</dd></div>)}</dl>{actions && <div className=\"folio-detail-actions\">{actions}</div>}</div>}\n </header>\n}\nexport interface ReadingLayoutProps extends HTMLAttributes<HTMLDivElement> { outline?: ReactNode }\nexport function ReadingLayout({ children, outline, className, ...rest }: ReadingLayoutProps) { return <div className={cn('folio-reading-layout', className)} {...rest}><div className=\"folio-reading-body\">{children}</div>{outline}</div> }\nexport interface ReadingSectionProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> { title?: ReactNode; caption?: ReactNode; lead?: ReactNode; compact?: boolean; seamless?: boolean }\n/** `seamless` lets a structured child continue directly from the section rule without drawing a second seam. */\nexport function ReadingSection({ title, caption, lead, compact, seamless, children, className, ...rest }: ReadingSectionProps) {\n return <section className={cn('folio-reading-section', className)} data-compact={compact || undefined} data-seamless={seamless || undefined} {...rest}>{(title || caption) && <div className=\"folio-reading-heading\"><h2>{title}</h2>{caption && <span>{caption}</span>}</div>}{lead && <p className=\"folio-reading-lead\">{lead}</p>}{children}</section>\n}\nexport interface ReadingLeadProps { children: ReactNode; muted?: ReactNode; description?: ReactNode }\nexport function ReadingLead({ children, muted, description }: ReadingLeadProps) { return <div className=\"folio-reading-lede\"><p>{children}{muted && <span> {muted}</span>}</p>{description && <p>{description}</p>}</div> }\nexport interface ReadingPagerItem { link: CollectionLink; direction: ReactNode; title: ReactNode; media?: ReactNode }\nexport interface RecordPagerProps { label: string; previous?: ReadingPagerItem; next?: ReadingPagerItem }\nexport function RecordPager({ label, previous, next }: RecordPagerProps) {\n if (!previous && !next) return null\n const cell = (item: ReadingPagerItem | undefined, direction: 'prev' | 'next') => item ? <Slot className=\"folio-record-pager-link\" data-direction={direction}>{replaceSlotContent(item.link, <>{item.media && <span className=\"folio-record-pager-media\">{item.media}</span>}<span><span className=\"folio-record-pager-direction\">{item.direction}</span>{' '}<strong>{item.title}</strong></span></>)}</Slot> : <span />\n return <nav className=\"folio-record-pager\" aria-label={label}>{cell(previous, 'prev')}{cell(next, 'next')}</nav>\n}\nexport interface OutlineItem { id: string; label: string; level: number }\nconst SELF_NUMBERED = /^\\s*\\d+[a-z]?\\s*[.)]\\s+/i\nexport function isSelfNumbered(items: OutlineItem[]): boolean {\n if (!items.length) return false\n const top = Math.min(...items.map((item) => item.level))\n const headings = items.filter((item) => item.level === top)\n return headings.length >= 2 && headings.filter((item) => SELF_NUMBERED.test(item.label)).length * 2 > headings.length\n}\nexport function numberToc(items: OutlineItem[]): string[] {\n const top = items.length ? Math.min(...items.map((item) => item.level)) : 0\n let major = 0; let minor = 0\n return items.map((item) => item.level <= top ? (minor = 0, String(++major)) : `${major}.${++minor}`)\n}\nexport interface TableOfContentsProps { items: OutlineItem[]; label: string; numbering?: 'auto' | 'none'; onNavigate?: (id: string) => void; expanded?: boolean }\nexport function TableOfContents({ items, label, numbering = 'auto', onNavigate, expanded = false }: TableOfContentsProps) {\n const [activeId, setActiveId] = useState(items[0]?.id ?? '')\n const pinnedId = useRef<string | null>(null)\n const releaseTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const numbers = numberToc(items)\n const showNumbers = numbering === 'auto' && !isSelfNumbered(items)\n const top = items.length ? Math.min(...items.map((item) => item.level)) : 0\n useEffect(() => () => clearTimeout(releaseTimer.current), [])\n useEffect(() => {\n const sections = items.map((item) => document.getElementById(item.id)).filter((item): item is HTMLElement => Boolean(item))\n const first = sections[0]\n if (!first) return\n const update = () => {\n let current = first\n for (const section of sections) if (section.getBoundingClientRect().top <= window.innerHeight * .28) current = section\n if (pinnedId.current && current.id !== pinnedId.current) return\n pinnedId.current = null\n setActiveId(current.id)\n }\n window.addEventListener('scroll', update, { passive: true }); window.addEventListener('resize', update); update()\n return () => { window.removeEventListener('scroll', update); window.removeEventListener('resize', update) }\n }, [items])\n const groups: { item: OutlineItem; index: number; subs: { item: OutlineItem; index: number }[] }[] = []\n items.forEach((item, index) => { const last = groups.at(-1); if (item.level <= top || !last) groups.push({ item, index, subs: [] }); else last.subs.push({ item, index }) })\n if (!items.length) return null\n const link = (item: OutlineItem, index: number, isOpen?: boolean) => <a href={`#${item.id}`} data-toc-id={item.id} aria-current={activeId === item.id ? 'true' : undefined} aria-expanded={isOpen} onClick={(event) => {\n pinnedId.current = item.id; clearTimeout(releaseTimer.current); releaseTimer.current = setTimeout(() => { pinnedId.current = null }, 1200); setActiveId(item.id)\n if (onNavigate) { event.preventDefault(); onNavigate(item.id) }\n }}>{showNumbers && <span aria-hidden>{numbers[index]}</span>}{item.label}</a>\n return <nav className=\"folio-toc\" aria-label={label}><div><p>{label}</p><ul>{groups.map((group) => {\n const open = expanded || group.item.id === activeId || group.subs.some(({ item }) => item.id === activeId)\n return <li key={group.item.id}>{link(group.item, group.index, group.subs.length ? open : undefined)}{group.subs.length > 0 && open && <ul>{group.subs.map(({ item, index }) => <li key={item.id}>{link(item, index)}</li>)}</ul>}</li>\n })}</ul></div></nav>\n}\nexport interface MobileOutlineProps { items: OutlineItem[]; title: string; openLabel: string; closeLabel: string }\nexport function MobileOutline({ items, title, openLabel, closeLabel }: MobileOutlineProps) {\n const [open, setOpen] = useState(false)\n if (!items.length) return null\n return <Sheet open={open} onOpenChange={setOpen}><SheetTrigger asChild><Button variant=\"secondary\" iconOnly aria-label={openLabel} className=\"folio-outline-trigger\"><RiListUnordered size={18} aria-hidden=\"true\" /></Button></SheetTrigger><SheetContent title={title} closeLabel={closeLabel} side=\"bottom\" className=\"folio-outline-sheet\" aria-describedby={undefined}><TableOfContents items={items} label={title} expanded onNavigate={(id) => {\n setOpen(false)\n requestAnimationFrame(() => { const target = document.getElementById(id); if (target) { target.scrollIntoView({ behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth', block: 'start' }); window.history.replaceState(null, '', `#${id}`) } })\n }} /></SheetContent></Sheet>\n}\nexport function ReadingProgress() {\n const [progress, setProgress] = useState(0)\n useEffect(() => {\n const update = () => { const doc = document.documentElement; const max = doc.scrollHeight - doc.clientHeight; setProgress(max > 0 ? Math.min(100, Math.max(0, doc.scrollTop / max * 100)) : 0) }\n update(); window.addEventListener('scroll', update, { passive: true }); window.addEventListener('resize', update)\n return () => { window.removeEventListener('scroll', update); window.removeEventListener('resize', update) }\n }, [])\n return <div className=\"folio-reading-progress\" aria-hidden><div style={{ width: `${progress}%` }} /></div>\n}\nexport interface AuthorPanelProps { avatar?: ReactNode; name: string; role?: ReactNode; bio?: ReactNode; links?: ReactNode }\nexport function AuthorPanel({ avatar, name, role, bio, links }: AuthorPanelProps) { return <aside className=\"folio-author-panel\">{avatar && <div className=\"folio-author-avatar\" aria-hidden>{avatar}</div>}<div><h2>{name}</h2>{role && <div className=\"folio-author-role\">{role}</div>}{bio && <p>{bio}</p>}{links && <div className=\"folio-author-links\">{links}</div>}</div></aside> }\nexport interface ReadingFigureProps { media: ReactNode; captionStart?: ReactNode; captionEnd?: ReactNode; width?: 'page' | 'fill'; ratio?: string; fit?: 'cover' | 'contain' }\n/** A reading image can preserve its source framing with `fit=\"contain\"`, rather than silently cropping it to a house ratio. */\nexport function ReadingFigure({ media, captionStart, captionEnd, width = 'page', ratio = '16 / 8', fit = 'cover' }: ReadingFigureProps) { return <figure className=\"folio-reading-figure\" data-width={width} data-fit={fit}><div style={{ aspectRatio: ratio }}>{media}</div>{(captionStart || captionEnd) && <figcaption><span>{captionStart}</span><span>{captionEnd}</span></figcaption>}</figure> }\nexport interface MediaPlaybackProps { src: string; poster?: string; label: string; playLabel: string; pauseLabel: string; fallback: ReactNode }\nexport function MediaPlayback({ src, poster, label, playLabel, pauseLabel, fallback }: MediaPlaybackProps) {\n const [reduceMotion, setReduceMotion] = useState(true)\n const [playing, setPlaying] = useState(false)\n const ref = useRef<HTMLVideoElement>(null)\n useEffect(() => { if (typeof window.matchMedia !== 'function') return; const query = window.matchMedia('(prefers-reduced-motion: reduce)'); const update = () => setReduceMotion(query.matches); update(); query.addEventListener('change', update); return () => query.removeEventListener('change', update) }, [])\n if (reduceMotion) return fallback\n return <div className=\"folio-media-playback\"><video ref={ref} src={src} poster={poster} aria-label={label} autoPlay muted loop playsInline preload=\"metadata\" onPlay={() => setPlaying(true)} onPause={() => setPlaying(false)} /><Button type=\"button\" variant=\"secondary\" iconOnly aria-label={playing ? pauseLabel : playLabel} onClick={() => { if (playing) ref.current?.pause(); else void ref.current?.play().catch(() => {}) }}>{playing ? <RiPauseFill size={18} aria-hidden /> : <RiPlayFill size={18} aria-hidden />}</Button></div>\n}\nexport interface ActionBandProps { title: ReactNode; description?: ReactNode; actions?: ReactNode; eyebrow?: ReactNode }\n/** A terminal project invitation with one strong entry action and quieter supporting actions. */\nexport function ActionBand({ title, description, actions, eyebrow }: ActionBandProps) { return <section className=\"folio-action-band\">{eyebrow && <span className=\"folio-action-band__eyebrow\">{eyebrow}</span>}<div className=\"folio-action-band__copy\"><h2>{title}</h2>{description && <p>{description}</p>}</div>{actions && <div className=\"folio-action-band__actions\">{actions}</div>}</section> }\nexport interface FeaturePairsProps { items: { id?: string; label?: ReactNode; title?: ReactNode; description: ReactNode }[] }\nexport function FeaturePairs({ items }: FeaturePairsProps) { return <div className=\"folio-feature-pairs\">{items.map((item, index) => <div key={item.id ?? index}>{item.label && <span>{item.label}</span>}{item.title && <h3>{item.title}</h3>}<div className=\"folio-feature-description\">{item.description}</div></div>)}</div> }\nexport interface DevicePreviewProps { kind: 'browser' | 'phone'; label?: string; media: ReactNode; caption?: ReactNode }\nexport function DevicePreview({ kind, label, media, caption }: DevicePreviewProps) { return <figure className=\"folio-device-preview\" data-kind={kind}><div>{kind === 'browser' && <div className=\"folio-browser-bar\"><span aria-hidden>● ● ●</span><span>{label}</span></div>}<div className=\"folio-device-screen\">{media}</div></div>{caption && <figcaption>{caption}</figcaption>}</figure> }\nexport interface PreviewPairProps { desktop: ReactNode; mobile?: ReactNode }\nexport interface DeviceRowProps { children: ReactNode; label?: string }\n/** Two or three phones side by side, the middle one raised a step, wrapping to a column on a narrow screen. */\nexport function DeviceRow({ children, label }: DeviceRowProps) { return <div className=\"folio-device-row\" role={label ? 'group' : undefined} aria-label={label}>{children}</div> }\nexport function PreviewPair({ desktop, mobile }: PreviewPairProps) { return <div className=\"folio-preview-pair\" data-mobile={Boolean(mobile) || undefined}>{desktop}{mobile}</div> }\nexport interface CommandTab { id: string; name: string; commands: string[]; then?: ReactNode; note?: ReactNode; link?: ReactNode }\nexport interface CommandTabsProps { label: string; tabs: CommandTab[]; copyLabel: string; copiedLabel: string; footer?: ReactNode }\nexport function CommandTabs({ label, tabs, copyLabel, copiedLabel, footer }: CommandTabsProps) {\n const first = tabs[0]\n if (!first) return null\n return <div className=\"folio-command-tabs\"><Tabs defaultValue={first.id}><TabsList aria-label={label}>{tabs.map((tab) => <TabsTrigger value={tab.id} key={tab.id}>{tab.name}</TabsTrigger>)}</TabsList>{tabs.map((tab) => <TabsContent value={tab.id} key={tab.id}>{tab.commands.map((command) => <CodeBlock key={command} code={command} copyLabel={copyLabel} copiedLabel={copiedLabel} />)}{tab.then && <p>{tab.then}</p>}{tab.note && <p>{tab.note}</p>}{tab.link}</TabsContent>)}</Tabs>{footer && <div className=\"folio-command-footer\">{footer}</div>}</div>\n}\nexport interface ReadingSurfaceProps extends HTMLAttributes<HTMLDivElement> { numbered?: boolean }\nexport function ReadingSurface({ numbered, children, className, ...rest }: ReadingSurfaceProps) { return <div className={cn('folio-reading-surface', className)} data-folio-article data-numbered={numbered || undefined} {...rest}>{children}</div> }\nexport interface ReadingFormProps extends React.FormHTMLAttributes<HTMLFormElement> { inline?: boolean }\nexport function ReadingForm({ inline, className, ...props }: ReadingFormProps) { return <form className={cn('folio-reading-form', className)} data-inline={inline || undefined} {...props} /> }\nexport interface ArchitectureColumnNode { id: string; title: string; description?: string }\nexport interface ArchitectureColumnsProps { columns: { title: string; connected?: boolean; nodes: ArchitectureColumnNode[] }[]; foundation?: ArchitectureColumnNode[] }\nexport function ArchitectureColumns({ columns, foundation }: ArchitectureColumnsProps) {\n return <div className=\"folio-architecture-columns\"><div>{columns.map((column, index) => <div key={index} data-connected={Boolean(foundation?.length && column.connected) || undefined}><h3>{column.title}</h3>{column.nodes.map((node) => <div className=\"folio-architecture-node\" key={node.id}><strong>{node.title}</strong>{node.description && <span>{node.description}</span>}</div>)}</div>)}</div>{foundation && foundation.length > 0 && <div className=\"folio-architecture-foundation\">{foundation.map((node) => <div key={node.id}><strong>{node.title}</strong>{node.description && <span>{node.description}</span>}</div>)}</div>}</div>\n}\nexport interface TokenLineProps { items: { label: ReactNode; strong?: boolean; icon?: ReactNode }[]; label?: ReactNode; separator?: string }\nexport function TokenLine({ items, label, separator = '·' }: TokenLineProps) {\n return <div className=\"folio-token-line\" data-flow={separator !== '·' || undefined}>\n {label && <span>{label}</span>}\n <ul role=\"list\" aria-label={typeof label === 'string' ? label : undefined}>\n {items.map((item, index) => <li key={index}>\n {index > 0 && <span aria-hidden className=\"folio-token-separator\">{separator}</span>}\n {item.icon && <span className=\"folio-token-icon\" aria-hidden>{item.icon}</span>}{item.strong ? <strong>{item.label}</strong> : item.label}\n </li>)}\n </ul>\n </div>\n}\nexport interface ContentFigureProps { children: ReactNode; caption?: ReactNode; wide?: boolean }\nexport function ContentFigure({ children, caption, wide }: ContentFigureProps) { return <figure className=\"folio-content-figure\" data-wide={wide || undefined}>{children}{caption && <figcaption>{caption}</figcaption>}</figure> }\nexport interface ReadingPageProps extends HTMLAttributes<HTMLElement> { children: ReactNode }\nexport function ReadingPage({ children, className, ...props }: ReadingPageProps) { return <section className={cn('folio-reading-page', className)} {...props}>{children}</section> }\nexport interface CommandPiece { text: string; emphasis?: 'strong' | 'normal' | 'muted' }\nexport interface CommandSnippetProps { code: string; pieces?: CommandPiece[]; copyLabel: string; copiedLabel: string; className?: string }\nexport function CommandSnippet({ code, pieces, copyLabel, copiedLabel, className }: CommandSnippetProps) {\n const escape = (value: string) => value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''')\n // Only use the highlighting when it describes the exact source being copied.\n const highlighted = pieces?.map((piece) => piece.text).join('') === code ? pieces : undefined\n const html = highlighted ? `<pre><code>${highlighted.map((piece) => `<span class=\"folio-command-${piece.emphasis ?? 'normal'}\">${escape(piece.text)}</span>`).join('')}</code></pre>` : undefined\n return <div className={cn('folio-command-snippet', className)}><CodeBlock code={code} html={html} copyLabel={copyLabel} copiedLabel={copiedLabel} /></div>\n}\n"],"mappings":"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","names":[]}
|
|
@@ -30,10 +30,18 @@ interface LoadingRecordsProps {
|
|
|
30
30
|
declare function LoadingRecords({ rows, media }: LoadingRecordsProps): react.JSX.Element;
|
|
31
31
|
interface WebsiteLoadingProps extends LoadingRecordsProps, LoadingRouteIntroProps {
|
|
32
32
|
label: string;
|
|
33
|
-
layout?: 'records' | 'gallery' | 'media' | 'metrics' | 'identity';
|
|
33
|
+
layout?: 'records' | 'gallery' | 'media' | 'metrics' | 'identity' | 'article' | 'photograph';
|
|
34
34
|
filters?: boolean;
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Named loading layouts for the website's reusable page shapes.
|
|
38
|
+
*
|
|
39
|
+
* Every layout waits a beat before it shows and then fades in, so a route that
|
|
40
|
+
* resolves within that beat goes straight from the old page to the new one
|
|
41
|
+
* instead of flashing grey bars for a frame. A detail route needs its own
|
|
42
|
+
* `article` or `photograph` shape: inheriting the list skeleton above it
|
|
43
|
+
* promises a layout the page then abandons.
|
|
44
|
+
*/
|
|
37
45
|
declare function WebsiteLoading({ label, layout, titleClassName, rows, media, filters }: WebsiteLoadingProps): react.JSX.Element;
|
|
38
46
|
|
|
39
47
|
export { LoadingRecords, type LoadingRecordsProps, LoadingRouteIntro, type LoadingRouteIntroProps, RecoveryLinks, type RecoveryLinksProps, RecoveryState, type RecoveryStateProps, WebsiteLoading, type WebsiteLoadingProps };
|
|
@@ -39,8 +39,42 @@ function LoadingRecords({ rows = 4, media = true }) {
|
|
|
39
39
|
] })
|
|
40
40
|
] }, index)) });
|
|
41
41
|
}
|
|
42
|
+
function LoadingArticle({ media }) {
|
|
43
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
44
|
+
/* @__PURE__ */ jsxs("header", { className: "folio-detail-masthead folio-loading-article", "data-loading-content": true, children: [
|
|
45
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "h-2.5 w-20" }),
|
|
46
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "mt-8 h-[clamp(2.5rem,5vw,4rem)] w-[min(100%,36rem)]" }),
|
|
47
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-6 h-3.5 w-[min(100%,40rem)]" }),
|
|
48
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-2.5 h-3.5 w-[min(100%,30rem)]" }),
|
|
49
|
+
/* @__PURE__ */ jsx("div", { className: "mt-10 flex flex-wrap gap-8", children: [0, 1, 2].map((cell) => /* @__PURE__ */ jsx(SkeletonLine, { className: "h-2.5 w-20" }, cell)) })
|
|
50
|
+
] }),
|
|
51
|
+
media && /* @__PURE__ */ jsx("div", { className: "folio-reading-figure", "data-loading-content": true, children: /* @__PURE__ */ jsx(SkeletonBlock, { className: "aspect-[16/9] w-full" }) }),
|
|
52
|
+
/* @__PURE__ */ jsx("div", { className: "folio-reading-layout", "data-loading-content": true, children: /* @__PURE__ */ jsx("div", { className: "folio-reading-body", children: ["w-full", "w-11/12", "w-full", "w-4/5", "w-full", "w-2/3"].map((width, index) => /* @__PURE__ */ jsx(SkeletonLine, { className: cn("mt-3.5 h-3.5", width) }, index)) }) })
|
|
53
|
+
] });
|
|
54
|
+
}
|
|
55
|
+
function LoadingPhotograph() {
|
|
56
|
+
return /* @__PURE__ */ jsx("div", { className: "folio-media-detail-page", children: /* @__PURE__ */ jsxs("div", { className: "folio-media-detail", "data-loading-content": true, children: [
|
|
57
|
+
/* @__PURE__ */ jsxs("header", { className: "folio-media-index-bar", children: [
|
|
58
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "h-3 w-24" }),
|
|
59
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "h-2.5 w-12" })
|
|
60
|
+
] }),
|
|
61
|
+
/* @__PURE__ */ jsxs("div", { className: "folio-media-spread", "data-photo-spread": "wide", children: [
|
|
62
|
+
/* @__PURE__ */ jsx("div", { className: "folio-media-well", children: /* @__PURE__ */ jsx(SkeletonBlock, { className: "aspect-[3/2] w-full" }) }),
|
|
63
|
+
/* @__PURE__ */ jsxs("div", { className: "folio-media-ledger", children: [
|
|
64
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
65
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "h-2.5 w-24" }),
|
|
66
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "mt-5 h-10 w-4/5" }),
|
|
67
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-6 h-3 w-full" }),
|
|
68
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-2.5 h-3 w-3/4" })
|
|
69
|
+
] }),
|
|
70
|
+
/* @__PURE__ */ jsx("div", { className: "mt-10", children: [0, 1, 2, 3].map((row) => /* @__PURE__ */ jsx(SkeletonLine, { className: "mt-3 h-2.5 w-2/3" }, row)) })
|
|
71
|
+
] })
|
|
72
|
+
] })
|
|
73
|
+
] }) });
|
|
74
|
+
}
|
|
42
75
|
function WebsiteLoading({ label, layout = "records", titleClassName, rows = 4, media = true, filters = false }) {
|
|
43
|
-
return /* @__PURE__ */
|
|
76
|
+
if (layout === "article" || layout === "photograph") return /* @__PURE__ */ jsx("div", { className: "folio-loading-page", children: /* @__PURE__ */ jsx(SkeletonPage, { label, children: layout === "article" ? /* @__PURE__ */ jsx(LoadingArticle, { media }) : /* @__PURE__ */ jsx(LoadingPhotograph, {}) }) });
|
|
77
|
+
return /* @__PURE__ */ jsx("div", { className: "folio-loading-page", children: /* @__PURE__ */ jsxs(SkeletonPage, { label, children: [
|
|
44
78
|
layout === "identity" ? /* @__PURE__ */ jsxs("header", { className: "folio-loading-identity folio-loading-container", children: [
|
|
45
79
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
46
80
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-5", children: [
|
|
@@ -84,7 +118,7 @@ function WebsiteLoading({ label, layout = "records", titleClassName, rows = 4, m
|
|
|
84
118
|
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-16 h-3 w-28" }),
|
|
85
119
|
/* @__PURE__ */ jsx(SkeletonBlock, { className: "mt-6 h-[220px] w-full" })
|
|
86
120
|
] })
|
|
87
|
-
] });
|
|
121
|
+
] }) });
|
|
88
122
|
}
|
|
89
123
|
export {
|
|
90
124
|
LoadingRecords,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/website/Recovery/Recovery.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from 'react'\nimport { Button } from '../../components/Button/Button'\nimport { ErrorState, type ErrorStateProps } from '../../components/ErrorState/ErrorState'\nimport { Heading } from '../../components/Heading/Heading'\nimport { SkeletonBlock, SkeletonCircle, SkeletonLine, SkeletonPage } from '../../components/Skeleton/Skeleton'\nimport { cn } from '../../lib/cn'\n\nexport interface RecoveryStateProps extends ErrorStateProps {\n elsewhere?: ReactNode\n}\n\n/** A recovery page composed from the system error primitive and caller-owned destinations. */\nexport function RecoveryState({ action, elsewhere, ...props }: RecoveryStateProps) {\n return <ErrorState {...props} action={<><div className=\"folio-recovery-actions\">{action}</div>{elsewhere}</>} />\n}\n\nexport interface RecoveryLinksProps {\n label: string\n items: { id: string; link: ReactElement }[]\n}\n\n/** Suggested destinations, with routing supplied by the host. */\nexport function RecoveryLinks({ label, items }: RecoveryLinksProps) {\n return <nav aria-label={label} className=\"folio-recovery-links\"><Heading level={2} size=\"label\">{label}</Heading><ul>{items.map((item) => <li key={item.id}><Button asChild variant=\"ghost\" className=\"min-h-11 w-full justify-start\">{item.link}</Button></li>)}</ul></nav>\n}\n\nexport interface LoadingRouteIntroProps {\n titleClassName?: string\n}\n\n/** The shared masthead geometry, drawn from the core loading primitives. */\nexport function LoadingRouteIntro({ titleClassName = 'w-[min(100%,18rem)]' }: LoadingRouteIntroProps) {\n return <header className=\"folio-loading-intro folio-loading-container\"><div><SkeletonLine className=\"h-2.5 w-28\" /><SkeletonBlock className={cn('mt-6 h-[clamp(2.5rem,4.6vw,3.375rem)]', titleClassName)} /><SkeletonLine className=\"mt-7 h-3.5 w-[min(100%,34rem)]\" /><SkeletonLine className=\"mt-2.5 h-3.5 w-[min(100%,26rem)]\" /></div><SkeletonLine className=\"hidden h-2.5 w-40 justify-self-end md:block\" /></header>\n}\n\nexport interface LoadingRecordsProps {\n rows?: number\n media?: boolean\n}\n\n/** A collection skeleton with or without a media column. */\nexport function LoadingRecords({ rows = 4, media = true }: LoadingRecordsProps) {\n return <div data-loading-content className=\"folio-loading-records folio-loading-container\">{Array.from({ length: rows }, (_, index) => <div key={index} className=\"folio-loading-records__row\" data-media={media || undefined}><SkeletonLine className=\"hidden h-2.5 w-8 sm:block\" />{media && <SkeletonBlock className=\"h-[clamp(140px,20vw,154px)]\" />}<div className=\"min-w-0\"><SkeletonLine className=\"h-2.5 w-24\" /><SkeletonBlock className=\"mt-4 h-6 w-[min(100%,20rem)]\" /><SkeletonLine className=\"mt-5 h-3 w-full max-w-(--measure-record)\" /><SkeletonLine className=\"mt-2.5 h-3 w-[min(100%,26rem)]\" /></div></div>)}</div>\n}\n\nexport interface WebsiteLoadingProps extends LoadingRecordsProps, LoadingRouteIntroProps {\n label: string\n layout?: 'records' | 'gallery' | 'media' | 'metrics' | 'identity'\n filters?: boolean\n}\n\n/** Named loading layouts for the website's reusable page shapes. */\nexport function WebsiteLoading({ label, layout = 'records', titleClassName, rows = 4, media = true, filters = false }: WebsiteLoadingProps) {\n return <SkeletonPage label={label}>\n {layout === 'identity' ? <header className=\"folio-loading-identity folio-loading-container\"><div><div className=\"flex items-center gap-5\"><SkeletonCircle className=\"size-12\" /><SkeletonBlock className=\"h-12 w-64\" /></div><SkeletonLine className=\"mt-9 h-3.5 w-full\" /><SkeletonLine className=\"mt-3 h-3.5 w-4/5\" /><SkeletonLine className=\"mt-10 h-3 w-2/3\" /></div><SkeletonBlock className=\"aspect-square w-full\" /></header> : <LoadingRouteIntro titleClassName={titleClassName} />}\n {filters && <div className=\"folio-loading-filters folio-loading-container\" data-loading-content><div className=\"flex flex-wrap gap-6\">{[8, 16, 12, 20].map((width) => <SkeletonLine key={width} className=\"h-3 w-12\" />)}</div><SkeletonBlock className=\"h-11 w-56\" /></div>}\n {(layout === 'records' || layout === 'identity') && <LoadingRecords rows={rows} media={media} />}\n {layout === 'gallery' && <section data-loading-content className=\"folio-loading-gallery folio-loading-container\">{Array.from({ length: rows }, (_, index) => <div key={index}><SkeletonBlock className=\"aspect-[4/5] w-full\" /><SkeletonLine className=\"mt-3 h-3 w-3/4\" /></div>)}</section>}\n {layout === 'media' && <section data-loading-content className=\"folio-loading-media\"><div data-loading-now-playing className=\"folio-media-feature folio-loading-container\"><div className=\"folio-media-feature__artwork\"><SkeletonBlock data-loading-artwork className=\"h-full w-full\" /></div><div><SkeletonLine className=\"h-2.5 w-28\" /><SkeletonBlock className=\"mt-5 h-16 w-4/5\" /><SkeletonLine className=\"mt-5 h-3.5 w-2/3\" /><SkeletonLine className=\"mt-6 h-1 w-full\" /></div></div></section>}\n {layout === 'metrics' && <div data-loading-content className=\"folio-loading-metrics folio-loading-container\"><div className=\"folio-loading-filters\"><SkeletonLine className=\"h-2.5 w-12\" /><SkeletonBlock className=\"h-11 w-72\" /></div><div className=\"folio-loading-metrics__figures\">{[0, 1, 2, 3].map((cell) => <div key={cell}><SkeletonLine className=\"h-2.5 w-24\" /><SkeletonBlock className=\"mt-4 h-9 w-20\" /><SkeletonLine className=\"mt-4 h-2.5 w-16\" /></div>)}</div><SkeletonLine className=\"mt-16 h-3 w-28\" /><SkeletonBlock className=\"mt-6 h-[220px] w-full\" /></div>}\n </SkeletonPage>\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/website/Recovery/Recovery.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from 'react'\nimport { Button } from '../../components/Button/Button'\nimport { ErrorState, type ErrorStateProps } from '../../components/ErrorState/ErrorState'\nimport { Heading } from '../../components/Heading/Heading'\nimport { SkeletonBlock, SkeletonCircle, SkeletonLine, SkeletonPage } from '../../components/Skeleton/Skeleton'\nimport { cn } from '../../lib/cn'\n\nexport interface RecoveryStateProps extends ErrorStateProps {\n elsewhere?: ReactNode\n}\n\n/** A recovery page composed from the system error primitive and caller-owned destinations. */\nexport function RecoveryState({ action, elsewhere, ...props }: RecoveryStateProps) {\n return <ErrorState {...props} action={<><div className=\"folio-recovery-actions\">{action}</div>{elsewhere}</>} />\n}\n\nexport interface RecoveryLinksProps {\n label: string\n items: { id: string; link: ReactElement }[]\n}\n\n/** Suggested destinations, with routing supplied by the host. */\nexport function RecoveryLinks({ label, items }: RecoveryLinksProps) {\n return <nav aria-label={label} className=\"folio-recovery-links\"><Heading level={2} size=\"label\">{label}</Heading><ul>{items.map((item) => <li key={item.id}><Button asChild variant=\"ghost\" className=\"min-h-11 w-full justify-start\">{item.link}</Button></li>)}</ul></nav>\n}\n\nexport interface LoadingRouteIntroProps {\n titleClassName?: string\n}\n\n/** The shared masthead geometry, drawn from the core loading primitives. */\nexport function LoadingRouteIntro({ titleClassName = 'w-[min(100%,18rem)]' }: LoadingRouteIntroProps) {\n return <header className=\"folio-loading-intro folio-loading-container\"><div><SkeletonLine className=\"h-2.5 w-28\" /><SkeletonBlock className={cn('mt-6 h-[clamp(2.5rem,4.6vw,3.375rem)]', titleClassName)} /><SkeletonLine className=\"mt-7 h-3.5 w-[min(100%,34rem)]\" /><SkeletonLine className=\"mt-2.5 h-3.5 w-[min(100%,26rem)]\" /></div><SkeletonLine className=\"hidden h-2.5 w-40 justify-self-end md:block\" /></header>\n}\n\nexport interface LoadingRecordsProps {\n rows?: number\n media?: boolean\n}\n\n/** A collection skeleton with or without a media column. */\nexport function LoadingRecords({ rows = 4, media = true }: LoadingRecordsProps) {\n return <div data-loading-content className=\"folio-loading-records folio-loading-container\">{Array.from({ length: rows }, (_, index) => <div key={index} className=\"folio-loading-records__row\" data-media={media || undefined}><SkeletonLine className=\"hidden h-2.5 w-8 sm:block\" />{media && <SkeletonBlock className=\"h-[clamp(140px,20vw,154px)]\" />}<div className=\"min-w-0\"><SkeletonLine className=\"h-2.5 w-24\" /><SkeletonBlock className=\"mt-4 h-6 w-[min(100%,20rem)]\" /><SkeletonLine className=\"mt-5 h-3 w-full max-w-(--measure-record)\" /><SkeletonLine className=\"mt-2.5 h-3 w-[min(100%,26rem)]\" /></div></div>)}</div>\n}\n\nexport interface WebsiteLoadingProps extends LoadingRecordsProps, LoadingRouteIntroProps {\n label: string\n layout?: 'records' | 'gallery' | 'media' | 'metrics' | 'identity' | 'article' | 'photograph'\n filters?: boolean\n}\n\n/** A detail page's masthead and opening paragraphs, drawn on the reading page's own frame. */\nfunction LoadingArticle({ media }: { media: boolean }) {\n return <>\n <header className=\"folio-detail-masthead folio-loading-article\" data-loading-content><SkeletonLine className=\"h-2.5 w-20\" /><SkeletonBlock className=\"mt-8 h-[clamp(2.5rem,5vw,4rem)] w-[min(100%,36rem)]\" /><SkeletonLine className=\"mt-6 h-3.5 w-[min(100%,40rem)]\" /><SkeletonLine className=\"mt-2.5 h-3.5 w-[min(100%,30rem)]\" /><div className=\"mt-10 flex flex-wrap gap-8\">{[0, 1, 2].map((cell) => <SkeletonLine key={cell} className=\"h-2.5 w-20\" />)}</div></header>\n {media && <div className=\"folio-reading-figure\" data-loading-content><SkeletonBlock className=\"aspect-[16/9] w-full\" /></div>}\n <div className=\"folio-reading-layout\" data-loading-content><div className=\"folio-reading-body\">{['w-full', 'w-11/12', 'w-full', 'w-4/5', 'w-full', 'w-2/3'].map((width, index) => <SkeletonLine key={index} className={cn('mt-3.5 h-3.5', width)} />)}</div></div>\n </>\n}\n\n/** One photograph's spread: the back bar, the image well and its ledger, in the detail page's own grid. */\nfunction LoadingPhotograph() {\n return <div className=\"folio-media-detail-page\"><div className=\"folio-media-detail\" data-loading-content>\n <header className=\"folio-media-index-bar\"><SkeletonLine className=\"h-3 w-24\" /><SkeletonLine className=\"h-2.5 w-12\" /></header>\n <div className=\"folio-media-spread\" data-photo-spread=\"wide\"><div className=\"folio-media-well\"><SkeletonBlock className=\"aspect-[3/2] w-full\" /></div><div className=\"folio-media-ledger\"><div><SkeletonLine className=\"h-2.5 w-24\" /><SkeletonBlock className=\"mt-5 h-10 w-4/5\" /><SkeletonLine className=\"mt-6 h-3 w-full\" /><SkeletonLine className=\"mt-2.5 h-3 w-3/4\" /></div><div className=\"mt-10\">{[0, 1, 2, 3].map((row) => <SkeletonLine key={row} className=\"mt-3 h-2.5 w-2/3\" />)}</div></div></div>\n </div></div>\n}\n\n/**\n * Named loading layouts for the website's reusable page shapes.\n *\n * Every layout waits a beat before it shows and then fades in, so a route that\n * resolves within that beat goes straight from the old page to the new one\n * instead of flashing grey bars for a frame. A detail route needs its own\n * `article` or `photograph` shape: inheriting the list skeleton above it\n * promises a layout the page then abandons.\n */\nexport function WebsiteLoading({ label, layout = 'records', titleClassName, rows = 4, media = true, filters = false }: WebsiteLoadingProps) {\n if (layout === 'article' || layout === 'photograph') return <div className=\"folio-loading-page\"><SkeletonPage label={label}>{layout === 'article' ? <LoadingArticle media={media} /> : <LoadingPhotograph />}</SkeletonPage></div>\n return <div className=\"folio-loading-page\"><SkeletonPage label={label}>\n {layout === 'identity' ? <header className=\"folio-loading-identity folio-loading-container\"><div><div className=\"flex items-center gap-5\"><SkeletonCircle className=\"size-12\" /><SkeletonBlock className=\"h-12 w-64\" /></div><SkeletonLine className=\"mt-9 h-3.5 w-full\" /><SkeletonLine className=\"mt-3 h-3.5 w-4/5\" /><SkeletonLine className=\"mt-10 h-3 w-2/3\" /></div><SkeletonBlock className=\"aspect-square w-full\" /></header> : <LoadingRouteIntro titleClassName={titleClassName} />}\n {filters && <div className=\"folio-loading-filters folio-loading-container\" data-loading-content><div className=\"flex flex-wrap gap-6\">{[8, 16, 12, 20].map((width) => <SkeletonLine key={width} className=\"h-3 w-12\" />)}</div><SkeletonBlock className=\"h-11 w-56\" /></div>}\n {(layout === 'records' || layout === 'identity') && <LoadingRecords rows={rows} media={media} />}\n {layout === 'gallery' && <section data-loading-content className=\"folio-loading-gallery folio-loading-container\">{Array.from({ length: rows }, (_, index) => <div key={index}><SkeletonBlock className=\"aspect-[4/5] w-full\" /><SkeletonLine className=\"mt-3 h-3 w-3/4\" /></div>)}</section>}\n {layout === 'media' && <section data-loading-content className=\"folio-loading-media\"><div data-loading-now-playing className=\"folio-media-feature folio-loading-container\"><div className=\"folio-media-feature__artwork\"><SkeletonBlock data-loading-artwork className=\"h-full w-full\" /></div><div><SkeletonLine className=\"h-2.5 w-28\" /><SkeletonBlock className=\"mt-5 h-16 w-4/5\" /><SkeletonLine className=\"mt-5 h-3.5 w-2/3\" /><SkeletonLine className=\"mt-6 h-1 w-full\" /></div></div></section>}\n {layout === 'metrics' && <div data-loading-content className=\"folio-loading-metrics folio-loading-container\"><div className=\"folio-loading-filters\"><SkeletonLine className=\"h-2.5 w-12\" /><SkeletonBlock className=\"h-11 w-72\" /></div><div className=\"folio-loading-metrics__figures\">{[0, 1, 2, 3].map((cell) => <div key={cell}><SkeletonLine className=\"h-2.5 w-24\" /><SkeletonBlock className=\"mt-4 h-9 w-20\" /><SkeletonLine className=\"mt-4 h-2.5 w-16\" /></div>)}</div><SkeletonLine className=\"mt-16 h-3 w-28\" /><SkeletonBlock className=\"mt-6 h-[220px] w-full\" /></div>}\n </SkeletonPage></div>\n}\n"],"mappings":"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","names":[]}
|
|
@@ -6,6 +6,7 @@ import { Badge } from "../../components/Badge/Badge.js";
|
|
|
6
6
|
import { Button } from "../../components/Button/Button.js";
|
|
7
7
|
import { CommandDialog, CommandEmpty, CommandFooter, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList } from "../../components/Command/Command.js";
|
|
8
8
|
import { Input } from "../../components/Input/Input.js";
|
|
9
|
+
const PANEL = "folio-search-palette top-[max(4rem,15svh)] w-[min(94vw,40rem)] data-[state=open]:animate-[folio-palette-in_var(--duration-base)_var(--ease)] data-[state=closed]:animate-[folio-palette-out_var(--duration-fast)_var(--ease)]";
|
|
9
10
|
function SearchPalette({
|
|
10
11
|
open,
|
|
11
12
|
onOpenChange,
|
|
@@ -37,6 +38,7 @@ function SearchPalette({
|
|
|
37
38
|
label,
|
|
38
39
|
inputLabel,
|
|
39
40
|
shouldFilter: false,
|
|
41
|
+
className: PANEL,
|
|
40
42
|
onOpenAutoFocus: () => {
|
|
41
43
|
previousFocus.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
42
44
|
},
|