@datalayer/primer-addons 1.0.17 → 1.0.18
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/lib/App.js +2 -2
- package/lib/components/box/Box.d.ts +1 -2
- package/lib/components/content-loader/ContentLoader.js +4 -2
- package/lib/components/icons/CircleIcon.js +6 -4
- package/lib/components/index.d.ts +1 -1
- package/lib/components/index.js +1 -1
- package/lib/components/logo/AI2.d.ts +20 -0
- package/lib/components/logo/AI2.js +23 -0
- package/lib/components/logo/DI.d.ts +19 -0
- package/lib/components/logo/DI.js +20 -0
- package/lib/components/logo/index.d.ts +2 -0
- package/lib/components/logo/index.js +2 -0
- package/lib/components/{overlay/Overlay.d.ts → side-overlay/SideOverlay.d.ts} +3 -3
- package/lib/components/{overlay/Overlay.js → side-overlay/SideOverlay.js} +16 -16
- package/lib/components/side-overlay/SideOverlay.stories.d.ts +16 -0
- package/lib/components/{overlay/Overlay.stories.js → side-overlay/SideOverlay.stories.js} +13 -13
- package/lib/components/slider/Slider.js +2 -1
- package/lib/components/toolbar/FloatingToolbar.js +2 -2
- package/lib/theme/css/createThemeCSSVars.js +7 -0
- package/lib/theme/useThemeStore.d.ts +5 -3
- package/lib/theme/useThemeStore.js +78 -9
- package/package.json +6 -4
- package/lib/components/overlay/Overlay.stories.d.ts +0 -16
package/lib/App.js
CHANGED
|
@@ -3,7 +3,7 @@ import { useState, useRef } from "react";
|
|
|
3
3
|
import { BaseStyles, Box, Text, NavList, Heading, ThemeProvider, Button, theme, ActionMenu, IconButton, ActionList } from "@primer/react";
|
|
4
4
|
import { KebabHorizontalIcon } from "@primer/octicons-react";
|
|
5
5
|
import { DatalayerIcon, LogOutIcon, SettingsIcon } from "@datalayer/icons-react";
|
|
6
|
-
import { Slider,
|
|
6
|
+
import { Slider, SideOverlay } from ".";
|
|
7
7
|
import "@primer/primitives/dist/css/base/typography/typography.css";
|
|
8
8
|
import "@primer/primitives/dist/css/base/motion/motion.css";
|
|
9
9
|
import "@primer/primitives/dist/css/functional/themes/light.css";
|
|
@@ -20,6 +20,6 @@ const App = () => {
|
|
|
20
20
|
const openButtonRef = useRef(null);
|
|
21
21
|
const closeButtonRef = useRef(null);
|
|
22
22
|
const headingRef = useRef(null);
|
|
23
|
-
return (_jsx(ThemeProvider, { colorMode: "day", theme: theme, children: _jsxs(BaseStyles, { children: [_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: KebabHorizontalIcon, variant: "invisible", "aria-label": "jupyter-runtimes-more" }) }), _jsx(ActionMenu.Overlay, { width: "medium", children: _jsxs(ActionList, { children: [_jsxs(ActionList.Group, { children: [_jsx(ActionList.GroupHeading, { children: "More\u2026" }), _jsxs(ActionList.Item, { onSelect: () => alert('click'), children: [_jsx(ActionList.LeadingVisual, { children: _jsx(SettingsIcon, {}) }), "Settings", _jsx(ActionList.Description, { variant: "block", children: "Configure your personal settings." })] }), _jsxs(ActionList.Item, { onSelect: () => alert('click'), children: [_jsx(ActionList.LeadingVisual, { children: _jsx(DatalayerIcon, {}) }), "About", _jsx(ActionList.Description, { variant: "block", children: "About Runtimes." })] })] }), _jsxs(_Fragment, { children: [_jsx(ActionList.Divider, {}), _jsxs(ActionList.Item, { variant: "danger", onSelect: () => alert('click'), children: [_jsx(ActionList.LeadingVisual, { children: _jsx(LogOutIcon, {}) }), "Logout"] })] })] }) })] }), _jsxs(Box, { bg: "canvas.default", sx: { display: 'flex' }, children: [_jsx(Box, { children: _jsxs(NavList, { children: [_jsx(NavList.Item, { href: "/", "aria-current": "page", children: "Home" }), _jsx(NavList.Item, { href: "/about", children: "About" }), _jsx(NavList.Item, { href: "/contact", children: "Contact" })] }) }), _jsxs(Box, { p: 3, sx: { flexGrow: 1 }, children: [_jsx(Box, { children: _jsx(Text, { children: "Primer React Addons" }) }), _jsx(Box, { children: _jsx(Slider, { id: "slider", name: "slider", min: 1, max: 10, onChange: () => { } }) }), _jsx(Box, { p: 3, bg: "canvas.default", children: _jsxs(Box, { children: [_jsx(Box, { sx: { width: '100%', bg: 'darkgray' }, children: _jsx(Heading, { ref: headingRef, children: "Header" }) }), _jsxs(Box, { children: [_jsx(Button, { ref: openButtonRef, onClick: () => { setIsOpen(!isOpen); }, children: "Open overlay" }), _jsx(
|
|
23
|
+
return (_jsx(ThemeProvider, { colorMode: "day", theme: theme, children: _jsxs(BaseStyles, { children: [_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: KebabHorizontalIcon, variant: "invisible", "aria-label": "jupyter-runtimes-more" }) }), _jsx(ActionMenu.Overlay, { width: "medium", children: _jsxs(ActionList, { children: [_jsxs(ActionList.Group, { children: [_jsx(ActionList.GroupHeading, { children: "More\u2026" }), _jsxs(ActionList.Item, { onSelect: () => alert('click'), children: [_jsx(ActionList.LeadingVisual, { children: _jsx(SettingsIcon, {}) }), "Settings", _jsx(ActionList.Description, { variant: "block", children: "Configure your personal settings." })] }), _jsxs(ActionList.Item, { onSelect: () => alert('click'), children: [_jsx(ActionList.LeadingVisual, { children: _jsx(DatalayerIcon, {}) }), "About", _jsx(ActionList.Description, { variant: "block", children: "About Runtimes." })] })] }), _jsxs(_Fragment, { children: [_jsx(ActionList.Divider, {}), _jsxs(ActionList.Item, { variant: "danger", onSelect: () => alert('click'), children: [_jsx(ActionList.LeadingVisual, { children: _jsx(LogOutIcon, {}) }), "Logout"] })] })] }) })] }), _jsxs(Box, { bg: "canvas.default", sx: { display: 'flex' }, children: [_jsx(Box, { children: _jsxs(NavList, { children: [_jsx(NavList.Item, { href: "/", "aria-current": "page", children: "Home" }), _jsx(NavList.Item, { href: "/about", children: "About" }), _jsx(NavList.Item, { href: "/contact", children: "Contact" })] }) }), _jsxs(Box, { p: 3, sx: { flexGrow: 1 }, children: [_jsx(Box, { children: _jsx(Text, { children: "Primer React Addons" }) }), _jsx(Box, { children: _jsx(Slider, { id: "slider", name: "slider", min: 1, max: 10, onChange: () => { } }) }), _jsx(Box, { p: 3, bg: "canvas.default", children: _jsxs(Box, { children: [_jsx(Box, { sx: { width: '100%', bg: 'darkgray' }, children: _jsx(Heading, { ref: headingRef, children: "Header" }) }), _jsxs(Box, { children: [_jsx(Button, { ref: openButtonRef, onClick: () => { setIsOpen(!isOpen); }, children: "Open overlay" }), _jsx(SideOverlay, { isOpen: isOpen, content: _jsxs(Text, { children: ["Look, I am an ", _jsx(Button, { children: "Overlay \uD83D\uDC49" })] }), setIsOpen: setIsOpen, openButtonRef: openButtonRef, closeButtonRef: closeButtonRef, headingRef: headingRef })] })] }) })] })] })] }) }));
|
|
24
24
|
};
|
|
25
25
|
export default App;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ComponentProps } from 'react';
|
|
2
2
|
import type { BackgroundProps, BorderProps, ColorProps, FlexboxProps, GridProps, LayoutProps, PositionProps, ShadowProps, SpaceProps, TypographyProps } from 'styled-system';
|
|
3
3
|
import { type SxProp } from './sx';
|
|
4
|
-
|
|
5
|
-
export declare const Box: import("styled-components").StyledComponent<"div", any, StyledBoxProps, never>;
|
|
4
|
+
export declare const Box: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "sx" | keyof SpaceProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> | keyof ColorProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> | keyof TypographyProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof LayoutProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof FlexboxProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof GridProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof BackgroundProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Background<import("styled-system").TLengthStyledSystem>> | keyof BorderProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Border<import("styled-system").TLengthStyledSystem>> | keyof PositionProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof ShadowProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>>> & SxProp & SpaceProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> & ColorProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> & TypographyProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & LayoutProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & FlexboxProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & GridProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & BackgroundProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Background<import("styled-system").TLengthStyledSystem>> & BorderProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Border<import("styled-system").TLengthStyledSystem>> & PositionProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & ShadowProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>>, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "sx" | keyof SpaceProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> | keyof ColorProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> | keyof TypographyProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof LayoutProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof FlexboxProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof GridProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof BackgroundProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Background<import("styled-system").TLengthStyledSystem>> | keyof BorderProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Border<import("styled-system").TLengthStyledSystem>> | keyof PositionProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> | keyof ShadowProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>>> & SxProp & SpaceProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> & ColorProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> & TypographyProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & LayoutProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & FlexboxProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & GridProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & BackgroundProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Background<import("styled-system").TLengthStyledSystem>> & BorderProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Border<import("styled-system").TLengthStyledSystem>> & PositionProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & ShadowProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>>, never>>> & string;
|
|
6
5
|
export type BoxProps = ComponentProps<typeof Box>;
|
|
7
6
|
export default Box;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Box } from "@primer/react";
|
|
2
|
+
import { Box, useTheme } from "@primer/react";
|
|
3
3
|
import Skeleton, { SkeletonTheme } from "react-loading-skeleton";
|
|
4
4
|
import 'react-loading-skeleton/dist/skeleton.css';
|
|
5
5
|
export const ContentLoader = (props) => {
|
|
6
|
-
|
|
6
|
+
const { colorMode } = useTheme();
|
|
7
|
+
const isDark = colorMode !== 'day';
|
|
8
|
+
return (_jsx(Box, { children: _jsx(SkeletonTheme, { baseColor: isDark ? 'var(--bgColor-muted, #21262d)' : 'var(--bgColor-muted, #ebebeb)', highlightColor: isDark ? 'var(--borderColor-muted, #30363d)' : 'var(--borderColor-muted, #f5f5f5)', children: _jsx(Skeleton, { ...props }) }) }));
|
|
7
9
|
};
|
|
8
10
|
export default ContentLoader;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useTheme } from '@primer/react';
|
|
3
3
|
import { CircleCurrentColorIcon } from '@datalayer/icons-react';
|
|
4
|
-
const COLORS = {
|
|
5
|
-
'danger': 'danger',
|
|
6
|
-
};
|
|
7
4
|
export const CircleIcon = ({ color = 'white', variant = 'fg', }) => {
|
|
8
5
|
const { theme } = useTheme();
|
|
9
|
-
|
|
6
|
+
const colorGroup = theme?.colors?.[color];
|
|
7
|
+
const resolvedColor = colorGroup && typeof colorGroup === 'object'
|
|
8
|
+
? colorGroup[variant] ??
|
|
9
|
+
colorGroup.fg
|
|
10
|
+
: undefined;
|
|
11
|
+
return (_jsx(CircleCurrentColorIcon, { fill: resolvedColor ?? color ?? 'currentColor', color: resolvedColor ?? color ?? 'currentColor' }));
|
|
10
12
|
};
|
|
11
13
|
export default CircleIcon;
|
|
@@ -5,7 +5,7 @@ export * from "./card/Card";
|
|
|
5
5
|
export * from "./content-loader/ContentLoader";
|
|
6
6
|
export * from "./closeable-flash/CloseableFlash";
|
|
7
7
|
export * from "./icons/CircleIcon";
|
|
8
|
-
export * from "./overlay/
|
|
8
|
+
export * from "./side-overlay/SideOverlay";
|
|
9
9
|
export * from "./slider/Slider";
|
|
10
10
|
export * from "./logo";
|
|
11
11
|
export * from "./appearance";
|
package/lib/components/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export * from "./card/Card";
|
|
|
5
5
|
export * from "./content-loader/ContentLoader";
|
|
6
6
|
export * from "./closeable-flash/CloseableFlash";
|
|
7
7
|
export * from "./icons/CircleIcon";
|
|
8
|
-
export * from "./overlay/
|
|
8
|
+
export * from "./side-overlay/SideOverlay";
|
|
9
9
|
export * from "./slider/Slider";
|
|
10
10
|
export * from "./logo";
|
|
11
11
|
export * from "./appearance";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type SVGProps } from 'react';
|
|
2
|
+
import { type ThemeVariant } from '../../theme';
|
|
3
|
+
export interface AI2Props extends Omit<SVGProps<SVGSVGElement>, 'ref'> {
|
|
4
|
+
size?: number;
|
|
5
|
+
variant?: ThemeVariant;
|
|
6
|
+
colorMode?: 'light' | 'dark' | 'auto';
|
|
7
|
+
/** Colour of the "I" glyph. */
|
|
8
|
+
primaryColor?: string;
|
|
9
|
+
/** Colour of the "A" glyph. */
|
|
10
|
+
secondaryColor?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Alternate AI glyph mark.
|
|
14
|
+
*
|
|
15
|
+
* A is rendered with an oblique left bar, a right vertical bar,
|
|
16
|
+
* and a horizontal crossbar.
|
|
17
|
+
* I is rendered as a simple vertical bar.
|
|
18
|
+
*/
|
|
19
|
+
export declare const AI2: import("react").ForwardRefExoticComponent<AI2Props & import("react").RefAttributes<SVGSVGElement>>;
|
|
20
|
+
export default AI2;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { forwardRef } from 'react';
|
|
7
|
+
import { getLogoColors } from './DatalayerLogo';
|
|
8
|
+
/**
|
|
9
|
+
* Alternate AI glyph mark.
|
|
10
|
+
*
|
|
11
|
+
* A is rendered with an oblique left bar, a right vertical bar,
|
|
12
|
+
* and a horizontal crossbar.
|
|
13
|
+
* I is rendered as a simple vertical bar.
|
|
14
|
+
*/
|
|
15
|
+
export const AI2 = forwardRef(function AI2({ size = 24, variant = 'datalayer', colorMode = 'light', primaryColor, secondaryColor, ...svgProps }, ref) {
|
|
16
|
+
const themed = getLogoColors(variant, colorMode);
|
|
17
|
+
const resolvedPrimary = primaryColor ?? themed.primary;
|
|
18
|
+
const resolvedSecondary = secondaryColor ?? themed.textColor;
|
|
19
|
+
const barWidth = 3.1;
|
|
20
|
+
const leftBarBottomInnerX = -2.2 + barWidth;
|
|
21
|
+
return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "-2.2 0 26.2 24", width: size, height: size, role: "img", "aria-label": "AI2", ref: ref, ...svgProps, children: [_jsx("path", { d: `M15.35 3.5h${barWidth}V20h-${barWidth}z`, fill: resolvedPrimary }), _jsx("path", { d: `M-2.2 20 9.8 3.5h${barWidth}L${leftBarBottomInnerX} 20H-2.2z`, fill: resolvedSecondary }), _jsx("path", { d: `M10.35 3.5h${barWidth}V20h-${barWidth}z`, fill: resolvedSecondary }), _jsx("path", { d: "M3.5 12.95h9.6v2.75H3.5z", fill: resolvedSecondary })] }));
|
|
22
|
+
});
|
|
23
|
+
export default AI2;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type SVGProps } from 'react';
|
|
2
|
+
import { type ThemeVariant } from '../../theme';
|
|
3
|
+
export interface DIProps extends Omit<SVGProps<SVGSVGElement>, 'ref'> {
|
|
4
|
+
size?: number;
|
|
5
|
+
variant?: ThemeVariant;
|
|
6
|
+
colorMode?: 'light' | 'dark' | 'auto';
|
|
7
|
+
/** Colour of the "I" glyph. */
|
|
8
|
+
primaryColor?: string;
|
|
9
|
+
/** Colour of the "D" glyph. */
|
|
10
|
+
secondaryColor?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* DI glyph mark.
|
|
14
|
+
*
|
|
15
|
+
* Uses the same public API and semantic color mapping as AI:
|
|
16
|
+
* primaryColor styles the "I", secondaryColor styles the "D".
|
|
17
|
+
*/
|
|
18
|
+
export declare const DI: import("react").ForwardRefExoticComponent<DIProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
19
|
+
export default DI;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { forwardRef } from 'react';
|
|
7
|
+
import { getLogoColors } from './DatalayerLogo';
|
|
8
|
+
/**
|
|
9
|
+
* DI glyph mark.
|
|
10
|
+
*
|
|
11
|
+
* Uses the same public API and semantic color mapping as AI:
|
|
12
|
+
* primaryColor styles the "I", secondaryColor styles the "D".
|
|
13
|
+
*/
|
|
14
|
+
export const DI = forwardRef(function DI({ size = 24, variant = 'datalayer', colorMode = 'light', primaryColor, secondaryColor, ...svgProps }, ref) {
|
|
15
|
+
const themed = getLogoColors(variant, colorMode);
|
|
16
|
+
const resolvedPrimary = primaryColor ?? themed.primary;
|
|
17
|
+
const resolvedSecondary = secondaryColor ?? themed.textColor;
|
|
18
|
+
return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", width: size, height: size, role: "img", "aria-label": "DI", ref: ref, ...svgProps, children: [_jsx("path", { d: "M2 3.932H5V20.068075H2ZM3.5 3.932H6.5L12.933 20.068075H9.933ZM2 17.068075H11.4V20.068075H2Z", fill: resolvedSecondary, strokeWidth: 0.25 }), _jsx("path", { d: "m10.788825 3.932 6.43325 16.136075h3.5279L14.316725 3.932H10.788825Z", fill: resolvedPrimary, strokeWidth: 0.25 })] }));
|
|
19
|
+
});
|
|
20
|
+
export default DI;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface SideOverlayProps {
|
|
2
2
|
closeButtonRef?: React.RefObject<HTMLButtonElement>;
|
|
3
3
|
content: JSX.Element;
|
|
4
4
|
direction?: 'left' | 'right';
|
|
@@ -9,5 +9,5 @@ export interface OverlayProps {
|
|
|
9
9
|
width?: number | string;
|
|
10
10
|
zIndex?: number;
|
|
11
11
|
}
|
|
12
|
-
export declare const
|
|
13
|
-
export default
|
|
12
|
+
export declare const SideOverlay: ({ width, direction, zIndex, ...rest }: SideOverlayProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export default SideOverlay;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
|
-
import { IconButton, Overlay as PrimerOverlay,
|
|
3
|
+
import { IconButton, Overlay as PrimerOverlay, ThemeProvider, useTheme } from "@primer/react";
|
|
4
4
|
import { XIcon } from "@primer/octicons-react";
|
|
5
5
|
import { Box } from '../box/Box';
|
|
6
6
|
const PrimerAddonOverlay = (props) => {
|
|
@@ -25,19 +25,19 @@ const PrimerAddonOverlay = (props) => {
|
|
|
25
25
|
}
|
|
26
26
|
closeOverlay();
|
|
27
27
|
};
|
|
28
|
-
const overlayContent = (_jsx(ThemeProvider, { theme: theme, colorMode: colorMode, children:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
const overlayContent = (_jsx(ThemeProvider, { theme: theme, colorMode: colorMode, children: _jsxs(Box, { sx: {
|
|
29
|
+
/* We need to remove the padding */
|
|
30
|
+
height: `calc(100vh - ${top}px - 8px)`,
|
|
31
|
+
width,
|
|
32
|
+
display: 'flex',
|
|
33
|
+
flexDirection: 'column',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
padding: '4px'
|
|
36
|
+
}, children: [_jsx(Box, { sx: {
|
|
37
|
+
display: 'flex',
|
|
38
|
+
justifyContent: 'right',
|
|
39
|
+
width: '100%'
|
|
40
|
+
}, children: _jsx(IconButton, { variant: 'invisible', ref: closeButtonRef, onClick: closeOverlay, icon: XIcon, "aria-labelledby": "close" }) }), content] }) }));
|
|
41
41
|
return (closeButtonRef && openButtonRef ?
|
|
42
42
|
_jsx(_Fragment, { children: isOpen ?
|
|
43
43
|
direction === 'left' ?
|
|
@@ -48,7 +48,7 @@ const PrimerAddonOverlay = (props) => {
|
|
|
48
48
|
:
|
|
49
49
|
_jsx(_Fragment, {}));
|
|
50
50
|
};
|
|
51
|
-
export const
|
|
51
|
+
export const SideOverlay = ({ width = '500px', direction = 'left', zIndex = 100, ...rest }) => {
|
|
52
52
|
return (_jsx(PrimerAddonOverlay, { width: width, direction: direction, zIndex: zIndex, ...rest }));
|
|
53
53
|
};
|
|
54
|
-
export default
|
|
54
|
+
export default SideOverlay;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/react';
|
|
2
|
+
import { SideOverlayProps } from '../..';
|
|
3
|
+
declare const meta: {
|
|
4
|
+
title: string;
|
|
5
|
+
component: ({ width, direction, zIndex, ...rest }: SideOverlayProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
tags: string[];
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export default meta;
|
|
12
|
+
type Story = StoryObj<typeof meta>;
|
|
13
|
+
export declare const SideOverlayDayLeft: Story;
|
|
14
|
+
export declare const SideOverlayDayRight: Story;
|
|
15
|
+
export declare const SideOverlayNightLeft: Story;
|
|
16
|
+
export declare const SideOverlayNightRight: Story;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useRef } from "react";
|
|
3
3
|
import { Heading, Text, Box, Button } from "@primer/react";
|
|
4
|
-
import {
|
|
4
|
+
import { SideOverlay } from '../..';
|
|
5
5
|
const meta = {
|
|
6
|
-
title: 'Components/
|
|
7
|
-
component:
|
|
6
|
+
title: 'Components/SideOverlay',
|
|
7
|
+
component: SideOverlay,
|
|
8
8
|
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
|
|
9
9
|
tags: ['autodocs'],
|
|
10
10
|
parameters: {
|
|
@@ -13,42 +13,42 @@ const meta = {
|
|
|
13
13
|
},
|
|
14
14
|
};
|
|
15
15
|
export default meta;
|
|
16
|
-
const
|
|
16
|
+
const ThemedSideOverlay = (props) => {
|
|
17
17
|
const [isOpen, setIsOpen] = useState(false);
|
|
18
18
|
const openButtonRef = useRef(null);
|
|
19
19
|
const closeButtonRef = useRef(null);
|
|
20
20
|
const headingRef = useRef(null);
|
|
21
|
-
return (_jsx(Box, { p: 3, bg: "canvas.default", children: _jsxs(Box, { children: [_jsx(Box, { sx: { width: '100%', bg: 'darkgray' }, children: _jsx(Heading, { ref: headingRef, children: "Header" }) }), _jsxs(Box, { children: [_jsx(Button, { ref: openButtonRef, onClick: () => { setIsOpen(!isOpen); }, children: "Open overlay" }), _jsx(
|
|
21
|
+
return (_jsx(Box, { p: 3, bg: "canvas.default", children: _jsxs(Box, { children: [_jsx(Box, { sx: { width: '100%', bg: 'darkgray' }, children: _jsx(Heading, { ref: headingRef, children: "Header" }) }), _jsxs(Box, { children: [_jsx(Button, { ref: openButtonRef, onClick: () => { setIsOpen(!isOpen); }, children: "Open overlay" }), _jsx(SideOverlay, { ...props, isOpen: isOpen, setIsOpen: setIsOpen, openButtonRef: openButtonRef, closeButtonRef: closeButtonRef })] })] }) }));
|
|
22
22
|
};
|
|
23
|
-
export const
|
|
23
|
+
export const SideOverlayDayLeft = {
|
|
24
24
|
args: {
|
|
25
25
|
content: _jsx(Text, { children: "\uD83D\uDC48 Look, left aligned, no heading." }),
|
|
26
26
|
direction: "left",
|
|
27
27
|
width: '500px',
|
|
28
28
|
},
|
|
29
|
-
render: (args) => _jsx(
|
|
29
|
+
render: (args) => _jsx(ThemedSideOverlay, { ...args, colorMode: "day" })
|
|
30
30
|
};
|
|
31
|
-
export const
|
|
31
|
+
export const SideOverlayDayRight = {
|
|
32
32
|
args: {
|
|
33
33
|
content: _jsx(Text, { children: "Look, right aligned, on heading \uD83D\uDC49" }),
|
|
34
34
|
direction: "right",
|
|
35
35
|
width: '500px',
|
|
36
36
|
},
|
|
37
|
-
render: (args) => _jsx(
|
|
37
|
+
render: (args) => _jsx(ThemedSideOverlay, { ...args, colorMode: "day" })
|
|
38
38
|
};
|
|
39
|
-
export const
|
|
39
|
+
export const SideOverlayNightLeft = {
|
|
40
40
|
args: {
|
|
41
41
|
content: _jsx(Text, { children: "\uD83D\uDC48 Look, left aligned, no heading." }),
|
|
42
42
|
direction: "left",
|
|
43
43
|
width: '300px',
|
|
44
44
|
},
|
|
45
|
-
render: (args) => _jsx(
|
|
45
|
+
render: (args) => _jsx(ThemedSideOverlay, { ...args, colorMode: "night" })
|
|
46
46
|
};
|
|
47
|
-
export const
|
|
47
|
+
export const SideOverlayNightRight = {
|
|
48
48
|
args: {
|
|
49
49
|
content: _jsx(Text, { children: "Look, right aligned, on heading \uD83D\uDC49" }),
|
|
50
50
|
direction: "right",
|
|
51
51
|
width: '300px',
|
|
52
52
|
},
|
|
53
|
-
render: (args) => _jsx(
|
|
53
|
+
render: (args) => _jsx(ThemedSideOverlay, { ...args, colorMode: "night" })
|
|
54
54
|
};
|
|
@@ -17,7 +17,8 @@ export const Slider = ({ name = "slider", id = "slider", min = 0, max = 10, valu
|
|
|
17
17
|
const sliderStyle = {
|
|
18
18
|
width,
|
|
19
19
|
...(orientation === "vertical" ? { transform: "rotate(-90deg)" } : {}),
|
|
20
|
-
colorScheme: colorMode == 'day' ? 'light' : 'dark'
|
|
20
|
+
colorScheme: colorMode == 'day' ? 'light' : 'dark',
|
|
21
|
+
accentColor: 'var(--fgColor-accent)',
|
|
21
22
|
};
|
|
22
23
|
return (_jsxs(Box, { display: "flex", alignItems: "center", children: [_jsx("input", { type: "range", id: id, name: name, min: min, max: max, value: sliderVal, step: step ?? "any", list: "slider-markers", style: sliderStyle, onChange: handleSliderChange, disabled: disabled }), markers && step && (_jsx("datalist", { id: "slider-markers", children: Array.from({ length: Math.floor((max - min) / step) + 1 }, (_, i) => min + i * step).map((e) => (
|
|
23
24
|
// TODO: Supply markers as array and show them here
|
|
@@ -114,9 +114,9 @@ export function FloatingToolbar({ items, extraItems, anchorElement, isVisible, c
|
|
|
114
114
|
gap: '2px',
|
|
115
115
|
px: 1,
|
|
116
116
|
py: '4px',
|
|
117
|
-
bg: '
|
|
117
|
+
bg: 'var(--overlay-bgColor, var(--bgColor-default))',
|
|
118
118
|
border: '1px solid',
|
|
119
|
-
borderColor: '
|
|
119
|
+
borderColor: 'var(--borderColor-muted, transparent)',
|
|
120
120
|
borderRadius: 2,
|
|
121
121
|
boxShadow: 'shadow.large',
|
|
122
122
|
position: 'absolute',
|
|
@@ -43,6 +43,13 @@ export function colorDefsToCSS(defs) {
|
|
|
43
43
|
'--bgColor-default': defs.canvas.default,
|
|
44
44
|
'--bgColor-inset': defs.canvas.default,
|
|
45
45
|
...optional,
|
|
46
|
+
/* ── Overlay (portaled surfaces: menus, dialogs, popovers) ────
|
|
47
|
+
* Primer's <Overlay> paints its surface with `var(--overlay-bgColor)`,
|
|
48
|
+
* which normally ships in @primer/primitives. Apps using this theme do
|
|
49
|
+
* NOT load primitives CSS, so define the overlay tokens here to avoid
|
|
50
|
+
* transparent overlay panels. */
|
|
51
|
+
'--overlay-bgColor': defs.canvas.default,
|
|
52
|
+
'--overlay-backdrop-bgColor': 'rgba(0, 0, 0, 0.5)',
|
|
46
53
|
/* ── Foreground / Text ───────────────────────────────────────── */
|
|
47
54
|
'--fgColor-default': defs.fg.default,
|
|
48
55
|
'--fgColor-muted': defs.fg.muted,
|
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
import { type StoreApi, type UseBoundStore } from 'zustand';
|
|
23
23
|
import type { ThemeVariant } from './themeRegistry';
|
|
24
24
|
import type { ColorMode } from './DatalayerBrandThemeProvider';
|
|
25
|
-
|
|
26
|
-
export type VariantDefaults = Record<string, {
|
|
25
|
+
export type VariantPreference = {
|
|
27
26
|
theme: ThemeVariant;
|
|
28
27
|
colorMode: ColorMode;
|
|
29
|
-
|
|
28
|
+
version?: number;
|
|
29
|
+
};
|
|
30
|
+
/** Per-variant theme + colorMode preferences. */
|
|
31
|
+
export type VariantDefaults = Record<string, VariantPreference>;
|
|
30
32
|
export interface ThemeState {
|
|
31
33
|
/** Current color mode (light, dark, or auto = follow OS). */
|
|
32
34
|
colorMode: ColorMode;
|
|
@@ -26,6 +26,33 @@
|
|
|
26
26
|
import { create } from 'zustand';
|
|
27
27
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
28
28
|
import { themeConfigs } from './themeRegistry';
|
|
29
|
+
const VARIANT_SCHEMA_VERSION = 1;
|
|
30
|
+
function normalizeVariantPreference(pref) {
|
|
31
|
+
return {
|
|
32
|
+
theme: pref.theme,
|
|
33
|
+
colorMode: pref.colorMode,
|
|
34
|
+
version: typeof pref.version === 'number' ? pref.version : VARIANT_SCHEMA_VERSION,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function normalizeVariants(variants) {
|
|
38
|
+
if (!variants) {
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
const normalized = {};
|
|
42
|
+
for (const [key, pref] of Object.entries(variants)) {
|
|
43
|
+
if (!pref || typeof pref !== 'object' || !('theme' in pref) || !('colorMode' in pref)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
normalized[key] = normalizeVariantPreference(pref);
|
|
47
|
+
}
|
|
48
|
+
return normalized;
|
|
49
|
+
}
|
|
50
|
+
function hasMissingVariantVersion(variants) {
|
|
51
|
+
if (!variants || Object.keys(variants).length === 0) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return Object.values(variants).some(pref => typeof pref?.version !== 'number');
|
|
55
|
+
}
|
|
29
56
|
/* ── Helpers ─────────────────────────────────────────────────────── */
|
|
30
57
|
const colorModeCycle = {
|
|
31
58
|
light: 'dark',
|
|
@@ -49,7 +76,7 @@ export function createThemeStore(storageKey, defaults) {
|
|
|
49
76
|
theme: defaults?.theme ?? 'matrix',
|
|
50
77
|
/* ── variant state ──────────────────────────────────── */
|
|
51
78
|
activeVariant: null,
|
|
52
|
-
variants: defaults?.variants
|
|
79
|
+
variants: normalizeVariants(defaults?.variants),
|
|
53
80
|
/* ── actions ────────────────────────────────────────── */
|
|
54
81
|
toggleColorMode: () => set(state => {
|
|
55
82
|
const next = colorModeCycle[state.colorMode];
|
|
@@ -58,7 +85,11 @@ export function createThemeStore(storageKey, defaults) {
|
|
|
58
85
|
colorMode: next,
|
|
59
86
|
variants: {
|
|
60
87
|
...state.variants,
|
|
61
|
-
[state.activeVariant]: {
|
|
88
|
+
[state.activeVariant]: {
|
|
89
|
+
...state.variants[state.activeVariant],
|
|
90
|
+
colorMode: next,
|
|
91
|
+
version: VARIANT_SCHEMA_VERSION,
|
|
92
|
+
},
|
|
62
93
|
},
|
|
63
94
|
};
|
|
64
95
|
}
|
|
@@ -70,7 +101,11 @@ export function createThemeStore(storageKey, defaults) {
|
|
|
70
101
|
colorMode: mode,
|
|
71
102
|
variants: {
|
|
72
103
|
...state.variants,
|
|
73
|
-
[state.activeVariant]: {
|
|
104
|
+
[state.activeVariant]: {
|
|
105
|
+
...state.variants[state.activeVariant],
|
|
106
|
+
colorMode: mode,
|
|
107
|
+
version: VARIANT_SCHEMA_VERSION,
|
|
108
|
+
},
|
|
74
109
|
},
|
|
75
110
|
};
|
|
76
111
|
}
|
|
@@ -86,7 +121,11 @@ export function createThemeStore(storageKey, defaults) {
|
|
|
86
121
|
colorMode: nextColorMode,
|
|
87
122
|
variants: {
|
|
88
123
|
...state.variants,
|
|
89
|
-
[state.activeVariant]: {
|
|
124
|
+
[state.activeVariant]: {
|
|
125
|
+
theme,
|
|
126
|
+
colorMode: nextColorMode,
|
|
127
|
+
version: VARIANT_SCHEMA_VERSION,
|
|
128
|
+
},
|
|
90
129
|
},
|
|
91
130
|
};
|
|
92
131
|
}
|
|
@@ -96,7 +135,13 @@ export function createThemeStore(storageKey, defaults) {
|
|
|
96
135
|
const merged = { ...state.variants };
|
|
97
136
|
for (const [key, val] of Object.entries(defs)) {
|
|
98
137
|
if (!merged[key]) {
|
|
99
|
-
merged[key] = val;
|
|
138
|
+
merged[key] = normalizeVariantPreference(val);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
merged[key] = normalizeVariantPreference({
|
|
142
|
+
...merged[key],
|
|
143
|
+
version: merged[key].version ?? VARIANT_SCHEMA_VERSION,
|
|
144
|
+
});
|
|
100
145
|
}
|
|
101
146
|
}
|
|
102
147
|
return { variants: merged };
|
|
@@ -114,7 +159,7 @@ export function createThemeStore(storageKey, defaults) {
|
|
|
114
159
|
}),
|
|
115
160
|
}), {
|
|
116
161
|
name: storageKey,
|
|
117
|
-
version:
|
|
162
|
+
version: 3,
|
|
118
163
|
storage: createJSONStorage(() => localStorage),
|
|
119
164
|
partialize: state => ({
|
|
120
165
|
colorMode: state.colorMode,
|
|
@@ -127,7 +172,31 @@ export function createThemeStore(storageKey, defaults) {
|
|
|
127
172
|
* value the persisted state is discarded and the store starts fresh
|
|
128
173
|
* from code-defined defaults.
|
|
129
174
|
*/
|
|
130
|
-
migrate:
|
|
175
|
+
migrate: persisted => {
|
|
176
|
+
const p = (persisted ?? {});
|
|
177
|
+
const legacyVariants = p.variants;
|
|
178
|
+
const missingVariantVersion = hasMissingVariantVersion(legacyVariants);
|
|
179
|
+
const variants = normalizeVariants(legacyVariants);
|
|
180
|
+
// Legacy snapshots without per-variant versions are upgraded to v1.
|
|
181
|
+
// Anonymous defaults are forced to matrix/dark during this upgrade.
|
|
182
|
+
if (missingVariantVersion) {
|
|
183
|
+
variants['agent-anonymous'] = {
|
|
184
|
+
theme: 'matrix',
|
|
185
|
+
colorMode: 'dark',
|
|
186
|
+
version: VARIANT_SCHEMA_VERSION,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
...p,
|
|
191
|
+
variants,
|
|
192
|
+
...(missingVariantVersion
|
|
193
|
+
? {
|
|
194
|
+
theme: p.activeVariant === 'agent-anonymous' ? 'matrix' : p.theme,
|
|
195
|
+
colorMode: p.activeVariant === 'agent-anonymous' ? 'dark' : p.colorMode,
|
|
196
|
+
}
|
|
197
|
+
: {}),
|
|
198
|
+
};
|
|
199
|
+
},
|
|
131
200
|
/**
|
|
132
201
|
* Deep-merge variants during hydration so that:
|
|
133
202
|
* - Code-defined variants (from defaults or registerVariants) are
|
|
@@ -139,11 +208,11 @@ export function createThemeStore(storageKey, defaults) {
|
|
|
139
208
|
const p = (persisted ?? {});
|
|
140
209
|
// Build merged variants: start from code-defined, then overlay
|
|
141
210
|
// any persisted variant whose prefs differ (user customisations).
|
|
142
|
-
const mergedVariants =
|
|
211
|
+
const mergedVariants = normalizeVariants(current.variants);
|
|
143
212
|
if (p.variants) {
|
|
144
213
|
for (const [key, val] of Object.entries(p.variants)) {
|
|
145
214
|
if (val && typeof val === 'object' && 'theme' in val) {
|
|
146
|
-
mergedVariants[key] = val;
|
|
215
|
+
mergedVariants[key] = normalizeVariantPreference(val);
|
|
147
216
|
}
|
|
148
217
|
}
|
|
149
218
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalayer/primer-addons",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsc && vite build",
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
"build:lib": "npm run clean:lib&& tsc -b",
|
|
9
9
|
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
|
|
10
10
|
"dev": "vite",
|
|
11
|
+
"gallery": "npm --prefix examples/gallery run dev",
|
|
12
|
+
"gallery:build": "npm --prefix examples/gallery run build",
|
|
11
13
|
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
12
14
|
"preview": "vite preview",
|
|
13
15
|
"start": "vite",
|
|
@@ -27,9 +29,9 @@
|
|
|
27
29
|
"homepage": "https://primer-addons.datalayer.tech",
|
|
28
30
|
"dependencies": {
|
|
29
31
|
"@datalayer/icons-react": "^1.0.0",
|
|
30
|
-
"@primer/octicons-react": "^19.
|
|
31
|
-
"@primer/primitives": "^10.
|
|
32
|
-
"@primer/react": "^37.
|
|
32
|
+
"@primer/octicons-react": "^19.29.1",
|
|
33
|
+
"@primer/primitives": "^10.7.0",
|
|
34
|
+
"@primer/react": "^37.31.0",
|
|
33
35
|
"react": "^18.3.1 || ^19.0.0",
|
|
34
36
|
"react-dom": "^18.3.1 || ^19.0.0",
|
|
35
37
|
"react-loading-skeleton": "^3.5.0",
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { StoryObj } from '@storybook/react';
|
|
2
|
-
import { OverlayProps } from '../..';
|
|
3
|
-
declare const meta: {
|
|
4
|
-
title: string;
|
|
5
|
-
component: ({ width, direction, zIndex, ...rest }: OverlayProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
-
tags: string[];
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: string;
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
export default meta;
|
|
12
|
-
type Story = StoryObj<typeof meta>;
|
|
13
|
-
export declare const OverlayDayLeft: Story;
|
|
14
|
-
export declare const OverlayDayRight: Story;
|
|
15
|
-
export declare const OverlayNightLeft: Story;
|
|
16
|
-
export declare const OverlayNightRight: Story;
|