@curvenote/theme-ui 1.0.1 → 2.0.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/components/layout/app-layout.d.ts +1 -1
- package/dist/components/layout/app-layout.d.ts.map +1 -1
- package/dist/components/layout/app-layout.js +6 -5
- package/dist/components/layout/app-sidebar.d.ts.map +1 -1
- package/dist/components/layout/app-sidebar.js +10 -6
- package/dist/components/layout/article-layout.d.ts +1 -1
- package/dist/components/layout/article-layout.d.ts.map +1 -1
- package/dist/components/layout/article-layout.js +6 -7
- package/dist/components/layout/header.js +1 -1
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/layout/index.js +1 -0
- package/dist/components/layout/loading-bar.d.ts +8 -1
- package/dist/components/layout/loading-bar.d.ts.map +1 -1
- package/dist/components/layout/loading-bar.js +12 -4
- package/dist/components/layout/site-header.d.ts +6 -1
- package/dist/components/layout/site-header.d.ts.map +1 -1
- package/dist/components/layout/site-header.js +7 -4
- package/dist/components/layout/types.d.ts +6 -0
- package/dist/components/layout/types.d.ts.map +1 -1
- package/dist/components/providers/analytics-boundary.d.ts +18 -0
- package/dist/components/providers/analytics-boundary.d.ts.map +1 -0
- package/dist/components/providers/analytics-boundary.js +53 -0
- package/dist/components/providers/analytics-dev-log.d.ts +11 -0
- package/dist/components/providers/analytics-dev-log.d.ts.map +1 -0
- package/dist/components/providers/analytics-dev-log.js +46 -0
- package/dist/components/providers/analytics-dev-tray.d.ts +2 -0
- package/dist/components/providers/analytics-dev-tray.d.ts.map +1 -0
- package/dist/components/providers/analytics-dev-tray.js +56 -0
- package/dist/components/providers/article-versions-provider.d.ts +19 -0
- package/dist/components/providers/article-versions-provider.d.ts.map +1 -0
- package/dist/components/providers/article-versions-provider.js +13 -0
- package/dist/components/providers/curvenote-providers.d.ts +12 -13
- package/dist/components/providers/curvenote-providers.d.ts.map +1 -1
- package/dist/components/providers/curvenote-providers.js +20 -27
- package/dist/components/providers/design.d.ts +3 -33
- package/dist/components/providers/design.d.ts.map +1 -1
- package/dist/components/providers/design.js +64 -21
- package/dist/components/providers/index.d.ts +4 -2
- package/dist/components/providers/index.d.ts.map +1 -1
- package/dist/components/providers/index.js +3 -1
- package/dist/components/providers/lightbox-provider.d.ts +8 -0
- package/dist/components/providers/lightbox-provider.d.ts.map +1 -1
- package/dist/components/providers/lightbox-provider.js +28 -5
- package/dist/components/providers/overlay-depth.d.ts +16 -0
- package/dist/components/providers/overlay-depth.d.ts.map +1 -0
- package/dist/components/providers/overlay-depth.js +16 -0
- package/dist/components/providers/ping-boundary.d.ts +3 -1
- package/dist/components/providers/ping-boundary.d.ts.map +1 -1
- package/dist/components/providers/ping-boundary.js +7 -4
- package/dist/components/providers/platform-providers.d.ts +0 -7
- package/dist/components/providers/platform-providers.d.ts.map +1 -1
- package/dist/components/providers/platform-providers.js +0 -14
- package/dist/components/ui/abbreviations.d.ts +3 -1
- package/dist/components/ui/abbreviations.d.ts.map +1 -1
- package/dist/components/ui/abbreviations.js +13 -6
- package/dist/components/ui/accessibility-skip-to.d.ts +13 -3
- package/dist/components/ui/accessibility-skip-to.d.ts.map +1 -1
- package/dist/components/ui/accessibility-skip-to.js +4 -1
- package/dist/components/ui/arrow.d.ts +6 -0
- package/dist/components/ui/arrow.d.ts.map +1 -0
- package/dist/components/ui/arrow.js +15 -0
- package/dist/components/ui/article-actions-downloads.d.ts.map +1 -1
- package/dist/components/ui/article-actions-downloads.js +74 -7
- package/dist/components/ui/article-actions-dropdown.d.ts +2 -1
- package/dist/components/ui/article-actions-dropdown.d.ts.map +1 -1
- package/dist/components/ui/article-actions-dropdown.js +102 -21
- package/dist/components/ui/article-actions-share.d.ts +18 -0
- package/dist/components/ui/article-actions-share.d.ts.map +1 -1
- package/dist/components/ui/article-actions-share.js +38 -2
- package/dist/components/ui/article-actions.d.ts.map +1 -1
- package/dist/components/ui/article-actions.js +16 -3
- package/dist/components/ui/article-bar.d.ts +3 -1
- package/dist/components/ui/article-bar.d.ts.map +1 -1
- package/dist/components/ui/article-bar.js +19 -5
- package/dist/components/ui/article-card.js +1 -1
- package/dist/components/ui/author-popover.d.ts +2 -1
- package/dist/components/ui/author-popover.d.ts.map +1 -1
- package/dist/components/ui/author-popover.js +42 -7
- package/dist/components/ui/backmatter.d.ts.map +1 -1
- package/dist/components/ui/backmatter.js +23 -5
- package/dist/components/ui/banner.d.ts.map +1 -1
- package/dist/components/ui/banner.js +1 -1
- package/dist/components/ui/bibliography.d.ts +2 -2
- package/dist/components/ui/bibliography.d.ts.map +1 -1
- package/dist/components/ui/bibliography.js +10 -9
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/button.js +2 -0
- package/dist/components/ui/calendar.d.ts +10 -0
- package/dist/components/ui/calendar.d.ts.map +1 -0
- package/dist/components/ui/calendar.js +85 -0
- package/dist/components/ui/citation.d.ts +2 -2
- package/dist/components/ui/citation.d.ts.map +1 -1
- package/dist/components/ui/citation.js +45 -15
- package/dist/components/ui/collapsible-backmatter-section.d.ts +28 -0
- package/dist/components/ui/collapsible-backmatter-section.d.ts.map +1 -0
- package/dist/components/ui/collapsible-backmatter-section.js +52 -0
- package/dist/components/ui/cookie-banner.d.ts +1 -1
- package/dist/components/ui/cookie-banner.d.ts.map +1 -1
- package/dist/components/ui/cookie-banner.js +9 -2
- package/dist/components/ui/document-outline.d.ts.map +1 -1
- package/dist/components/ui/document-outline.js +38 -20
- package/dist/components/ui/footer-links.d.ts.map +1 -1
- package/dist/components/ui/footer-links.js +4 -0
- package/dist/components/ui/frontmatter-badges.d.ts +15 -5
- package/dist/components/ui/frontmatter-badges.d.ts.map +1 -1
- package/dist/components/ui/frontmatter-badges.js +41 -15
- package/dist/components/ui/frontmatter.js +1 -1
- package/dist/components/ui/hash-link.d.ts +56 -0
- package/dist/components/ui/hash-link.d.ts.map +1 -0
- package/dist/components/ui/hash-link.js +83 -0
- package/dist/components/ui/image.d.ts +5 -2
- package/dist/components/ui/image.d.ts.map +1 -1
- package/dist/components/ui/image.js +10 -8
- package/dist/components/ui/index.d.ts +10 -2
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +9 -2
- package/dist/components/ui/keywords.d.ts +4 -0
- package/dist/components/ui/keywords.d.ts.map +1 -0
- package/dist/components/ui/keywords.js +18 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +6 -0
- package/dist/components/ui/license-description.d.ts.map +1 -1
- package/dist/components/ui/license-description.js +8 -5
- package/dist/components/ui/license-frontmatter.d.ts.map +1 -1
- package/dist/components/ui/license-frontmatter.js +14 -3
- package/dist/components/ui/lightbox-container.d.ts.map +1 -1
- package/dist/components/ui/lightbox-container.js +2 -2
- package/dist/components/ui/lightbox.d.ts +3 -1
- package/dist/components/ui/lightbox.d.ts.map +1 -1
- package/dist/components/ui/lightbox.js +155 -25
- package/dist/components/ui/link-card.d.ts +2 -1
- package/dist/components/ui/link-card.d.ts.map +1 -1
- package/dist/components/ui/link-card.js +2 -2
- package/dist/components/ui/pagination.d.ts +15 -0
- package/dist/components/ui/pagination.d.ts.map +1 -0
- package/dist/components/ui/pagination.js +31 -0
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/search.d.ts +2 -1
- package/dist/components/ui/search.d.ts.map +1 -1
- package/dist/components/ui/search.js +24 -8
- package/dist/components/ui/select.d.ts +16 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/select.js +38 -0
- package/dist/components/ui/separator.js +1 -1
- package/dist/components/ui/sidebar.d.ts +2 -12
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/sidebar.js +2 -34
- package/dist/components/ui/tooltip.d.ts +4 -2
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/components/ui/tooltip.js +5 -4
- package/dist/components/ui/types.d.ts +9 -8
- package/dist/components/ui/types.d.ts.map +1 -1
- package/dist/components/ui/types.js +1 -0
- package/dist/lib/dedupeAbbreviations.d.ts +10 -0
- package/dist/lib/dedupeAbbreviations.d.ts.map +1 -0
- package/dist/lib/dedupeAbbreviations.js +36 -0
- package/dist/lib/knownParts.d.ts +18 -0
- package/dist/lib/knownParts.d.ts.map +1 -1
- package/dist/lib/knownParts.js +38 -1
- package/package.json +12 -9
- package/dist/components/providers/types.d.ts +0 -30
- package/dist/components/providers/types.d.ts.map +0 -1
- package/dist/components/providers/types.js +0 -1
|
@@ -2,10 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { useFrontmatter, useReferences } from '@myst-theme/providers';
|
|
4
4
|
import { toText } from 'myst-common';
|
|
5
|
-
import { HashLink } from 'myst-to-react';
|
|
6
5
|
import { cn } from '../../lib/utils';
|
|
7
6
|
import { selectAll } from 'unist-util-select';
|
|
8
7
|
import { PART_IDS } from './types';
|
|
8
|
+
import { useCollapsibleBackmatter, CollapsibleBackmatterHeader, CollapsibleBackmatterFooterButton, } from './collapsible-backmatter-section';
|
|
9
|
+
import { dedupeAbbreviationEntries } from '../../lib/dedupeAbbreviations';
|
|
10
|
+
const DEFAULT_MANY_ABBREVIATIONS = 5;
|
|
9
11
|
function useAbbreviations() {
|
|
10
12
|
const frontmatter = useFrontmatter();
|
|
11
13
|
const references = useReferences();
|
|
@@ -15,17 +17,22 @@ function useAbbreviations() {
|
|
|
15
17
|
.filter(Boolean);
|
|
16
18
|
const fullTree = { type: 'page', children: [page, ...parts].filter(Boolean) };
|
|
17
19
|
const inTextAbbreviations = selectAll('abbreviation', fullTree);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
+
const entries = inTextAbbreviations.map((node) => [toText(node), node.title]);
|
|
21
|
+
const deduped = dedupeAbbreviationEntries(entries, frontmatter?.abbreviations);
|
|
22
|
+
if (deduped.length === 0)
|
|
20
23
|
return undefined;
|
|
21
|
-
return
|
|
24
|
+
return Object.fromEntries(deduped);
|
|
22
25
|
}
|
|
23
|
-
export function Abbreviations({ sorted = true, className, }) {
|
|
26
|
+
export function Abbreviations({ sorted = true, className, hideManyAbbreviations = DEFAULT_MANY_ABBREVIATIONS, }) {
|
|
27
|
+
if (hideManyAbbreviations === true)
|
|
28
|
+
hideManyAbbreviations = DEFAULT_MANY_ABBREVIATIONS;
|
|
24
29
|
const abbreviations = useAbbreviations();
|
|
25
30
|
if (!abbreviations)
|
|
26
31
|
return null;
|
|
27
32
|
const sortedAbbreviations = sorted
|
|
28
33
|
? Object.entries(abbreviations).sort(([a], [b]) => a.localeCompare(b))
|
|
29
34
|
: Object.entries(abbreviations);
|
|
30
|
-
|
|
35
|
+
const { hidden, toggle, displayedCount, isCollapsible } = useCollapsibleBackmatter(sortedAbbreviations.length, hideManyAbbreviations, DEFAULT_MANY_ABBREVIATIONS);
|
|
36
|
+
const displayed = sortedAbbreviations.slice(0, displayedCount);
|
|
37
|
+
return (_jsxs("section", { id: PART_IDS.abbreviations, className: cn('min-w-full prose dark:prose-invert prose-sm', className), children: [_jsx(CollapsibleBackmatterHeader, { id: PART_IDS.abbreviations, title: "Abbreviations", linkTitle: "Link to Abbreviations", hidden: hidden, onToggle: toggle, isCollapsible: isCollapsible }), _jsxs("div", { className: cn('pl-3 mb-8 text-xs text-stone-500 dark:text-stone-300'), children: [_jsx("dl", { className: "grid grid-cols-[auto_1fr] gap-x-6 gap-y-2", children: displayed.map(([abbreviation, description]) => (_jsxs(React.Fragment, { children: [_jsx("dt", { className: "py-1 pt-0 m-0 mt-0 font-medium text-stone-900 dark:text-white", children: abbreviation }), _jsx("dd", { className: "flex items-center py-1 pt-0 m-0 mt-0 text-center text-stone-600 dark:text-stone-400", children: description })] }, abbreviation))) }), isCollapsible && (_jsx(CollapsibleBackmatterFooterButton, { hidden: hidden, onToggle: toggle, totalCount: sortedAbbreviations.length, itemLabel: "abbreviations", sectionId: PART_IDS.abbreviations, className: "flex justify-center pt-2", as: "div" }))] })] }));
|
|
31
38
|
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { PART_IDS } from './types';
|
|
3
|
+
export declare function createSkipToTargets(): ({
|
|
4
|
+
id: "skip-to-content";
|
|
4
5
|
title: string;
|
|
5
|
-
}
|
|
6
|
+
} | {
|
|
7
|
+
id: "skip-to-frontmatter";
|
|
8
|
+
title: string;
|
|
9
|
+
} | {
|
|
10
|
+
id: "skip-to-backmatter";
|
|
11
|
+
title: string;
|
|
12
|
+
})[];
|
|
6
13
|
/**
|
|
7
14
|
* Add a skip navigation unit with links based on a list of targets
|
|
8
15
|
*/
|
|
@@ -12,4 +19,7 @@ export declare const SkipTo: React.MemoExoticComponent<({ targets }: {
|
|
|
12
19
|
title: string;
|
|
13
20
|
}[];
|
|
14
21
|
}) => import("react/jsx-runtime").JSX.Element>;
|
|
22
|
+
export declare function SkipToAnchor({ id }: {
|
|
23
|
+
id: (typeof PART_IDS)[keyof typeof PART_IDS];
|
|
24
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
15
25
|
//# sourceMappingURL=accessibility-skip-to.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessibility-skip-to.d.ts","sourceRoot":"","sources":["../../../src/components/ui/accessibility-skip-to.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"accessibility-skip-to.d.ts","sourceRoot":"","sources":["../../../src/components/ui/accessibility-skip-to.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAgBnC,wBAAgB,mBAAmB;;;;;;;;;KAMlC;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,0CAA4B;IAAE,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,6CAkBzF,CAAC;AAEH,wBAAgB,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE;IAAE,EAAE,EAAE,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAA;CAAE,2CAEpF"}
|
|
@@ -27,5 +27,8 @@ export function createSkipToTargets() {
|
|
|
27
27
|
* Add a skip navigation unit with links based on a list of targets
|
|
28
28
|
*/
|
|
29
29
|
export const SkipTo = React.memo(({ targets }) => {
|
|
30
|
-
return (_jsx("div", { className: "fixed top-1 left-1 h-
|
|
30
|
+
return (_jsx("div", { className: "overflow-hidden fixed top-1 left-1 w-0 h-0 bg-white focus-within:z-100 focus-within:h-auto focus-within:w-auto focus-within:p-2 focus-within:ring-1 focus-within:ring-blue-500 focus-within:shadow-lg", "aria-label": "skip to content options", children: targets.map(({ id, title }) => (_jsx("a", { href: `#${id}`, className: "block px-2 py-1 text-black underline hover:text-blue-600 focus:text-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500", onClick: makeSkipClickHandler(id), children: title }, id))) }));
|
|
31
31
|
});
|
|
32
|
+
export function SkipToAnchor({ id }) {
|
|
33
|
+
return _jsx("div", { id: id, className: "absolute w-0 h-0" });
|
|
34
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { LinkProps } from 'react-router';
|
|
3
|
+
export declare function Arrow(): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare function LongArrowIcon({ className, ...props }: React.SVGProps<SVGSVGElement>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare function ArrowLink({ children, className, ...props }: LinkProps): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
//# sourceMappingURL=arrow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arrow.d.ts","sourceRoot":"","sources":["../../../src/components/ui/arrow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,wBAAgB,KAAK,4CASpB;AAED,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,2CAiBnF;AAED,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,kDAerE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { Link } from 'react-router';
|
|
5
|
+
export function Arrow() {
|
|
6
|
+
return (_jsxs("div", { className: "flex h-5 w-full -translate-y-[25%] items-center", children: [_jsx("div", { className: "h-5", children: _jsx("div", { className: "w-3 h-4 rounded-bl-xl border-b-2 border-l-2 border-current" }) }), _jsx("div", { className: "mt-2.5 h-0.5 w-full bg-current" })] }));
|
|
7
|
+
}
|
|
8
|
+
export function LongArrowIcon({ className, ...props }) {
|
|
9
|
+
return (_jsx("svg", { width: "42", height: "8", viewBox: "0 0 42 8", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: className, ...props, children: _jsx("path", { d: "M41.5 4.99365L36.5 2.1069V7.8804L41.5 4.99365ZM6 4.99365V5.49365H37V4.99365V4.49365H6V4.99365ZM1 -0.00634766H0.5C0.5 3.03122 2.96243 5.49365 6 5.49365V4.99365V4.49365C3.51472 4.49365 1.5 2.47893 1.5 -0.00634766H1Z", fill: "currentColor" }) }));
|
|
10
|
+
}
|
|
11
|
+
export function ArrowLink({ children, className, ...props }) {
|
|
12
|
+
if (typeof children !== 'string')
|
|
13
|
+
return null;
|
|
14
|
+
return (_jsxs(Link, { ...props, className: clsx('inline-flex items-center space-x-2 group font-nm type-nm-h6 text-brand hover:opacity-75', className), children: [_jsx("span", { children: children }), _jsx(LongArrowIcon, { className: "origin-top-left transition-transform duration-150 ease-out group-hover:scale-x-[1.05]" })] }));
|
|
15
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"article-actions-downloads.d.ts","sourceRoot":"","sources":["../../../src/components/ui/article-actions-downloads.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"article-actions-downloads.d.ts","sourceRoot":"","sources":["../../../src/components/ui/article-actions-downloads.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK1D;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,gBAKzE;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,gBA0BtE;AAsCD,wBAAgB,YAAY;;;;;EAa3B;AA0HD,wBAAgB,oBAAoB,mDA8CnC;AAED,wBAAgB,kBAAkB,mDAgDjC"}
|
|
@@ -2,9 +2,10 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { DropdownMenuItem, DropdownMenuSeparator, DropdownMenuLabel } from '.';
|
|
3
3
|
import { useFrontmatter, useProjectManifest, useSiteManifest } from '@myst-theme/providers';
|
|
4
4
|
import { toast } from 'sonner';
|
|
5
|
-
import { File, FileText, FileCode, FileArchive, ScrollText } from 'lucide-react';
|
|
5
|
+
import { File, FileText, FileCode, FileArchive, ScrollText, FileVolume } from 'lucide-react';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import { BibTeXCitationMenuItem, useShowCitation } from './citation';
|
|
8
|
+
import { useAnalytics, useDesign } from '../providers';
|
|
8
9
|
/**
|
|
9
10
|
* triggerDirectDownload - aims to trigger a direct download for the
|
|
10
11
|
*
|
|
@@ -66,6 +67,8 @@ function getFormatDisplayName(format) {
|
|
|
66
67
|
return 'BibTeX';
|
|
67
68
|
case 'ipynb':
|
|
68
69
|
return 'Jupyter Notebook';
|
|
70
|
+
case 'mp3':
|
|
71
|
+
return 'MP3';
|
|
69
72
|
case 'tex':
|
|
70
73
|
return 'LaTeX';
|
|
71
74
|
case 'html':
|
|
@@ -91,9 +94,28 @@ export function useDownloads() {
|
|
|
91
94
|
articleDownloads: article?.downloads ?? [],
|
|
92
95
|
};
|
|
93
96
|
}
|
|
94
|
-
|
|
97
|
+
function buildDownloadAnalyticsProps(download, ctx) {
|
|
98
|
+
const format = download.format || formatFromUrl(download.url) || 'unknown';
|
|
99
|
+
return {
|
|
100
|
+
category: ctx.category,
|
|
101
|
+
scope: ctx.scope,
|
|
102
|
+
surface: ctx.surface,
|
|
103
|
+
format,
|
|
104
|
+
downloadUrl: download.url,
|
|
105
|
+
downloadFilename: download.filename,
|
|
106
|
+
downloadTitle: download.title,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
async function handleDownload(download, capture, ctx) {
|
|
110
|
+
const baseProps = buildDownloadAnalyticsProps(download, ctx);
|
|
111
|
+
capture('article_download', { action: 'clicked', ...baseProps });
|
|
95
112
|
toast.success(_jsxs(_Fragment, { children: ["Download starting... ", _jsx("br", {}), _jsx("code", { children: download.filename })] }));
|
|
96
113
|
await triggerDirectDownload(download.url, download.filename).catch((error) => {
|
|
114
|
+
capture('article_download', {
|
|
115
|
+
action: 'failed',
|
|
116
|
+
...baseProps,
|
|
117
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
118
|
+
});
|
|
97
119
|
console.error('Download failed:', error);
|
|
98
120
|
toast.error('Download failed. Please try again.');
|
|
99
121
|
});
|
|
@@ -106,6 +128,7 @@ const formatIconMap = {
|
|
|
106
128
|
omex: FileArchive,
|
|
107
129
|
tex: ScrollText,
|
|
108
130
|
typst: ScrollText,
|
|
131
|
+
mp3: FileVolume,
|
|
109
132
|
};
|
|
110
133
|
function getIconForFormat(format) {
|
|
111
134
|
const lowerFormat = format.toLowerCase();
|
|
@@ -116,28 +139,72 @@ function getIconForFormat(format) {
|
|
|
116
139
|
}
|
|
117
140
|
return File;
|
|
118
141
|
}
|
|
119
|
-
function
|
|
142
|
+
function formatFromUrl(url) {
|
|
143
|
+
try {
|
|
144
|
+
const urlObj = new URL(url);
|
|
145
|
+
const pathname = urlObj.pathname;
|
|
146
|
+
const format = pathname.split('.').pop()?.toLowerCase();
|
|
147
|
+
if (format && format.length <= 6) {
|
|
148
|
+
return format;
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function renderDownloadItems(downloads, capture, ctx, options = {}) {
|
|
120
157
|
return downloads.map((download, index) => {
|
|
121
|
-
const format = download.format || 'unknown';
|
|
158
|
+
const format = download.format || formatFromUrl(download.url) || 'unknown';
|
|
122
159
|
const downloadName = download.title || getFormatDisplayName(format);
|
|
123
160
|
const icon = getIconForFormat(format);
|
|
124
|
-
|
|
161
|
+
if (options.linkMode) {
|
|
162
|
+
return (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs("a", { href: download.url, download: download.filename, target: "_blank", rel: "noopener noreferrer", onClick: () => capture('article_download', {
|
|
163
|
+
action: 'clicked',
|
|
164
|
+
...buildDownloadAnalyticsProps(download, ctx),
|
|
165
|
+
}), children: [React.createElement(icon, { className: 'mr-2 h-4 w-4' }), downloadName] }) }, index));
|
|
166
|
+
}
|
|
167
|
+
return (_jsxs(DropdownMenuItem, { onClick: () => handleDownload(download, capture, ctx), children: [React.createElement(icon, { className: 'mr-2 h-4 w-4' }), downloadName] }, index));
|
|
125
168
|
});
|
|
126
169
|
}
|
|
127
170
|
export function ArticleDownloadItems() {
|
|
128
171
|
const { projectDownloads, articleDownloads } = useDownloads();
|
|
172
|
+
const capture = useAnalytics();
|
|
173
|
+
const { link_downloads } = useDesign();
|
|
129
174
|
const hasProjectDownloads = projectDownloads.length > 0;
|
|
130
175
|
const hasArticleDownloads = articleDownloads.length > 0;
|
|
131
176
|
if (!hasProjectDownloads && !hasArticleDownloads)
|
|
132
177
|
return null;
|
|
133
|
-
|
|
178
|
+
const surface = 'actions_menu_downloads_submenu';
|
|
179
|
+
const linkMode = !!link_downloads;
|
|
180
|
+
return (_jsxs(_Fragment, { children: [hasProjectDownloads && (_jsxs(_Fragment, { children: [renderDownloadItems(projectDownloads, capture, {
|
|
181
|
+
category: 'download',
|
|
182
|
+
scope: 'project',
|
|
183
|
+
surface,
|
|
184
|
+
}, { linkMode }), hasArticleDownloads && _jsx(DropdownMenuSeparator, {})] })), hasArticleDownloads && (_jsxs(_Fragment, { children: [_jsx(DropdownMenuLabel, { children: "Page Downloads" }), renderDownloadItems(articleDownloads, capture, {
|
|
185
|
+
category: 'download',
|
|
186
|
+
scope: 'article',
|
|
187
|
+
surface,
|
|
188
|
+
}, { linkMode })] }))] }));
|
|
134
189
|
}
|
|
135
190
|
export function ArticleExportItems() {
|
|
136
191
|
const { projectExports, articleExports } = useDownloads();
|
|
137
192
|
const showCitation = useShowCitation();
|
|
193
|
+
const capture = useAnalytics();
|
|
194
|
+
const { link_downloads } = useDesign();
|
|
138
195
|
const hasProjectExports = projectExports.length > 0;
|
|
139
196
|
const hasArticleExports = articleExports.length > 0;
|
|
140
197
|
if (!hasProjectExports && !hasArticleExports)
|
|
141
198
|
return null;
|
|
142
|
-
|
|
199
|
+
const surface = 'actions_menu_exports_submenu';
|
|
200
|
+
const linkMode = !!link_downloads;
|
|
201
|
+
return (_jsxs(_Fragment, { children: [(hasProjectExports || showCitation) && (_jsxs(_Fragment, { children: [renderDownloadItems(projectExports, capture, {
|
|
202
|
+
category: 'export',
|
|
203
|
+
scope: 'project',
|
|
204
|
+
surface,
|
|
205
|
+
}, { linkMode }), showCitation && _jsx(BibTeXCitationMenuItem, {}), hasArticleExports && _jsx(DropdownMenuSeparator, {})] })), hasArticleExports && (_jsxs(_Fragment, { children: [_jsx(DropdownMenuLabel, { children: "Page Exports" }), renderDownloadItems(articleExports, capture, {
|
|
206
|
+
category: 'export',
|
|
207
|
+
scope: 'article',
|
|
208
|
+
surface,
|
|
209
|
+
}, { linkMode })] }))] }));
|
|
143
210
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export declare function ArticleActionsDropdown({ children }: {
|
|
2
|
+
export declare function ArticleActionsDropdown({ children, onOpenChange, }: {
|
|
3
3
|
children: React.ReactNode;
|
|
4
|
+
onOpenChange?: (open: boolean) => void;
|
|
4
5
|
}): import("react/jsx-runtime").JSX.Element;
|
|
5
6
|
//# sourceMappingURL=article-actions-dropdown.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"article-actions-dropdown.d.ts","sourceRoot":"","sources":["../../../src/components/ui/article-actions-dropdown.tsx"],"names":[],"mappings":"AAqCA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"article-actions-dropdown.d.ts","sourceRoot":"","sources":["../../../src/components/ui/article-actions-dropdown.tsx"],"names":[],"mappings":"AAqCA,OAAO,KAAK,MAAM,OAAO,CAAC;AAuF1B,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,YAAY,GACb,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC,2CA4TA"}
|
|
@@ -1,26 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, Badge, } from '.';
|
|
3
3
|
import { Citation } from './citation';
|
|
4
4
|
import { useFrontmatter, useProjectManifest } from '@myst-theme/providers';
|
|
5
5
|
import { toast } from 'sonner';
|
|
6
6
|
import { doi } from 'doi-utils';
|
|
7
|
-
import { Download, Quote, Copy,
|
|
7
|
+
import { Download, Quote, Copy, Pencil, Clock, BlocksIcon, Share, Sun, Moon, Monitor, FolderCode, FileText, Scale, } from 'lucide-react';
|
|
8
8
|
import { ArticleDownloadItems, ArticleExportItems, useDownloads, triggerDirectDownload, } from './article-actions-downloads';
|
|
9
9
|
import React from 'react';
|
|
10
|
-
import { ArticleActionsShare } from './article-actions-share';
|
|
10
|
+
import { ArticleActionsShare, useVisibleShareOptions } from './article-actions-share';
|
|
11
11
|
import { useTheme } from 'next-themes';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
description: 'Fixed a bug in the notebook that was causing the notebook to not run correctly.',
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
number: 1,
|
|
20
|
-
date: '2025-03-10',
|
|
21
|
-
description: '',
|
|
22
|
-
},
|
|
23
|
-
];
|
|
12
|
+
import { useAnalytics, useDesign } from '../providers';
|
|
13
|
+
import { useArticleVersions } from '../providers/article-versions-provider';
|
|
14
|
+
import { HashLink } from './hash-link';
|
|
15
|
+
import { PART_IDS } from './types';
|
|
24
16
|
function formatDate(dateStr) {
|
|
25
17
|
return new Date(dateStr).toLocaleDateString('en-US', {
|
|
26
18
|
month: 'short',
|
|
@@ -28,14 +20,37 @@ function formatDate(dateStr) {
|
|
|
28
20
|
year: 'numeric',
|
|
29
21
|
});
|
|
30
22
|
}
|
|
31
|
-
function ArticleVersionList(
|
|
32
|
-
|
|
23
|
+
function ArticleVersionList() {
|
|
24
|
+
const { versions, currentVersionTag } = useArticleVersions();
|
|
25
|
+
const capture = useAnalytics();
|
|
26
|
+
if (!versions.length)
|
|
27
|
+
return null;
|
|
28
|
+
return (_jsx(_Fragment, { children: versions.map((v) => (_jsx(DropdownMenuItem, { asChild: true, children: _jsx("a", { href: v.href, className: "cursor-pointer", onClick: () => capture('article_version_selected', {
|
|
29
|
+
versionNumber: v.tag,
|
|
30
|
+
versionDate: v.date ?? null,
|
|
31
|
+
isCurrent: Boolean(currentVersionTag && v.tag.toLowerCase() === currentVersionTag.toLowerCase()),
|
|
32
|
+
surface: 'actions_menu_versions_submenu',
|
|
33
|
+
}), children: _jsxs("div", { className: "flex flex-col", children: [_jsxs("div", { className: "flex items-center", children: [_jsx("span", { className: "mr-4 font-mono text-muted-foreground", children: v.tag }), v.date ? _jsx("span", { className: "mr-4", children: formatDate(v.date) }) : null, _jsx("span", { className: "flex-1" }), currentVersionTag && v.tag.toLowerCase() === currentVersionTag.toLowerCase() && (_jsx(Badge, { variant: "outline", children: "Current" }))] }), v.description ? (_jsx("div", { className: "mt-1 max-w-xs text-xs leading-snug text-muted-foreground", children: v.description })) : null] }) }) }, v.tag))) }));
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
function ArticleVersionsMenu() {
|
|
36
|
+
const { versions } = useArticleVersions();
|
|
37
|
+
const capture = useAnalytics();
|
|
38
|
+
if (!versions.length)
|
|
39
|
+
return null;
|
|
40
|
+
return (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuSub, { onOpenChange: (open) => open &&
|
|
41
|
+
capture('article_versions_submenu_opened', {
|
|
42
|
+
versionCount: versions.length,
|
|
43
|
+
}), children: [_jsxs(DropdownMenuSubTrigger, { children: [_jsx(Clock, { className: "mr-4 w-4 h-4" }), "Versions"] }), _jsx(DropdownMenuSubContent, { children: _jsx(ArticleVersionList, {}) })] }), _jsx(DropdownMenuSeparator, {})] }));
|
|
44
|
+
}
|
|
45
|
+
export function ArticleActionsDropdown({ children, onOpenChange, }) {
|
|
35
46
|
const project = useProjectManifest();
|
|
36
47
|
const article = useFrontmatter();
|
|
37
48
|
const { projectDownloads, articleDownloads, projectExports, articleExports } = useDownloads();
|
|
38
49
|
const { theme, setTheme } = useTheme();
|
|
50
|
+
const capture = useAnalytics();
|
|
51
|
+
const { hide_exports, link_downloads } = useDesign();
|
|
52
|
+
const visibleShareOptions = useVisibleShareOptions();
|
|
53
|
+
const hasShareOptions = visibleShareOptions.length > 0;
|
|
39
54
|
const allDownloads = [...projectDownloads, ...articleDownloads];
|
|
40
55
|
const hasDownloads = allDownloads.length > 0;
|
|
41
56
|
const hasExports = projectExports.length > 0 || articleExports.length > 0;
|
|
@@ -44,11 +59,31 @@ export function ArticleActionsDropdown({ children }) {
|
|
|
44
59
|
(allDownloads[0]?.format?.toLowerCase() === 'pdf' ||
|
|
45
60
|
allDownloads[0]?.url?.toLowerCase().endsWith('.pdf'));
|
|
46
61
|
const singlePdfDownload = hasSinglePdfDownload ? allDownloads[0] : null;
|
|
62
|
+
const singlePdfScope = singlePdfDownload && projectDownloads.includes(singlePdfDownload) ? 'project' : 'article';
|
|
47
63
|
const handleSinglePdfDownload = async () => {
|
|
48
64
|
if (!singlePdfDownload)
|
|
49
65
|
return;
|
|
66
|
+
capture('article_download', {
|
|
67
|
+
action: 'clicked',
|
|
68
|
+
category: 'download',
|
|
69
|
+
format: 'pdf',
|
|
70
|
+
downloadUrl: singlePdfDownload.url,
|
|
71
|
+
downloadFilename: singlePdfDownload.filename,
|
|
72
|
+
scope: singlePdfScope,
|
|
73
|
+
surface: 'actions_menu_single_pdf',
|
|
74
|
+
});
|
|
50
75
|
toast.success(_jsxs(_Fragment, { children: ["Download starting... ", _jsx("br", {}), _jsx("code", { children: singlePdfDownload.filename })] }));
|
|
51
76
|
await triggerDirectDownload(singlePdfDownload.url, singlePdfDownload.filename).catch((error) => {
|
|
77
|
+
capture('article_download', {
|
|
78
|
+
action: 'failed',
|
|
79
|
+
category: 'download',
|
|
80
|
+
format: 'pdf',
|
|
81
|
+
downloadUrl: singlePdfDownload.url,
|
|
82
|
+
downloadFilename: singlePdfDownload.filename,
|
|
83
|
+
scope: singlePdfScope,
|
|
84
|
+
surface: 'actions_menu_single_pdf',
|
|
85
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
86
|
+
});
|
|
52
87
|
console.error('Download failed:', error);
|
|
53
88
|
toast.error('Download failed. Please try again.');
|
|
54
89
|
});
|
|
@@ -57,12 +92,58 @@ export function ArticleActionsDropdown({ children }) {
|
|
|
57
92
|
const handleCopyDOI = () => {
|
|
58
93
|
if (doiString) {
|
|
59
94
|
navigator.clipboard.writeText(doiString);
|
|
95
|
+
capture('article_doi_copied', { doi: doiString, surface: 'actions_menu' });
|
|
60
96
|
toast.success(_jsxs("div", { children: ["DOI copied to clipboard: ", _jsx("br", {}), _jsx("a", { href: doiString, children: doiString })] }));
|
|
61
97
|
}
|
|
62
98
|
};
|
|
63
|
-
|
|
99
|
+
const editProvider = article?.edit_url?.includes('github.com')
|
|
100
|
+
? 'github'
|
|
101
|
+
: article?.edit_url?.includes('gitlab')
|
|
102
|
+
? 'gitlab'
|
|
103
|
+
: 'other';
|
|
104
|
+
const hasLicenseSection = Boolean(project?.license ||
|
|
105
|
+
project?.open_access ||
|
|
106
|
+
project?.copyright ||
|
|
107
|
+
article?.license ||
|
|
108
|
+
article?.open_access ||
|
|
109
|
+
article?.copyright);
|
|
110
|
+
return (_jsxs(DropdownMenu, { onOpenChange: onOpenChange, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: children }), _jsxs(DropdownMenuContent, { className: "w-56", align: "end", children: [_jsx(DropdownMenuLabel, { children: "Article Actions" }), _jsx(DropdownMenuSeparator, {}), hasSinglePdfDownload && singlePdfDownload ? (link_downloads ? (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs("a", { href: singlePdfDownload.url, download: singlePdfDownload.filename, target: "_blank", rel: "noopener noreferrer", onClick: () => capture('article_download', {
|
|
111
|
+
action: 'clicked',
|
|
112
|
+
category: 'download',
|
|
113
|
+
format: 'pdf',
|
|
114
|
+
downloadUrl: singlePdfDownload.url,
|
|
115
|
+
downloadFilename: singlePdfDownload.filename,
|
|
116
|
+
scope: singlePdfScope,
|
|
117
|
+
surface: 'actions_menu_single_pdf',
|
|
118
|
+
}), children: [_jsx(FileText, { className: "mr-2 w-4 h-4" }), "Download PDF"] }) })) : (_jsxs(DropdownMenuItem, { onClick: handleSinglePdfDownload, children: [_jsx(FileText, { className: "mr-2 w-4 h-4" }), "Download PDF"] }))) : (hasDownloads && (_jsxs(DropdownMenuSub, { onOpenChange: (open) => open &&
|
|
119
|
+
capture('article_downloads_submenu_opened', {
|
|
120
|
+
downloadCount: allDownloads.length,
|
|
121
|
+
formats: allDownloads.map((d) => d.format ?? null),
|
|
122
|
+
}), children: [_jsxs(DropdownMenuSubTrigger, { children: [_jsx(Download, { className: "mr-4 w-4 h-4" }), "Download"] }), _jsx(DropdownMenuSubContent, { children: _jsx(ArticleDownloadItems, {}) })] }))), hasExports && !hide_exports && (_jsxs(DropdownMenuSub, { onOpenChange: (open) => open &&
|
|
123
|
+
capture('article_exports_submenu_opened', {
|
|
124
|
+
exportCount: projectExports.length + articleExports.length,
|
|
125
|
+
formats: [...projectExports, ...articleExports].map((e) => e.format ?? null),
|
|
126
|
+
}), children: [_jsxs(DropdownMenuSubTrigger, { children: [_jsx(FolderCode, { className: "mr-4 w-4 h-4" }), "Exports"] }), _jsx(DropdownMenuSubContent, { children: _jsx(ArticleExportItems, {}) })] })), _jsx(ArticleVersionsMenu, {}), _jsx(Citation, { onOpenChange: (open) => open && capture('article_citation_opened', { surface: 'actions_menu' }), children: _jsxs(DropdownMenuItem, { onSelect: (e) => e.preventDefault(), children: [_jsx(Quote, { className: "mr-2 w-4 h-4" }), "Cite Article"] }) }), hasShareOptions && (_jsxs(DropdownMenuSub, { onOpenChange: (open) => open && capture('article_share_submenu_opened'), children: [_jsxs(DropdownMenuSubTrigger, { children: [_jsx(Share, { className: "mr-4 w-4 h-4" }), "Share"] }), _jsx(DropdownMenuSubContent, { children: _jsx(ArticleActionsShare, { title: article?.title || '' }) })] })), project?.github && (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs("a", { href: project.github, target: "_blank", rel: "noopener noreferrer", onClick: () => capture('article_repo_clicked', {
|
|
127
|
+
repoUrl: project.github,
|
|
128
|
+
surface: 'actions_menu',
|
|
129
|
+
}), children: [_jsx(BlocksIcon, { className: "mr-2 w-4 h-4" }), "GitHub Repository"] }) })), doiString && (_jsxs(DropdownMenuItem, { onClick: handleCopyDOI, children: [_jsx(Copy, { className: "mr-2 w-4 h-4" }), "Copy DOI"] })), hasLicenseSection && (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs(HashLink, { id: PART_IDS.license, title: null, className: "flex items-center px-2 py-1.5 text-sm cursor-pointer outline-none focus:bg-accent focus:text-accent-foreground hover:no-underline", scrollBehavior: "instant", scrollDelay: 300, analyticsEvent: "article_license_anchor_clicked", analytics: {
|
|
130
|
+
linkKind: 'license_information_menu',
|
|
131
|
+
properties: { surface: 'actions_menu' },
|
|
132
|
+
}, children: [_jsx(Scale, { className: "mr-2 w-4 h-4" }), "License Information"] }) })), _jsx(DropdownMenuSeparator, {}), article?.edit_url && (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs("a", { href: article?.edit_url, target: "_blank", rel: "noopener noreferrer", onClick: () => capture('article_edit_source_clicked', {
|
|
133
|
+
editUrl: article?.edit_url,
|
|
134
|
+
provider: editProvider,
|
|
135
|
+
}), children: [_jsx(Pencil, { className: "mr-2 w-4 h-4" }), editProvider === 'github'
|
|
64
136
|
? 'Edit in GitHub'
|
|
65
|
-
:
|
|
137
|
+
: editProvider === 'gitlab'
|
|
66
138
|
? 'Edit in GitLab'
|
|
67
|
-
: 'Edit source'] }) })), _jsxs(DropdownMenuSub, {
|
|
139
|
+
: 'Edit source'] }) })), _jsxs(DropdownMenuSub, { onOpenChange: (open) => open && capture('theme_submenu_opened', { currentTheme: theme }), children: [_jsxs(DropdownMenuSubTrigger, { children: [theme === 'dark' ? (_jsx(Sun, { className: "mr-2 w-4 h-4" })) : (_jsx(Moon, { className: "mr-2 w-4 h-4" })), "Theme"] }), _jsxs(DropdownMenuSubContent, { children: [_jsxs(DropdownMenuItem, { onClick: () => {
|
|
140
|
+
capture('theme_changed', { theme: 'light', previousTheme: theme });
|
|
141
|
+
setTheme('light');
|
|
142
|
+
}, children: [_jsx(Sun, { className: "mr-2 w-4 h-4" }), "Light"] }), _jsxs(DropdownMenuItem, { onClick: () => {
|
|
143
|
+
capture('theme_changed', { theme: 'dark', previousTheme: theme });
|
|
144
|
+
setTheme('dark');
|
|
145
|
+
}, children: [_jsx(Moon, { className: "mr-2 w-4 h-4" }), "Dark"] }), _jsxs(DropdownMenuItem, { onClick: () => {
|
|
146
|
+
capture('theme_changed', { theme: 'system', previousTheme: theme });
|
|
147
|
+
setTheme('system');
|
|
148
|
+
}, children: [_jsx(Monitor, { className: "mr-2 w-4 h-4" }), "System"] })] })] })] })] }));
|
|
68
149
|
}
|
|
@@ -1,5 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { DesignOptions } from '@curvenote/common';
|
|
3
|
+
type ShareDestination = 'bluesky' | 'semble' | 'linkedin' | 'x' | 'email';
|
|
4
|
+
/**
|
|
5
|
+
* Returns share options visible under the current design configuration.
|
|
6
|
+
* Returns an empty array when the entire share menu is hidden via
|
|
7
|
+
* `hide_social_shares`, otherwise filters by per-platform `hide_social_share_*` flags.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useVisibleShareOptions(): {
|
|
10
|
+
name: string;
|
|
11
|
+
destination: ShareDestination;
|
|
12
|
+
hideKey: keyof DesignOptions;
|
|
13
|
+
Icon: React.ComponentType<{
|
|
14
|
+
className?: string;
|
|
15
|
+
}>;
|
|
16
|
+
getUrl: (url: string, title: string) => string;
|
|
17
|
+
}[];
|
|
1
18
|
export declare function ArticleActionsShare({ url, title }: {
|
|
2
19
|
url?: string;
|
|
3
20
|
title: string;
|
|
4
21
|
}): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export {};
|
|
5
23
|
//# sourceMappingURL=article-actions-share.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"article-actions-share.d.ts","sourceRoot":"","sources":["../../../src/components/ui/article-actions-share.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"article-actions-share.d.ts","sourceRoot":"","sources":["../../../src/components/ui/article-actions-share.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAavD,KAAK,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,GAAG,GAAG,OAAO,CAAC;AAoE1E;;;;GAIG;AACH,wBAAgB,sBAAsB;UAtE9B,MAAM;iBACC,gBAAgB;aACpB,MAAM,aAAa;UACtB,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;YACzC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM;IAsE/C;AAED,wBAAgB,mBAAmB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,2CAqClF"}
|
|
@@ -4,10 +4,13 @@ import { DropdownMenuItem } from '.';
|
|
|
4
4
|
import { BlueskyIcon,
|
|
5
5
|
// RedditIcon,
|
|
6
6
|
// FacebookIcon,
|
|
7
|
-
LinkedinIcon, XIcon, EmailIcon, } from '@scienceicons/react/24/solid';
|
|
7
|
+
LinkedinIcon, XIcon, EmailIcon, SembleIcon, } from '@scienceicons/react/24/solid';
|
|
8
|
+
import { useAnalytics, useDesign } from '../providers';
|
|
8
9
|
const SHARE_OPTIONS = [
|
|
9
10
|
{
|
|
10
11
|
name: 'Bluesky',
|
|
12
|
+
destination: 'bluesky',
|
|
13
|
+
hideKey: 'hide_social_share_bluesky',
|
|
11
14
|
Icon: BlueskyIcon,
|
|
12
15
|
getUrl: (url, title) => `https://bsky.app/intent/compose?text=${encodeURIComponent(title + ' ' + url)}`,
|
|
13
16
|
},
|
|
@@ -27,26 +30,59 @@ const SHARE_OPTIONS = [
|
|
|
27
30
|
// },
|
|
28
31
|
{
|
|
29
32
|
name: 'Linkedin',
|
|
33
|
+
destination: 'linkedin',
|
|
34
|
+
hideKey: 'hide_social_share_linkedin',
|
|
30
35
|
Icon: LinkedinIcon,
|
|
31
36
|
getUrl: (url, title) => `https://www.linkedin.com/shareArticle?url=${encodeURIComponent(url)}&title=${encodeURIComponent(title)}`,
|
|
32
37
|
},
|
|
33
38
|
{
|
|
34
39
|
name: '𝕏',
|
|
40
|
+
destination: 'x',
|
|
41
|
+
hideKey: 'hide_social_share_x',
|
|
35
42
|
Icon: XIcon,
|
|
36
43
|
getUrl: (url, title) => `https://twitter.com/intent/tweet?text=${encodeURIComponent(title)}&url=${encodeURIComponent(url)}`,
|
|
37
44
|
},
|
|
45
|
+
{
|
|
46
|
+
name: 'Semble',
|
|
47
|
+
destination: 'semble',
|
|
48
|
+
hideKey: 'hide_social_share_semble',
|
|
49
|
+
Icon: SembleIcon,
|
|
50
|
+
getUrl: (url) => `https://semble.so/url?id=${encodeURIComponent(url)}`,
|
|
51
|
+
},
|
|
38
52
|
{
|
|
39
53
|
name: 'Email',
|
|
54
|
+
destination: 'email',
|
|
55
|
+
hideKey: 'hide_social_share_email',
|
|
40
56
|
Icon: EmailIcon,
|
|
41
57
|
getUrl: (url, title) => `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(url)}`,
|
|
42
58
|
},
|
|
43
59
|
];
|
|
60
|
+
/**
|
|
61
|
+
* Returns share options visible under the current design configuration.
|
|
62
|
+
* Returns an empty array when the entire share menu is hidden via
|
|
63
|
+
* `hide_social_shares`, otherwise filters by per-platform `hide_social_share_*` flags.
|
|
64
|
+
*/
|
|
65
|
+
export function useVisibleShareOptions() {
|
|
66
|
+
const design = useDesign();
|
|
67
|
+
if (design.hide_social_shares)
|
|
68
|
+
return [];
|
|
69
|
+
return SHARE_OPTIONS.filter(({ hideKey }) => !design[hideKey]);
|
|
70
|
+
}
|
|
44
71
|
export function ArticleActionsShare({ url, title }) {
|
|
45
72
|
const [shareUrl, setShareUrl] = useState(url || '');
|
|
73
|
+
const capture = useAnalytics();
|
|
74
|
+
const visibleOptions = useVisibleShareOptions();
|
|
46
75
|
useEffect(() => {
|
|
47
76
|
if (!url) {
|
|
48
77
|
setShareUrl(window.location.href);
|
|
49
78
|
}
|
|
50
79
|
}, [url]);
|
|
51
|
-
return (_jsx(_Fragment, { children:
|
|
80
|
+
return (_jsx(_Fragment, { children: visibleOptions.map(({ name, destination, Icon, getUrl }) => {
|
|
81
|
+
const targetUrl = getUrl(shareUrl, title);
|
|
82
|
+
return (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs("a", { href: targetUrl, target: "_blank", rel: "noopener noreferrer", "aria-label": `Share on ${name}`, onClick: () => capture('article_share_clicked', {
|
|
83
|
+
destination,
|
|
84
|
+
shareUrl: targetUrl,
|
|
85
|
+
surface: 'actions_menu_share_submenu',
|
|
86
|
+
}), children: [_jsx(Icon, { className: "mr-2 w-4 h-4" }), name] }) }, name));
|
|
87
|
+
}) }));
|
|
52
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"article-actions.d.ts","sourceRoot":"","sources":["../../../src/components/ui/article-actions.tsx"],"names":[],"mappings":"AASA,wBAAgB,cAAc,
|
|
1
|
+
{"version":3,"file":"article-actions.d.ts","sourceRoot":"","sources":["../../../src/components/ui/article-actions.tsx"],"names":[],"mappings":"AASA,wBAAgB,cAAc,4CA6G7B"}
|
|
@@ -5,16 +5,29 @@ import { Citation } from './citation';
|
|
|
5
5
|
import { ArticleActionsDropdown } from './article-actions-dropdown';
|
|
6
6
|
import { useDownloads } from './article-actions-downloads';
|
|
7
7
|
import { SearchDialog } from './search';
|
|
8
|
-
import { useDesign } from '../providers';
|
|
8
|
+
import { useAnalytics, useDesign } from '../providers';
|
|
9
9
|
import { useBaseurl, withBaseurl } from '@myst-theme/providers';
|
|
10
10
|
export function ArticleActions() {
|
|
11
11
|
const { projectDownloads, articleDownloads } = useDownloads();
|
|
12
12
|
const design = useDesign();
|
|
13
13
|
const baseurl = useBaseurl();
|
|
14
|
+
const capture = useAnalytics();
|
|
14
15
|
// Combine all downloads for PDF search
|
|
15
16
|
const allDownloads = [...projectDownloads, ...articleDownloads];
|
|
16
17
|
// Find PDF download
|
|
17
18
|
const pdfDownload = allDownloads.find((download) => download.format?.toLowerCase() === 'pdf' || download.url?.toLowerCase().endsWith('.pdf'));
|
|
18
|
-
const
|
|
19
|
-
|
|
19
|
+
const pdfDownloadScope = pdfDownload && projectDownloads.includes(pdfDownload) ? 'project' : 'article';
|
|
20
|
+
// When nice_pdf_links is disabled, always use the server-provided download URL rather than the
|
|
21
|
+
// rewritten `{baseurl}.pdf` link, which may not resolve in environments like theme previews.
|
|
22
|
+
const useNicePdfLink = design.nice_pdf_links !== false;
|
|
23
|
+
const pdfDownloadUrl = useNicePdfLink && baseurl ? withBaseurl('.pdf', baseurl) : pdfDownload?.url;
|
|
24
|
+
return (_jsxs("div", { className: "flex gap-2 items-center", children: [!design.hide_search && (_jsx(SearchDialog, { onOpenChange: (open) => open && capture('search_opened', { surface: 'article_bar' }), children: _jsx(SimpleTooltip, { title: "Search", children: _jsx(Button, { variant: "outline", size: "icon", "aria-label": "Search", asChild: true, children: _jsx("div", { children: _jsx(SearchIcon, {}) }) }) }) })), pdfDownload && (_jsx(SimpleTooltip, { title: "Download PDF", children: _jsx(Button, { variant: "outline", className: "hidden cursor-pointer sm:inline-flex", size: "icon", "aria-label": "Download PDF", asChild: true, children: _jsx("a", { href: pdfDownloadUrl, target: "_blank", rel: "noopener noreferrer", onClick: () => capture('article_download', {
|
|
25
|
+
action: 'clicked',
|
|
26
|
+
category: 'download',
|
|
27
|
+
format: 'pdf',
|
|
28
|
+
downloadUrl: pdfDownloadUrl,
|
|
29
|
+
downloadFilename: pdfDownload.filename,
|
|
30
|
+
scope: pdfDownloadScope,
|
|
31
|
+
surface: 'article_bar_button',
|
|
32
|
+
}), children: _jsx(FileDown, {}) }) }) })), _jsx(Citation, { onOpenChange: (open) => open && capture('article_citation_opened', { surface: 'article_bar_button' }), children: _jsx(SimpleTooltip, { title: "Cite this article", children: _jsx(Button, { variant: "outline", className: "hidden cursor-pointer sm:inline-flex", size: "icon", "aria-label": "Cite this article", children: _jsx(QuoteIcon, {}) }) }) }), _jsx(ArticleActionsDropdown, { onOpenChange: (open) => open && capture('article_actions_menu_opened', { surface: 'article_bar' }), children: _jsx(SimpleTooltip, { title: "More article actions", children: _jsx(Button, { variant: "ghost", size: "icon", className: "cursor-pointer", "aria-label": "More article actions", children: _jsx(EllipsisVerticalIcon, {}) }) }) })] }));
|
|
20
33
|
}
|