@misoto22/folio 0.18.0 → 0.19.1
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 +1 -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 +1 -1
- package/dist/agent/Recovery.md +4 -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 +5 -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 +1 -1
- 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 +2 -1
- package/dist/agent/index.md +1 -1
- package/dist/components/Spinner/Spinner.d.ts +7 -1
- package/dist/components/Spinner/Spinner.js +5 -2
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/semantic.css +1 -0
- package/dist/styles.css +1 -1
- package/dist/tokens.css +3 -0
- package/dist/tokens.d.ts +2 -0
- package/dist/tokens.js +11 -0
- package/dist/tokens.json +11 -0
- package/dist/website/Media/Media.js +2 -2
- package/dist/website/Media/Media.js.map +1 -1
- package/dist/website/Recovery/Recovery.d.ts +14 -7
- package/dist/website/Recovery/Recovery.js +59 -44
- package/dist/website/Recovery/Recovery.js.map +1 -1
- package/dist/website-actions.css +1 -1
- package/dist/website-media.css +13 -8
- package/dist/website-recovery.css +13 -6
- package/package.json +1 -1
package/dist/tokens.d.ts
CHANGED
|
@@ -84,6 +84,7 @@ export type TokenName =
|
|
|
84
84
|
| 'duration-base'
|
|
85
85
|
| 'duration-fast'
|
|
86
86
|
| 'duration-slow'
|
|
87
|
+
| 'duration-wait'
|
|
87
88
|
| 'ease'
|
|
88
89
|
| 'ease-out-expo'
|
|
89
90
|
| 'fast'
|
|
@@ -194,6 +195,7 @@ export type TokenName =
|
|
|
194
195
|
| 'table-pad-y'
|
|
195
196
|
| 'w-page'
|
|
196
197
|
| 'w-reading'
|
|
198
|
+
| 'wait'
|
|
197
199
|
| 'warn'
|
|
198
200
|
| 'warn-soft'
|
|
199
201
|
| 'warning'
|
package/dist/tokens.js
CHANGED
|
@@ -593,6 +593,12 @@ export const TOKENS = {
|
|
|
593
593
|
"category": "motion",
|
|
594
594
|
"light": "0.34s"
|
|
595
595
|
},
|
|
596
|
+
"wait": {
|
|
597
|
+
"layer": "tokens",
|
|
598
|
+
"category": "other",
|
|
599
|
+
"light": "0.3s",
|
|
600
|
+
"comment": "How long a page waits before it admits it is loading. Under this, a skeleton would only flash; over it, the reader needs to see something."
|
|
601
|
+
},
|
|
596
602
|
"z-rule": {
|
|
597
603
|
"layer": "tokens",
|
|
598
604
|
"category": "layer",
|
|
@@ -955,6 +961,11 @@ export const TOKENS = {
|
|
|
955
961
|
"category": "motion",
|
|
956
962
|
"light": "var(--slow)"
|
|
957
963
|
},
|
|
964
|
+
"duration-wait": {
|
|
965
|
+
"layer": "semantic",
|
|
966
|
+
"category": "motion",
|
|
967
|
+
"light": "var(--wait)"
|
|
968
|
+
},
|
|
958
969
|
"overlay": {
|
|
959
970
|
"layer": "semantic",
|
|
960
971
|
"category": "colour",
|
package/dist/tokens.json
CHANGED
|
@@ -592,6 +592,12 @@
|
|
|
592
592
|
"category": "motion",
|
|
593
593
|
"light": "0.34s"
|
|
594
594
|
},
|
|
595
|
+
"wait": {
|
|
596
|
+
"layer": "tokens",
|
|
597
|
+
"category": "other",
|
|
598
|
+
"light": "0.3s",
|
|
599
|
+
"comment": "How long a page waits before it admits it is loading. Under this, a skeleton would only flash; over it, the reader needs to see something."
|
|
600
|
+
},
|
|
595
601
|
"z-rule": {
|
|
596
602
|
"layer": "tokens",
|
|
597
603
|
"category": "layer",
|
|
@@ -954,6 +960,11 @@
|
|
|
954
960
|
"category": "motion",
|
|
955
961
|
"light": "var(--slow)"
|
|
956
962
|
},
|
|
963
|
+
"duration-wait": {
|
|
964
|
+
"layer": "semantic",
|
|
965
|
+
"category": "motion",
|
|
966
|
+
"light": "var(--wait)"
|
|
967
|
+
},
|
|
957
968
|
"overlay": {
|
|
958
969
|
"layer": "semantic",
|
|
959
970
|
"category": "colour",
|
|
@@ -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__ */ jsx("div", { className: "folio-loading-page", children: /* @__PURE__ */ jsxs(SkeletonPage, { label, "aria-label": label, children: [
|
|
55
|
+
return /* @__PURE__ */ jsx("div", { className: "folio-loading-page", children: /* @__PURE__ */ jsx("div", { className: "folio-loading-data", 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 <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":[]}
|
|
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 <div className=\"folio-loading-data\"><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></div>\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":[]}
|
|
@@ -30,18 +30,25 @@ 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' | 'article' | 'photograph';
|
|
33
|
+
layout?: 'records' | 'gallery' | 'media' | 'metrics' | 'identity' | 'article' | 'photograph' | 'cards';
|
|
34
|
+
/**
|
|
35
|
+
* The route's real opening — its title and description — rendered at once,
|
|
36
|
+
* in place of the skeleton masthead. A route's own words never wait on its
|
|
37
|
+
* data, so drawing grey bars where they will be is a promise of nothing.
|
|
38
|
+
*/
|
|
39
|
+
intro?: ReactNode;
|
|
34
40
|
filters?: boolean;
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
37
43
|
* Named loading layouts for the website's reusable page shapes.
|
|
38
44
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
45
|
+
* Static parts at once, data after a wait: an `intro` renders immediately and
|
|
46
|
+
* for real, and the skeleton for the data waits `--duration-wait` before it
|
|
47
|
+
* fades in, so a route that resolves inside the wait goes straight from the
|
|
48
|
+
* old page to the new one. Every shape is the real one's — a detail route
|
|
49
|
+
* needs `article` or `photograph`, a card grid needs `cards` — because a
|
|
50
|
+
* skeleton the page then abandons is the jump it exists to prevent.
|
|
44
51
|
*/
|
|
45
|
-
declare function WebsiteLoading({ label, layout, titleClassName, rows, media, filters }: WebsiteLoadingProps): react.JSX.Element;
|
|
52
|
+
declare function WebsiteLoading({ label, layout, titleClassName, rows, media, filters, intro }: WebsiteLoadingProps): react.JSX.Element;
|
|
46
53
|
|
|
47
54
|
export { LoadingRecords, type LoadingRecordsProps, LoadingRouteIntro, type LoadingRouteIntroProps, RecoveryLinks, type RecoveryLinksProps, RecoveryState, type RecoveryStateProps, WebsiteLoading, type WebsiteLoadingProps };
|
|
@@ -72,53 +72,68 @@ function LoadingPhotograph() {
|
|
|
72
72
|
] })
|
|
73
73
|
] }) });
|
|
74
74
|
}
|
|
75
|
-
function WebsiteLoading({ label, layout = "records", titleClassName, rows = 4, media = true, filters = false }) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
layout === "
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
] }),
|
|
84
|
-
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-9 h-3.5 w-full" }),
|
|
85
|
-
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-3 h-3.5 w-4/5" }),
|
|
86
|
-
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-10 h-3 w-2/3" })
|
|
75
|
+
function WebsiteLoading({ label, layout = "records", titleClassName, rows = 4, media = true, filters = false, intro }) {
|
|
76
|
+
return /* @__PURE__ */ jsxs("div", { className: "folio-loading-page", children: [
|
|
77
|
+
intro,
|
|
78
|
+
/* @__PURE__ */ jsx("div", { className: "folio-loading-data", children: /* @__PURE__ */ jsx(SkeletonPage, { label, children: layout === "article" ? /* @__PURE__ */ jsx(LoadingArticle, { media }) : layout === "photograph" ? /* @__PURE__ */ jsx(LoadingPhotograph, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
79
|
+
!intro && (layout === "identity" ? /* @__PURE__ */ jsx(LoadingIdentity, {}) : /* @__PURE__ */ jsx(LoadingRouteIntro, { titleClassName })),
|
|
80
|
+
filters && /* @__PURE__ */ jsxs("div", { className: "folio-loading-filters folio-loading-container", "data-loading-content": true, children: [
|
|
81
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-6", children: [8, 16, 12, 20].map((width) => /* @__PURE__ */ jsx(SkeletonLine, { className: "h-3 w-12" }, width)) }),
|
|
82
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "h-11 w-56" })
|
|
87
83
|
] }),
|
|
88
|
-
/* @__PURE__ */ jsx(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
/* @__PURE__ */ jsx(
|
|
105
|
-
/* @__PURE__ */
|
|
84
|
+
(layout === "records" || layout === "identity") && /* @__PURE__ */ jsx(LoadingRecords, { rows, media }),
|
|
85
|
+
layout === "cards" && /* @__PURE__ */ jsx("section", { "data-loading-content": true, className: "folio-loading-cards folio-loading-container", children: Array.from({ length: rows }, (_, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
86
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
87
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "size-7" }),
|
|
88
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "h-2.5 w-16" })
|
|
89
|
+
] }),
|
|
90
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-5 h-4 w-28" }),
|
|
91
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-2.5 h-2.5 w-24" }),
|
|
92
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-4 h-3 w-full" }),
|
|
93
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-2 h-3 w-4/5" })
|
|
94
|
+
] }, index)) }),
|
|
95
|
+
layout === "gallery" && /* @__PURE__ */ jsx("section", { "data-loading-content": true, className: "folio-loading-gallery folio-loading-container", children: Array.from({ length: rows }, (_, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
96
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "aspect-[4/5] w-full" }),
|
|
97
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-3 h-3 w-3/4" })
|
|
98
|
+
] }, index)) }),
|
|
99
|
+
layout === "media" && /* @__PURE__ */ jsx("section", { "data-loading-content": true, className: "folio-loading-media", children: /* @__PURE__ */ jsxs("div", { "data-loading-now-playing": true, className: "folio-media-feature folio-loading-container", children: [
|
|
100
|
+
/* @__PURE__ */ jsx("div", { className: "folio-media-feature__artwork", children: /* @__PURE__ */ jsx(SkeletonBlock, { "data-loading-artwork": true, className: "h-full w-full" }) }),
|
|
101
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
102
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "h-2.5 w-28" }),
|
|
103
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "mt-5 h-16 w-4/5" }),
|
|
104
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-5 h-3.5 w-2/3" }),
|
|
105
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-6 h-1 w-full" })
|
|
106
|
+
] })
|
|
107
|
+
] }) }),
|
|
108
|
+
layout === "metrics" && /* @__PURE__ */ jsxs("div", { "data-loading-content": true, className: "folio-loading-metrics folio-loading-container", children: [
|
|
109
|
+
/* @__PURE__ */ jsxs("div", { className: "folio-loading-filters", children: [
|
|
110
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "h-2.5 w-12" }),
|
|
111
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "h-11 w-72" })
|
|
112
|
+
] }),
|
|
113
|
+
/* @__PURE__ */ jsx("div", { className: "folio-loading-metrics__figures", children: [0, 1, 2, 3].map((cell) => /* @__PURE__ */ jsxs("div", { children: [
|
|
114
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "h-2.5 w-24" }),
|
|
115
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "mt-4 h-9 w-20" }),
|
|
116
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-4 h-2.5 w-16" })
|
|
117
|
+
] }, cell)) }),
|
|
118
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-16 h-3 w-28" }),
|
|
119
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "mt-6 h-[220px] w-full" })
|
|
106
120
|
] })
|
|
107
|
-
] }) })
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
121
|
+
] }) }) })
|
|
122
|
+
] });
|
|
123
|
+
}
|
|
124
|
+
function LoadingIdentity() {
|
|
125
|
+
return /* @__PURE__ */ jsxs("header", { className: "folio-loading-identity folio-loading-container", children: [
|
|
126
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
127
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-5", children: [
|
|
128
|
+
/* @__PURE__ */ jsx(SkeletonCircle, { className: "size-12" }),
|
|
129
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "h-12 w-64" })
|
|
112
130
|
] }),
|
|
113
|
-
/* @__PURE__ */ jsx(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/* @__PURE__ */ jsx(SkeletonBlock, { className: "mt-6 h-[220px] w-full" })
|
|
120
|
-
] })
|
|
121
|
-
] }) });
|
|
131
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-9 h-3.5 w-full" }),
|
|
132
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-3 h-3.5 w-4/5" }),
|
|
133
|
+
/* @__PURE__ */ jsx(SkeletonLine, { className: "mt-10 h-3 w-2/3" })
|
|
134
|
+
] }),
|
|
135
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { className: "aspect-square w-full" })
|
|
136
|
+
] });
|
|
122
137
|
}
|
|
123
138
|
export {
|
|
124
139
|
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' | '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":[]}
|
|
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' | 'cards'\n /**\n * The route's real opening — its title and description — rendered at once,\n * in place of the skeleton masthead. A route's own words never wait on its\n * data, so drawing grey bars where they will be is a promise of nothing.\n */\n intro?: ReactNode\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 * Static parts at once, data after a wait: an `intro` renders immediately and\n * for real, and the skeleton for the data waits `--duration-wait` before it\n * fades in, so a route that resolves inside the wait goes straight from the\n * old page to the new one. Every shape is the real one's — a detail route\n * needs `article` or `photograph`, a card grid needs `cards` — because a\n * skeleton the page then abandons is the jump it exists to prevent.\n */\nexport function WebsiteLoading({ label, layout = 'records', titleClassName, rows = 4, media = true, filters = false, intro }: WebsiteLoadingProps) {\n return <div className=\"folio-loading-page\">\n {intro}\n <div className=\"folio-loading-data\"><SkeletonPage label={label}>\n {layout === 'article' ? <LoadingArticle media={media} />\n : layout === 'photograph' ? <LoadingPhotograph />\n : <>\n {!intro && (layout === 'identity' ? <LoadingIdentity /> : <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 === 'cards' && <section data-loading-content className=\"folio-loading-cards folio-loading-container\">{Array.from({ length: rows }, (_, index) => <div key={index}><div className=\"flex items-center gap-2\"><SkeletonBlock className=\"size-7\" /><SkeletonLine className=\"h-2.5 w-16\" /></div><SkeletonLine className=\"mt-5 h-4 w-28\" /><SkeletonLine className=\"mt-2.5 h-2.5 w-24\" /><SkeletonLine className=\"mt-4 h-3 w-full\" /><SkeletonLine className=\"mt-2 h-3 w-4/5\" /></div>)}</section>}\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 </>}\n </SkeletonPage></div>\n </div>\n}\n\n/** A profile opening: a mark beside a name, a lead, and the portrait. */\nfunction LoadingIdentity() {\n return <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>\n}\n"],"mappings":"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","names":[]}
|
package/dist/website-actions.css
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
.folio-scroll-control { transition: opacity var(--duration-fast) var(--ease); }
|
|
4
4
|
.folio-scroll-control-hidden { opacity: 0; pointer-events: none; }
|
|
5
5
|
@media (prefers-reduced-motion: reduce) { .folio-scroll-control { transition: none; } }
|
|
6
|
-
[data-motion='
|
|
6
|
+
[data-motion='still'] .folio-scroll-control { transition: none; }
|
package/dist/website-media.css
CHANGED
|
@@ -171,11 +171,16 @@
|
|
|
171
171
|
.folio-media-map-marker { position: relative; min-inline-size: 44px; min-block-size: 44px; padding: 0; border: 0; border-radius: var(--radius-pill); background: transparent; }
|
|
172
172
|
.folio-media-map-marker:hover { background: transparent; }
|
|
173
173
|
.folio-media-map-marker:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
|
|
174
|
-
|
|
175
|
-
.
|
|
176
|
-
|
|
174
|
+
/* A place is a small ink dot; only the selected or hovered one takes the
|
|
175
|
+
accent. The pin used to be a 2rem accent ring with a filled centre, and on a
|
|
176
|
+
map holding dozens of frames the rings overlapped into orange clusters that
|
|
177
|
+
read louder than the map. The ink dot's 2px paper ring keeps it apart from
|
|
178
|
+
the basemap's own black city dots. The 44px hit area stays on the marker
|
|
179
|
+
button. */
|
|
180
|
+
.folio-media-map-pin { position: relative; display: grid; inline-size: 2rem; block-size: 2rem; place-items: center; pointer-events: none; }
|
|
181
|
+
.folio-media-map-pin > span { inline-size: 0.625rem; block-size: 0.625rem; border: 2px solid var(--background); border-radius: var(--radius-pill); background: var(--foreground); transition: transform var(--duration-fast) var(--ease), background-color var(--duration-fast) var(--ease); }
|
|
177
182
|
.folio-media-map-pin[data-active] > span,
|
|
178
|
-
.folio-media-map-marker:hover .folio-media-map-pin > span { transform: scale(1.
|
|
183
|
+
.folio-media-map-marker:hover .folio-media-map-pin > span { background: var(--accent); transform: scale(1.4); }
|
|
179
184
|
.folio-media-map-frame-compact { display: grid; gap: 0.75rem; margin-block-start: 1.5rem; }
|
|
180
185
|
.folio-media-map-label { color: var(--secondary-text); font-family: var(--label-font); font-size: 0.625rem; letter-spacing: calc(0.14em * var(--label-tracking-scale)); text-transform: var(--label-case); }
|
|
181
186
|
.folio-media-map-frame-compact .folio-media-map-stage { block-size: 9.375rem; }
|
|
@@ -227,7 +232,7 @@
|
|
|
227
232
|
.folio-media-lightbox[role='dialog'] { animation: none; }
|
|
228
233
|
}
|
|
229
234
|
|
|
230
|
-
[data-motion='
|
|
231
|
-
[data-motion='
|
|
232
|
-
[data-motion='
|
|
233
|
-
[data-motion='
|
|
235
|
+
[data-motion='still'] .folio-media-gallery-link img,
|
|
236
|
+
[data-motion='still'] .folio-media-map-pin > span { transition: none; }
|
|
237
|
+
[data-motion='still'] .folio-media-gallery-link:hover img { transform: none; }
|
|
238
|
+
[data-motion='still'] .folio-media-lightbox[role='dialog'] { animation: none; }
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
/* Static parts at once, the skeleton after a wait. A route's own words — its
|
|
2
|
+
title, its description — are known before any data, so they render for real
|
|
3
|
+
and immediately; only the data's shapes wait `--duration-wait`, then fade in.
|
|
4
|
+
A route that answers inside the wait never shows a bar at all. The pulse
|
|
5
|
+
lives on the SkeletonPage itself, so the fade sits on the wrapper around it
|
|
6
|
+
and the two animations never fight for a property. */
|
|
7
|
+
.folio-loading-page > .folio-loading-data { animation: folio-loading-in var(--duration-base) var(--ease) var(--duration-wait) both; }
|
|
6
8
|
@keyframes folio-loading-in { from { opacity: 0; } to { opacity: 1; } }
|
|
7
|
-
|
|
9
|
+
/* Reduced motion drops the fade, not the wait: `animation: none` here showed
|
|
10
|
+
the grey bars at once — on every quick navigation, to exactly the readers
|
|
11
|
+
who asked for less movement. */
|
|
12
|
+
@media (prefers-reduced-motion: reduce) { .folio-loading-page > .folio-loading-data { animation-duration: 1ms; } }
|
|
13
|
+
.folio-loading-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 17.5rem), 1fr)); gap: 1rem; padding-block: 1.5rem clamp(4rem, 9vw, 8rem); }
|
|
14
|
+
.folio-loading-cards > div { padding: 1.25rem 1.25rem 1.5rem; border: 1px solid var(--rule); border-radius: var(--radius-lg); }
|
|
8
15
|
.folio-recovery-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem; }
|
|
9
16
|
.folio-recovery-links { margin-block: clamp(3.5rem, 7vw, 6rem) 3rem; }
|
|
10
17
|
.folio-recovery-links ul { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0 4rem; margin: .25rem 0 0; padding: 0; list-style: none; }
|