@datalayer/primer-addons 1.0.7 → 1.0.9

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.
Files changed (45) hide show
  1. package/lib/components/box/sx.d.ts +3 -1
  2. package/lib/components/box/sx.js +1 -1
  3. package/lib/components/overlay/Overlay.js +15 -2
  4. package/lib/components/toolbar/FloatingToolbar.js +18 -12
  5. package/lib/components/toolbar/Toolbar.js +1 -1
  6. package/lib/components/toolbar/ToolbarButton.js +1 -1
  7. package/lib/components/toolbar/ToolbarDropdown.js +68 -17
  8. package/lib/components/toolbar/types.d.ts +6 -0
  9. package/lib/index.d.ts +1 -0
  10. package/lib/index.js +2 -0
  11. package/lib/theme/DatalayerBrandThemeProvider.d.ts +41 -0
  12. package/lib/theme/DatalayerBrandThemeProvider.js +32 -0
  13. package/lib/theme/DatalayerThemeProvider.d.ts +36 -0
  14. package/lib/theme/DatalayerThemeProvider.js +35 -0
  15. package/lib/theme/Palette.d.ts +4 -0
  16. package/lib/theme/Palette.js +10 -0
  17. package/lib/theme/colors/datalayerColors.d.ts +15 -0
  18. package/lib/theme/colors/datalayerColors.js +21 -0
  19. package/lib/theme/colors/index.d.ts +4 -0
  20. package/lib/theme/colors/index.js +8 -0
  21. package/lib/theme/colors/lovelyColors.d.ts +15 -0
  22. package/lib/theme/colors/lovelyColors.js +21 -0
  23. package/lib/theme/colors/matrixColors.d.ts +20 -0
  24. package/lib/theme/colors/matrixColors.js +26 -0
  25. package/lib/theme/colors/spatialColors.d.ts +15 -0
  26. package/lib/theme/colors/spatialColors.js +21 -0
  27. package/lib/theme/index.d.ts +11 -0
  28. package/lib/theme/index.js +15 -0
  29. package/lib/theme/themes/createThemeCSSVars.d.ts +131 -0
  30. package/lib/theme/themes/createThemeCSSVars.js +172 -0
  31. package/lib/theme/themes/datalayerTheme.d.ts +1093 -0
  32. package/lib/theme/themes/datalayerTheme.js +191 -0
  33. package/lib/theme/themes/lovelyTheme.d.ts +1093 -0
  34. package/lib/theme/themes/lovelyTheme.js +190 -0
  35. package/lib/theme/themes/matrixTheme.d.ts +1093 -0
  36. package/lib/theme/themes/matrixTheme.js +190 -0
  37. package/lib/theme/themes/spatialTheme.d.ts +1093 -0
  38. package/lib/theme/themes/spatialTheme.js +190 -0
  39. package/lib/theme/themes-brand/index.d.ts +1 -0
  40. package/lib/theme/themes-brand/index.js +5 -0
  41. package/lib/theme/themes-brand/spatialBrandTheme.d.ts +16 -0
  42. package/lib/theme/themes-brand/spatialBrandTheme.js +157 -0
  43. package/lib/theme/useSystemColorMode.d.ts +9 -0
  44. package/lib/theme/useSystemColorMode.js +26 -0
  45. package/package.json +1 -1
@@ -16,6 +16,8 @@ export type BetterSystemStyleObject = BetterCssProperties | SystemStyleObject |
16
16
  export interface SxProp {
17
17
  sx?: BetterSystemStyleObject;
18
18
  }
19
- declare const sx: (props: SxProp) => import("@styled-system/css").CssFunctionReturnType;
19
+ declare const sx: (props: SxProp & {
20
+ theme?: Record<string, unknown>;
21
+ }) => import("@styled-system/css").CSSObject;
20
22
  export default sx;
21
23
  export { merge };
@@ -5,6 +5,6 @@
5
5
  */
6
6
  import css from '@styled-system/css';
7
7
  import merge from 'deepmerge';
8
- const sx = (props) => css(props.sx);
8
+ const sx = (props) => css(props.sx)(props.theme ?? {});
9
9
  export default sx;
10
10
  export { merge };
@@ -12,6 +12,19 @@ const PrimerAddonOverlay = (props) => {
12
12
  setTop(headingRef?.current?.getBoundingClientRect().bottom ?? 0);
13
13
  }, [headingRef]);
14
14
  const closeOverlay = () => setIsOpen(false);
