@neo4j-ndl/react 4.17.0 → 4.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/ai/chat-title/ChatTitle.js +43 -0
- package/lib/cjs/ai/chat-title/ChatTitle.js.map +1 -0
- package/lib/cjs/ai/chat-title/index.js +38 -0
- package/lib/cjs/ai/chat-title/index.js.map +1 -0
- package/lib/cjs/ai/chat-title/stories/chat-title-default.story.js +30 -0
- package/lib/cjs/ai/chat-title/stories/chat-title-default.story.js.map +1 -0
- package/lib/cjs/ai/chat-title/stories/index.js +32 -0
- package/lib/cjs/ai/chat-title/stories/index.js.map +1 -0
- package/lib/cjs/ai/index.js +3 -1
- package/lib/cjs/ai/index.js.map +1 -1
- package/lib/cjs/ai/response/stories/response-full-example.story.js +4 -4
- package/lib/cjs/ai/response/stories/response-full-example.story.js.map +1 -1
- package/lib/cjs/data-grid/stories/datagrid-search-and-filters.stories.js +3 -4
- package/lib/cjs/data-grid/stories/datagrid-search-and-filters.stories.js.map +1 -1
- package/lib/cjs/drawer/Drawer.js.map +1 -1
- package/lib/cjs/hooks/use-debounce-callback/index.js.map +1 -1
- package/lib/cjs/next/tree-view/TreeView.js.map +1 -1
- package/lib/cjs/popover/Popover.js.map +1 -1
- package/lib/cjs/popover/use-popover.js.map +1 -1
- package/lib/cjs/slider/Slider.js.map +1 -1
- package/lib/cjs/spotlight/SpotlightTarget.js.map +1 -1
- package/lib/cjs/spotlight/use-spotlight.js.map +1 -1
- package/lib/cjs/text-input/TextInput.js.map +1 -1
- package/lib/cjs/text-overflow/TextOverflow.js +1 -1
- package/lib/cjs/text-overflow/TextOverflow.js.map +1 -1
- package/lib/cjs/text-overflow/text-overflow-utils.js +3 -3
- package/lib/cjs/text-overflow/text-overflow-utils.js.map +1 -1
- package/lib/cjs/text-overflow/use-truncate-with-button.js +2 -2
- package/lib/cjs/text-overflow/use-truncate-with-button.js.map +1 -1
- package/lib/cjs/tooltip/Tooltip.js.map +1 -1
- package/lib/cjs/tooltip/use-tooltip.js.map +1 -1
- package/lib/cjs/tree-view/TreeViewItem.js.map +1 -1
- package/lib/esm/ai/chat-title/ChatTitle.js +39 -0
- package/lib/esm/ai/chat-title/ChatTitle.js.map +1 -0
- package/lib/esm/ai/chat-title/index.js +22 -0
- package/lib/esm/ai/chat-title/index.js.map +1 -0
- package/lib/esm/ai/chat-title/stories/chat-title-default.story.js +28 -0
- package/lib/esm/ai/chat-title/stories/chat-title-default.story.js.map +1 -0
- package/lib/esm/ai/chat-title/stories/index.js +25 -0
- package/lib/esm/ai/chat-title/stories/index.js.map +1 -0
- package/lib/esm/ai/index.js +1 -0
- package/lib/esm/ai/index.js.map +1 -1
- package/lib/esm/ai/response/stories/response-full-example.story.js +4 -4
- package/lib/esm/ai/response/stories/response-full-example.story.js.map +1 -1
- package/lib/esm/data-grid/stories/datagrid-search-and-filters.stories.js +3 -4
- package/lib/esm/data-grid/stories/datagrid-search-and-filters.stories.js.map +1 -1
- package/lib/esm/drawer/Drawer.js.map +1 -1
- package/lib/esm/hooks/use-debounce-callback/index.js.map +1 -1
- package/lib/esm/next/tree-view/TreeView.js.map +1 -1
- package/lib/esm/popover/Popover.js.map +1 -1
- package/lib/esm/popover/use-popover.js.map +1 -1
- package/lib/esm/slider/Slider.js.map +1 -1
- package/lib/esm/spotlight/SpotlightTarget.js.map +1 -1
- package/lib/esm/spotlight/use-spotlight.js.map +1 -1
- package/lib/esm/text-input/TextInput.js.map +1 -1
- package/lib/esm/text-overflow/TextOverflow.js +1 -1
- package/lib/esm/text-overflow/TextOverflow.js.map +1 -1
- package/lib/esm/text-overflow/text-overflow-utils.js +3 -3
- package/lib/esm/text-overflow/text-overflow-utils.js.map +1 -1
- package/lib/esm/text-overflow/use-truncate-with-button.js +2 -2
- package/lib/esm/text-overflow/use-truncate-with-button.js.map +1 -1
- package/lib/esm/tooltip/Tooltip.js.map +1 -1
- package/lib/esm/tooltip/use-tooltip.js.map +1 -1
- package/lib/esm/tree-view/TreeViewItem.js.map +1 -1
- package/lib/types/ai/chat-title/ChatTitle.d.ts +27 -0
- package/lib/types/ai/chat-title/ChatTitle.d.ts.map +1 -0
- package/lib/types/ai/chat-title/index.d.ts +22 -0
- package/lib/types/ai/chat-title/index.d.ts.map +1 -0
- package/lib/types/ai/chat-title/stories/chat-title-default.story.d.ts +24 -0
- package/lib/types/ai/chat-title/stories/chat-title-default.story.d.ts.map +1 -0
- package/lib/types/ai/chat-title/stories/index.d.ts +23 -0
- package/lib/types/ai/chat-title/stories/index.d.ts.map +1 -0
- package/lib/types/ai/index.d.ts +1 -0
- package/lib/types/ai/index.d.ts.map +1 -1
- package/lib/types/data-grid/stories/datagrid-search-and-filters.stories.d.ts.map +1 -1
- package/lib/types/drawer/Drawer.d.ts.map +1 -1
- package/lib/types/hooks/use-debounce-callback/index.d.ts.map +1 -1
- package/lib/types/next/tree-view/TreeView.d.ts.map +1 -1
- package/lib/types/popover/Popover.d.ts.map +1 -1
- package/lib/types/popover/use-popover.d.ts.map +1 -1
- package/lib/types/slider/Slider.d.ts.map +1 -1
- package/lib/types/spotlight/SpotlightTarget.d.ts.map +1 -1
- package/lib/types/spotlight/use-spotlight.d.ts.map +1 -1
- package/lib/types/text-input/TextInput.d.ts.map +1 -1
- package/lib/types/text-overflow/text-overflow-utils.d.ts +1 -1
- package/lib/types/text-overflow/text-overflow-utils.d.ts.map +1 -1
- package/lib/types/tooltip/Tooltip.d.ts.map +1 -1
- package/lib/types/tooltip/use-tooltip.d.ts.map +1 -1
- package/lib/types/tree-view/TreeViewItem.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-popover.js","sourceRoot":"","sources":["../../../src/popover/use-popover.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,UAAU,EACV,IAAI,EAEJ,MAAM,EAGN,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,UAAU,EACV,WAAW,EACX,eAAe,EAEf,OAAO,EACP,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"use-popover.js","sourceRoot":"","sources":["../../../src/popover/use-popover.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,UAAU,EACV,IAAI,EAEJ,MAAM,EAGN,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,UAAU,EACV,WAAW,EACX,eAAe,EAEf,OAAO,EACP,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAuD1C,MAAM,UAAU,UAAU,CAAC,EACzB,aAAa,GAAG,KAAK,EACrB,SAAS,GAAG,QAAQ,EACpB,MAAM,EAAE,cAAc,EACtB,YAAY,EAAE,iBAAiB,EAC/B,YAAY,GAAG,EAAE,EACjB,aAAa,EACb,cAAc,EACd,2BAA2B,EAC3B,kBAAkB,EAClB,YAAY,EACZ,IAAI,EAAE,QAAQ,EACd,mBAAmB,EACnB,qBAAqB,EACrB,WAAW,EACX,QAAQ,GAAG,UAAU,EACrB,UAAU,GAAG,IAAI,EACjB,mBAAmB,GAAG,KAAK,MACT,EAAE;;IACpB,oEAAoE;IACpE,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC5E,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,EAAsB,CAAC;IAC7D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,EAAsB,CAAC;IAEzE,0EAA0E;IAC1E,oDAAoD;IACpD,MAAM,MAAM,GAAG,cAAc,aAAd,cAAc,cAAd,cAAc,GAAI,kBAAkB,CAAC;IAEpD,MAAM,IAAI,GAAG,WAAW,CAAC;QACvB,QAAQ,EAAE;YACR,SAAS,EAAE,aAAa;SACzB;QACD,UAAU,EAAE;YACV,MAAM,CAAC,YAAY,CAAC;YACpB,IAAI,CAAC;gBACH,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAClC,yBAAyB,EAAE,KAAK;gBAChC,OAAO,EAAE,CAAC;aACX,CAAC;YACF,KAAK,EAAE;YACP,GAAG,CAAC,mBAAmB;gBACrB,CAAC,CAAC;oBACE,IAAI,CAAC;wBACH,KAAK,CAAC,EAAE,eAAe,EAAE,cAAc,EAAE,QAAQ,EAAE;4BACjD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE;gCACrC,SAAS,EAAE,GAAG,eAAe,IAAI;gCACjC,QAAQ,EAAE,GAAG,cAAc,IAAI;6BAChC,CAAC,CAAC;wBACL,CAAC;wBACD,OAAO,EAAE,CAAC;qBACX,CAAC;iBACH;gBACH,CAAC,CAAC,EAAE,CAAC;SACR;QACD,wEAAwE;QACxE,uEAAuE;QACvE,yEAAyE;QACzE,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAC5B,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAC5B,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAG,IAAI,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,SAAS;QACpB,QAAQ;QACR,oBAAoB,EAAE,UAAU;KACjC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAE7B,2EAA2E;IAC3E,wEAAwE;IACxE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE;QAC9B,OAAO,EAAE,cAAc,KAAK,SAAS;KACtC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,EAAE;QAClC,YAAY,EAAE,mBAAmB;QACjC,cAAc,EAAE,qBAAqB;KACtC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE;QAC5B,IAAI,EAAE,QAAQ;KACf,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE;QAC1C,OAAO,EAAE,cAAc,KAAK,SAAS;QACrC,CAAC,EAAE,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,CAAC;QACpB,CAAC,EAAE,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,CAAC;KACrB,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,eAAe,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;IAE1E,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,mBAAmB,CAAC,OAAO,EAAE;QAChE,QAAQ,EAAE,MAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,mCAAI,CAAC;KAC7D,CAAC,CAAC;IAEH,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,+CACD,IAAI,GACJ,YAAY,KACf,2BAA2B;QAC3B,aAAa;QACb,YAAY;QACZ,MAAM;QACN,UAAU;QACV,OAAO;QACP,WAAW;QACX,gBAAgB;QAChB,UAAU;QACV,kBAAkB;QAClB,gBAAgB,IAChB,EACF;QACE,MAAM;QACN,YAAY;QACZ,IAAI;QACJ,gBAAgB;QAChB,OAAO;QACP,aAAa;QACb,2BAA2B;QAC3B,kBAAkB;QAClB,YAAY;QACZ,UAAU;QACV,WAAW;KACZ,CACF,CAAC;AACJ,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 */\nimport {\n autoUpdate,\n flip,\n type FloatingFocusManagerProps,\n offset,\n type OffsetOptions,\n type Placement,\n shift,\n size,\n useClick,\n useClientPoint,\n useDismiss,\n useFloating,\n useInteractions,\n type UseInteractionsReturn,\n useRole,\n useTransitionStyles,\n} from '@floating-ui/react';\nimport { tokens } from '@neo4j-ndl/base';\nimport { useMemo, useState } from 'react';\n\nexport interface PopoverOptions {\n isInitialOpen?: boolean;\n placement?: Placement;\n isOpen?: boolean;\n onOpenChange?: (open: boolean, event?: Event) => void;\n offsetOption?: OffsetOptions;\n anchorElement?: Element | null;\n anchorPosition?: {\n x: number;\n y: number;\n };\n // TODO v5: fix boolean naming convention\n // eslint-disable-next-line @typescript-eslint/naming-convention\n anchorElementAsPortalAnchor?: boolean;\n shouldCaptureFocus?: boolean;\n initialFocus?: number | React.RefObject<HTMLElement | null>;\n role?:\n | 'tooltip'\n | 'dialog'\n | 'alertdialog'\n | 'menu'\n | 'listbox'\n | 'grid'\n | 'tree';\n // TODO v5: decide if this naming is okay, or change it\n // eslint-disable-next-line @typescript-eslint/naming-convention\n closeOnClickOutside?: boolean;\n // TODO v5: decide if this naming is okay, or change it\n // eslint-disable-next-line @typescript-eslint/naming-convention\n closeOnReferencePress?: boolean;\n returnFocus?: FloatingFocusManagerProps['returnFocus'];\n strategy?: 'fixed' | 'absolute';\n isPortaled?: boolean;\n shouldConstrainSize?: boolean;\n}\n\nexport interface UsePopoverReturn\n extends UseInteractionsReturn, ReturnType<typeof useFloating> {\n isOpen: boolean;\n labelId: string | undefined;\n descriptionId: string | undefined;\n transitionStyles: React.CSSProperties;\n setLabelId: (labelId: string | undefined) => void;\n setDescriptionId: (descriptionId: string | undefined) => void;\n // TODO v5: fix boolean naming convention\n // eslint-disable-next-line @typescript-eslint/naming-convention\n anchorElementAsPortalAnchor: boolean | undefined;\n shouldCaptureFocus: boolean | undefined;\n initialFocus: number | React.RefObject<HTMLElement | null> | undefined;\n isPortaled: boolean;\n returnFocus: FloatingFocusManagerProps['returnFocus'];\n}\n\nexport function usePopover({\n isInitialOpen = false,\n placement = 'bottom',\n isOpen: controlledOpen,\n onOpenChange: setControlledOpen,\n offsetOption = 10,\n anchorElement,\n anchorPosition,\n anchorElementAsPortalAnchor,\n shouldCaptureFocus,\n initialFocus,\n role: roleProp,\n closeOnClickOutside,\n closeOnReferencePress,\n returnFocus,\n strategy = 'absolute',\n isPortaled = true,\n shouldConstrainSize = false,\n}: PopoverOptions = {}): UsePopoverReturn {\n // Internal state for uncontrolled mode (no `isOpen` prop provided).\n const [isOpenUncontrolled, setIsOpenUncontrolled] = useState(isInitialOpen);\n const [labelId, setLabelId] = useState<string | undefined>();\n const [descriptionId, setDescriptionId] = useState<string | undefined>();\n\n // Controlled/uncontrolled pattern: prefer the consumer-provided `isOpen`,\n // falling back to internal state when not provided.\n const isOpen = controlledOpen ?? isOpenUncontrolled;\n\n const data = useFloating({\n elements: {\n reference: anchorElement,\n },\n middleware: [\n offset(offsetOption),\n flip({\n crossAxis: placement.includes('-'),\n fallbackAxisSideDirection: 'end',\n padding: 5,\n }),\n shift(),\n ...(shouldConstrainSize\n ? [\n size({\n apply({ availableHeight, availableWidth, elements }) {\n Object.assign(elements.floating.style, {\n maxHeight: `${availableHeight}px`,\n maxWidth: `${availableWidth}px`,\n });\n },\n padding: 5,\n }),\n ]\n : []),\n ],\n // Floating UI calls this when interactions (useClick, useDismiss, etc.)\n // trigger an open/close. We always sync internal state so uncontrolled\n // mode works, and notify the consumer callback exactly once if provided.\n onOpenChange: (open, event) => {\n setIsOpenUncontrolled(open);\n setControlledOpen?.(open, event);\n },\n open: isOpen,\n placement: placement,\n strategy,\n whileElementsMounted: autoUpdate,\n });\n const context = data.context;\n\n // Only enable built-in click-to-toggle in uncontrolled mode. In controlled\n // mode the consumer owns the open state and wires up their own trigger.\n const click = useClick(context, {\n enabled: controlledOpen === undefined,\n });\n\n const dismiss = useDismiss(context, {\n outsidePress: closeOnClickOutside,\n referencePress: closeOnReferencePress,\n });\n const role = useRole(context, {\n role: roleProp,\n });\n\n const clientPoint = useClientPoint(context, {\n enabled: anchorPosition !== undefined,\n x: anchorPosition?.x,\n y: anchorPosition?.y,\n });\n\n const interactions = useInteractions([click, dismiss, role, clientPoint]);\n\n const { styles: transitionStyles } = useTransitionStyles(context, {\n duration: Number.parseInt(tokens.motion.duration.quick) ?? 0,\n });\n\n return useMemo(\n () => ({\n ...data,\n ...interactions,\n anchorElementAsPortalAnchor,\n descriptionId,\n initialFocus,\n isOpen,\n isPortaled,\n labelId,\n returnFocus,\n setDescriptionId,\n setLabelId,\n shouldCaptureFocus,\n transitionStyles,\n }),\n [\n isOpen,\n interactions,\n data,\n transitionStyles,\n labelId,\n descriptionId,\n anchorElementAsPortalAnchor,\n shouldCaptureFocus,\n initialFocus,\n isPortaled,\n returnFocus,\n ],\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../src/slider/Slider.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 React, { useCallback, useEffect } from 'react';\nimport {\n mergeProps,\n useFocusRing,\n useSlider,\n useSliderThumb,\n VisuallyHidden,\n} from 'react-aria';\nimport { type SliderState, useSliderState } from 'react-stately';\n\nimport {\n type HtmlAttributes,\n type PolymorphicCommonProps,\n} from '../_common/types';\nimport { Tooltip } from '../tooltip';\n\ntype SliderPropsBase = {\n /** Input props of the underlying input element */\n inputProps?: HtmlAttributes<'input'>;\n /** Determines the step size that will be added or removed from the current value when moving the slider button */\n step?: number;\n /** Whether the slider is disabled */\n isDisabled?: boolean;\n /** The minimum value possible to choose */\n minValue?: number;\n /** The maximum value possible to choose */\n maxValue?: number;\n /** Whether to display a tooltip with the current value when the slider is being dragged */\n showValues?: boolean;\n /** Whether to display visual indicators for each step in the slider */\n showSteps?: boolean;\n};\n\ntype SingleSlider = SliderPropsBase & {\n /** Type of the slider */\n type?: 'single';\n /** Current value of the single slider. **Only required when the type is 'single'**. */\n value: number;\n /** Callback function triggered when the slider value(s) changes. The function parameter varies depending on the slider type, for single slider, it is a number and for range slider, it is an array of two numbers. */\n onChange: (value: number) => void;\n};\n\ntype RangeSlider = SliderPropsBase & {\n /** Type of the slider */\n type: 'range';\n /** Current values of the range slider as an array of two numbers `[min, max]`. **Only required when the type is 'range'**.*/\n values: [number, number];\n /** Callback function triggered when the slider value(s) changes. The function parameter varies depending on the slider type, for single slider, it is a number and for range slider, it is an array of two numbers. */\n onChange: (value: [number, number]) => void;\n};\n\n/**\n * @remarks\n * The `type` prop is used to determine the type of the slider. It can be `single` or `range`. The `value` prop is required when the `type` is `single` and `values` is required when the `type` is `range`. It also affects the `onChange` prop type.\n */\ntype SliderProps = SingleSlider | RangeSlider;\n\nexport const Slider = <T extends React.ElementType = 'div'>({\n as,\n inputProps = {},\n className,\n style,\n minValue = 0,\n maxValue = 100,\n isDisabled = false,\n showSteps = false,\n showValues = false,\n step = 1,\n type = 'single',\n onChange,\n htmlAttributes,\n ref,\n ...restProps\n}: PolymorphicCommonProps<T, SliderProps>) => {\n const trackRef = React.useRef<HTMLDivElement | null>(null);\n\n const castedValue =\n type === 'range'\n ? (restProps as RangeSlider).values\n : (restProps as SingleSlider).value;\n\n const castedOnChange =\n type === 'range'\n ? (onChange as RangeSlider['onChange'])\n : (onChange as SingleSlider['onChange']);\n\n const state = useSliderState<typeof castedValue>({\n defaultValue: castedValue,\n isDisabled,\n maxValue,\n minValue,\n numberFormatter: new Intl.NumberFormat('en-US'),\n // oxlint-disable-next-line no-explicit-any\n onChange: castedOnChange as any,\n step,\n });\n\n const { setThumbValue } = state;\n\n const { groupProps, trackProps } = useSlider(\n { 'aria-label': 'slider' },\n state,\n trackRef,\n );\n\n const updatesSliderValue = useCallback(\n (newValue: number | [number, number]) => {\n if (type === 'single' && typeof newValue === 'number') {\n setThumbValue(0, newValue);\n } else if (type === 'range' && Array.isArray(newValue)) {\n setThumbValue(0, newValue[0]);\n setThumbValue(1, newValue[1]);\n }\n },\n [type, setThumbValue],\n );\n\n useEffect(() => {\n updatesSliderValue(castedValue);\n // Needed to make the slider work with controlled values\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [castedValue]);\n\n const Component: React.ElementType = as ?? 'div';\n\n return (\n <Component\n className={classNames('ndl-slider', className)}\n style={style}\n role=\"presentation\"\n ref={ref}\n {...groupProps}\n {...restProps}\n {...htmlAttributes}\n >\n {/* The track element holds the visible track line, the filled track line and the thumb. */}\n <div\n {...trackProps}\n ref={trackRef as React.RefObject<HTMLDivElement>}\n className={classNames('ndl-track', {\n 'ndl-is-disabled': state.isDisabled,\n })}\n >\n {/* Circular marks, acting as indicators for the steps */}\n {showSteps && (\n <TrackMarks state={state} min={minValue} max={maxValue} />\n )}\n <FilledTrack state={state} />\n <Thumb\n index={0}\n state={state}\n trackRef={trackRef as React.RefObject<HTMLDivElement>}\n showValues={showValues}\n inputForwardedProps={inputProps}\n />\n {type === 'range' && (\n <Thumb\n index={1}\n state={state}\n trackRef={trackRef as React.RefObject<HTMLDivElement>}\n showValues={showValues}\n inputForwardedProps={inputProps}\n />\n )}\n </div>\n </Component>\n );\n};\n\nSlider.displayName = 'Slider';\n\nfunction FilledTrack({ state }: { state: SliderState }) {\n let width: number;\n let left: number;\n if (state.values.length === 1) {\n width = state.getValuePercent(state.values[0]) * 100;\n left = 0;\n } else {\n width =\n state.getValuePercent(state.values[1]) * 100 -\n state.getValuePercent(state.values[0]) * 100;\n left = state.getValuePercent(state.values[0]) * 100;\n }\n\n return (\n <div\n className=\"ndl-filled-track\"\n style={{\n left: `${left}%`,\n width: `${width}%`,\n }}\n />\n );\n}\n\nfunction TrackMarks({\n state,\n max,\n min,\n}: {\n state: SliderState;\n max: number;\n min: number;\n}) {\n const markNo = Math.round((max - min) / state.step);\n\n return (\n <div role=\"presentation\" className=\"ndl-track-marks\">\n {Array.from({ length: markNo - 1 }).map((_, index) => {\n const percent = (index / markNo) * 100;\n\n let isFilled;\n if (state.values.length === 1) {\n isFilled = state.getValuePercent(state.values[0]) * 100 > percent;\n } else {\n isFilled =\n state.getValuePercent(state.values[0]) * 100 < percent &&\n state.getValuePercent(state.values[1]) * 100 > percent;\n }\n\n return (\n <div\n key={`track-mark-${index}`}\n className={classNames('ndl-track-mark', {\n 'ndl-on-active-track': isFilled,\n })}\n style={{\n left: `${((index + 1) / markNo) * 100}%`,\n }}\n />\n );\n })}\n </div>\n );\n}\n\nfunction Thumb(props: {\n index: number;\n state: SliderState;\n showValues?: boolean;\n trackRef: React.RefObject<HTMLDivElement>;\n inputForwardedProps: HtmlAttributes<'input'>;\n}) {\n const { state, trackRef, index, inputForwardedProps } = props;\n const inputRef = React.useRef(null);\n const { thumbProps, inputProps, isDragging } = useSliderThumb(\n {\n index,\n inputRef,\n name: 'slider-thumb',\n trackRef,\n },\n state,\n );\n\n const { focusProps, isFocusVisible } = useFocusRing();\n\n /**\n * Solve issue with:\n * Warning: Received NaN for the `value` attribute. If this is expected, cast the value to a string.\n * Receiving NaN for other attributes also, like `max`. Waiting for a fix in react-aria.\n * @see https://github.com/adobe/react-spectrum/issues/5859\n * @see https://github.com/adobe/react-spectrum/pull/5861\n */\n const mergedProps = mergeProps(\n inputProps,\n focusProps,\n // Omitting aria-valuetext double announcements, unless explicitly provided\n { 'aria-valuetext': '' },\n inputForwardedProps,\n );\n const value =\n mergedProps.value !== undefined || mergedProps.value === 0\n ? mergedProps.value\n : '';\n\n return (\n <Tooltip\n isDisabled={props.showValues !== true}\n isOpen={isDragging || undefined}\n placement=\"top\"\n type=\"simple\"\n >\n <Tooltip.Trigger hasButtonWrapper>\n <div\n {...thumbProps}\n className={classNames('ndl-thumb', {\n 'ndl-focus': isFocusVisible,\n 'ndl-is-dragging': isDragging,\n })}\n >\n <VisuallyHidden>\n <input ref={inputRef} {...mergedProps} />\n </VisuallyHidden>\n </div>\n </Tooltip.Trigger>\n <Tooltip.Content>{value}</Tooltip.Content>\n </Tooltip>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../src/slider/Slider.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 React, { useCallback, useEffect } from 'react';\nimport {\n mergeProps,\n useFocusRing,\n useSlider,\n useSliderThumb,\n VisuallyHidden,\n} from 'react-aria';\nimport { type SliderState, useSliderState } from 'react-stately';\n\nimport {\n type HtmlAttributes,\n type PolymorphicCommonProps,\n} from '../_common/types';\nimport { Tooltip } from '../tooltip';\n\ntype SliderPropsBase = {\n /** Input props of the underlying input element */\n inputProps?: HtmlAttributes<'input'>;\n /** Determines the step size that will be added or removed from the current value when moving the slider button */\n step?: number;\n /** Whether the slider is disabled */\n isDisabled?: boolean;\n /** The minimum value possible to choose */\n minValue?: number;\n /** The maximum value possible to choose */\n maxValue?: number;\n /** Whether to display a tooltip with the current value when the slider is being dragged */\n // TODO v5: decide if this naming is okay, or change it\n // eslint-disable-next-line @typescript-eslint/naming-convention\n showValues?: boolean;\n /** Whether to display visual indicators for each step in the slider */\n // TODO v5: decide if this naming is okay, or change it\n // eslint-disable-next-line @typescript-eslint/naming-convention\n showSteps?: boolean;\n};\n\ntype SingleSlider = SliderPropsBase & {\n /** Type of the slider */\n type?: 'single';\n /** Current value of the single slider. **Only required when the type is 'single'**. */\n value: number;\n /** Callback function triggered when the slider value(s) changes. The function parameter varies depending on the slider type, for single slider, it is a number and for range slider, it is an array of two numbers. */\n onChange: (value: number) => void;\n};\n\ntype RangeSlider = SliderPropsBase & {\n /** Type of the slider */\n type: 'range';\n /** Current values of the range slider as an array of two numbers `[min, max]`. **Only required when the type is 'range'**.*/\n values: [number, number];\n /** Callback function triggered when the slider value(s) changes. The function parameter varies depending on the slider type, for single slider, it is a number and for range slider, it is an array of two numbers. */\n onChange: (value: [number, number]) => void;\n};\n\n/**\n * @remarks\n * The `type` prop is used to determine the type of the slider. It can be `single` or `range`. The `value` prop is required when the `type` is `single` and `values` is required when the `type` is `range`. It also affects the `onChange` prop type.\n */\ntype SliderProps = SingleSlider | RangeSlider;\n\nexport const Slider = <T extends React.ElementType = 'div'>({\n as,\n inputProps = {},\n className,\n style,\n minValue = 0,\n maxValue = 100,\n isDisabled = false,\n showSteps = false,\n showValues = false,\n step = 1,\n type = 'single',\n onChange,\n htmlAttributes,\n ref,\n ...restProps\n}: PolymorphicCommonProps<T, SliderProps>) => {\n const trackRef = React.useRef<HTMLDivElement | null>(null);\n\n const castedValue =\n type === 'range'\n ? (restProps as RangeSlider).values\n : (restProps as SingleSlider).value;\n\n const castedOnChange =\n type === 'range'\n ? (onChange as RangeSlider['onChange'])\n : (onChange as SingleSlider['onChange']);\n\n const state = useSliderState<typeof castedValue>({\n defaultValue: castedValue,\n isDisabled,\n maxValue,\n minValue,\n numberFormatter: new Intl.NumberFormat('en-US'),\n // oxlint-disable-next-line no-explicit-any\n onChange: castedOnChange as any,\n step,\n });\n\n const { setThumbValue } = state;\n\n const { groupProps, trackProps } = useSlider(\n { 'aria-label': 'slider' },\n state,\n trackRef,\n );\n\n const updatesSliderValue = useCallback(\n (newValue: number | [number, number]) => {\n if (type === 'single' && typeof newValue === 'number') {\n setThumbValue(0, newValue);\n } else if (type === 'range' && Array.isArray(newValue)) {\n setThumbValue(0, newValue[0]);\n setThumbValue(1, newValue[1]);\n }\n },\n [type, setThumbValue],\n );\n\n useEffect(() => {\n updatesSliderValue(castedValue);\n // Needed to make the slider work with controlled values\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [castedValue]);\n\n const Component: React.ElementType = as ?? 'div';\n\n return (\n <Component\n className={classNames('ndl-slider', className)}\n style={style}\n role=\"presentation\"\n ref={ref}\n {...groupProps}\n {...restProps}\n {...htmlAttributes}\n >\n {/* The track element holds the visible track line, the filled track line and the thumb. */}\n <div\n {...trackProps}\n ref={trackRef as React.RefObject<HTMLDivElement>}\n className={classNames('ndl-track', {\n 'ndl-is-disabled': state.isDisabled,\n })}\n >\n {/* Circular marks, acting as indicators for the steps */}\n {showSteps && (\n <TrackMarks state={state} min={minValue} max={maxValue} />\n )}\n <FilledTrack state={state} />\n <Thumb\n index={0}\n state={state}\n trackRef={trackRef as React.RefObject<HTMLDivElement>}\n showValues={showValues}\n inputForwardedProps={inputProps}\n />\n {type === 'range' && (\n <Thumb\n index={1}\n state={state}\n trackRef={trackRef as React.RefObject<HTMLDivElement>}\n showValues={showValues}\n inputForwardedProps={inputProps}\n />\n )}\n </div>\n </Component>\n );\n};\n\nSlider.displayName = 'Slider';\n\nfunction FilledTrack({ state }: { state: SliderState }) {\n let width: number;\n let left: number;\n if (state.values.length === 1) {\n width = state.getValuePercent(state.values[0]) * 100;\n left = 0;\n } else {\n width =\n state.getValuePercent(state.values[1]) * 100 -\n state.getValuePercent(state.values[0]) * 100;\n left = state.getValuePercent(state.values[0]) * 100;\n }\n\n return (\n <div\n className=\"ndl-filled-track\"\n style={{\n left: `${left}%`,\n width: `${width}%`,\n }}\n />\n );\n}\n\nfunction TrackMarks({\n state,\n max,\n min,\n}: {\n state: SliderState;\n max: number;\n min: number;\n}) {\n const markNo = Math.round((max - min) / state.step);\n\n return (\n <div role=\"presentation\" className=\"ndl-track-marks\">\n {Array.from({ length: markNo - 1 }).map((_, index) => {\n const percent = (index / markNo) * 100;\n\n let isFilled;\n if (state.values.length === 1) {\n isFilled = state.getValuePercent(state.values[0]) * 100 > percent;\n } else {\n isFilled =\n state.getValuePercent(state.values[0]) * 100 < percent &&\n state.getValuePercent(state.values[1]) * 100 > percent;\n }\n\n return (\n <div\n key={`track-mark-${index}`}\n className={classNames('ndl-track-mark', {\n 'ndl-on-active-track': isFilled,\n })}\n style={{\n left: `${((index + 1) / markNo) * 100}%`,\n }}\n />\n );\n })}\n </div>\n );\n}\n\nfunction Thumb(props: {\n index: number;\n state: SliderState;\n // TODO v5: decide if this naming is okay, or change it\n // eslint-disable-next-line @typescript-eslint/naming-convention\n showValues?: boolean;\n trackRef: React.RefObject<HTMLDivElement>;\n inputForwardedProps: HtmlAttributes<'input'>;\n}) {\n const { state, trackRef, index, inputForwardedProps } = props;\n const inputRef = React.useRef(null);\n const { thumbProps, inputProps, isDragging } = useSliderThumb(\n {\n index,\n inputRef,\n name: 'slider-thumb',\n trackRef,\n },\n state,\n );\n\n const { focusProps, isFocusVisible } = useFocusRing();\n\n /**\n * Solve issue with:\n * Warning: Received NaN for the `value` attribute. If this is expected, cast the value to a string.\n * Receiving NaN for other attributes also, like `max`. Waiting for a fix in react-aria.\n * @see https://github.com/adobe/react-spectrum/issues/5859\n * @see https://github.com/adobe/react-spectrum/pull/5861\n */\n const mergedProps = mergeProps(\n inputProps,\n focusProps,\n // Omitting aria-valuetext double announcements, unless explicitly provided\n { 'aria-valuetext': '' },\n inputForwardedProps,\n );\n const value =\n mergedProps.value !== undefined || mergedProps.value === 0\n ? mergedProps.value\n : '';\n\n return (\n <Tooltip\n isDisabled={props.showValues !== true}\n isOpen={isDragging || undefined}\n placement=\"top\"\n type=\"simple\"\n >\n <Tooltip.Trigger hasButtonWrapper>\n <div\n {...thumbProps}\n className={classNames('ndl-thumb', {\n 'ndl-focus': isFocusVisible,\n 'ndl-is-dragging': isDragging,\n })}\n >\n <VisuallyHidden>\n <input ref={inputRef} {...mergedProps} />\n </VisuallyHidden>\n </div>\n </Tooltip.Trigger>\n <Tooltip.Content>{value}</Tooltip.Content>\n </Tooltip>\n );\n}\n"]}
|
|
@@ -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 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
|
+
{"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 // TODO v5: decide if this naming is okay, don't see how to follow the rule without a name that is tooo long\n // eslint-disable-next-line @typescript-eslint/naming-convention\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":"use-spotlight.js","sourceRoot":"","sources":["../../../src/spotlight/use-spotlight.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,UAAU,EACV,IAAI,EACJ,MAAM,EAEN,KAAK,EACL,QAAQ,EACR,UAAU,EACV,WAAW,EACX,eAAe,EAEf,OAAO,EACP,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"use-spotlight.js","sourceRoot":"","sources":["../../../src/spotlight/use-spotlight.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 {\n autoUpdate,\n flip,\n offset,\n type Placement,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useInteractions,\n type UseInteractionsReturn,\n useRole,\n useTransitionStyles,\n} from '@floating-ui/react';\nimport { tokens } from '@neo4j-ndl/base';\nimport { useMemo, useState } from 'react';\n\nexport interface SpotlightOptions {\n isInitialOpen?: boolean;\n placement?: Placement;\n isOpen?: boolean;\n onOpenChange?: (open: boolean, event?: Event) => void;\n anchorElement?: Element | null;\n // TODO v5: fix boolean naming convention\n // eslint-disable-next-line @typescript-eslint/naming-convention\n anchorElementAsPortalAnchor?: boolean;\n initialFocus?: number | React.MutableRefObject<HTMLElement | null>;\n // TODO v5: fix boolean naming convention\n // eslint-disable-next-line @typescript-eslint/naming-convention\n closeOnClickOutside?: boolean;\n strategy?: 'fixed' | 'absolute';\n}\n\nexport interface UseSpotlightReturn\n extends UseInteractionsReturn, ReturnType<typeof useFloating> {\n isOpen: boolean;\n setIsOpen: (isOpen: boolean) => void;\n labelId: string | undefined;\n transitionStyles: React.CSSProperties;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n anchorElementAsPortalAnchor: boolean | undefined;\n initialFocus: number | React.MutableRefObject<HTMLElement | null> | undefined;\n}\n\nexport function useSpotlight({\n isInitialOpen = false,\n placement = 'bottom',\n isOpen: controlledOpen,\n onOpenChange: setControlledOpen,\n anchorElement,\n anchorElementAsPortalAnchor,\n initialFocus,\n closeOnClickOutside,\n strategy = 'absolute',\n}: SpotlightOptions = {}): UseSpotlightReturn {\n const [isOpenUncontrolled, setIsOpenUncontrolled] = useState(isInitialOpen);\n const [labelId, setLabelId] = useState<string | undefined>();\n const [descriptionId, setDescriptionId] = useState<string | undefined>();\n const isOpen = controlledOpen ?? isOpenUncontrolled;\n const setIsOpen = setControlledOpen ?? setIsOpenUncontrolled;\n const data = useFloating({\n elements: {\n reference: anchorElement,\n },\n middleware: [\n offset(10),\n flip({\n crossAxis: placement.includes('-'),\n fallbackAxisSideDirection: 'end',\n padding: 5,\n }),\n shift({ padding: 5 }),\n ],\n onOpenChange: (open, event) => {\n setIsOpen(open);\n setControlledOpen?.(open, event);\n },\n open: isOpen,\n placement: placement,\n strategy,\n whileElementsMounted: autoUpdate,\n });\n const context = data.context;\n\n const click = useClick(context, {\n enabled: controlledOpen === undefined,\n });\n\n const dismiss = useDismiss(context, {\n outsidePress: closeOnClickOutside,\n });\n const role = useRole(context, {\n role: 'dialog',\n });\n\n const interactions = useInteractions([click, dismiss, role]);\n\n const { styles: transitionStyles } = useTransitionStyles(context, {\n duration: Number.parseInt(tokens.motion.duration.quick) ?? 0,\n });\n\n return useMemo(\n () => ({\n isOpen,\n setIsOpen,\n ...interactions,\n ...data,\n anchorElementAsPortalAnchor,\n descriptionId,\n initialFocus,\n labelId,\n setDescriptionId,\n setLabelId,\n transitionStyles,\n }),\n [\n isOpen,\n setIsOpen,\n interactions,\n data,\n transitionStyles,\n labelId,\n anchorElementAsPortalAnchor,\n descriptionId,\n initialFocus,\n ],\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput.js","sourceRoot":"","sources":["../../../src/text-input/TextInput.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 */\n\nimport classNames from 'classnames';\nimport {\n type InputHTMLAttributes,\n type ReactElement,\n type ReactNode,\n useId,\n useMemo,\n} from 'react';\n\nimport { customLabelAndNoAriaLabelWarningMessage } from '../_common/messages';\nimport { type CommonProps, type TooltipObjectProps } from '../_common/types';\nimport { useSemiControlledInput } from '../_common/use-semi-controlled-input';\nimport { needleWarningMessage } from '../_common/utils';\nimport { ExclamationCircleIconSolid } from '../icons/generated/heroIcons/ExclamationCircleIconSolid';\nimport { InformationCircleIconOutline } from '../icons/generated/heroIcons/InformationCircleIconOutline';\nimport { XMarkIconOutline } from '../icons/generated/heroIcons/XMarkIconOutline';\nimport { LoadingSpinner } from '../loading-spinner';\nimport { Skeleton } from '../skeleton';\nimport { Tooltip } from '../tooltip';\nimport { Typography } from '../typography';\n\n/**\n * @remarks\n * When `moreInformationText` is provided, a tooltip is rendered next to the label, and the `tooltipProps` prop is used to configure the tooltip. The `TooltipObjectProps` type is defined as: `{ root?: Partial<React.ComponentProps<typeof Tooltip>>; trigger?: Partial<React.ComponentProps<typeof Tooltip.Trigger>>; content?: Partial<React.ComponentProps<typeof Tooltip.Content>>; }`, see the Tooltip component for more details.\n *\n * @remarks\n * When `isSkeletonLoading` is true, the input is rendered as a loading skeleton and the `skeletonProps` prop is used to configure the skeleton. For more information, see the Skeleton documentation.\n */\ntype TextInputProps = {\n /** Assistive text displayed below the input */\n helpText?: string | ReactNode;\n\n /** Error message displayed below the input. When provided, it overrides `helpText` and shows an error icon */\n errorText?: string | ReactNode;\n\n /** Leading element rendered inside the input */\n leadingElement?: ReactElement;\n\n /** Trailing element rendered inside the input */\n trailingElement?: ReactElement;\n\n /** Size of the input */\n size?: 'small' | 'medium' | 'large';\n\n /** Whether the input is read-only */\n isReadOnly?: boolean;\n\n /**\n * Whether to display the Required/Optional label next to the field label.\n * Shows Required if isRequired is true, otherwise shows Optional.\n * @default false\n */\n showRequiredOrOptionalLabel?: boolean;\n\n /** Whether the input is disabled */\n isDisabled?: boolean;\n\n /** Whether the input is required */\n isRequired?: boolean;\n\n /** The current value of the input */\n value?: React.ComponentPropsWithoutRef<'input'>['value'];\n\n /** Placeholder text displayed when the input is empty */\n placeholder?: React.ComponentPropsWithoutRef<'input'>['placeholder'];\n\n /** Callback function triggered when the input value changes */\n onChange?: React.ComponentPropsWithoutRef<'input'>['onChange'];\n\n /** Whether the input should take the full available width */\n isFluid?: boolean;\n\n /** Text displayed in the information tooltip shown next to the label */\n moreInformationText?: React.ReactNode;\n\n /** The label displayed above the input */\n label?: string | React.ReactNode;\n\n /** Props for the Tooltip component used by the information icon */\n tooltipProps?: TooltipObjectProps;\n\n /** Whether to render skeletons instead of content */\n isSkeletonLoading?: boolean;\n\n /** Additional props forwarded to the underlying Skeleton components */\n skeletonProps?: React.ComponentProps<typeof Skeleton>;\n\n /** Whether to show the clear button */\n isClearable?: boolean;\n\n /** Whether to show the loading spinner */\n isLoading?: boolean;\n};\n\n/**\n *\n *\n * TextInput Component\n *\n *\n */\n\nexport const TextInput = ({\n label,\n isFluid,\n errorText,\n helpText,\n leadingElement,\n trailingElement,\n showRequiredOrOptionalLabel = false,\n moreInformationText,\n size = 'medium',\n placeholder,\n value,\n tooltipProps,\n htmlAttributes,\n isDisabled,\n isReadOnly,\n isRequired,\n onChange,\n isClearable = false,\n className,\n style,\n isSkeletonLoading = false,\n isLoading = false,\n skeletonProps,\n ref,\n ...restProps\n}: CommonProps<'input', TextInputProps>) => {\n const [currentValue, handleChange] = useSemiControlledInput({\n inputType: 'text',\n isControlled: value !== undefined,\n onChange,\n state: value ?? '',\n });\n const hintId = useId();\n const helpTextId = useId();\n const errorTextId = useId();\n\n const containerWrappingClasses = classNames(`ndl-text-input`, className, {\n 'ndl-disabled': isDisabled,\n 'ndl-has-error': errorText,\n 'ndl-has-icon': leadingElement || trailingElement || errorText,\n 'ndl-has-leading-icon': leadingElement,\n 'ndl-has-trailing-icon': trailingElement || errorText,\n 'ndl-large': size === 'large',\n 'ndl-medium': size === 'medium',\n 'ndl-read-only': isReadOnly,\n 'ndl-small': size === 'small',\n });\n\n const hasEmptyLabelValue =\n label === undefined || label === null || label === '';\n\n const labelWrappingClasses = classNames('ndl-form-item-label', {\n 'ndl-fluid': isFluid,\n 'ndl-form-item-no-label': hasEmptyLabelValue,\n });\n\n const combinedHtmlInputAttributes: InputHTMLAttributes<HTMLInputElement> = {\n ...htmlAttributes,\n className: classNames('ndl-input', htmlAttributes?.className),\n };\n const ariaLabel = combinedHtmlInputAttributes['aria-label'];\n const isCustomLabel = Boolean(label) && typeof label !== 'string';\n const hasCustomLabelAndNoAriaLabel =\n isCustomLabel && (ariaLabel === undefined || ariaLabel === '');\n const shouldRenderHint = isClearable || isLoading;\n\n const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (isClearable && event.key === 'Escape' && Boolean(currentValue)) {\n event.preventDefault();\n event.stopPropagation();\n handleChange?.({\n target: { value: '' },\n } as React.ChangeEvent<HTMLInputElement>);\n }\n htmlAttributes?.onKeyDown?.(event);\n };\n\n useMemo(() => {\n if (!label && !ariaLabel) {\n needleWarningMessage(\n 'A TextInput without a label does not have an aria label, be sure to include an aria label for screen readers. Link: https://dequeuniversity.com/rules/axe/4.2/label?application=axeAPI',\n );\n }\n\n if (hasCustomLabelAndNoAriaLabel) {\n needleWarningMessage(customLabelAndNoAriaLabelWarningMessage);\n }\n }, [label, ariaLabel, hasCustomLabelAndNoAriaLabel]);\n\n const informationIconClasses = classNames({\n 'ndl-information-icon-large': size === 'large',\n 'ndl-information-icon-small': size === 'small' || size === 'medium',\n });\n\n const combinedAriaDescribedby = useMemo(() => {\n const ariaDescribedby = [];\n\n if (hintId && shouldRenderHint) {\n ariaDescribedby.push(hintId);\n }\n if (helpText && !errorText) {\n ariaDescribedby.push(helpTextId);\n } else if (errorText) {\n ariaDescribedby.push(errorTextId);\n }\n return ariaDescribedby.join(' ');\n }, [hintId, shouldRenderHint, helpText, errorText, helpTextId, errorTextId]);\n\n return (\n <div className={containerWrappingClasses} style={style}>\n {/* We enable implicit label wrapping */}\n {/* Source: https://dequeuniversity.com/rules/axe/4.2/label?application=axeAPI */}\n <label className={labelWrappingClasses}>\n {!hasEmptyLabelValue && (\n <Skeleton\n onBackground=\"weak\"\n shape=\"rectangular\"\n {...skeletonProps}\n isLoading={isSkeletonLoading}\n >\n <div className=\"ndl-label-text-wrapper\">\n <Typography\n variant={size === 'large' ? 'body-large' : 'body-medium'}\n className=\"ndl-label-text\"\n >\n {label}\n </Typography>\n {Boolean(moreInformationText) && (\n <Tooltip {...tooltipProps?.root} type=\"simple\">\n <Tooltip.Trigger\n {...tooltipProps?.trigger}\n className={informationIconClasses}\n hasButtonWrapper\n >\n <div\n tabIndex={0}\n role=\"button\"\n aria-label=\"Information icon\"\n >\n <InformationCircleIconOutline />\n </div>\n </Tooltip.Trigger>\n <Tooltip.Content {...tooltipProps?.content}>\n {moreInformationText}\n </Tooltip.Content>\n </Tooltip>\n )}\n {showRequiredOrOptionalLabel && (\n <Typography\n variant={size === 'large' ? 'body-large' : 'body-medium'}\n className=\"ndl-form-item-optional\"\n >\n {isRequired === true ? 'Required' : 'Optional'}\n </Typography>\n )}\n </div>\n </Skeleton>\n )}\n <Skeleton\n onBackground=\"weak\"\n shape=\"rectangular\"\n {...skeletonProps}\n isLoading={isSkeletonLoading}\n >\n <div className=\"ndl-input-wrapper\">\n {(leadingElement || (isLoading && !trailingElement)) && (\n <div className=\"ndl-element-leading ndl-element\">\n {isLoading ? (\n <LoadingSpinner\n size={size === 'large' ? 'medium' : 'small'}\n className={\n size === 'large'\n ? 'ndl-medium-spinner'\n : 'ndl-small-spinner'\n }\n />\n ) : (\n leadingElement\n )}\n </div>\n )}\n <div\n className={classNames('ndl-input-container', {\n 'ndl-clearable': isClearable,\n })}\n >\n <input\n ref={ref}\n readOnly={isReadOnly}\n disabled={isDisabled}\n required={isRequired}\n value={currentValue}\n placeholder={placeholder}\n type=\"text\"\n onChange={handleChange}\n aria-describedby={combinedAriaDescribedby}\n aria-invalid={Boolean(errorText)}\n {...combinedHtmlInputAttributes}\n onKeyDown={handleInputKeyDown}\n {...restProps}\n />\n {shouldRenderHint && (\n <span\n id={hintId}\n className=\"ndl-text-input-hint\"\n aria-hidden={true}\n >\n {isLoading && 'Loading '}\n {isClearable && 'Press Escape to clear input.'}\n </span>\n )}\n {isClearable && Boolean(currentValue) && (\n <div className=\"ndl-element-clear ndl-element\">\n <button\n tabIndex={-1}\n aria-hidden={true}\n type=\"button\"\n title=\"Clear input (Esc)\"\n onClick={() => {\n handleChange?.({\n target: { value: '' },\n } as React.ChangeEvent<HTMLInputElement>);\n }}\n >\n <XMarkIconOutline className=\"n-size-4\" />\n </button>\n </div>\n )}\n </div>\n {trailingElement && (\n <div className=\"ndl-element-trailing ndl-element\">\n {isLoading && !leadingElement ? (\n <LoadingSpinner\n size={size === 'large' ? 'medium' : 'small'}\n className={\n size === 'large'\n ? 'ndl-medium-spinner'\n : 'ndl-small-spinner'\n }\n />\n ) : (\n trailingElement\n )}\n </div>\n )}\n </div>\n </Skeleton>\n </label>\n {Boolean(helpText) && !errorText && (\n <Skeleton\n onBackground=\"weak\"\n shape=\"rectangular\"\n isLoading={isSkeletonLoading}\n >\n <Typography\n variant={size === 'large' ? 'body-medium' : 'body-small'}\n className=\"ndl-form-message\"\n htmlAttributes={{\n 'aria-live': 'polite',\n id: helpTextId,\n }}\n >\n {helpText}\n </Typography>\n </Skeleton>\n )}\n {Boolean(errorText) && (\n // TODO v4: We might want to have a min width for the container for the messages to help skeleton loading.\n // Currently the message fills 100% of the width while the rest of the text input has a set width.\n <Skeleton\n onBackground=\"weak\"\n shape=\"rectangular\"\n width=\"fit-content\"\n {...skeletonProps}\n isLoading={isSkeletonLoading}\n >\n <div className=\"ndl-form-message\">\n <div className=\"ndl-error-icon\">\n <ExclamationCircleIconSolid />\n </div>\n <Typography\n className=\"ndl-error-text\"\n variant={size === 'large' ? 'body-medium' : 'body-small'}\n htmlAttributes={{\n 'aria-live': 'polite',\n id: errorTextId,\n }}\n >\n {errorText}\n </Typography>\n </div>\n </Skeleton>\n )}\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"TextInput.js","sourceRoot":"","sources":["../../../src/text-input/TextInput.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 */\n\nimport classNames from 'classnames';\nimport {\n type InputHTMLAttributes,\n type ReactElement,\n type ReactNode,\n useId,\n useMemo,\n} from 'react';\n\nimport { customLabelAndNoAriaLabelWarningMessage } from '../_common/messages';\nimport { type CommonProps, type TooltipObjectProps } from '../_common/types';\nimport { useSemiControlledInput } from '../_common/use-semi-controlled-input';\nimport { needleWarningMessage } from '../_common/utils';\nimport { ExclamationCircleIconSolid } from '../icons/generated/heroIcons/ExclamationCircleIconSolid';\nimport { InformationCircleIconOutline } from '../icons/generated/heroIcons/InformationCircleIconOutline';\nimport { XMarkIconOutline } from '../icons/generated/heroIcons/XMarkIconOutline';\nimport { LoadingSpinner } from '../loading-spinner';\nimport { Skeleton } from '../skeleton';\nimport { Tooltip } from '../tooltip';\nimport { Typography } from '../typography';\n\n/**\n * @remarks\n * When `moreInformationText` is provided, a tooltip is rendered next to the label, and the `tooltipProps` prop is used to configure the tooltip. The `TooltipObjectProps` type is defined as: `{ root?: Partial<React.ComponentProps<typeof Tooltip>>; trigger?: Partial<React.ComponentProps<typeof Tooltip.Trigger>>; content?: Partial<React.ComponentProps<typeof Tooltip.Content>>; }`, see the Tooltip component for more details.\n *\n * @remarks\n * When `isSkeletonLoading` is true, the input is rendered as a loading skeleton and the `skeletonProps` prop is used to configure the skeleton. For more information, see the Skeleton documentation.\n */\ntype TextInputProps = {\n /** Assistive text displayed below the input */\n helpText?: string | ReactNode;\n\n /** Error message displayed below the input. When provided, it overrides `helpText` and shows an error icon */\n errorText?: string | ReactNode;\n\n /** Leading element rendered inside the input */\n leadingElement?: ReactElement;\n\n /** Trailing element rendered inside the input */\n trailingElement?: ReactElement;\n\n /** Size of the input */\n size?: 'small' | 'medium' | 'large';\n\n /** Whether the input is read-only */\n isReadOnly?: boolean;\n\n /**\n * Whether to display the Required/Optional label next to the field label.\n * Shows Required if isRequired is true, otherwise shows Optional.\n * @default false\n */\n // TODO v5: decide if this naming is okay, or change it\n // eslint-disable-next-line @typescript-eslint/naming-convention\n showRequiredOrOptionalLabel?: boolean;\n\n /** Whether the input is disabled */\n isDisabled?: boolean;\n\n /** Whether the input is required */\n isRequired?: boolean;\n\n /** The current value of the input */\n value?: React.ComponentPropsWithoutRef<'input'>['value'];\n\n /** Placeholder text displayed when the input is empty */\n placeholder?: React.ComponentPropsWithoutRef<'input'>['placeholder'];\n\n /** Callback function triggered when the input value changes */\n onChange?: React.ComponentPropsWithoutRef<'input'>['onChange'];\n\n /** Whether the input should take the full available width */\n isFluid?: boolean;\n\n /** Text displayed in the information tooltip shown next to the label */\n moreInformationText?: React.ReactNode;\n\n /** The label displayed above the input */\n label?: string | React.ReactNode;\n\n /** Props for the Tooltip component used by the information icon */\n tooltipProps?: TooltipObjectProps;\n\n /** Whether to render skeletons instead of content */\n isSkeletonLoading?: boolean;\n\n /** Additional props forwarded to the underlying Skeleton components */\n skeletonProps?: React.ComponentProps<typeof Skeleton>;\n\n /** Whether to show the clear button */\n isClearable?: boolean;\n\n /** Whether to show the loading spinner */\n isLoading?: boolean;\n};\n\n/**\n *\n *\n * TextInput Component\n *\n *\n */\n\nexport const TextInput = ({\n label,\n isFluid,\n errorText,\n helpText,\n leadingElement,\n trailingElement,\n showRequiredOrOptionalLabel = false,\n moreInformationText,\n size = 'medium',\n placeholder,\n value,\n tooltipProps,\n htmlAttributes,\n isDisabled,\n isReadOnly,\n isRequired,\n onChange,\n isClearable = false,\n className,\n style,\n isSkeletonLoading = false,\n isLoading = false,\n skeletonProps,\n ref,\n ...restProps\n}: CommonProps<'input', TextInputProps>) => {\n const [currentValue, handleChange] = useSemiControlledInput({\n inputType: 'text',\n isControlled: value !== undefined,\n onChange,\n state: value ?? '',\n });\n const hintId = useId();\n const helpTextId = useId();\n const errorTextId = useId();\n\n const containerWrappingClasses = classNames(`ndl-text-input`, className, {\n 'ndl-disabled': isDisabled,\n 'ndl-has-error': errorText,\n 'ndl-has-icon': leadingElement || trailingElement || errorText,\n 'ndl-has-leading-icon': leadingElement,\n 'ndl-has-trailing-icon': trailingElement || errorText,\n 'ndl-large': size === 'large',\n 'ndl-medium': size === 'medium',\n 'ndl-read-only': isReadOnly,\n 'ndl-small': size === 'small',\n });\n\n const hasEmptyLabelValue =\n label === undefined || label === null || label === '';\n\n const labelWrappingClasses = classNames('ndl-form-item-label', {\n 'ndl-fluid': isFluid,\n 'ndl-form-item-no-label': hasEmptyLabelValue,\n });\n\n const combinedHtmlInputAttributes: InputHTMLAttributes<HTMLInputElement> = {\n ...htmlAttributes,\n className: classNames('ndl-input', htmlAttributes?.className),\n };\n const ariaLabel = combinedHtmlInputAttributes['aria-label'];\n const isCustomLabel = Boolean(label) && typeof label !== 'string';\n const hasCustomLabelAndNoAriaLabel =\n isCustomLabel && (ariaLabel === undefined || ariaLabel === '');\n const shouldRenderHint = isClearable || isLoading;\n\n const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (isClearable && event.key === 'Escape' && Boolean(currentValue)) {\n event.preventDefault();\n event.stopPropagation();\n handleChange?.({\n target: { value: '' },\n } as React.ChangeEvent<HTMLInputElement>);\n }\n htmlAttributes?.onKeyDown?.(event);\n };\n\n useMemo(() => {\n if (!label && !ariaLabel) {\n needleWarningMessage(\n 'A TextInput without a label does not have an aria label, be sure to include an aria label for screen readers. Link: https://dequeuniversity.com/rules/axe/4.2/label?application=axeAPI',\n );\n }\n\n if (hasCustomLabelAndNoAriaLabel) {\n needleWarningMessage(customLabelAndNoAriaLabelWarningMessage);\n }\n }, [label, ariaLabel, hasCustomLabelAndNoAriaLabel]);\n\n const informationIconClasses = classNames({\n 'ndl-information-icon-large': size === 'large',\n 'ndl-information-icon-small': size === 'small' || size === 'medium',\n });\n\n const combinedAriaDescribedby = useMemo(() => {\n const ariaDescribedby = [];\n\n if (hintId && shouldRenderHint) {\n ariaDescribedby.push(hintId);\n }\n if (helpText && !errorText) {\n ariaDescribedby.push(helpTextId);\n } else if (errorText) {\n ariaDescribedby.push(errorTextId);\n }\n return ariaDescribedby.join(' ');\n }, [hintId, shouldRenderHint, helpText, errorText, helpTextId, errorTextId]);\n\n return (\n <div className={containerWrappingClasses} style={style}>\n {/* We enable implicit label wrapping */}\n {/* Source: https://dequeuniversity.com/rules/axe/4.2/label?application=axeAPI */}\n <label className={labelWrappingClasses}>\n {!hasEmptyLabelValue && (\n <Skeleton\n onBackground=\"weak\"\n shape=\"rectangular\"\n {...skeletonProps}\n isLoading={isSkeletonLoading}\n >\n <div className=\"ndl-label-text-wrapper\">\n <Typography\n variant={size === 'large' ? 'body-large' : 'body-medium'}\n className=\"ndl-label-text\"\n >\n {label}\n </Typography>\n {Boolean(moreInformationText) && (\n <Tooltip {...tooltipProps?.root} type=\"simple\">\n <Tooltip.Trigger\n {...tooltipProps?.trigger}\n className={informationIconClasses}\n hasButtonWrapper\n >\n <div\n tabIndex={0}\n role=\"button\"\n aria-label=\"Information icon\"\n >\n <InformationCircleIconOutline />\n </div>\n </Tooltip.Trigger>\n <Tooltip.Content {...tooltipProps?.content}>\n {moreInformationText}\n </Tooltip.Content>\n </Tooltip>\n )}\n {showRequiredOrOptionalLabel && (\n <Typography\n variant={size === 'large' ? 'body-large' : 'body-medium'}\n className=\"ndl-form-item-optional\"\n >\n {isRequired === true ? 'Required' : 'Optional'}\n </Typography>\n )}\n </div>\n </Skeleton>\n )}\n <Skeleton\n onBackground=\"weak\"\n shape=\"rectangular\"\n {...skeletonProps}\n isLoading={isSkeletonLoading}\n >\n <div className=\"ndl-input-wrapper\">\n {(leadingElement || (isLoading && !trailingElement)) && (\n <div className=\"ndl-element-leading ndl-element\">\n {isLoading ? (\n <LoadingSpinner\n size={size === 'large' ? 'medium' : 'small'}\n className={\n size === 'large'\n ? 'ndl-medium-spinner'\n : 'ndl-small-spinner'\n }\n />\n ) : (\n leadingElement\n )}\n </div>\n )}\n <div\n className={classNames('ndl-input-container', {\n 'ndl-clearable': isClearable,\n })}\n >\n <input\n ref={ref}\n readOnly={isReadOnly}\n disabled={isDisabled}\n required={isRequired}\n value={currentValue}\n placeholder={placeholder}\n type=\"text\"\n onChange={handleChange}\n aria-describedby={combinedAriaDescribedby}\n aria-invalid={Boolean(errorText)}\n {...combinedHtmlInputAttributes}\n onKeyDown={handleInputKeyDown}\n {...restProps}\n />\n {shouldRenderHint && (\n <span\n id={hintId}\n className=\"ndl-text-input-hint\"\n aria-hidden={true}\n >\n {isLoading && 'Loading '}\n {isClearable && 'Press Escape to clear input.'}\n </span>\n )}\n {isClearable && Boolean(currentValue) && (\n <div className=\"ndl-element-clear ndl-element\">\n <button\n tabIndex={-1}\n aria-hidden={true}\n type=\"button\"\n title=\"Clear input (Esc)\"\n onClick={() => {\n handleChange?.({\n target: { value: '' },\n } as React.ChangeEvent<HTMLInputElement>);\n }}\n >\n <XMarkIconOutline className=\"n-size-4\" />\n </button>\n </div>\n )}\n </div>\n {trailingElement && (\n <div className=\"ndl-element-trailing ndl-element\">\n {isLoading && !leadingElement ? (\n <LoadingSpinner\n size={size === 'large' ? 'medium' : 'small'}\n className={\n size === 'large'\n ? 'ndl-medium-spinner'\n : 'ndl-small-spinner'\n }\n />\n ) : (\n trailingElement\n )}\n </div>\n )}\n </div>\n </Skeleton>\n </label>\n {Boolean(helpText) && !errorText && (\n <Skeleton\n onBackground=\"weak\"\n shape=\"rectangular\"\n isLoading={isSkeletonLoading}\n >\n <Typography\n variant={size === 'large' ? 'body-medium' : 'body-small'}\n className=\"ndl-form-message\"\n htmlAttributes={{\n 'aria-live': 'polite',\n id: helpTextId,\n }}\n >\n {helpText}\n </Typography>\n </Skeleton>\n )}\n {Boolean(errorText) && (\n // TODO v4: We might want to have a min width for the container for the messages to help skeleton loading.\n // Currently the message fills 100% of the width while the rest of the text input has a set width.\n <Skeleton\n onBackground=\"weak\"\n shape=\"rectangular\"\n width=\"fit-content\"\n {...skeletonProps}\n isLoading={isSkeletonLoading}\n >\n <div className=\"ndl-form-message\">\n <div className=\"ndl-error-icon\">\n <ExclamationCircleIconSolid />\n </div>\n <Typography\n className=\"ndl-error-text\"\n variant={size === 'large' ? 'body-medium' : 'body-small'}\n htmlAttributes={{\n 'aria-live': 'polite',\n id: errorTextId,\n }}\n >\n {errorText}\n </Typography>\n </div>\n </Skeleton>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -65,7 +65,7 @@ export const TextOverflow = (_a) => {
|
|
|
65
65
|
const characterTruncatedContent = useMemo(() => {
|
|
66
66
|
if (maxCharacters !== undefined && expandButton === undefined) {
|
|
67
67
|
const result = truncateReactNodeByCharacters(children, maxCharacters);
|
|
68
|
-
return result.
|
|
68
|
+
return result.shouldTruncation ? result.truncatedContent : null;
|
|
69
69
|
}
|
|
70
70
|
return null;
|
|
71
71
|
}, [maxCharacters, expandButton, children]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextOverflow.js","sourceRoot":"","sources":["../../../src/text-overflow/TextOverflow.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';\nimport { useCallback, useMemo, useRef, useState } from 'react';\n\nimport type {\n PolymorphicCommonProps,\n TooltipObjectProps,\n} from '../_common/types';\nimport { TextLink } from '../text-link';\nimport { Tooltip } from '../tooltip';\nimport { Typography } from '../typography';\nimport { COLLAPSE_BUTTON_TEXT, ELLIPSIS_CHAR } from './constants';\nimport {\n getTextContent,\n truncateReactNodeByCharacters,\n} from './text-overflow-utils';\nimport { useTruncateWithButton } from './use-truncate-with-button';\n\ntype TextOverflowProps = {\n /** The content to be truncated. Can be text, Typography components, or complex JSX. */\n children: React.ReactNode;\n\n /**\n * Controls the expand/collapse UI.\n * - string: show expand/collapse button with custom text (e.g., \"View more\")\n * - undefined: content is not expandable, only truncated with ellipsis\n * @default undefined\n */\n expandButton?: 'view-more' | 'ellipsis';\n\n /**\n * Maximum number of characters to display. Takes precedence over line-based truncation when set.\n */\n maxCharacters?: number;\n\n /**\n * Number of lines to show before truncation.\n * Uses CSS line-clamp for non-expandable content.\n * Uses DOM measurement for expandable content.\n * **Note**: Ignored if `maxCharacters` is explicitly set to a custom value.\n */\n lines?: number;\n\n /**\n * Whether to show tooltip with full text on hover when content is truncated.\n * @default true\n */\n shouldShowTooltip?: boolean;\n\n /** Props to pass to tooltip component */\n tooltipProps?: TooltipObjectProps;\n\n /** Callback function called when content is expanded or collapsed */\n onExpandedToggle?: (isExpanded: boolean) => void;\n\n /**\n * The typography variant to use for the text.\n * @default 'body-medium'\n */\n typographyVariant?: React.ComponentProps<typeof Typography>['variant'];\n};\n\nconst expandButtonTexts = {\n ellipsis: ELLIPSIS_CHAR,\n 'view-more': 'View more',\n};\n\nexport const TextOverflow = <T extends React.ElementType = 'div'>({\n as,\n children,\n className,\n htmlAttributes,\n lines,\n tooltipProps,\n onExpandedToggle,\n expandButton,\n maxCharacters,\n shouldShowTooltip = true,\n typographyVariant = 'body-medium',\n ref,\n ...restProps\n}: PolymorphicCommonProps<T, TextOverflowProps>) => {\n const contentRef = useRef<HTMLDivElement>(null);\n const textElementRef = useRef<HTMLSpanElement>(null);\n const [isTooltipOpen, setIsTooltipOpen] = useState(false);\n\n // Use truncate with button hook when expandButton is provided\n const shouldUseTruncateWithButton = expandButton !== undefined;\n const truncateWithButtonResult = useTruncateWithButton({\n button: expandButtonTexts[expandButton!] || 'View more',\n buttonType: expandButton,\n closeTooltip: () => setIsTooltipOpen(false),\n content: children,\n // Disable expensive calculations when no expand button is needed\n isDisabled: !shouldUseTruncateWithButton,\n lineClamp: lines ?? 1,\n maxCharacters,\n onExpandedToggle,\n });\n\n // Handle character-based truncation when no expand button is used\n const characterTruncatedContent = useMemo(() => {\n if (maxCharacters !== undefined && expandButton === undefined) {\n const result = truncateReactNodeByCharacters(children, maxCharacters);\n return result.needsTruncation ? result.truncatedContent : null;\n }\n return null;\n }, [maxCharacters, expandButton, children]);\n\n // Memoize text content extraction to avoid repeated traversals\n const textContent = useMemo(() => getTextContent(children), [children]);\n\n // Memoize tooltip truncation detection logic\n const checkTruncationForTooltip = useCallback(() => {\n if (shouldUseTruncateWithButton) {\n return truncateWithButtonResult.isTruncated;\n }\n\n // Character based truncation\n if (maxCharacters !== undefined) {\n return characterTruncatedContent !== null;\n }\n\n const element = textElementRef.current;\n if (element === null) {\n return false;\n }\n\n // Regular multiline truncation\n if (lines !== undefined && lines > 1) {\n return element.scrollHeight > element.clientHeight;\n }\n\n // Regular single line truncation\n return element.scrollWidth > element.clientWidth;\n }, [\n shouldUseTruncateWithButton,\n truncateWithButtonResult.isTruncated,\n maxCharacters,\n characterTruncatedContent,\n lines,\n ]);\n\n const renderContent = () => {\n const isMultiline = typeof lines === 'number' && lines > 1;\n\n const textStyle = {\n '--ndl-line-clamp': isMultiline ? lines.toString() : undefined,\n } as React.CSSProperties;\n\n const textClasses = classNames({\n 'ndl-text-overflow-multi-line': isMultiline,\n 'ndl-text-overflow-single-line':\n !isMultiline && maxCharacters === undefined,\n });\n\n if (shouldUseTruncateWithButton) {\n return (\n <div ref={truncateWithButtonResult.containerRef}>\n <div\n className={truncateWithButtonResult.isExpanded ? '' : textClasses}\n style={textStyle}\n >\n {truncateWithButtonResult.contentToRender}\n {truncateWithButtonResult.isTruncated && (\n <TextLink\n as=\"button\"\n className={classNames('ndl-text-overflow-toggle', {\n 'ndl-text-overflow-toggle-margin-left':\n expandButton !== 'ellipsis' ||\n truncateWithButtonResult.isExpanded,\n })}\n htmlAttributes={{\n onClick: truncateWithButtonResult.toggleExpand,\n }}\n >\n {truncateWithButtonResult.isExpanded\n ? COLLAPSE_BUTTON_TEXT\n : expandButtonTexts[expandButton!]}\n </TextLink>\n )}\n </div>\n <div\n ref={truncateWithButtonResult.measureRef}\n style={{\n position: 'absolute',\n top: '-9999px',\n visibility: 'hidden',\n }}\n />\n </div>\n );\n }\n\n return (\n <span ref={textElementRef} className={textClasses} style={textStyle}>\n {characterTruncatedContent ?? children}\n </span>\n );\n };\n\n const isTooltipDisabled =\n !shouldShowTooltip ||\n (expandButton !== undefined && truncateWithButtonResult.isExpanded);\n\n return (\n <Tooltip\n {...tooltipProps?.root}\n type=\"simple\"\n isDisabled={isTooltipDisabled}\n isOpen={isTooltipOpen}\n onOpenChange={(open) => {\n if (open) {\n setIsTooltipOpen(checkTruncationForTooltip());\n } else {\n setIsTooltipOpen(false);\n }\n }}\n >\n <Tooltip.Trigger {...tooltipProps?.trigger} hasButtonWrapper>\n <Typography\n as={as ?? 'div'}\n ref={ref}\n variant={typographyVariant}\n className={classNames('ndl-text-overflow', className)}\n htmlAttributes={{\n ...htmlAttributes,\n }}\n {...restProps}\n {...(!isTooltipDisabled &&\n expandButton === undefined && {\n tabIndex: 0,\n })}\n >\n <div className=\"ndl-text-overflow-content\" ref={contentRef}>\n {renderContent()}\n </div>\n </Typography>\n </Tooltip.Trigger>\n <Tooltip.Content\n className={classNames(\n 'ndl-text-overflow-tooltip-content',\n tooltipProps?.content?.className,\n )}\n {...tooltipProps?.content}\n >\n {textContent}\n </Tooltip.Content>\n </Tooltip>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"TextOverflow.js","sourceRoot":"","sources":["../../../src/text-overflow/TextOverflow.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';\nimport { useCallback, useMemo, useRef, useState } from 'react';\n\nimport type {\n PolymorphicCommonProps,\n TooltipObjectProps,\n} from '../_common/types';\nimport { TextLink } from '../text-link';\nimport { Tooltip } from '../tooltip';\nimport { Typography } from '../typography';\nimport { COLLAPSE_BUTTON_TEXT, ELLIPSIS_CHAR } from './constants';\nimport {\n getTextContent,\n truncateReactNodeByCharacters,\n} from './text-overflow-utils';\nimport { useTruncateWithButton } from './use-truncate-with-button';\n\ntype TextOverflowProps = {\n /** The content to be truncated. Can be text, Typography components, or complex JSX. */\n children: React.ReactNode;\n\n /**\n * Controls the expand/collapse UI.\n * - string: show expand/collapse button with custom text (e.g., \"View more\")\n * - undefined: content is not expandable, only truncated with ellipsis\n * @default undefined\n */\n expandButton?: 'view-more' | 'ellipsis';\n\n /**\n * Maximum number of characters to display. Takes precedence over line-based truncation when set.\n */\n maxCharacters?: number;\n\n /**\n * Number of lines to show before truncation.\n * Uses CSS line-clamp for non-expandable content.\n * Uses DOM measurement for expandable content.\n * **Note**: Ignored if `maxCharacters` is explicitly set to a custom value.\n */\n lines?: number;\n\n /**\n * Whether to show tooltip with full text on hover when content is truncated.\n * @default true\n */\n shouldShowTooltip?: boolean;\n\n /** Props to pass to tooltip component */\n tooltipProps?: TooltipObjectProps;\n\n /** Callback function called when content is expanded or collapsed */\n onExpandedToggle?: (isExpanded: boolean) => void;\n\n /**\n * The typography variant to use for the text.\n * @default 'body-medium'\n */\n typographyVariant?: React.ComponentProps<typeof Typography>['variant'];\n};\n\nconst expandButtonTexts = {\n ellipsis: ELLIPSIS_CHAR,\n 'view-more': 'View more',\n};\n\nexport const TextOverflow = <T extends React.ElementType = 'div'>({\n as,\n children,\n className,\n htmlAttributes,\n lines,\n tooltipProps,\n onExpandedToggle,\n expandButton,\n maxCharacters,\n shouldShowTooltip = true,\n typographyVariant = 'body-medium',\n ref,\n ...restProps\n}: PolymorphicCommonProps<T, TextOverflowProps>) => {\n const contentRef = useRef<HTMLDivElement>(null);\n const textElementRef = useRef<HTMLSpanElement>(null);\n const [isTooltipOpen, setIsTooltipOpen] = useState(false);\n\n // Use truncate with button hook when expandButton is provided\n const shouldUseTruncateWithButton = expandButton !== undefined;\n const truncateWithButtonResult = useTruncateWithButton({\n button: expandButtonTexts[expandButton!] || 'View more',\n buttonType: expandButton,\n closeTooltip: () => setIsTooltipOpen(false),\n content: children,\n // Disable expensive calculations when no expand button is needed\n isDisabled: !shouldUseTruncateWithButton,\n lineClamp: lines ?? 1,\n maxCharacters,\n onExpandedToggle,\n });\n\n // Handle character-based truncation when no expand button is used\n const characterTruncatedContent = useMemo(() => {\n if (maxCharacters !== undefined && expandButton === undefined) {\n const result = truncateReactNodeByCharacters(children, maxCharacters);\n return result.shouldTruncation ? result.truncatedContent : null;\n }\n return null;\n }, [maxCharacters, expandButton, children]);\n\n // Memoize text content extraction to avoid repeated traversals\n const textContent = useMemo(() => getTextContent(children), [children]);\n\n // Memoize tooltip truncation detection logic\n const checkTruncationForTooltip = useCallback(() => {\n if (shouldUseTruncateWithButton) {\n return truncateWithButtonResult.isTruncated;\n }\n\n // Character based truncation\n if (maxCharacters !== undefined) {\n return characterTruncatedContent !== null;\n }\n\n const element = textElementRef.current;\n if (element === null) {\n return false;\n }\n\n // Regular multiline truncation\n if (lines !== undefined && lines > 1) {\n return element.scrollHeight > element.clientHeight;\n }\n\n // Regular single line truncation\n return element.scrollWidth > element.clientWidth;\n }, [\n shouldUseTruncateWithButton,\n truncateWithButtonResult.isTruncated,\n maxCharacters,\n characterTruncatedContent,\n lines,\n ]);\n\n const renderContent = () => {\n const isMultiline = typeof lines === 'number' && lines > 1;\n\n const textStyle = {\n '--ndl-line-clamp': isMultiline ? lines.toString() : undefined,\n } as React.CSSProperties;\n\n const textClasses = classNames({\n 'ndl-text-overflow-multi-line': isMultiline,\n 'ndl-text-overflow-single-line':\n !isMultiline && maxCharacters === undefined,\n });\n\n if (shouldUseTruncateWithButton) {\n return (\n <div ref={truncateWithButtonResult.containerRef}>\n <div\n className={truncateWithButtonResult.isExpanded ? '' : textClasses}\n style={textStyle}\n >\n {truncateWithButtonResult.contentToRender}\n {truncateWithButtonResult.isTruncated && (\n <TextLink\n as=\"button\"\n className={classNames('ndl-text-overflow-toggle', {\n 'ndl-text-overflow-toggle-margin-left':\n expandButton !== 'ellipsis' ||\n truncateWithButtonResult.isExpanded,\n })}\n htmlAttributes={{\n onClick: truncateWithButtonResult.toggleExpand,\n }}\n >\n {truncateWithButtonResult.isExpanded\n ? COLLAPSE_BUTTON_TEXT\n : expandButtonTexts[expandButton!]}\n </TextLink>\n )}\n </div>\n <div\n ref={truncateWithButtonResult.measureRef}\n style={{\n position: 'absolute',\n top: '-9999px',\n visibility: 'hidden',\n }}\n />\n </div>\n );\n }\n\n return (\n <span ref={textElementRef} className={textClasses} style={textStyle}>\n {characterTruncatedContent ?? children}\n </span>\n );\n };\n\n const isTooltipDisabled =\n !shouldShowTooltip ||\n (expandButton !== undefined && truncateWithButtonResult.isExpanded);\n\n return (\n <Tooltip\n {...tooltipProps?.root}\n type=\"simple\"\n isDisabled={isTooltipDisabled}\n isOpen={isTooltipOpen}\n onOpenChange={(open) => {\n if (open) {\n setIsTooltipOpen(checkTruncationForTooltip());\n } else {\n setIsTooltipOpen(false);\n }\n }}\n >\n <Tooltip.Trigger {...tooltipProps?.trigger} hasButtonWrapper>\n <Typography\n as={as ?? 'div'}\n ref={ref}\n variant={typographyVariant}\n className={classNames('ndl-text-overflow', className)}\n htmlAttributes={{\n ...htmlAttributes,\n }}\n {...restProps}\n {...(!isTooltipDisabled &&\n expandButton === undefined && {\n tabIndex: 0,\n })}\n >\n <div className=\"ndl-text-overflow-content\" ref={contentRef}>\n {renderContent()}\n </div>\n </Typography>\n </Tooltip.Trigger>\n <Tooltip.Content\n className={classNames(\n 'ndl-text-overflow-tooltip-content',\n tooltipProps?.content?.className,\n )}\n {...tooltipProps?.content}\n >\n {textContent}\n </Tooltip.Content>\n </Tooltip>\n );\n};\n"]}
|
|
@@ -51,7 +51,7 @@ export const truncateReactNodeByCharacters = (node, maxCharacters, shouldAddElli
|
|
|
51
51
|
// Get the total character count first to determine if truncation is needed
|
|
52
52
|
const totalLength = getTextContent(normalizedNode).length;
|
|
53
53
|
if (totalLength <= maxCharacters) {
|
|
54
|
-
return {
|
|
54
|
+
return { shouldTruncation: false, truncatedContent: null };
|
|
55
55
|
}
|
|
56
56
|
let charCount = 0;
|
|
57
57
|
let hasReachedLimit = false;
|
|
@@ -149,10 +149,10 @@ export const truncateReactNodeByCharacters = (node, maxCharacters, shouldAddElli
|
|
|
149
149
|
// Add ellipsis if needed
|
|
150
150
|
if (shouldAddEllipsis && finalResult !== null) {
|
|
151
151
|
const withEllipsis = React.createElement(React.Fragment, null, finalResult, ELLIPSIS_CHAR);
|
|
152
|
-
return {
|
|
152
|
+
return { shouldTruncation: true, truncatedContent: withEllipsis };
|
|
153
153
|
}
|
|
154
154
|
return {
|
|
155
|
-
|
|
155
|
+
shouldTruncation: true,
|
|
156
156
|
truncatedContent: finalResult,
|
|
157
157
|
};
|
|
158
158
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-overflow-utils.js","sourceRoot":"","sources":["../../../src/text-overflow/text-overflow-utils.ts"],"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 React, { type ReactNode } from 'react';\n\nimport { ELLIPSIS_CHAR, ESTIMATION_FACTORS } from './constants';\n\ntype ReactNodeTruncationResult = {\n needsTruncation: boolean;\n truncatedContent: React.ReactNode | null;\n};\n\n/**\n * Recursively extracts plain text from React nodes\n */\nexport const getTextContent = (node: React.ReactNode): string => {\n if (typeof node === 'string') {\n return node;\n }\n if (typeof node === 'number') {\n return node.toString();\n }\n if (React.isValidElement(node)) {\n // Type assertion to access props safely\n const element = node as React.ReactElement<{ children?: ReactNode }>;\n return getTextContent(element.props.children);\n }\n if (Array.isArray(node)) {\n return node.map(getTextContent).join('');\n }\n return '';\n};\n\n/**\n * Truncates React node content by character count while preserving element structure.\n */\nexport const truncateReactNodeByCharacters = (\n node: React.ReactNode,\n maxCharacters: number,\n shouldAddEllipsis = true,\n): ReactNodeTruncationResult => {\n // Handle the case where node is an array (React children)\n const normalizedNode = Array.isArray(node)\n ? React.createElement(React.Fragment, null, ...node)\n : node;\n\n // Get the total character count first to determine if truncation is needed\n const totalLength = getTextContent(normalizedNode).length;\n\n if (totalLength <= maxCharacters) {\n return { needsTruncation: false, truncatedContent: null };\n }\n\n let charCount = 0;\n let hasReachedLimit = false;\n\n const truncateNode = (currentNode: React.ReactNode): React.ReactNode => {\n // Stop processing if character limit is reached\n if (hasReachedLimit || charCount >= maxCharacters) {\n hasReachedLimit = true;\n return null;\n }\n\n // Handle arrays of children (mixed content case)\n if (Array.isArray(currentNode)) {\n const truncatedChildren: React.ReactNode[] = [];\n\n for (const child of currentNode) {\n if (hasReachedLimit || charCount >= maxCharacters) {\n break;\n }\n\n const truncatedChild = truncateNode(child);\n if (truncatedChild !== null) {\n truncatedChildren.push(truncatedChild);\n }\n }\n\n return truncatedChildren.length > 0 ? truncatedChildren : null;\n }\n\n if (typeof currentNode === 'string') {\n const availableChars = maxCharacters - charCount;\n\n if (currentNode.length <= availableChars) {\n charCount += currentNode.length;\n return currentNode;\n }\n\n // Truncate at character limit, preferring word boundaries\n let truncated = currentNode.substring(0, availableChars);\n const lastSpaceIndex = truncated.lastIndexOf(' ');\n\n if (lastSpaceIndex > availableChars * ESTIMATION_FACTORS.WORD_BOUNDARY) {\n truncated = truncated.substring(0, lastSpaceIndex);\n }\n\n truncated = truncated.trim();\n charCount += truncated.length;\n hasReachedLimit = true;\n return truncated;\n }\n\n if (typeof currentNode === 'number') {\n const str = currentNode.toString();\n const availableChars = maxCharacters - charCount;\n\n if (str.length <= availableChars) {\n charCount += str.length;\n return currentNode;\n }\n\n const truncated = str.substring(0, availableChars);\n charCount += truncated.length;\n hasReachedLimit = true;\n return truncated;\n }\n\n if (!React.isValidElement(currentNode)) {\n return currentNode;\n }\n\n const { children } = currentNode.props as { children?: ReactNode };\n if (children === null || children === undefined) {\n return currentNode;\n }\n\n if (typeof children === 'string') {\n const truncatedChild = truncateNode(children);\n if (truncatedChild === null) {\n return null;\n }\n return React.cloneElement(currentNode, {}, truncatedChild);\n }\n\n if (Array.isArray(children)) {\n const truncatedChildren: React.ReactNode[] = [];\n for (const child of children) {\n if (hasReachedLimit || charCount >= maxCharacters) {\n break;\n }\n\n const truncatedChild = truncateNode(child);\n if (truncatedChild !== null) {\n truncatedChildren.push(truncatedChild);\n }\n }\n\n if (truncatedChildren.length === 0) {\n return null;\n }\n return React.cloneElement(currentNode, {}, ...truncatedChildren);\n }\n\n // Single React element child\n const truncatedChild = truncateNode(children);\n if (truncatedChild === null) {\n return null;\n }\n return React.cloneElement(currentNode, {}, truncatedChild);\n };\n\n const truncatedResult = truncateNode(normalizedNode);\n\n // Convert array results to proper React elements\n const finalResult = Array.isArray(truncatedResult)\n ? React.createElement(React.Fragment, null, ...truncatedResult)\n : truncatedResult;\n\n // Add ellipsis if needed\n if (shouldAddEllipsis && finalResult !== null) {\n const withEllipsis = React.createElement(\n React.Fragment,\n null,\n finalResult,\n ELLIPSIS_CHAR,\n );\n return { needsTruncation: true, truncatedContent: withEllipsis };\n }\n\n return {\n needsTruncation: true,\n truncatedContent: finalResult,\n };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"text-overflow-utils.js","sourceRoot":"","sources":["../../../src/text-overflow/text-overflow-utils.ts"],"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 React, { type ReactNode } from 'react';\n\nimport { ELLIPSIS_CHAR, ESTIMATION_FACTORS } from './constants';\n\ntype ReactNodeTruncationResult = {\n shouldTruncation: boolean;\n truncatedContent: React.ReactNode | null;\n};\n\n/**\n * Recursively extracts plain text from React nodes\n */\nexport const getTextContent = (node: React.ReactNode): string => {\n if (typeof node === 'string') {\n return node;\n }\n if (typeof node === 'number') {\n return node.toString();\n }\n if (React.isValidElement(node)) {\n // Type assertion to access props safely\n const element = node as React.ReactElement<{ children?: ReactNode }>;\n return getTextContent(element.props.children);\n }\n if (Array.isArray(node)) {\n return node.map(getTextContent).join('');\n }\n return '';\n};\n\n/**\n * Truncates React node content by character count while preserving element structure.\n */\nexport const truncateReactNodeByCharacters = (\n node: React.ReactNode,\n maxCharacters: number,\n shouldAddEllipsis = true,\n): ReactNodeTruncationResult => {\n // Handle the case where node is an array (React children)\n const normalizedNode = Array.isArray(node)\n ? React.createElement(React.Fragment, null, ...node)\n : node;\n\n // Get the total character count first to determine if truncation is needed\n const totalLength = getTextContent(normalizedNode).length;\n\n if (totalLength <= maxCharacters) {\n return { shouldTruncation: false, truncatedContent: null };\n }\n\n let charCount = 0;\n let hasReachedLimit = false;\n\n const truncateNode = (currentNode: React.ReactNode): React.ReactNode => {\n // Stop processing if character limit is reached\n if (hasReachedLimit || charCount >= maxCharacters) {\n hasReachedLimit = true;\n return null;\n }\n\n // Handle arrays of children (mixed content case)\n if (Array.isArray(currentNode)) {\n const truncatedChildren: React.ReactNode[] = [];\n\n for (const child of currentNode) {\n if (hasReachedLimit || charCount >= maxCharacters) {\n break;\n }\n\n const truncatedChild = truncateNode(child);\n if (truncatedChild !== null) {\n truncatedChildren.push(truncatedChild);\n }\n }\n\n return truncatedChildren.length > 0 ? truncatedChildren : null;\n }\n\n if (typeof currentNode === 'string') {\n const availableChars = maxCharacters - charCount;\n\n if (currentNode.length <= availableChars) {\n charCount += currentNode.length;\n return currentNode;\n }\n\n // Truncate at character limit, preferring word boundaries\n let truncated = currentNode.substring(0, availableChars);\n const lastSpaceIndex = truncated.lastIndexOf(' ');\n\n if (lastSpaceIndex > availableChars * ESTIMATION_FACTORS.WORD_BOUNDARY) {\n truncated = truncated.substring(0, lastSpaceIndex);\n }\n\n truncated = truncated.trim();\n charCount += truncated.length;\n hasReachedLimit = true;\n return truncated;\n }\n\n if (typeof currentNode === 'number') {\n const str = currentNode.toString();\n const availableChars = maxCharacters - charCount;\n\n if (str.length <= availableChars) {\n charCount += str.length;\n return currentNode;\n }\n\n const truncated = str.substring(0, availableChars);\n charCount += truncated.length;\n hasReachedLimit = true;\n return truncated;\n }\n\n if (!React.isValidElement(currentNode)) {\n return currentNode;\n }\n\n const { children } = currentNode.props as { children?: ReactNode };\n if (children === null || children === undefined) {\n return currentNode;\n }\n\n if (typeof children === 'string') {\n const truncatedChild = truncateNode(children);\n if (truncatedChild === null) {\n return null;\n }\n return React.cloneElement(currentNode, {}, truncatedChild);\n }\n\n if (Array.isArray(children)) {\n const truncatedChildren: React.ReactNode[] = [];\n for (const child of children) {\n if (hasReachedLimit || charCount >= maxCharacters) {\n break;\n }\n\n const truncatedChild = truncateNode(child);\n if (truncatedChild !== null) {\n truncatedChildren.push(truncatedChild);\n }\n }\n\n if (truncatedChildren.length === 0) {\n return null;\n }\n return React.cloneElement(currentNode, {}, ...truncatedChildren);\n }\n\n // Single React element child\n const truncatedChild = truncateNode(children);\n if (truncatedChild === null) {\n return null;\n }\n return React.cloneElement(currentNode, {}, truncatedChild);\n };\n\n const truncatedResult = truncateNode(normalizedNode);\n\n // Convert array results to proper React elements\n const finalResult = Array.isArray(truncatedResult)\n ? React.createElement(React.Fragment, null, ...truncatedResult)\n : truncatedResult;\n\n // Add ellipsis if needed\n if (shouldAddEllipsis && finalResult !== null) {\n const withEllipsis = React.createElement(\n React.Fragment,\n null,\n finalResult,\n ELLIPSIS_CHAR,\n );\n return { shouldTruncation: true, truncatedContent: withEllipsis };\n }\n\n return {\n shouldTruncation: true,\n truncatedContent: finalResult,\n };\n};\n"]}
|
|
@@ -111,8 +111,8 @@ export function useTruncateWithButton({ content, lineClamp, button, onExpandedTo
|
|
|
111
111
|
// Character-based truncation takes precedence
|
|
112
112
|
if (typeof maxCharacters === 'number') {
|
|
113
113
|
const result = truncateReactNodeByCharacters(content, maxCharacters);
|
|
114
|
-
setIsTruncated(result.
|
|
115
|
-
setTruncatedContent(result.
|
|
114
|
+
setIsTruncated(result.shouldTruncation);
|
|
115
|
+
setTruncatedContent(result.shouldTruncation ? result.truncatedContent : content);
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
118
|
// Fallback to line-based truncation
|