@neo4j-ndl/react 4.7.0 → 4.7.2

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.
@@ -66,6 +66,16 @@ function StatusIndicator({ size, status, }) {
66
66
  const statusClasses = `ndl-avatar-status ndl-avatar-status-${status}`;
67
67
  return ((0, jsx_runtime_1.jsx)("div", { className: statusClasses, title: status.charAt(0).toUpperCase() + status.slice(1), role: "presentation", children: (0, jsx_runtime_1.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", height: diameter, width: diameter, viewBox: `0 0 ${diameter} ${diameter}`, fill: "none", children: [(0, jsx_runtime_1.jsx)("circle", { cx: cxAndCy, cy: cxAndCy, r: rOuter, className: "ndl-avatar-status-circle-outer" }), (0, jsx_runtime_1.jsx)("circle", { cx: cxAndCy, cy: cxAndCy, r: status === 'unknown' ? rInner - 1 : rInner, className: "ndl-avatar-status-circle-inner" })] }) }));
68
68
  }
69
+ const getLettersDisplay = (displayName) => {
70
+ const words = displayName.trim().split(/\s+/).filter(Boolean);
71
+ if (words.length <= 1) {
72
+ return displayName.trim();
73
+ }
74
+ return words
75
+ .map((word) => word.charAt(0))
76
+ .join('')
77
+ .toUpperCase();
78
+ };
69
79
  const Avatar = (_a) => {
70
80
  var { as, hasStatus = false, isDisabled = false, name, shape = 'circle', size = 'medium', source, status, type: initialType = 'image', className, style, htmlAttributes, ref } = _a, restProps = __rest(_a, ["as", "hasStatus", "isDisabled", "name", "shape", "size", "source", "status", "type", "className", "style", "htmlAttributes", "ref"]);
71
81
  // If source is not provided, fallback to icon
@@ -82,7 +92,7 @@ const Avatar = (_a) => {
82
92
  const renderImageType = () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("img", { "data-testid": "ndl-avatar-image", src: source, alt: name }), (0, jsx_runtime_1.jsx)("div", { "data-testid": "ndl-avatar-image-overlay", className: `${shapeClasses} ndl-avatar-image-overlay` })] }));
83
93
  const renderIconType = () => (0, jsx_runtime_1.jsx)(icons_1.UserIconOutline, {});
84
94
  const renderLettersType = () => {
85
- return ((0, jsx_runtime_1.jsx)(typography_1.Typography, { variant: "subheading-small", className: "ndl-avatar-typography", children: name }));
95
+ return ((0, jsx_runtime_1.jsx)(typography_1.Typography, { variant: "subheading-small", className: "ndl-avatar-typography", children: getLettersDisplay(name !== null && name !== void 0 ? name : '') }));
86
96
  };
87
97
  const TypeComponent = type === 'image'
88
98
  ? renderImageType()
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../src/avatar/Avatar.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport classNames from 'classnames';\nimport type React from 'react';\n\nimport { type PolymorphicCommonProps } from '../_common/types';\nimport { UserIconOutline } from '../icons';\nimport { Typography } from '../typography';\n\ntype SizeType = AvatarProps['size'];\ntype StatusType = NonNullable<AvatarProps['status']>;\n\ninterface CircleProperties {\n /** Center coordinates of the circles */\n cxAndCy: number;\n /** Diameter of the circles */\n diameter: number;\n /** Radius of the inner circle */\n rInner: number;\n /** Radius of the outer circle */\n rOuter: number;\n}\n\nfunction circleSizeFactory(size: SizeType): CircleProperties {\n switch (size) {\n case 'x-small':\n case 'small':\n case 'medium':\n return {\n cxAndCy: 4.5,\n diameter: 9,\n rInner: 3,\n rOuter: 4.5,\n };\n case 'large':\n case 'x-large':\n default:\n return {\n cxAndCy: 6,\n diameter: 12,\n rInner: 4,\n rOuter: 6,\n };\n }\n}\n\nfunction StatusIndicator({\n size,\n status,\n}: {\n size: SizeType;\n status: StatusType;\n}) {\n const { cxAndCy, diameter, rInner, rOuter } = circleSizeFactory(size);\n const statusClasses = `ndl-avatar-status ndl-avatar-status-${status}`;\n\n return (\n <div\n className={statusClasses}\n title={status.charAt(0).toUpperCase() + status.slice(1)}\n role=\"presentation\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height={diameter}\n width={diameter}\n viewBox={`0 0 ${diameter} ${diameter}`}\n fill=\"none\"\n >\n <circle\n cx={cxAndCy}\n cy={cxAndCy}\n r={rOuter}\n className=\"ndl-avatar-status-circle-outer\"\n />\n <circle\n cx={cxAndCy}\n cy={cxAndCy}\n r={status === 'unknown' ? rInner - 1 : rInner}\n className=\"ndl-avatar-status-circle-inner\"\n />\n </svg>\n </div>\n );\n}\n\ntype AvatarProps = {\n /** Whether to display a status indicator */\n hasStatus?: boolean;\n /** Whether the avatar is disabled. When disabled, status indicators are hidden and `onClick` handlers are disabled when cast as a button */\n isDisabled?: boolean;\n /** The name associated with the avatar. Used for alt text and aria-label. For letters type, this text is displayed */\n name?: string;\n /** The shape of the avatar */\n shape?: 'circle' | 'square';\n /** The size of the avatar */\n size?: 'x-small' | 'small' | 'medium' | 'large' | 'x-large';\n /** Source URI for the image. When provided with `type=\"image`\", displays the image */\n source?: string;\n /** The status to display. Only shown when `hasStatus` is `true` and component is not disabled */\n status?: 'offline' | 'online' | 'unknown';\n /** The type of avatar content. If `type=\"image\"` and no source is provided, automatically falls back to `icon` */\n type?: 'icon' | 'image' | 'letters';\n} & (\n | {\n as: 'button';\n onClick: () => void;\n }\n | {\n as?: React.ElementType;\n }\n);\n\nexport const Avatar = <T extends React.ElementType = 'div'>({\n as,\n hasStatus = false,\n isDisabled = false,\n name,\n shape = 'circle',\n size = 'medium',\n source,\n status,\n type: initialType = 'image',\n className,\n style,\n htmlAttributes,\n ref,\n ...restProps\n}: PolymorphicCommonProps<T, AvatarProps>) => {\n // If source is not provided, fallback to icon\n const type =\n initialType === 'image' && (source === undefined || source === '')\n ? 'icon'\n : initialType;\n\n const Component: React.ElementType = as ?? 'div';\n const isButton = Component === 'button';\n const classes = classNames(\n `ndl-avatar ndl-avatar-${shape} ndl-avatar-${size}`,\n className,\n );\n const shapeClasses = classNames(\n `ndl-avatar-shape ndl-avatar-${shape} ndl-avatar-${shape}-${size}`,\n {\n 'ndl-avatar-disabled': isDisabled,\n },\n );\n\n const typeClass = `ndl-avatar-${type}`;\n\n const renderImageType = () => (\n <>\n <img data-testid=\"ndl-avatar-image\" src={source} alt={name} />\n <div\n data-testid=\"ndl-avatar-image-overlay\"\n className={`${shapeClasses} ndl-avatar-image-overlay`}\n />\n </>\n );\n\n const renderIconType = () => <UserIconOutline />;\n\n const renderLettersType = () => {\n return (\n <Typography variant=\"subheading-small\" className=\"ndl-avatar-typography\">\n {name}\n </Typography>\n );\n };\n\n const TypeComponent =\n type === 'image'\n ? renderImageType()\n : type === 'icon'\n ? renderIconType()\n : type === 'letters' && Boolean(name)\n ? renderLettersType()\n : null;\n\n const isStatusIndicatorVisible =\n hasStatus && !isDisabled && status !== undefined;\n\n return (\n <Component\n ref={ref}\n className={classes}\n style={style}\n aria-hidden={!isButton}\n {...(isButton && {\n disabled: isDisabled,\n })}\n aria-label={`Avatar ${name}`}\n {...restProps}\n {...htmlAttributes}\n >\n <div className={classNames(shapeClasses, typeClass)}>{TypeComponent}</div>\n {isStatusIndicatorVisible && (\n <StatusIndicator size={size} status={status} />\n )}\n </Component>\n );\n};\n"]}
1
+ {"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../src/avatar/Avatar.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport classNames from 'classnames';\nimport type React from 'react';\n\nimport { type PolymorphicCommonProps } from '../_common/types';\nimport { UserIconOutline } from '../icons';\nimport { Typography } from '../typography';\n\ntype SizeType = AvatarProps['size'];\ntype StatusType = NonNullable<AvatarProps['status']>;\n\ninterface CircleProperties {\n /** Center coordinates of the circles */\n cxAndCy: number;\n /** Diameter of the circles */\n diameter: number;\n /** Radius of the inner circle */\n rInner: number;\n /** Radius of the outer circle */\n rOuter: number;\n}\n\nfunction circleSizeFactory(size: SizeType): CircleProperties {\n switch (size) {\n case 'x-small':\n case 'small':\n case 'medium':\n return {\n cxAndCy: 4.5,\n diameter: 9,\n rInner: 3,\n rOuter: 4.5,\n };\n case 'large':\n case 'x-large':\n default:\n return {\n cxAndCy: 6,\n diameter: 12,\n rInner: 4,\n rOuter: 6,\n };\n }\n}\n\nfunction StatusIndicator({\n size,\n status,\n}: {\n size: SizeType;\n status: StatusType;\n}) {\n const { cxAndCy, diameter, rInner, rOuter } = circleSizeFactory(size);\n const statusClasses = `ndl-avatar-status ndl-avatar-status-${status}`;\n\n return (\n <div\n className={statusClasses}\n title={status.charAt(0).toUpperCase() + status.slice(1)}\n role=\"presentation\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height={diameter}\n width={diameter}\n viewBox={`0 0 ${diameter} ${diameter}`}\n fill=\"none\"\n >\n <circle\n cx={cxAndCy}\n cy={cxAndCy}\n r={rOuter}\n className=\"ndl-avatar-status-circle-outer\"\n />\n <circle\n cx={cxAndCy}\n cy={cxAndCy}\n r={status === 'unknown' ? rInner - 1 : rInner}\n className=\"ndl-avatar-status-circle-inner\"\n />\n </svg>\n </div>\n );\n}\n\ntype AvatarProps = {\n /** Whether to display a status indicator */\n hasStatus?: boolean;\n /** Whether the avatar is disabled. When disabled, status indicators are hidden and `onClick` handlers are disabled when cast as a button */\n isDisabled?: boolean;\n /** The name associated with the avatar. Used for alt text and aria-label. For letters type, this text is displayed */\n name?: string;\n /** The shape of the avatar */\n shape?: 'circle' | 'square';\n /** The size of the avatar */\n size?: 'x-small' | 'small' | 'medium' | 'large' | 'x-large';\n /** Source URI for the image. When provided with `type=\"image`\", displays the image */\n source?: string;\n /** The status to display. Only shown when `hasStatus` is `true` and component is not disabled */\n status?: 'offline' | 'online' | 'unknown';\n /** The type of avatar content. If `type=\"image\"` and no source is provided, automatically falls back to `icon` */\n type?: 'icon' | 'image' | 'letters';\n} & (\n | {\n as: 'button';\n onClick: () => void;\n }\n | {\n as?: React.ElementType;\n }\n);\n\nconst getLettersDisplay = (displayName: string) => {\n const words = displayName.trim().split(/\\s+/).filter(Boolean);\n if (words.length <= 1) {\n return displayName.trim();\n }\n return words\n .map((word) => word.charAt(0))\n .join('')\n .toUpperCase();\n};\n\nexport const Avatar = <T extends React.ElementType = 'div'>({\n as,\n hasStatus = false,\n isDisabled = false,\n name,\n shape = 'circle',\n size = 'medium',\n source,\n status,\n type: initialType = 'image',\n className,\n style,\n htmlAttributes,\n ref,\n ...restProps\n}: PolymorphicCommonProps<T, AvatarProps>) => {\n // If source is not provided, fallback to icon\n const type =\n initialType === 'image' && (source === undefined || source === '')\n ? 'icon'\n : initialType;\n\n const Component: React.ElementType = as ?? 'div';\n const isButton = Component === 'button';\n const classes = classNames(\n `ndl-avatar ndl-avatar-${shape} ndl-avatar-${size}`,\n className,\n );\n const shapeClasses = classNames(\n `ndl-avatar-shape ndl-avatar-${shape} ndl-avatar-${shape}-${size}`,\n {\n 'ndl-avatar-disabled': isDisabled,\n },\n );\n\n const typeClass = `ndl-avatar-${type}`;\n\n const renderImageType = () => (\n <>\n <img data-testid=\"ndl-avatar-image\" src={source} alt={name} />\n <div\n data-testid=\"ndl-avatar-image-overlay\"\n className={`${shapeClasses} ndl-avatar-image-overlay`}\n />\n </>\n );\n\n const renderIconType = () => <UserIconOutline />;\n\n const renderLettersType = () => {\n return (\n <Typography variant=\"subheading-small\" className=\"ndl-avatar-typography\">\n {getLettersDisplay(name ?? '')}\n </Typography>\n );\n };\n\n const TypeComponent =\n type === 'image'\n ? renderImageType()\n : type === 'icon'\n ? renderIconType()\n : type === 'letters' && Boolean(name)\n ? renderLettersType()\n : null;\n\n const isStatusIndicatorVisible =\n hasStatus && !isDisabled && status !== undefined;\n\n return (\n <Component\n ref={ref}\n className={classes}\n style={style}\n aria-hidden={!isButton}\n {...(isButton && {\n disabled: isDisabled,\n })}\n aria-label={`Avatar ${name}`}\n {...restProps}\n {...htmlAttributes}\n >\n <div className={classNames(shapeClasses, typeClass)}>{TypeComponent}</div>\n {isStatusIndicatorVisible && (\n <StatusIndicator size={size} status={status} />\n )}\n </Component>\n );\n};\n"]}
@@ -24,7 +24,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
24
24
  require("@neo4j-ndl/base/lib/neo4j-ds-styles.css");
25
25
  const react_1 = require("@neo4j-ndl/react");
26
26
  const Component = () => {
27
- return ((0, jsx_runtime_1.jsxs)("div", { className: "n-flex n-gap-token-16", children: [(0, jsx_runtime_1.jsx)(react_1.Avatar, { type: "icon", name: "KM" }), (0, jsx_runtime_1.jsx)(react_1.Avatar, { type: "letters", name: "KM" }), (0, jsx_runtime_1.jsx)(react_1.Avatar, { type: "image", name: "KM", source: "https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=" })] }));
27
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "n-flex n-gap-token-16", children: [(0, jsx_runtime_1.jsx)(react_1.Avatar, { type: "icon", name: "Karl Morrison" }), (0, jsx_runtime_1.jsx)(react_1.Avatar, { type: "letters", name: "Karl Morrison" }), (0, jsx_runtime_1.jsx)(react_1.Avatar, { type: "image", name: "Karl Morrison", source: "https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=" })] }));
28
28
  };