15
+ /**
16
+ * Don't close the overlay when the click outside lands on a portaled
17
+ * Dialog (role="dialog"). Primer Dialogs render in a portal at
18
+ * document.body, so they are "outside" the Overlay DOM tree and would
19
+ * otherwise trigger an unwanted close.
20
+ */
21
+ const handleClickOutside = (e) => {
22
+ if (e.target instanceof HTMLElement &&
23
+ e.target.closest('[role="dialog"]')) {
24
+ return;
25
+ }
26
+ closeOverlay();
27
+ };
15
28
  const overlayContent = (_jsx(ThemeProvider, { theme: theme, colorMode: colorMode, children: _jsx(BaseStyles, { children: _jsxs(Box, { sx: {
16
29
  /* We need to remove the padding */
17
30
  height: `calc(100vh - ${top}px - 8px)`,
@@ -28,9 +41,9 @@ const PrimerAddonOverlay = (props) => {
28
41
  return (closeButtonRef && openButtonRef ?
29
42
  _jsx(_Fragment, { children: isOpen ?
30
43
  direction === 'left' ?
31
- _jsx(Box, { sx: { zIndex }, children: _jsx(PrimerOverlay, { initialFocusRef: closeButtonRef, returnFocusRef: openButtonRef, ignoreClickRefs: [openButtonRef], onEscape: closeOverlay, onClickOutside: closeOverlay, width: "auto", anchorSide: "inside-right", left: 0, position: "fixed", top: top, children: overlayContent }) })
44
+ _jsx(Box, { sx: { zIndex }, children: _jsx(PrimerOverlay, { initialFocusRef: closeButtonRef, returnFocusRef: openButtonRef, ignoreClickRefs: [openButtonRef], onEscape: closeOverlay, onClickOutside: handleClickOutside, width: "auto", anchorSide: "inside-right", left: 0, position: "fixed", top: top, children: overlayContent }) })
32
45
  :
33
- _jsx(Box, { sx: { zIndex }, children: _jsx(PrimerOverlay, { initialFocusRef: closeButtonRef, returnFocusRef: openButtonRef, ignoreClickRefs: [openButtonRef], onEscape: closeOverlay, onClickOutside: closeOverlay, width: "auto", anchorSide: 'inside-left', right: 0, position: "fixed", top: top, children: overlayContent }) })
46
+ _jsx(Box, { sx: { zIndex }, children: _jsx(PrimerOverlay, { initialFocusRef: closeButtonRef, returnFocusRef: openButtonRef, ignoreClickRefs: [openButtonRef], onEscape: closeOverlay, onClickOutside: handleClickOutside, width: "auto", anchorSide: 'inside-left', right: 0, position: "fixed", top: top, children: overlayContent }) })
34
47
  : _jsx(_Fragment, {}) })
35
48
  :
36
49
  _jsx(_Fragment, {}));
@@ -31,8 +31,7 @@ import { ToolbarRenderer } from './ToolbarRenderer';
31
31
  * Position the floating element relative to a DOMRect within an anchor element.
32
32
  */
33
33
  function setFloatingPosition(targetRect, floatingElem, anchorElem, verticalGap = 10, horizontalOffset = 5) {
34
- const scrollerElem = anchorElem.parentElement;
35
- if (targetRect === null || !scrollerElem) {
34
+ if (targetRect === null) {
36
35
  floatingElem.style.opacity = '0';
37
36
  floatingElem.style.transform = 'translateY(-4px)';
38
37
  floatingElem.style.top = '-10000px';
@@ -41,17 +40,21 @@ function setFloatingPosition(targetRect, floatingElem, anchorElem, verticalGap =
41
40
  }
42
41
  const floatingElemRect = floatingElem.getBoundingClientRect();
43
42
  const anchorElementRect = anchorElem.getBoundingClientRect();
44
- const editorScrollerRect = scrollerElem.getBoundingClientRect();
45
- let top = targetRect.top - floatingElemRect.height - verticalGap;
46
- let left = targetRect.left -
47
- horizontalOffset -
48
- (anchorElementRect.left - editorScrollerRect.left);
49
- // Keep within anchor bounds
50
- if (top < anchorElementRect.top) {
51
- top = targetRect.bottom + verticalGap;
43
+ // Convert viewport-relative coordinates to anchor-relative coordinates.
44
+ // The toolbar is position:absolute inside anchorElem (position:relative),
45
+ // so top/left must be relative to the anchor's border box.
46
+ let top = targetRect.top - anchorElementRect.top - floatingElemRect.height - verticalGap;
47
+ let left = targetRect.left - anchorElementRect.left - horizontalOffset;
48
+ // If toolbar would go above the anchor, flip it below the selection
49
+ if (top < 0) {
50
+ top = targetRect.bottom - anchorElementRect.top + verticalGap;
52
51
  }
53
- if (left + floatingElemRect.width > editorScrollerRect.right) {
54
- left = editorScrollerRect.right - floatingElemRect.width - horizontalOffset;
52
+ // Keep within horizontal bounds
53
+ if (left + floatingElemRect.width > anchorElementRect.width) {
54
+ left = anchorElementRect.width - floatingElemRect.width - horizontalOffset;
55
+ }
56
+ if (left < horizontalOffset) {
57
+ left = horizontalOffset;
55
58
  }
56
59
  floatingElem.style.opacity = '1';
57
60
  floatingElem.style.transform = 'translateY(0)';
@@ -85,6 +88,8 @@ export function FloatingToolbar({ items, extraItems, anchorElement, isVisible, c
85
88
  return;
86
89
  const update = () => updatePosition();
87
90
  window.addEventListener('resize', update);
91
+ // Capture phase catches scroll on any ancestor (page, container, etc.)
92
+ window.addEventListener('scroll', update, true);
88
93
  const scrollerElem = anchorElement?.parentElement;
89
94
  if (scrollerElem) {
90
95
  scrollerElem.addEventListener('scroll', update);
@@ -93,6 +98,7 @@ export function FloatingToolbar({ items, extraItems, anchorElement, isVisible, c
93
98
  update();
94
99
  return () => {
95
100
  window.removeEventListener('resize', update);
101
+ window.removeEventListener('scroll', update, true);
96
102
  if (scrollerElem) {
97
103
  scrollerElem.removeEventListener('scroll', update);
98
104
  }
@@ -44,7 +44,7 @@ export function Toolbar({ items, extraItems, className, disabled, ariaLabel = 'E
44
44
  borderColor: 'border.default',
45
45
  position: 'sticky',
46
46
  top: 0,
47
- zIndex: 2,
47
+ zIndex: 1,
48
48
  }, children: _jsx(ToolbarRenderer, { items: allItems, disabled: disabled, size: "medium" }) }));
49
49
  }
50
50
  export default Toolbar;
@@ -38,7 +38,7 @@ export function ToolbarButton({ item, size = 'medium' }) {
38
38
  iconElement = _jsx("span", { style: { fontSize: 12, fontWeight: 600, lineHeight: 1 }, children: label });
39
39
  }
40
40
  const btnSize = size === 'small' ? 28 : 32;
41
- return (_jsx("button", { type: "button", "aria-label": ariaLabel, title: title, onClick: onClick, disabled: disabled, style: {
41
+ return (_jsx("button", { type: "button", "aria-label": ariaLabel, title: title, onMouseDown: (e) => e.preventDefault(), onClick: onClick, disabled: disabled, style: {
42
42
  display: 'inline-flex',
43
43
  alignItems: 'center',
44
44
  justifyContent: 'center',
@@ -8,34 +8,85 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  *
9
9
  * Uses Primer React ActionMenu for accessible dropdown menus.
10
10
  *
11
+ * The trigger button highlights (accent colour) when any option is active,
12
+ * matching the behavior of regular ToolbarButton items.
13
+ *
14
+ * All option rows render a fixed-width LeadingVisual slot so that labels
15
+ * stay left-aligned regardless of whether the option has an icon.
16
+ *
11
17
  * @module components/toolbar/ToolbarDropdown
12
18
  */
13
- import { isValidElement } from 'react';
19
+ import { isValidElement, useMemo } from 'react';
14
20
  import { ActionMenu, ActionList, Text } from '@primer/react';
15
21
  import { Box } from '../box/Box';
22
+ /**
23
+ * Resolve an icon prop to a ReactNode.
24
+ *
25
+ * Octicon components use React.forwardRef which returns an *object*
26
+ * (typeof === 'object'), NOT a function. We check isValidElement first
27
+ * (already-instantiated JSX), then treat anything else as a component type.
28
+ */
16
29
  function renderIcon(icon) {
17
30
  if (!icon)
18
31
  return null;
19
- if (typeof icon === 'function') {
20
- const IconComp = icon;
21
- return _jsx(IconComp, { size: 16 });
22
- }
23
32
  if (isValidElement(icon)) {
24
33
  return icon;
25
34
  }
26
- return null;
35
+ // Component type: function component, forwardRef, or memo wrapper
36
+ const IconComp = icon;
37
+ return _jsx(IconComp, { size: 16 });
38
+ }
39
+ /** Whether any dropdown option in the list has an icon. */
40
+ function hasAnyIcon(options) {
41
+ return options.some(o => !!o.icon);
27
42
  }
28
43
  export function ToolbarDropdown({ item, size = 'medium' }) {
29
- const { ariaLabel, icon, label, options, disabled } = item;
30
- return (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { "aria-label": ariaLabel, disabled: disabled, variant: "invisible", size: size, sx: {
31
- color: 'fg.muted',
32
- fontWeight: 'normal',
33
- fontSize: size === 'small' ? 0 : 1,
34
- px: 2,
35
- '&:hover:not([disabled])': {
36
- bg: 'neutral.muted',
37
- color: 'fg.default',
38
- },
39
- }, children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [renderIcon(icon), label && (_jsx(Text, { sx: { fontSize: size === 'small' ? 0 : 1 }, children: label }))] }) }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsx(ActionList, { children: options.map(option => (_jsxs(ActionList.Item, { onSelect: option.onClick, disabled: option.disabled, active: option.isActive, children: [option.icon && (_jsx(ActionList.LeadingVisual, { children: renderIcon(option.icon) })), _jsxs(Box, { sx: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', gap: 3 }, children: [_jsx(Text, { children: option.label }), option.shortcut && (_jsx(Text, { sx: { color: 'fg.subtle', fontSize: 0, fontFamily: 'mono' }, children: option.shortcut }))] })] }, option.key))) }) })] }));
44
+ const { ariaLabel, icon, label, minWidth, options, disabled } = item;
45
+ // Highlight the trigger when any option is active.
46
+ const anyActive = useMemo(() => options.some(o => o.isActive), [options]);
47
+ // If any option has an icon we reserve a leading-visual column for all rows.
48
+ const showLeadingVisual = useMemo(() => hasAnyIcon(options), [options]);
49
+ const btnSize = size === 'small' ? 28 : 32;
50
+ return (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsxs("button", { type: "button", "aria-label": ariaLabel, title: ariaLabel, disabled: disabled, style: {
51
+ display: 'inline-flex',
52
+ alignItems: 'center',
53
+ justifyContent: 'center',
54
+ gap: 4,
55
+ minWidth: btnSize,
56
+ height: btnSize,
57
+ padding: label ? '0 8px' : 0,
58
+ margin: 0,
59
+ border: 'none',
60
+ borderRadius: 6,
61
+ cursor: disabled ? 'not-allowed' : 'pointer',
62
+ background: anyActive
63
+ ? 'var(--bgColor-accent-muted, rgba(9,105,218,0.1))'
64
+ : 'transparent',
65
+ color: anyActive
66
+ ? 'var(--fgColor-accent, #0969da)'
67
+ : 'var(--fgColor-muted, #656d76)',
68
+ opacity: disabled ? 0.5 : 1,
69
+ fontSize: size === 'small' ? 12 : 14,
70
+ fontWeight: 'normal',
71
+ fontFamily: 'inherit',
72
+ lineHeight: 1,
73
+ }, onMouseEnter: (e) => {
74
+ if (!disabled) {
75
+ e.currentTarget.style.background =
76
+ 'var(--bgColor-neutral-muted, rgba(175,184,193,0.2))';
77
+ e.currentTarget.style.color = 'var(--fgColor-default, #1f2328)';
78
+ }
79
+ }, onMouseLeave: (e) => {
80
+ e.currentTarget.style.background = anyActive
81
+ ? 'var(--bgColor-accent-muted, rgba(9,105,218,0.1))'
82
+ : 'transparent';
83
+ e.currentTarget.style.color = anyActive
84
+ ? 'var(--fgColor-accent, #0969da)'
85
+ : 'var(--fgColor-muted, #656d76)';
86
+ }, children: [renderIcon(icon), label && (_jsx("span", { style: {
87
+ display: 'inline-block',
88
+ minWidth: minWidth ? minWidth : undefined,
89
+ textAlign: 'left',
90
+ }, children: label }))] }) }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsx(ActionList, { children: options.map(option => (_jsxs(ActionList.Item, { onSelect: option.onClick, disabled: option.disabled, active: option.isActive, children: [showLeadingVisual && (_jsx(ActionList.LeadingVisual, { children: option.icon ? renderIcon(option.icon) : _jsx(Box, { sx: { width: 16 } }) })), _jsxs(Box, { sx: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', gap: 3 }, children: [_jsx(Text, { children: option.label }), option.shortcut && (_jsx(Text, { sx: { color: 'fg.subtle', fontSize: 0, fontFamily: 'mono' }, children: option.shortcut }))] })] }, option.key))) }) })] }));
40
91
  }
41
92
  export default ToolbarDropdown;
@@ -73,6 +73,12 @@ export interface ToolbarDropdownItem extends ToolbarItemBase {
73
73
  icon?: React.ComponentType<IconProps> | ReactNode;
74
74
  /** Text label for the trigger */
75
75
  label?: string;
76
+ /**
77
+ * Fixed minimum width (in px) for the trigger's label area.
78
+ * Set this to the width of the longest possible label so the
79
+ * toolbar doesn't reflow when the selection changes.
80
+ */
81
+ minWidth?: number;
76
82
  /** Dropdown options */
77
83
  options: ToolbarDropdownOption[];
78
84
  }
package/lib/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./components";
2
2
  export * from "./utils";
3
+ export * from './theme';
package/lib/index.js CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from "./components";
2
2
  export * from "./utils";
3
+ // Export Theme.
4
+ export * from './theme';
@@ -0,0 +1,41 @@
1
+ import { type CSSProperties, type ReactNode } from 'react';
2
+ import type { BrandTheme } from './themes-brand/spatialBrandTheme';
3
+ export type ColorMode = 'light' | 'dark' | 'auto';
4
+ export interface IDatalayerBrandThemeProviderProps {
5
+ /**
6
+ * Color mode to use.
7
+ * - `'light'` / `'dark'` — explicit override
8
+ * - `'auto'` — follow the operating system preference (prefers-color-scheme)
9
+ */
10
+ colorMode?: ColorMode;
11
+ /**
12
+ * A brand theme object with per-mode CSS variable overrides.
13
+ * Each key (`light` / `dark`) is a `CSSProperties` map whose entries
14
+ * are `--brand-color-*` / `--brand-button-*` custom properties.
15
+ *
16
+ * When omitted, the default Primer Brand tokens are used unchanged.
17
+ */
18
+ brandTheme?: BrandTheme;
19
+ /**
20
+ * Additional inline styles merged on top of the resolved brand theme.
21
+ */
22
+ style?: CSSProperties;
23
+ children: ReactNode;
24
+ }
25
+ /**
26
+ * Theme provider for Primer Brand (`@primer/react-brand`) components.
27
+ *
28
+ * Works by passing CSS custom-property overrides as inline `style` to
29
+ * `ThemeProvider`, which scopes them to its DOM subtree — exactly how
30
+ * the VS Code extension re-skins Primer via CSS variables.
31
+ *
32
+ * ```tsx
33
+ * import { DatalayerBrandThemeProvider } from '@datalayer/core/lib/theme';
34
+ * import { spatialBrandTheme } from '@datalayer/core/lib/theme/themes-brand/spatialBrandTheme';
35
+ *
36
+ * <DatalayerBrandThemeProvider colorMode="dark" brandTheme={spatialBrandTheme}>
37
+ * <Hero>…</Hero>
38
+ * </DatalayerBrandThemeProvider>
39
+ * ```
40
+ */
41
+ export declare function DatalayerBrandThemeProvider({ colorMode, brandTheme, style, children, }: IDatalayerBrandThemeProviderProps): JSX.Element;
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ThemeProvider as PrimerBrandThemeProvider } from '@primer/react-brand';
3
+ import { useSystemColorMode } from './useSystemColorMode';
4
+ /**
5
+ * Theme provider for Primer Brand (`@primer/react-brand`) components.
6
+ *
7
+ * Works by passing CSS custom-property overrides as inline `style` to
8
+ * `ThemeProvider`, which scopes them to its DOM subtree — exactly how
9
+ * the VS Code extension re-skins Primer via CSS variables.
10
+ *
11
+ * ```tsx
12
+ * import { DatalayerBrandThemeProvider } from '@datalayer/core/lib/theme';
13
+ * import { spatialBrandTheme } from '@datalayer/core/lib/theme/themes-brand/spatialBrandTheme';
14
+ *
15
+ * <DatalayerBrandThemeProvider colorMode="dark" brandTheme={spatialBrandTheme}>
16
+ * <Hero>…</Hero>
17
+ * </DatalayerBrandThemeProvider>
18
+ * ```
19
+ */
20
+ export function DatalayerBrandThemeProvider({ colorMode = 'light', brandTheme, style, children, }) {
21
+ const systemMode = useSystemColorMode();
22
+ const resolved = colorMode === 'auto' ? systemMode : colorMode;
23
+ const themeOverrides = brandTheme
24
+ ? resolved === 'dark'
25
+ ? brandTheme.dark
26
+ : brandTheme.light
27
+ : undefined;
28
+ return (_jsx(PrimerBrandThemeProvider, { colorMode: resolved, style: {
29
+ ...themeOverrides,
30
+ ...style,
31
+ }, children: children }));
32
+ }
@@ -0,0 +1,36 @@
1
+ import { type CSSProperties } from 'react';
2
+ import { ThemeProviderProps } from '@primer/react';
3
+ export interface IDatalayerThemeProviderProps extends Omit<ThemeProviderProps, 'theme' | 'colorMode'> {
4
+ /**
5
+ * Color mode to use.
6
+ * - `'light'` / `'dark'` — explicit override
7
+ * - `'auto'` — follow the operating system preference (prefers-color-scheme)
8
+ * - Primer's `'day'` / `'night'` are still accepted.
9
+ */
10
+ colorMode?: 'light' | 'dark' | 'auto' | 'day' | 'night';
11
+ /**
12
+ * Additional base styles merged on top of theme defaults.
13
+ */
14
+ baseStyles?: CSSProperties;
15
+ /**
16
+ * Optional Primer theme object. Defaults to the built-in datalayerTheme
17
+ * (which is the unmodified default Primer theme — all theming is done
18
+ * via CSS custom-property overrides in `themeStyles`).
19
+ */
20
+ theme?: Record<string, any>;
21
+ /**
22
+ * Per-mode CSS-property overrides (background, foreground, and all
23
+ * Primer functional-token CSS custom properties).
24
+ *
25
+ * When provided, these replace the built-in datalayer styles entirely.
26
+ * The `baseStyles` prop is still merged on top.
27
+ *
28
+ * Use the `buildThemeStyles` helper from `./themes/createThemeCSSVars`
29
+ * to generate comprehensive overrides from a `ThemeColorDefs` pair.
30
+ */
31
+ themeStyles?: {
32
+ light: CSSProperties;
33
+ dark: CSSProperties;
34
+ };
35
+ }
36
+ export declare function DatalayerThemeProvider(props: React.PropsWithChildren<IDatalayerThemeProviderProps>): JSX.Element;
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { BaseStyles, ThemeProvider } from '@primer/react';
3
+ import { useSystemColorMode } from './useSystemColorMode';
4
+ import { datalayerTheme, datalayerThemeStyles } from './themes/datalayerTheme';
5
+ /**
6
+ * Shared typographic rhythm — clean, spacious feel inspired by
7
+ * modern developer-blog aesthetics (generous line-height, open
8
+ * letter-spacing on headings, crisp body text).
9
+ */
10
+ const typographyVars = {
11
+ '--text-body-lineHeight': '1.7',
12
+ '--text-title-lineHeight': '1.2',
13
+ '--text-title-letterSpacing': '-0.02em',
14
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',
15
+ WebkitFontSmoothing: 'antialiased',
16
+ MozOsxFontSmoothing: 'grayscale',
17
+ textRendering: 'optimizeLegibility',
18
+ };
19
+ export function DatalayerThemeProvider(props) {
20
+ const { children, colorMode, baseStyles, theme, themeStyles, ...rest } = props;
21
+ // Resolve 'auto' → actual system preference ('light' or 'dark').
22
+ const systemMode = useSystemColorMode();
23
+ const resolvedColorMode = colorMode === 'auto' ? systemMode : (colorMode ?? 'light');
24
+ const isDark = resolvedColorMode === 'dark' || resolvedColorMode === 'night';
25
+ const resolvedTheme = theme ?? datalayerTheme;
26
+ const styles = themeStyles ?? datalayerThemeStyles;
27
+ const resolvedStyles = isDark ? styles.dark : styles.light;
28
+ return (_jsx(ThemeProvider, { colorMode: resolvedColorMode, theme: resolvedTheme, ...rest, children: _jsx(BaseStyles, { style: {
29
+ lineHeight: '1.7',
30
+ transition: 'background-color 0.25s ease, color 0.25s ease',
31
+ ...typographyVars,
32
+ ...resolvedStyles,
33
+ ...baseStyles,
34
+ }, children: children }) }));
35
+ }
@@ -0,0 +1,4 @@
1
+ export declare const RESERVATION_CIRCLE_COLOR = "#656D76";
2
+ export declare const CREDITS_CIRCLE_COLOR = "#16A085";
3
+ export declare const JOINED_INVITE_COLOR = "#0366d6";
4
+ export declare const PENDING_INVITE_COLOR = "#cfd3d7";
@@ -0,0 +1,10 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ // export const RESERVATION_CIRCLE_COLOR_VAR = '--data-yellow-color';
6
+ export const RESERVATION_CIRCLE_COLOR = '#656D76';
7
+ // export const CREDITS_CIRCLE_COLOR_VAR = '--data-blue-color';
8
+ export const CREDITS_CIRCLE_COLOR = '#16A085';
9
+ export const JOINED_INVITE_COLOR = '#0366d6';
10
+ export const PENDING_INVITE_COLOR = '#cfd3d7';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Datalayer Accessible Color System
3
+ * Based on Datalayer's brand manual - WCAG AA/AAA compliant
4
+ */
5
+ export declare const datalayerColors: {
6
+ black: string;
7
+ gray: string;
8
+ white: string;
9
+ greenBrand: string;
10
+ greenAccent: string;
11
+ greenText: string;
12
+ greenTint: string;
13
+ greenBright: string;
14
+ greenHover: string;
15
+ };
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * Datalayer Accessible Color System
7
+ * Based on Datalayer's brand manual - WCAG AA/AAA compliant
8
+ */
9
+ export const datalayerColors = {
10
+ // Core Neutrals
11
+ black: '#000000', // Primary text - AAA on white
12
+ gray: '#59595C', // Secondary text - AA on white
13
+ white: '#FFFFFF', // Background
14
+ // Greens (Brand & Accessibility)
15
+ greenBrand: '#16A085', // Brand accent, icons, dividers, headings
16
+ greenAccent: '#1ABC9C', // Icons, charts, highlights on dark surfaces
17
+ greenText: '#117A65', // Accessible green for text & buttons (AA+ on white)
18
+ greenTint: '#E9F7F1', // Soft background for success / callouts
19
+ greenBright: '#2ECC71', // Highlights and glow on dark backgrounds
20
+ greenHover: '#0E6655', // Primary button hover
21
+ };
@@ -0,0 +1,4 @@
1
+ export { datalayerColors } from './datalayerColors';
2
+ export { spatialColors } from './spatialColors';
3
+ export { lovelyColors } from './lovelyColors';
4
+ export { matrixColors } from './matrixColors';
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ export { datalayerColors } from './datalayerColors';
6
+ export { spatialColors } from './spatialColors';
7
+ export { lovelyColors } from './lovelyColors';
8
+ export { matrixColors } from './matrixColors';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Lovely Color System – Warm & Pink-Inspired
3
+ * Rose, magenta, blush — designed for light-first usage.
4
+ */
5
+ export declare const lovelyColors: {
6
+ black: string;
7
+ gray: string;
8
+ white: string;
9
+ roseBrand: string;
10
+ roseAccent: string;
11
+ roseText: string;
12
+ roseTint: string;
13
+ roseBright: string;
14
+ roseHover: string;
15
+ };
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * Lovely Color System – Warm & Pink-Inspired
7
+ * Rose, magenta, blush — designed for light-first usage.
8
+ */
9
+ export const lovelyColors = {
10
+ // Core Neutrals
11
+ black: '#1A0A14', // Deep plum — primary dark background
12
+ gray: '#9D7A8F', // Mauve gray — secondary text
13
+ white: '#FFF5F7', // Rose white — primary light background
14
+ // Rose / Pink palette
15
+ roseBrand: '#DB2777', // Core brand — headings, icons, dividers
16
+ roseAccent: '#EC4899', // Charts, highlights on dark surfaces
17
+ roseText: '#9D174D', // Accessible text & buttons on light (AA+)
18
+ roseTint: '#FDF2F8', // Soft background for callouts
19
+ roseBright: '#F472B6', // Highlights & glow on dark
20
+ roseHover: '#831843', // Primary button hover
21
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Matrix Color System – Terminal & Phosphor-Green
3
+ *
4
+ * Inspired by the iconic green-on-black aesthetic of The Matrix.
5
+ * Dark-first, CRT feel. Uses Datalayer brand greens for accessible text
6
+ * and introduces phosphor-green accents for the signature glow.
7
+ */
8
+ export declare const matrixColors: {
9
+ black: string;
10
+ gray: string;
11
+ white: string;
12
+ greenBrand: string;
13
+ greenAccent: string;
14
+ greenText: string;
15
+ greenTint: string;
16
+ greenPhosphor: string;
17
+ greenGlow: string;
18
+ greenHover: string;
19
+ greenTerminal: string;
20
+ };
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * Matrix Color System – Terminal & Phosphor-Green
7
+ *
8
+ * Inspired by the iconic green-on-black aesthetic of The Matrix.
9
+ * Dark-first, CRT feel. Uses Datalayer brand greens for accessible text
10
+ * and introduces phosphor-green accents for the signature glow.
11
+ */
12
+ export const matrixColors = {
13
+ // Core Neutrals — CRT / terminal aesthetic
14
+ black: '#0D0208', // Matrix void — near-black with faint warm undertone
15
+ gray: '#4A7856', // Dim terminal gray-green — secondary text
16
+ white: '#F0FFF0', // Honeydew — light bg with subtle green cast (CRT paper)
17
+ // Green palette — Datalayer brand greens + Matrix phosphor highlights
18
+ greenBrand: '#16A085', // Datalayer brand — headings, icons, dividers
19
+ greenAccent: '#1ABC9C', // Datalayer accent — icons, charts on dark surfaces
20
+ greenText: '#117A65', // Datalayer text — accessible buttons & text on light (AA+)
21
+ greenTint: '#E8F5E9', // Matrix-tinted soft background for callouts
22
+ greenPhosphor: '#00FF41', // Iconic Matrix falling-code green — dark mode highlights
23
+ greenGlow: '#39FF14', // Neon phosphor glow — brightest accent on dark
24
+ greenHover: '#0E6655', // Datalayer hover — primary button hover
25
+ greenTerminal: '#003B00', // Deep terminal — dark mode subtle/canvas
26
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Spatial Color System – Cosmic & Space-Inspired
3
+ * Deep blues, indigo, nebula purples — designed for dark-first usage.
4
+ */
5
+ export declare const spatialColors: {
6
+ black: string;
7
+ gray: string;
8
+ white: string;
9
+ indigoBrand: string;
10
+ indigoAccent: string;
11
+ indigoText: string;
12
+ indigoTint: string;
13
+ indigoBright: string;
14
+ indigoHover: string;
15
+ };
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * Spatial Color System – Cosmic & Space-Inspired
7
+ * Deep blues, indigo, nebula purples — designed for dark-first usage.
8
+ */
9
+ export const spatialColors = {
10
+ // Core Neutrals
11
+ black: '#0B1120', // Deep space — primary dark background
12
+ gray: '#8892B0', // Nebula gray — secondary text
13
+ white: '#F8FAFF', // Star white — primary light background
14
+ // Indigo / Cosmic palette
15
+ indigoBrand: '#4F46E5', // Core brand — headings, icons, dividers
16
+ indigoAccent: '#6366F1', // Charts, highlights on dark surfaces
17
+ indigoText: '#3730A3', // Accessible text & buttons on light (AA+)
18
+ indigoTint: '#EEF2FF', // Soft background for callouts
19
+ indigoBright: '#818CF8', // Highlights & glow on dark
20
+ indigoHover: '#312E81', // Primary button hover
21
+ };
@@ -0,0 +1,11 @@
1
+ export * from './colors';
2
+ export * from './themes/createThemeCSSVars';
3
+ export * from './themes/datalayerTheme';
4
+ export * from './DatalayerThemeProvider';
5
+ export * from './DatalayerBrandThemeProvider';
6
+ export * from './themes/spatialTheme';
7
+ export * from './themes/lovelyTheme';
8
+ export * from './themes/matrixTheme';
9
+ export * from './themes-brand/spatialBrandTheme';
10
+ export * from './Palette';
11
+ export * from './useSystemColorMode';
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ export * from './colors';
6
+ export * from './themes/createThemeCSSVars';
7
+ export * from './themes/datalayerTheme';
8
+ export * from './DatalayerThemeProvider';
9
+ export * from './DatalayerBrandThemeProvider';
10
+ export * from './themes/spatialTheme';
11
+ export * from './themes/lovelyTheme';
12
+ export * from './themes/matrixTheme';
13
+ export * from './themes-brand/spatialBrandTheme';
14
+ export * from './Palette';
15
+ export * from './useSystemColorMode';