29
29
  exports.default = Component;
30
30
  //# sourceMappingURL=avatar-types.story.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"avatar-types.story.js","sourceRoot":"","sources":["../../../../src/avatar/stories/avatar-types.story.tsx"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mDAAiD;AAEjD,4CAA0C;AAE1C,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,CACL,iCAAK,SAAS,EAAC,uBAAuB,aACpC,uBAAC,cAAM,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,IAAI,GAAG,EAChC,uBAAC,cAAM,IAAC,IAAI,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,GAAG,EACnC,uBAAC,cAAM,IACL,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,IAAI,EACT,MAAM,EAAC,uIAAuI,GAC9I,IACE,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,SAAS,CAAC","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport '@neo4j-ndl/base/lib/neo4j-ds-styles.css';\n\nimport { Avatar } from '@neo4j-ndl/react';\n\nconst Component = () => {\n return (\n <div className=\"n-flex n-gap-token-16\">\n <Avatar type=\"icon\" name=\"KM\" />\n <Avatar type=\"letters\" name=\"KM\" />\n <Avatar\n type=\"image\"\n name=\"KM\"\n source=\"https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=\"\n />\n </div>\n );\n};\n\nexport default Component;\n"]}
1
+ {"version":3,"file":"avatar-types.story.js","sourceRoot":"","sources":["../../../../src/avatar/stories/avatar-types.story.tsx"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mDAAiD;AAEjD,4CAA0C;AAE1C,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,CACL,iCAAK,SAAS,EAAC,uBAAuB,aACpC,uBAAC,cAAM,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,eAAe,GAAG,EAC3C,uBAAC,cAAM,IAAC,IAAI,EAAC,SAAS,EAAC,IAAI,EAAC,eAAe,GAAG,EAC9C,uBAAC,cAAM,IACL,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,eAAe,EACpB,MAAM,EAAC,uIAAuI,GAC9I,IACE,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,SAAS,CAAC","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport '@neo4j-ndl/base/lib/neo4j-ds-styles.css';\n\nimport { Avatar } from '@neo4j-ndl/react';\n\nconst Component = () => {\n return (\n <div className=\"n-flex n-gap-token-16\">\n <Avatar type=\"icon\" name=\"Karl Morrison\" />\n <Avatar type=\"letters\" name=\"Karl Morrison\" />\n <Avatar\n type=\"image\"\n name=\"Karl Morrison\"\n source=\"https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=\"\n />\n </div>\n );\n};\n\nexport default Component;\n"]}
@@ -80,9 +80,13 @@ const SpotlightTarget = (_a) => {
80
80
  const Component = as !== null && as !== void 0 ? as : 'div';
81
81
  const { isActiveSpotlight, isOpen, setIsOpen, registerTarget, unregisterTarget, setActiveSpotlight, } = (0, SpotlightProvider_1.useSpotlightContext)();
82
82
  const internalRef = react_2.default.useRef(null);
83
+ const childRef = asChild && react_2.default.isValidElement(children)
84
+ ? children.ref
85
+ : undefined;
83
86
  const mergedRefs = (0, react_1.useMergeRefs)([
84
87
  ref,
85
88
  internalRef,
89
+ childRef,
86
90
  ]);
87
91
  (0, react_2.useEffect)(() => {
88
92
  if (internalRef.current !== null) {
@@ -1 +1 @@
1
- {"version":3,"file":"SpotlightTarget.js","sourceRoot":"","sources":["../../../src/spotlight/SpotlightTarget.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { FloatingPortal, useMergeRefs } from '@floating-ui/react';\nimport classNames from 'classnames';\nimport React, { useEffect } from 'react';\n\nimport { type PolymorphicCommonProps } from '../_common/types';\nimport { ConditionalWrap } from '../conditional-wrap';\nimport { useSpotlightContext } from './SpotlightProvider';\nimport {\n type IndicatorPlacement,\n type IndicatorVariant,\n useIndicator,\n} from './use-indicator';\n\ntype SpotlightTargetProps = {\n /** The id of the wrapper. This should match a `target` prop in a `Spotlight`, to indicate that this is where it should be rendered when open */\n id: string;\n /** A boolean that controls if the pulse animation should be used or not */\n hasPulse?: boolean;\n /** A string that controls the style of the indicator. It can be either \"point\" or \"border\" */\n indicatorVariant?: IndicatorVariant;\n /** A string that controls the placement of the indicator. A combination of \"middle\", \"top\", \"right\", \"bottom\" and \"left\" separated by a dash, e.g. \"top-right\" */\n indicatorPlacement?: IndicatorPlacement;\n /** An inline style CSS property to control the border radius of the wrapper */\n borderRadius?: React.CSSProperties['borderRadius'];\n /** The content to wrap */\n children?: React.ReactNode;\n /** Fit the target size to the children. */\n shouldFitToChildren?: boolean;\n /**\n * When true, merges the spotlight target props directly with the child element instead of wrapping it in a div.\n *\n * This is useful for applying spotlight functionality to existing interactive elements (buttons, links, etc.)\n * while preserving their original behavior, styling, and accessibility attributes.\n *\n * @example\n * ```tsx\n * <SpotlightTarget id=\"my-button\" asChild>\n * <FilledButton>Click me</FilledButton>\n * </SpotlightTarget>\n * ```\n *\n * @warning Only use with interactive elements that can receive focus and handle click events\n * @warning The child element's `id` will be overridden with the target's `id`\n */\n asChild?: boolean;\n};\n\nexport const SpotlightTarget = ({\n id,\n hasPulse = true,\n indicatorVariant = 'border',\n indicatorPlacement = 'top-right',\n borderRadius,\n shouldFitToChildren = false,\n children,\n className,\n htmlAttributes,\n style,\n as,\n ref,\n asChild,\n ...restProps\n}: PolymorphicCommonProps<'div', SpotlightTargetProps>) => {\n const Component = as ?? 'div';\n\n const {\n isActiveSpotlight,\n isOpen,\n setIsOpen,\n registerTarget,\n unregisterTarget,\n setActiveSpotlight,\n } = useSpotlightContext();\n\n const internalRef = React.useRef<HTMLElement>(null);\n const mergedRefs = useMergeRefs<HTMLElement>([\n ref as React.RefObject<HTMLElement>,\n internalRef as React.RefObject<HTMLElement>,\n ]);\n useEffect(() => {\n if (internalRef.current !== null) {\n registerTarget(id, internalRef as React.RefObject<HTMLElement>);\n }\n return () => unregisterTarget(id);\n }, [id, registerTarget, unregisterTarget]);\n\n const isActive = isActiveSpotlight(id);\n const indicator = useIndicator({\n hasPulse,\n indicatorPlacement,\n indicatorVariant,\n isOpen: isActive,\n targetRef: internalRef,\n });\n\n if (asChild === true && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n className?: string;\n style?: React.CSSProperties;\n onClick?: (e: React.MouseEvent<HTMLElement>) => void;\n onKeyDown?: (e: React.KeyboardEvent<HTMLElement>) => void;\n }>;\n\n const onClick = (e: React.MouseEvent<HTMLElement>) => {\n if (isActive) {\n // When spotlight is active, always prevent the child's click handler\n e.preventDefault();\n\n if (!isOpen) {\n setIsOpen(true);\n }\n // Don't call child.props?.onClick when spotlight is active\n return;\n }\n\n // Only call the child's click handler when spotlight is not active\n child.props?.onClick?.(e);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (isActive && !isOpen && (e.code === 'Enter' || e.code === 'Space')) {\n e.preventDefault();\n setIsOpen(true);\n return;\n }\n\n if (isActive && e.code === 'Escape') {\n e.preventDefault();\n setActiveSpotlight(null);\n return;\n }\n\n child.props?.onKeyDown?.(e);\n };\n\n // IMPORTANT: do NOT force role/tabIndex here; preserves Composite semantics for the SideNavigation\n const mergedProps = {\n id,\n onClick,\n onKeyDown,\n ref: mergedRefs,\n style: {\n ...style,\n ...child.props.style,\n },\n // Avoid overriding the child's own role/tabIndex with any passed htmlAttributes\n ...(htmlAttributes\n ? { ...htmlAttributes, role: undefined, tabIndex: undefined }\n : {}),\n };\n\n return (\n <>\n {React.cloneElement(child, mergedProps as Record<string, unknown>)}\n <ConditionalWrap\n shouldWrap={isActive && isOpen}\n wrap={(wrapChildren) => (\n <FloatingPortal>{wrapChildren}</FloatingPortal>\n )}\n >\n {indicator.context.open && (\n <div\n className={indicator.indicatorClasses}\n ref={indicator.context.refs.setFloating}\n style={{ ...indicator.floatingStyles, ...indicator.style }}\n />\n )}\n </ConditionalWrap>\n </>\n );\n }\n\n const classes = classNames(\n 'ndl-spotlight-target',\n {\n 'ndl-spotlight-target-fit-to-children': shouldFitToChildren,\n 'ndl-spotlight-target-open': isOpen && isActive,\n },\n className,\n );\n\n const inertClasses = classNames(\n 'ndl-spotlight-target-inert',\n {\n 'ndl-spotlight-target-inert-fit-to-children': shouldFitToChildren,\n },\n className,\n );\n\n return (\n <>\n <Component\n role={isActive ? 'button' : undefined}\n id={id}\n ref={mergedRefs}\n className={classes}\n onClick={(e) => {\n if (isActive) {\n e.preventDefault();\n e.stopPropagation();\n\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n }}\n style={{ borderRadius, ...style }}\n onKeyDown={(e) => {\n if (\n isActive &&\n !isOpen &&\n (e.code === 'Enter' || e.code === 'Space')\n ) {\n setIsOpen(true);\n e.preventDefault();\n } else if (e.code === 'Escape' && isActive) {\n setActiveSpotlight(null);\n }\n }}\n tabIndex={isActive ? 0 : undefined}\n {...(isActive && { 'aria-label': 'Open spotlight' })}\n {...restProps}\n {...htmlAttributes}\n >\n <ConditionalWrap\n shouldWrap={isActive}\n wrap={(children) => (\n <div inert aria-disabled className={inertClasses}>\n {children}\n </div>\n )}\n >\n {children}\n </ConditionalWrap>\n </Component>\n <ConditionalWrap\n shouldWrap={isActive && isOpen}\n wrap={(wrapChildren) => <FloatingPortal>{wrapChildren}</FloatingPortal>}\n >\n {indicator.context.open && (\n <div\n className={indicator.indicatorClasses}\n ref={indicator.context.refs.setFloating}\n style={{ ...indicator.floatingStyles, ...indicator.style }}\n />\n )}\n </ConditionalWrap>\n </>\n );\n};\n"]}
1
+ {"version":3,"file":"SpotlightTarget.js","sourceRoot":"","sources":["../../../src/spotlight/SpotlightTarget.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { FloatingPortal, useMergeRefs } from '@floating-ui/react';\nimport classNames from 'classnames';\nimport React, { useEffect } from 'react';\n\nimport { type PolymorphicCommonProps } from '../_common/types';\nimport { ConditionalWrap } from '../conditional-wrap';\nimport { useSpotlightContext } from './SpotlightProvider';\nimport {\n type IndicatorPlacement,\n type IndicatorVariant,\n useIndicator,\n} from './use-indicator';\n\ntype SpotlightTargetProps = {\n /** The id of the wrapper. This should match a `target` prop in a `Spotlight`, to indicate that this is where it should be rendered when open */\n id: string;\n /** A boolean that controls if the pulse animation should be used or not */\n hasPulse?: boolean;\n /** A string that controls the style of the indicator. It can be either \"point\" or \"border\" */\n indicatorVariant?: IndicatorVariant;\n /** A string that controls the placement of the indicator. A combination of \"middle\", \"top\", \"right\", \"bottom\" and \"left\" separated by a dash, e.g. \"top-right\" */\n indicatorPlacement?: IndicatorPlacement;\n /** An inline style CSS property to control the border radius of the wrapper */\n borderRadius?: React.CSSProperties['borderRadius'];\n /** The content to wrap */\n children?: React.ReactNode;\n /** Fit the target size to the children. */\n shouldFitToChildren?: boolean;\n /**\n * When true, merges the spotlight target props directly with the child element instead of wrapping it in a div.\n *\n * This is useful for applying spotlight functionality to existing interactive elements (buttons, links, etc.)\n * while preserving their original behavior, styling, and accessibility attributes.\n *\n * @example\n * ```tsx\n * <SpotlightTarget id=\"my-button\" asChild>\n * <FilledButton>Click me</FilledButton>\n * </SpotlightTarget>\n * ```\n *\n * @warning Only use with interactive elements that can receive focus and handle click events\n * @warning The child element's `id` will be overridden with the target's `id`\n */\n asChild?: boolean;\n};\n\nexport const SpotlightTarget = ({\n id,\n hasPulse = true,\n indicatorVariant = 'border',\n indicatorPlacement = 'top-right',\n borderRadius,\n shouldFitToChildren = false,\n children,\n className,\n htmlAttributes,\n style,\n as,\n ref,\n asChild,\n ...restProps\n}: PolymorphicCommonProps<'div', SpotlightTargetProps>) => {\n const Component = as ?? 'div';\n\n const {\n isActiveSpotlight,\n isOpen,\n setIsOpen,\n registerTarget,\n unregisterTarget,\n setActiveSpotlight,\n } = useSpotlightContext();\n\n const internalRef = React.useRef<HTMLElement>(null);\n const childRef =\n asChild && React.isValidElement(children)\n ? (\n children as React.ReactElement<unknown> & {\n ref?: React.Ref<HTMLElement>;\n }\n ).ref\n : undefined;\n const mergedRefs = useMergeRefs<HTMLElement>([\n ref as React.RefObject<HTMLElement>,\n internalRef as React.RefObject<HTMLElement>,\n childRef as React.Ref<HTMLElement> | undefined,\n ]);\n useEffect(() => {\n if (internalRef.current !== null) {\n registerTarget(id, internalRef as React.RefObject<HTMLElement>);\n }\n return () => unregisterTarget(id);\n }, [id, registerTarget, unregisterTarget]);\n\n const isActive = isActiveSpotlight(id);\n const indicator = useIndicator({\n hasPulse,\n indicatorPlacement,\n indicatorVariant,\n isOpen: isActive,\n targetRef: internalRef,\n });\n\n if (asChild === true && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n className?: string;\n style?: React.CSSProperties;\n onClick?: (e: React.MouseEvent<HTMLElement>) => void;\n onKeyDown?: (e: React.KeyboardEvent<HTMLElement>) => void;\n }>;\n\n const onClick = (e: React.MouseEvent<HTMLElement>) => {\n if (isActive) {\n // When spotlight is active, always prevent the child's click handler\n e.preventDefault();\n\n if (!isOpen) {\n setIsOpen(true);\n }\n // Don't call child.props?.onClick when spotlight is active\n return;\n }\n\n // Only call the child's click handler when spotlight is not active\n child.props?.onClick?.(e);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (isActive && !isOpen && (e.code === 'Enter' || e.code === 'Space')) {\n e.preventDefault();\n setIsOpen(true);\n return;\n }\n\n if (isActive && e.code === 'Escape') {\n e.preventDefault();\n setActiveSpotlight(null);\n return;\n }\n\n child.props?.onKeyDown?.(e);\n };\n\n // IMPORTANT: do NOT force role/tabIndex here; preserves Composite semantics for the SideNavigation\n const mergedProps = {\n id,\n onClick,\n onKeyDown,\n ref: mergedRefs,\n style: {\n ...style,\n ...child.props.style,\n },\n // Avoid overriding the child's own role/tabIndex with any passed htmlAttributes\n ...(htmlAttributes\n ? { ...htmlAttributes, role: undefined, tabIndex: undefined }\n : {}),\n };\n\n return (\n <>\n {React.cloneElement(child, mergedProps as Record<string, unknown>)}\n <ConditionalWrap\n shouldWrap={isActive && isOpen}\n wrap={(wrapChildren) => (\n <FloatingPortal>{wrapChildren}</FloatingPortal>\n )}\n >\n {indicator.context.open && (\n <div\n className={indicator.indicatorClasses}\n ref={indicator.context.refs.setFloating}\n style={{ ...indicator.floatingStyles, ...indicator.style }}\n />\n )}\n </ConditionalWrap>\n </>\n );\n }\n\n const classes = classNames(\n 'ndl-spotlight-target',\n {\n 'ndl-spotlight-target-fit-to-children': shouldFitToChildren,\n 'ndl-spotlight-target-open': isOpen && isActive,\n },\n className,\n );\n\n const inertClasses = classNames(\n 'ndl-spotlight-target-inert',\n {\n 'ndl-spotlight-target-inert-fit-to-children': shouldFitToChildren,\n },\n className,\n );\n\n return (\n <>\n <Component\n role={isActive ? 'button' : undefined}\n id={id}\n ref={mergedRefs}\n className={classes}\n onClick={(e) => {\n if (isActive) {\n e.preventDefault();\n e.stopPropagation();\n\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n }}\n style={{ borderRadius, ...style }}\n onKeyDown={(e) => {\n if (\n isActive &&\n !isOpen &&\n (e.code === 'Enter' || e.code === 'Space')\n ) {\n setIsOpen(true);\n e.preventDefault();\n } else if (e.code === 'Escape' && isActive) {\n setActiveSpotlight(null);\n }\n }}\n tabIndex={isActive ? 0 : undefined}\n {...(isActive && { 'aria-label': 'Open spotlight' })}\n {...restProps}\n {...htmlAttributes}\n >\n <ConditionalWrap\n shouldWrap={isActive}\n wrap={(children) => (\n <div inert aria-disabled className={inertClasses}>\n {children}\n </div>\n )}\n >\n {children}\n </ConditionalWrap>\n </Component>\n <ConditionalWrap\n shouldWrap={isActive && isOpen}\n wrap={(wrapChildren) => <FloatingPortal>{wrapChildren}</FloatingPortal>}\n >\n {indicator.context.open && (\n <div\n className={indicator.indicatorClasses}\n ref={indicator.context.refs.setFloating}\n style={{ ...indicator.floatingStyles, ...indicator.style }}\n />\n )}\n </ConditionalWrap>\n </>\n );\n};\n"]}
@@ -60,6 +60,16 @@ function StatusIndicator({ size, status, }) {
60
60
  const statusClasses = `ndl-avatar-status ndl-avatar-status-${status}`;
61
61
  return (_jsx("div", { className: statusClasses, title: status.charAt(0).toUpperCase() + status.slice(1), role: "presentation", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", height: diameter, width: diameter, viewBox: `0 0 ${diameter} ${diameter}`, fill: "none", children: [_jsx("circle", { cx: cxAndCy, cy: cxAndCy, r: rOuter, className: "ndl-avatar-status-circle-outer" }), _jsx("circle", { cx: cxAndCy, cy: cxAndCy, r: status === 'unknown' ? rInner - 1 : rInner, className: "ndl-avatar-status-circle-inner" })] }) }));
62
62
  }
63
+ const getLettersDisplay = (displayName) => {
64
+ const words = displayName.trim().split(/\s+/).filter(Boolean);
65
+ if (words.length <= 1) {
66
+ return displayName.trim();
67
+ }
68
+ return words
69
+ .map((word) => word.charAt(0))
70
+ .join('')
71
+ .toUpperCase();
72
+ };
63
73
  export const Avatar = (_a) => {
64
74
  var { as, hasStatus = false, isDisabled = false, name, shape = 'circle', size = 'medium', source, status, type: initialType = 'image', className, style, htmlAttributes, ref } = _a, restProps = __rest(_a, ["as", "hasStatus", "isDisabled", "name", "shape", "size", "source", "status", "type", "className", "style", "htmlAttributes", "ref"]);
65
75
  // If source is not provided, fallback to icon
@@ -76,7 +86,7 @@ export const Avatar = (_a) => {
76
86
  const renderImageType = () => (_jsxs(_Fragment, { children: [_jsx("img", { "data-testid": "ndl-avatar-image", src: source, alt: name }), _jsx("div", { "data-testid": "ndl-avatar-image-overlay", className: `${shapeClasses} ndl-avatar-image-overlay` })] }));
77
87
  const renderIconType = () => _jsx(UserIconOutline, {});
78
88
  const renderLettersType = () => {
79
- return (_jsx(Typography, { variant: "subheading-small", className: "ndl-avatar-typography", children: name }));
89
+ return (_jsx(Typography, { variant: "subheading-small", className: "ndl-avatar-typography", children: getLettersDisplay(name !== null && name !== void 0 ? name : '') }));
80
90
  };
81
91
  const TypeComponent = type === 'image'
82
92
  ? renderImageType()
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../src/avatar/Avatar.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport classNames from 'classnames';\nimport type React from 'react';\n\nimport { type PolymorphicCommonProps } from '../_common/types';\nimport { UserIconOutline } from '../icons';\nimport { Typography } from '../typography';\n\ntype SizeType = AvatarProps['size'];\ntype StatusType = NonNullable<AvatarProps['status']>;\n\ninterface CircleProperties {\n /** Center coordinates of the circles */\n cxAndCy: number;\n /** Diameter of the circles */\n diameter: number;\n /** Radius of the inner circle */\n rInner: number;\n /** Radius of the outer circle */\n rOuter: number;\n}\n\nfunction circleSizeFactory(size: SizeType): CircleProperties {\n switch (size) {\n case 'x-small':\n case 'small':\n case 'medium':\n return {\n cxAndCy: 4.5,\n diameter: 9,\n rInner: 3,\n rOuter: 4.5,\n };\n case 'large':\n case 'x-large':\n default:\n return {\n cxAndCy: 6,\n diameter: 12,\n rInner: 4,\n rOuter: 6,\n };\n }\n}\n\nfunction StatusIndicator({\n size,\n status,\n}: {\n size: SizeType;\n status: StatusType;\n}) {\n const { cxAndCy, diameter, rInner, rOuter } = circleSizeFactory(size);\n const statusClasses = `ndl-avatar-status ndl-avatar-status-${status}`;\n\n return (\n <div\n className={statusClasses}\n title={status.charAt(0).toUpperCase() + status.slice(1)}\n role=\"presentation\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height={diameter}\n width={diameter}\n viewBox={`0 0 ${diameter} ${diameter}`}\n fill=\"none\"\n >\n <circle\n cx={cxAndCy}\n cy={cxAndCy}\n r={rOuter}\n className=\"ndl-avatar-status-circle-outer\"\n />\n <circle\n cx={cxAndCy}\n cy={cxAndCy}\n r={status === 'unknown' ? rInner - 1 : rInner}\n className=\"ndl-avatar-status-circle-inner\"\n />\n </svg>\n </div>\n );\n}\n\ntype AvatarProps = {\n /** Whether to display a status indicator */\n hasStatus?: boolean;\n /** Whether the avatar is disabled. When disabled, status indicators are hidden and `onClick` handlers are disabled when cast as a button */\n isDisabled?: boolean;\n /** The name associated with the avatar. Used for alt text and aria-label. For letters type, this text is displayed */\n name?: string;\n /** The shape of the avatar */\n shape?: 'circle' | 'square';\n /** The size of the avatar */\n size?: 'x-small' | 'small' | 'medium' | 'large' | 'x-large';\n /** Source URI for the image. When provided with `type=\"image`\", displays the image */\n source?: string;\n /** The status to display. Only shown when `hasStatus` is `true` and component is not disabled */\n status?: 'offline' | 'online' | 'unknown';\n /** The type of avatar content. If `type=\"image\"` and no source is provided, automatically falls back to `icon` */\n type?: 'icon' | 'image' | 'letters';\n} & (\n | {\n as: 'button';\n onClick: () => void;\n }\n | {\n as?: React.ElementType;\n }\n);\n\nexport const Avatar = <T extends React.ElementType = 'div'>({\n as,\n hasStatus = false,\n isDisabled = false,\n name,\n shape = 'circle',\n size = 'medium',\n source,\n status,\n type: initialType = 'image',\n className,\n style,\n htmlAttributes,\n ref,\n ...restProps\n}: PolymorphicCommonProps<T, AvatarProps>) => {\n // If source is not provided, fallback to icon\n const type =\n initialType === 'image' && (source === undefined || source === '')\n ? 'icon'\n : initialType;\n\n const Component: React.ElementType = as ?? 'div';\n const isButton = Component === 'button';\n const classes = classNames(\n `ndl-avatar ndl-avatar-${shape} ndl-avatar-${size}`,\n className,\n );\n const shapeClasses = classNames(\n `ndl-avatar-shape ndl-avatar-${shape} ndl-avatar-${shape}-${size}`,\n {\n 'ndl-avatar-disabled': isDisabled,\n },\n );\n\n const typeClass = `ndl-avatar-${type}`;\n\n const renderImageType = () => (\n <>\n <img data-testid=\"ndl-avatar-image\" src={source} alt={name} />\n <div\n data-testid=\"ndl-avatar-image-overlay\"\n className={`${shapeClasses} ndl-avatar-image-overlay`}\n />\n </>\n );\n\n const renderIconType = () => <UserIconOutline />;\n\n const renderLettersType = () => {\n return (\n <Typography variant=\"subheading-small\" className=\"ndl-avatar-typography\">\n {name}\n </Typography>\n );\n };\n\n const TypeComponent =\n type === 'image'\n ? renderImageType()\n : type === 'icon'\n ? renderIconType()\n : type === 'letters' && Boolean(name)\n ? renderLettersType()\n : null;\n\n const isStatusIndicatorVisible =\n hasStatus && !isDisabled && status !== undefined;\n\n return (\n <Component\n ref={ref}\n className={classes}\n style={style}\n aria-hidden={!isButton}\n {...(isButton && {\n disabled: isDisabled,\n })}\n aria-label={`Avatar ${name}`}\n {...restProps}\n {...htmlAttributes}\n >\n <div className={classNames(shapeClasses, typeClass)}>{TypeComponent}</div>\n {isStatusIndicatorVisible && (\n <StatusIndicator size={size} status={status} />\n )}\n </Component>\n );\n};\n"]}
1
+ {"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../src/avatar/Avatar.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport classNames from 'classnames';\nimport type React from 'react';\n\nimport { type PolymorphicCommonProps } from '../_common/types';\nimport { UserIconOutline } from '../icons';\nimport { Typography } from '../typography';\n\ntype SizeType = AvatarProps['size'];\ntype StatusType = NonNullable<AvatarProps['status']>;\n\ninterface CircleProperties {\n /** Center coordinates of the circles */\n cxAndCy: number;\n /** Diameter of the circles */\n diameter: number;\n /** Radius of the inner circle */\n rInner: number;\n /** Radius of the outer circle */\n rOuter: number;\n}\n\nfunction circleSizeFactory(size: SizeType): CircleProperties {\n switch (size) {\n case 'x-small':\n case 'small':\n case 'medium':\n return {\n cxAndCy: 4.5,\n diameter: 9,\n rInner: 3,\n rOuter: 4.5,\n };\n case 'large':\n case 'x-large':\n default:\n return {\n cxAndCy: 6,\n diameter: 12,\n rInner: 4,\n rOuter: 6,\n };\n }\n}\n\nfunction StatusIndicator({\n size,\n status,\n}: {\n size: SizeType;\n status: StatusType;\n}) {\n const { cxAndCy, diameter, rInner, rOuter } = circleSizeFactory(size);\n const statusClasses = `ndl-avatar-status ndl-avatar-status-${status}`;\n\n return (\n <div\n className={statusClasses}\n title={status.charAt(0).toUpperCase() + status.slice(1)}\n role=\"presentation\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height={diameter}\n width={diameter}\n viewBox={`0 0 ${diameter} ${diameter}`}\n fill=\"none\"\n >\n <circle\n cx={cxAndCy}\n cy={cxAndCy}\n r={rOuter}\n className=\"ndl-avatar-status-circle-outer\"\n />\n <circle\n cx={cxAndCy}\n cy={cxAndCy}\n r={status === 'unknown' ? rInner - 1 : rInner}\n className=\"ndl-avatar-status-circle-inner\"\n />\n </svg>\n </div>\n );\n}\n\ntype AvatarProps = {\n /** Whether to display a status indicator */\n hasStatus?: boolean;\n /** Whether the avatar is disabled. When disabled, status indicators are hidden and `onClick` handlers are disabled when cast as a button */\n isDisabled?: boolean;\n /** The name associated with the avatar. Used for alt text and aria-label. For letters type, this text is displayed */\n name?: string;\n /** The shape of the avatar */\n shape?: 'circle' | 'square';\n /** The size of the avatar */\n size?: 'x-small' | 'small' | 'medium' | 'large' | 'x-large';\n /** Source URI for the image. When provided with `type=\"image`\", displays the image */\n source?: string;\n /** The status to display. Only shown when `hasStatus` is `true` and component is not disabled */\n status?: 'offline' | 'online' | 'unknown';\n /** The type of avatar content. If `type=\"image\"` and no source is provided, automatically falls back to `icon` */\n type?: 'icon' | 'image' | 'letters';\n} & (\n | {\n as: 'button';\n onClick: () => void;\n }\n | {\n as?: React.ElementType;\n }\n);\n\nconst getLettersDisplay = (displayName: string) => {\n const words = displayName.trim().split(/\\s+/).filter(Boolean);\n if (words.length <= 1) {\n return displayName.trim();\n }\n return words\n .map((word) => word.charAt(0))\n .join('')\n .toUpperCase();\n};\n\nexport const Avatar = <T extends React.ElementType = 'div'>({\n as,\n hasStatus = false,\n isDisabled = false,\n name,\n shape = 'circle',\n size = 'medium',\n source,\n status,\n type: initialType = 'image',\n className,\n style,\n htmlAttributes,\n ref,\n ...restProps\n}: PolymorphicCommonProps<T, AvatarProps>) => {\n // If source is not provided, fallback to icon\n const type =\n initialType === 'image' && (source === undefined || source === '')\n ? 'icon'\n : initialType;\n\n const Component: React.ElementType = as ?? 'div';\n const isButton = Component === 'button';\n const classes = classNames(\n `ndl-avatar ndl-avatar-${shape} ndl-avatar-${size}`,\n className,\n );\n const shapeClasses = classNames(\n `ndl-avatar-shape ndl-avatar-${shape} ndl-avatar-${shape}-${size}`,\n {\n 'ndl-avatar-disabled': isDisabled,\n },\n );\n\n const typeClass = `ndl-avatar-${type}`;\n\n const renderImageType = () => (\n <>\n <img data-testid=\"ndl-avatar-image\" src={source} alt={name} />\n <div\n data-testid=\"ndl-avatar-image-overlay\"\n className={`${shapeClasses} ndl-avatar-image-overlay`}\n />\n </>\n );\n\n const renderIconType = () => <UserIconOutline />;\n\n const renderLettersType = () => {\n return (\n <Typography variant=\"subheading-small\" className=\"ndl-avatar-typography\">\n {getLettersDisplay(name ?? '')}\n </Typography>\n );\n };\n\n const TypeComponent =\n type === 'image'\n ? renderImageType()\n : type === 'icon'\n ? renderIconType()\n : type === 'letters' && Boolean(name)\n ? renderLettersType()\n : null;\n\n const isStatusIndicatorVisible =\n hasStatus && !isDisabled && status !== undefined;\n\n return (\n <Component\n ref={ref}\n className={classes}\n style={style}\n aria-hidden={!isButton}\n {...(isButton && {\n disabled: isDisabled,\n })}\n aria-label={`Avatar ${name}`}\n {...restProps}\n {...htmlAttributes}\n >\n <div className={classNames(shapeClasses, typeClass)}>{TypeComponent}</div>\n {isStatusIndicatorVisible && (\n <StatusIndicator size={size} status={status} />\n )}\n </Component>\n );\n};\n"]}
@@ -22,7 +22,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
22
  import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
23
23
  import { Avatar } from '@neo4j-ndl/react';
24
24
  const Component = () => {
25
- return (_jsxs("div", { className: "n-flex n-gap-token-16", children: [_jsx(Avatar, { type: "icon", name: "KM" }), _jsx(Avatar, { type: "letters", name: "KM" }), _jsx(Avatar, { type: "image", name: "KM", source: "https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=" })] }));
25
+ return (_jsxs("div", { className: "n-flex n-gap-token-16", children: [_jsx(Avatar, { type: "icon", name: "Karl Morrison" }), _jsx(Avatar, { type: "letters", name: "Karl Morrison" }), _jsx(Avatar, { type: "image", name: "Karl Morrison", source: "https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=" })] }));
26
26
  };
27
27
  export default Component;
28
28
  //# sourceMappingURL=avatar-types.story.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"avatar-types.story.js","sourceRoot":"","sources":["../../../../src/avatar/stories/avatar-types.story.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,CACL,eAAK,SAAS,EAAC,uBAAuB,aACpC,KAAC,MAAM,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,IAAI,GAAG,EAChC,KAAC,MAAM,IAAC,IAAI,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,GAAG,EACnC,KAAC,MAAM,IACL,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,IAAI,EACT,MAAM,EAAC,uIAAuI,GAC9I,IACE,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,SAAS,CAAC","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport '@neo4j-ndl/base/lib/neo4j-ds-styles.css';\n\nimport { Avatar } from '@neo4j-ndl/react';\n\nconst Component = () => {\n return (\n <div className=\"n-flex n-gap-token-16\">\n <Avatar type=\"icon\" name=\"KM\" />\n <Avatar type=\"letters\" name=\"KM\" />\n <Avatar\n type=\"image\"\n name=\"KM\"\n source=\"https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=\"\n />\n </div>\n );\n};\n\nexport default Component;\n"]}
1
+ {"version":3,"file":"avatar-types.story.js","sourceRoot":"","sources":["../../../../src/avatar/stories/avatar-types.story.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,CACL,eAAK,SAAS,EAAC,uBAAuB,aACpC,KAAC,MAAM,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,eAAe,GAAG,EAC3C,KAAC,MAAM,IAAC,IAAI,EAAC,SAAS,EAAC,IAAI,EAAC,eAAe,GAAG,EAC9C,KAAC,MAAM,IACL,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,eAAe,EACpB,MAAM,EAAC,uIAAuI,GAC9I,IACE,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,SAAS,CAAC","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport '@neo4j-ndl/base/lib/neo4j-ds-styles.css';\n\nimport { Avatar } from '@neo4j-ndl/react';\n\nconst Component = () => {\n return (\n <div className=\"n-flex n-gap-token-16\">\n <Avatar type=\"icon\" name=\"Karl Morrison\" />\n <Avatar type=\"letters\" name=\"Karl Morrison\" />\n <Avatar\n type=\"image\"\n name=\"Karl Morrison\"\n source=\"https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=\"\n />\n </div>\n );\n};\n\nexport default Component;\n"]}
@@ -41,9 +41,13 @@ export const SpotlightTarget = (_a) => {
41
41
  const Component = as !== null && as !== void 0 ? as : 'div';
42
42
  const { isActiveSpotlight, isOpen, setIsOpen, registerTarget, unregisterTarget, setActiveSpotlight, } = useSpotlightContext();
43
43
  const internalRef = React.useRef(null);
44
+ const childRef = asChild && React.isValidElement(children)
45
+ ? children.ref
46
+ : undefined;
44
47
  const mergedRefs = useMergeRefs([
45
48
  ref,
46
49
  internalRef,
50
+ childRef,
47
51
  ]);
48
52
  useEffect(() => {
49
53
  if (internalRef.current !== null) {
@@ -1 +1 @@
1
- {"version":3,"file":"SpotlightTarget.js","sourceRoot":"","sources":["../../../src/spotlight/SpotlightTarget.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { FloatingPortal, useMergeRefs } from '@floating-ui/react';\nimport classNames from 'classnames';\nimport React, { useEffect } from 'react';\n\nimport { type PolymorphicCommonProps } from '../_common/types';\nimport { ConditionalWrap } from '../conditional-wrap';\nimport { useSpotlightContext } from './SpotlightProvider';\nimport {\n type IndicatorPlacement,\n type IndicatorVariant,\n useIndicator,\n} from './use-indicator';\n\ntype SpotlightTargetProps = {\n /** The id of the wrapper. This should match a `target` prop in a `Spotlight`, to indicate that this is where it should be rendered when open */\n id: string;\n /** A boolean that controls if the pulse animation should be used or not */\n hasPulse?: boolean;\n /** A string that controls the style of the indicator. It can be either \"point\" or \"border\" */\n indicatorVariant?: IndicatorVariant;\n /** A string that controls the placement of the indicator. A combination of \"middle\", \"top\", \"right\", \"bottom\" and \"left\" separated by a dash, e.g. \"top-right\" */\n indicatorPlacement?: IndicatorPlacement;\n /** An inline style CSS property to control the border radius of the wrapper */\n borderRadius?: React.CSSProperties['borderRadius'];\n /** The content to wrap */\n children?: React.ReactNode;\n /** Fit the target size to the children. */\n shouldFitToChildren?: boolean;\n /**\n * When true, merges the spotlight target props directly with the child element instead of wrapping it in a div.\n *\n * This is useful for applying spotlight functionality to existing interactive elements (buttons, links, etc.)\n * while preserving their original behavior, styling, and accessibility attributes.\n *\n * @example\n * ```tsx\n * <SpotlightTarget id=\"my-button\" asChild>\n * <FilledButton>Click me</FilledButton>\n * </SpotlightTarget>\n * ```\n *\n * @warning Only use with interactive elements that can receive focus and handle click events\n * @warning The child element's `id` will be overridden with the target's `id`\n */\n asChild?: boolean;\n};\n\nexport const SpotlightTarget = ({\n id,\n hasPulse = true,\n indicatorVariant = 'border',\n indicatorPlacement = 'top-right',\n borderRadius,\n shouldFitToChildren = false,\n children,\n className,\n htmlAttributes,\n style,\n as,\n ref,\n asChild,\n ...restProps\n}: PolymorphicCommonProps<'div', SpotlightTargetProps>) => {\n const Component = as ?? 'div';\n\n const {\n isActiveSpotlight,\n isOpen,\n setIsOpen,\n registerTarget,\n unregisterTarget,\n setActiveSpotlight,\n } = useSpotlightContext();\n\n const internalRef = React.useRef<HTMLElement>(null);\n const mergedRefs = useMergeRefs<HTMLElement>([\n ref as React.RefObject<HTMLElement>,\n internalRef as React.RefObject<HTMLElement>,\n ]);\n useEffect(() => {\n if (internalRef.current !== null) {\n registerTarget(id, internalRef as React.RefObject<HTMLElement>);\n }\n return () => unregisterTarget(id);\n }, [id, registerTarget, unregisterTarget]);\n\n const isActive = isActiveSpotlight(id);\n const indicator = useIndicator({\n hasPulse,\n indicatorPlacement,\n indicatorVariant,\n isOpen: isActive,\n targetRef: internalRef,\n });\n\n if (asChild === true && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n className?: string;\n style?: React.CSSProperties;\n onClick?: (e: React.MouseEvent<HTMLElement>) => void;\n onKeyDown?: (e: React.KeyboardEvent<HTMLElement>) => void;\n }>;\n\n const onClick = (e: React.MouseEvent<HTMLElement>) => {\n if (isActive) {\n // When spotlight is active, always prevent the child's click handler\n e.preventDefault();\n\n if (!isOpen) {\n setIsOpen(true);\n }\n // Don't call child.props?.onClick when spotlight is active\n return;\n }\n\n // Only call the child's click handler when spotlight is not active\n child.props?.onClick?.(e);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (isActive && !isOpen && (e.code === 'Enter' || e.code === 'Space')) {\n e.preventDefault();\n setIsOpen(true);\n return;\n }\n\n if (isActive && e.code === 'Escape') {\n e.preventDefault();\n setActiveSpotlight(null);\n return;\n }\n\n child.props?.onKeyDown?.(e);\n };\n\n // IMPORTANT: do NOT force role/tabIndex here; preserves Composite semantics for the SideNavigation\n const mergedProps = {\n id,\n onClick,\n onKeyDown,\n ref: mergedRefs,\n style: {\n ...style,\n ...child.props.style,\n },\n // Avoid overriding the child's own role/tabIndex with any passed htmlAttributes\n ...(htmlAttributes\n ? { ...htmlAttributes, role: undefined, tabIndex: undefined }\n : {}),\n };\n\n return (\n <>\n {React.cloneElement(child, mergedProps as Record<string, unknown>)}\n <ConditionalWrap\n shouldWrap={isActive && isOpen}\n wrap={(wrapChildren) => (\n <FloatingPortal>{wrapChildren}</FloatingPortal>\n )}\n >\n {indicator.context.open && (\n <div\n className={indicator.indicatorClasses}\n ref={indicator.context.refs.setFloating}\n style={{ ...indicator.floatingStyles, ...indicator.style }}\n />\n )}\n </ConditionalWrap>\n </>\n );\n }\n\n const classes = classNames(\n 'ndl-spotlight-target',\n {\n 'ndl-spotlight-target-fit-to-children': shouldFitToChildren,\n 'ndl-spotlight-target-open': isOpen && isActive,\n },\n className,\n );\n\n const inertClasses = classNames(\n 'ndl-spotlight-target-inert',\n {\n 'ndl-spotlight-target-inert-fit-to-children': shouldFitToChildren,\n },\n className,\n );\n\n return (\n <>\n <Component\n role={isActive ? 'button' : undefined}\n id={id}\n ref={mergedRefs}\n className={classes}\n onClick={(e) => {\n if (isActive) {\n e.preventDefault();\n e.stopPropagation();\n\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n }}\n style={{ borderRadius, ...style }}\n onKeyDown={(e) => {\n if (\n isActive &&\n !isOpen &&\n (e.code === 'Enter' || e.code === 'Space')\n ) {\n setIsOpen(true);\n e.preventDefault();\n } else if (e.code === 'Escape' && isActive) {\n setActiveSpotlight(null);\n }\n }}\n tabIndex={isActive ? 0 : undefined}\n {...(isActive && { 'aria-label': 'Open spotlight' })}\n {...restProps}\n {...htmlAttributes}\n >\n <ConditionalWrap\n shouldWrap={isActive}\n wrap={(children) => (\n <div inert aria-disabled className={inertClasses}>\n {children}\n </div>\n )}\n >\n {children}\n </ConditionalWrap>\n </Component>\n <ConditionalWrap\n shouldWrap={isActive && isOpen}\n wrap={(wrapChildren) => <FloatingPortal>{wrapChildren}</FloatingPortal>}\n >\n {indicator.context.open && (\n <div\n className={indicator.indicatorClasses}\n ref={indicator.context.refs.setFloating}\n style={{ ...indicator.floatingStyles, ...indicator.style }}\n />\n )}\n </ConditionalWrap>\n </>\n );\n};\n"]}
1
+ {"version":3,"file":"SpotlightTarget.js","sourceRoot":"","sources":["../../../src/spotlight/SpotlightTarget.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { FloatingPortal, useMergeRefs } from '@floating-ui/react';\nimport classNames from 'classnames';\nimport React, { useEffect } from 'react';\n\nimport { type PolymorphicCommonProps } from '../_common/types';\nimport { ConditionalWrap } from '../conditional-wrap';\nimport { useSpotlightContext } from './SpotlightProvider';\nimport {\n type IndicatorPlacement,\n type IndicatorVariant,\n useIndicator,\n} from './use-indicator';\n\ntype SpotlightTargetProps = {\n /** The id of the wrapper. This should match a `target` prop in a `Spotlight`, to indicate that this is where it should be rendered when open */\n id: string;\n /** A boolean that controls if the pulse animation should be used or not */\n hasPulse?: boolean;\n /** A string that controls the style of the indicator. It can be either \"point\" or \"border\" */\n indicatorVariant?: IndicatorVariant;\n /** A string that controls the placement of the indicator. A combination of \"middle\", \"top\", \"right\", \"bottom\" and \"left\" separated by a dash, e.g. \"top-right\" */\n indicatorPlacement?: IndicatorPlacement;\n /** An inline style CSS property to control the border radius of the wrapper */\n borderRadius?: React.CSSProperties['borderRadius'];\n /** The content to wrap */\n children?: React.ReactNode;\n /** Fit the target size to the children. */\n shouldFitToChildren?: boolean;\n /**\n * When true, merges the spotlight target props directly with the child element instead of wrapping it in a div.\n *\n * This is useful for applying spotlight functionality to existing interactive elements (buttons, links, etc.)\n * while preserving their original behavior, styling, and accessibility attributes.\n *\n * @example\n * ```tsx\n * <SpotlightTarget id=\"my-button\" asChild>\n * <FilledButton>Click me</FilledButton>\n * </SpotlightTarget>\n * ```\n *\n * @warning Only use with interactive elements that can receive focus and handle click events\n * @warning The child element's `id` will be overridden with the target's `id`\n */\n asChild?: boolean;\n};\n\nexport const SpotlightTarget = ({\n id,\n hasPulse = true,\n indicatorVariant = 'border',\n indicatorPlacement = 'top-right',\n borderRadius,\n shouldFitToChildren = false,\n children,\n className,\n htmlAttributes,\n style,\n as,\n ref,\n asChild,\n ...restProps\n}: PolymorphicCommonProps<'div', SpotlightTargetProps>) => {\n const Component = as ?? 'div';\n\n const {\n isActiveSpotlight,\n isOpen,\n setIsOpen,\n registerTarget,\n unregisterTarget,\n setActiveSpotlight,\n } = useSpotlightContext();\n\n const internalRef = React.useRef<HTMLElement>(null);\n const childRef =\n asChild && React.isValidElement(children)\n ? (\n children as React.ReactElement<unknown> & {\n ref?: React.Ref<HTMLElement>;\n }\n ).ref\n : undefined;\n const mergedRefs = useMergeRefs<HTMLElement>([\n ref as React.RefObject<HTMLElement>,\n internalRef as React.RefObject<HTMLElement>,\n childRef as React.Ref<HTMLElement> | undefined,\n ]);\n useEffect(() => {\n if (internalRef.current !== null) {\n registerTarget(id, internalRef as React.RefObject<HTMLElement>);\n }\n return () => unregisterTarget(id);\n }, [id, registerTarget, unregisterTarget]);\n\n const isActive = isActiveSpotlight(id);\n const indicator = useIndicator({\n hasPulse,\n indicatorPlacement,\n indicatorVariant,\n isOpen: isActive,\n targetRef: internalRef,\n });\n\n if (asChild === true && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n className?: string;\n style?: React.CSSProperties;\n onClick?: (e: React.MouseEvent<HTMLElement>) => void;\n onKeyDown?: (e: React.KeyboardEvent<HTMLElement>) => void;\n }>;\n\n const onClick = (e: React.MouseEvent<HTMLElement>) => {\n if (isActive) {\n // When spotlight is active, always prevent the child's click handler\n e.preventDefault();\n\n if (!isOpen) {\n setIsOpen(true);\n }\n // Don't call child.props?.onClick when spotlight is active\n return;\n }\n\n // Only call the child's click handler when spotlight is not active\n child.props?.onClick?.(e);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (isActive && !isOpen && (e.code === 'Enter' || e.code === 'Space')) {\n e.preventDefault();\n setIsOpen(true);\n return;\n }\n\n if (isActive && e.code === 'Escape') {\n e.preventDefault();\n setActiveSpotlight(null);\n return;\n }\n\n child.props?.onKeyDown?.(e);\n };\n\n // IMPORTANT: do NOT force role/tabIndex here; preserves Composite semantics for the SideNavigation\n const mergedProps = {\n id,\n onClick,\n onKeyDown,\n ref: mergedRefs,\n style: {\n ...style,\n ...child.props.style,\n },\n // Avoid overriding the child's own role/tabIndex with any passed htmlAttributes\n ...(htmlAttributes\n ? { ...htmlAttributes, role: undefined, tabIndex: undefined }\n : {}),\n };\n\n return (\n <>\n {React.cloneElement(child, mergedProps as Record<string, unknown>)}\n <ConditionalWrap\n shouldWrap={isActive && isOpen}\n wrap={(wrapChildren) => (\n <FloatingPortal>{wrapChildren}</FloatingPortal>\n )}\n >\n {indicator.context.open && (\n <div\n className={indicator.indicatorClasses}\n ref={indicator.context.refs.setFloating}\n style={{ ...indicator.floatingStyles, ...indicator.style }}\n />\n )}\n </ConditionalWrap>\n </>\n );\n }\n\n const classes = classNames(\n 'ndl-spotlight-target',\n {\n 'ndl-spotlight-target-fit-to-children': shouldFitToChildren,\n 'ndl-spotlight-target-open': isOpen && isActive,\n },\n className,\n );\n\n const inertClasses = classNames(\n 'ndl-spotlight-target-inert',\n {\n 'ndl-spotlight-target-inert-fit-to-children': shouldFitToChildren,\n },\n className,\n );\n\n return (\n <>\n <Component\n role={isActive ? 'button' : undefined}\n id={id}\n ref={mergedRefs}\n className={classes}\n onClick={(e) => {\n if (isActive) {\n e.preventDefault();\n e.stopPropagation();\n\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n }}\n style={{ borderRadius, ...style }}\n onKeyDown={(e) => {\n if (\n isActive &&\n !isOpen &&\n (e.code === 'Enter' || e.code === 'Space')\n ) {\n setIsOpen(true);\n e.preventDefault();\n } else if (e.code === 'Escape' && isActive) {\n setActiveSpotlight(null);\n }\n }}\n tabIndex={isActive ? 0 : undefined}\n {...(isActive && { 'aria-label': 'Open spotlight' })}\n {...restProps}\n {...htmlAttributes}\n >\n <ConditionalWrap\n shouldWrap={isActive}\n wrap={(children) => (\n <div inert aria-disabled className={inertClasses}>\n {children}\n </div>\n )}\n >\n {children}\n </ConditionalWrap>\n </Component>\n <ConditionalWrap\n shouldWrap={isActive && isOpen}\n wrap={(wrapChildren) => <FloatingPortal>{wrapChildren}</FloatingPortal>}\n >\n {indicator.context.open && (\n <div\n className={indicator.indicatorClasses}\n ref={indicator.context.refs.setFloating}\n style={{ ...indicator.floatingStyles, ...indicator.style }}\n />\n )}\n </ConditionalWrap>\n </>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/avatar/Avatar.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAiF/D,KAAK,WAAW,GAAG;IACjB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4IAA4I;IAC5I,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sHAAsH;IACtH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5D,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC1C,kHAAkH;IAClH,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACrC,GAAG,CACA;IACE,EAAE,EAAE,QAAQ,CAAC;IACb,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,GACD;IACE,EAAE,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;CACxB,CACJ,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,KAAK,EAAE,0IAezD,sBAAsB,CAAC,CAAC,EAAE,WAAW,CAAC,4CAyExC,CAAC"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/avatar/Avatar.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAiF/D,KAAK,WAAW,GAAG;IACjB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4IAA4I;IAC5I,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sHAAsH;IACtH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5D,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC1C,kHAAkH;IAClH,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACrC,GAAG,CACA;IACE,EAAE,EAAE,QAAQ,CAAC;IACb,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,GACD;IACE,EAAE,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;CACxB,CACJ,CAAC;AAaF,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,KAAK,EAAE,0IAezD,sBAAsB,CAAC,CAAC,EAAE,WAAW,CAAC,4CAyExC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"SpotlightTarget.d.ts","sourceRoot":"","sources":["../../../src/spotlight/SpotlightTarget.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAEtB,MAAM,iBAAiB,CAAC;AAEzB,KAAK,oBAAoB,GAAG;IAC1B,gJAAgJ;IAChJ,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kKAAkK;IAClK,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,+EAA+E;IAC/E,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IACnD,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,2CAA2C;IAC3C,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,uKAe7B,sBAAsB,CAAC,KAAK,EAAE,oBAAoB,CAAC,4CA2LrD,CAAC"}
1
+ {"version":3,"file":"SpotlightTarget.d.ts","sourceRoot":"","sources":["../../../src/spotlight/SpotlightTarget.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAEtB,MAAM,iBAAiB,CAAC;AAEzB,KAAK,oBAAoB,GAAG;IAC1B,gJAAgJ;IAChJ,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kKAAkK;IAClK,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,+EAA+E;IAC/E,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IACnD,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,2CAA2C;IAC3C,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,uKAe7B,sBAAsB,CAAC,KAAK,EAAE,oBAAoB,CAAC,4CAoMrD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neo4j-ndl/react",
3
- "version": "4.7.0",
3
+ "version": "4.7.2",
4
4
  "sideEffects": false,
5
5
  "description": "React implementation of Neo4j Design System",
6
6
  "keywords": [
@@ -85,7 +85,7 @@
85
85
  "@tanstack/react-table": "8.21.3",
86
86
  "react": ">=19.0.0",
87
87
  "react-dom": ">=19.0.0",
88
- "@neo4j-ndl/base": "^4.7.0"
88
+ "@neo4j-ndl/base": "^4.7.1"
89
89
  },
90
90
  "dependencies": {
91
91
  "@dnd-kit/core": "6.3.1",