@ably/ui 17.11.0-dev.4c4b6b55 → 17.11.0-dev.672950e8
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/core/Expander.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{
|
|
1
|
+
import React,{useMemo,useRef,useState}from"react";import*as RadixCollapsible from"@radix-ui/react-collapsible";import cn from"./utils/cn";import{useContentHeight}from"./hooks/use-content-height";const Expander=({heightThreshold=200,className,fadeClassName,controlsClassName,controlsOpenedLabel,controlsClosedLabel,children})=>{const innerRef=useRef(null);const[expanded,setExpanded]=useState(false);const contentHeight=useContentHeight(innerRef,heightThreshold);const showControls=useMemo(()=>contentHeight>=heightThreshold,[contentHeight,heightThreshold]);const height=useMemo(()=>contentHeight<heightThreshold?"auto":expanded?contentHeight:heightThreshold,[contentHeight,heightThreshold,expanded]);return React.createElement(RadixCollapsible.Root,{open:expanded,onOpenChange:setExpanded},React.createElement("div",{style:{height},"data-testid":"expander-container",className:cn("overflow-hidden transition-all relative",className)},showControls&&!expanded&&React.createElement("div",{className:cn("h-16 w-full bg-gradient-to-t from-white to-transparent absolute bottom-0 left-0 right-0",fadeClassName)}),React.createElement("div",{ref:innerRef},children)),showControls&&React.createElement(RadixCollapsible.Trigger,{asChild:true},React.createElement("button",{"data-testid":"expander-controls",className:cn(heightThreshold===0&&!expanded?"":"mt-4","cursor-pointer font-bold text-gui-blue-default-light hover:text-gui-blue-hover-light",controlsClassName)},expanded?controlsOpenedLabel??"View less -":controlsClosedLabel??"View all +")))};export default Expander;
|
|
2
2
|
//# sourceMappingURL=Expander.js.map
|
package/core/Expander.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/Expander.tsx"],"sourcesContent":["import React, {\n PropsWithChildren,\n ReactNode,\n
|
|
1
|
+
{"version":3,"sources":["../../src/core/Expander.tsx"],"sourcesContent":["import React, {\n PropsWithChildren,\n ReactNode,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport * as RadixCollapsible from \"@radix-ui/react-collapsible\";\nimport cn from \"./utils/cn\";\nimport { useContentHeight } from \"./hooks/use-content-height\";\n\ntype ExpanderProps = {\n heightThreshold?: number;\n className?: string;\n fadeClassName?: string;\n controlsClassName?: string;\n controlsOpenedLabel?: string | ReactNode;\n controlsClosedLabel?: string | ReactNode;\n};\n\nconst Expander = ({\n heightThreshold = 200,\n className,\n fadeClassName,\n controlsClassName,\n controlsOpenedLabel,\n controlsClosedLabel,\n children,\n}: PropsWithChildren<ExpanderProps>) => {\n const innerRef = useRef<HTMLDivElement>(null);\n const [expanded, setExpanded] = useState(false);\n\n const contentHeight = useContentHeight(innerRef, heightThreshold);\n\n const showControls = useMemo(\n () => contentHeight >= heightThreshold,\n [contentHeight, heightThreshold]\n );\n\n const height = useMemo(\n () =>\n contentHeight < heightThreshold\n ? \"auto\"\n : expanded\n ? contentHeight\n : heightThreshold,\n [contentHeight, heightThreshold, expanded]\n );\n\n return (\n <RadixCollapsible.Root open={expanded} onOpenChange={setExpanded}>\n <div\n style={{ height }}\n data-testid=\"expander-container\"\n className={cn(\"overflow-hidden transition-all relative\", className)}\n >\n {showControls && !expanded && (\n <div\n className={cn(\n \"h-16 w-full bg-gradient-to-t from-white to-transparent absolute bottom-0 left-0 right-0\",\n fadeClassName,\n )}\n ></div>\n )}\n <div ref={innerRef}>{children}</div>\n </div>\n {showControls && (\n <RadixCollapsible.Trigger asChild>\n <button\n data-testid=\"expander-controls\"\n className={cn(\n heightThreshold === 0 && !expanded ? \"\" : \"mt-4\",\n \"cursor-pointer font-bold text-gui-blue-default-light hover:text-gui-blue-hover-light\",\n controlsClassName,\n )}\n >\n {expanded\n ? (controlsOpenedLabel ?? \"View less -\")\n : (controlsClosedLabel ?? \"View all +\")}\n </button>\n </RadixCollapsible.Trigger>\n )}\n </RadixCollapsible.Root>\n );\n};\n\nexport default Expander;\n"],"names":["React","useMemo","useRef","useState","RadixCollapsible","cn","useContentHeight","Expander","heightThreshold","className","fadeClassName","controlsClassName","controlsOpenedLabel","controlsClosedLabel","children","innerRef","expanded","setExpanded","contentHeight","showControls","height","Root","open","onOpenChange","div","style","data-testid","ref","Trigger","asChild","button"],"mappings":"AAAA,OAAOA,OAGLC,OAAO,CACPC,MAAM,CACNC,QAAQ,KACH,OAAQ,AACf,WAAYC,qBAAsB,6BAA8B,AAChE,QAAOC,OAAQ,YAAa,AAC5B,QAASC,gBAAgB,KAAQ,4BAA6B,CAW9D,MAAMC,SAAW,CAAC,CAChBC,gBAAkB,GAAG,CACrBC,SAAS,CACTC,aAAa,CACbC,iBAAiB,CACjBC,mBAAmB,CACnBC,mBAAmB,CACnBC,QAAQ,CACyB,IACjC,MAAMC,SAAWb,OAAuB,MACxC,KAAM,CAACc,SAAUC,YAAY,CAAGd,SAAS,OAEzC,MAAMe,cAAgBZ,iBAAiBS,SAAUP,iBAEjD,MAAMW,aAAelB,QACnB,IAAMiB,eAAiBV,gBACvB,CAACU,cAAeV,gBAAgB,EAGlC,MAAMY,OAASnB,QACb,IACEiB,cAAgBV,gBACZ,OACAQ,SACEE,cACAV,gBACR,CAACU,cAAeV,gBAAiBQ,SAAS,EAG5C,OACE,oBAACZ,iBAAiBiB,IAAI,EAACC,KAAMN,SAAUO,aAAcN,aACnD,oBAACO,OACCC,MAAO,CAAEL,MAAO,EAChBM,cAAY,qBACZjB,UAAWJ,GAAG,0CAA2CI,YAExDU,cAAgB,CAACH,UAChB,oBAACQ,OACCf,UAAWJ,GACT,0FACAK,iBAIN,oBAACc,OAAIG,IAAKZ,UAAWD,WAEtBK,cACC,oBAACf,iBAAiBwB,OAAO,EAACC,QAAAA,MACxB,oBAACC,UACCJ,cAAY,oBACZjB,UAAWJ,GACTG,kBAAoB,GAAK,CAACQ,SAAW,GAAK,OAC1C,uFACAL,oBAGDK,SACIJ,qBAAuB,cACvBC,qBAAuB,eAMxC,CAEA,gBAAeN,QAAS"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{useState,useEffect,useRef}from"react";export function useContentHeight(ref,initialHeight=0){const[contentHeight,setContentHeight]=useState(initialHeight);const observerRef=useRef(null);useEffect(()=>{const element=ref.current;if(!element){return}observerRef.current=new ResizeObserver(entries=>{requestAnimationFrame(()=>{const entry=entries[0];if(entry&&entry.contentRect){const newHeight=Math.round(entry.contentRect.height);setContentHeight(newHeight)}})});observerRef.current.observe(element);return()=>{observerRef.current?.disconnect();observerRef.current=null}},[ref]);return contentHeight}
|
|
2
|
+
//# sourceMappingURL=use-content-height.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/hooks/use-content-height.ts"],"sourcesContent":["import { useState, useEffect, useRef, RefObject } from \"react\";\n\n/**\n * Custom hook that tracks the content height of an element using ResizeObserver.\n * This eliminates forced reflows by using the browser's native resize observation API\n * instead of synchronous clientHeight/getBoundingClientRect queries.\n *\n * @param ref - React ref to the element to observe\n * @param initialHeight - Initial height value (default: 0)\n * @returns Current content height in pixels\n */\nexport function useContentHeight(\n ref: RefObject<HTMLElement>,\n initialHeight = 0\n): number {\n const [contentHeight, setContentHeight] = useState<number>(initialHeight);\n const observerRef = useRef<ResizeObserver | null>(null);\n\n useEffect(() => {\n const element = ref.current;\n\n if (!element) {\n return;\n }\n\n observerRef.current = new ResizeObserver((entries) => {\n requestAnimationFrame(() => {\n const entry = entries[0];\n if (entry && entry.contentRect) {\n const newHeight = Math.round(entry.contentRect.height);\n setContentHeight(newHeight);\n }\n });\n });\n\n observerRef.current.observe(element);\n\n return () => {\n observerRef.current?.disconnect();\n observerRef.current = null;\n };\n }, [ref]);\n\n return contentHeight;\n}\n"],"names":["useState","useEffect","useRef","useContentHeight","ref","initialHeight","contentHeight","setContentHeight","observerRef","element","current","ResizeObserver","entries","requestAnimationFrame","entry","contentRect","newHeight","Math","round","height","observe","disconnect"],"mappings":"AAAA,OAASA,QAAQ,CAAEC,SAAS,CAAEC,MAAM,KAAmB,OAAQ,AAW/D,QAAO,SAASC,iBACdC,GAA2B,CAC3BC,cAAgB,CAAC,EAEjB,KAAM,CAACC,cAAeC,iBAAiB,CAAGP,SAAiBK,eAC3D,MAAMG,YAAcN,OAA8B,MAElDD,UAAU,KACR,MAAMQ,QAAUL,IAAIM,OAAO,CAE3B,GAAI,CAACD,QAAS,CACZ,MACF,CAEAD,YAAYE,OAAO,CAAG,IAAIC,eAAe,AAACC,UACxCC,sBAAsB,KACpB,MAAMC,MAAQF,OAAO,CAAC,EAAE,CACxB,GAAIE,OAASA,MAAMC,WAAW,CAAE,CAC9B,MAAMC,UAAYC,KAAKC,KAAK,CAACJ,MAAMC,WAAW,CAACI,MAAM,EACrDZ,iBAAiBS,UACnB,CACF,EACF,GAEAR,YAAYE,OAAO,CAACU,OAAO,CAACX,SAE5B,MAAO,KACLD,YAAYE,OAAO,EAAEW,YACrBb,CAAAA,YAAYE,OAAO,CAAG,IACxB,CACF,EAAG,CAACN,IAAI,EAER,OAAOE,aACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/hooks/use-themed-scrollpoints.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\n\nimport { describe, it, expect, beforeEach, afterEach, vi } from \"vitest\";\nimport { renderHook, waitFor } from \"@testing-library/react\";\nimport { useThemedScrollpoints } from \"./use-themed-scrollpoints\";\n\ndescribe(\"useThemedScrollpoints\", () => {\n let observerCallback: IntersectionObserverCallback;\n let mockObserve: ReturnType<typeof vi.fn>;\n let mockUnobserve: ReturnType<typeof vi.fn>;\n let mockDisconnect: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n // Mock IntersectionObserver\n mockObserve = vi.fn();\n mockUnobserve = vi.fn();\n mockDisconnect = vi.fn();\n\n global.IntersectionObserver = vi.fn((callback) => {\n observerCallback = callback;\n return {\n observe: mockObserve,\n unobserve: mockUnobserve,\n disconnect: mockDisconnect,\n };\n }) as any;\n\n // Mock requestAnimationFrame\n global.requestAnimationFrame = vi.fn((cb) => {\n cb(0);\n return 0;\n });\n });\n\n afterEach(() => {\n vi.clearAllMocks();\n document.body.innerHTML = \"\";\n });\n\n it(\"returns first scrollpoint className on mount\", () => {\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(result.current).toBe(\"theme-light\");\n });\n\n it(\"returns empty string when no scrollpoints provided\", () => {\n const { result } = renderHook(() => useThemedScrollpoints([]));\n expect(result.current).toBe(\"\");\n });\n\n it(\"does not create IntersectionObserver when no scrollpoints provided\", () => {\n renderHook(() => useThemedScrollpoints([]));\n\n expect(IntersectionObserver).not.toHaveBeenCalled();\n });\n\n it(\"creates IntersectionObserver with correct config\", () => {\n const scrollpoints = [{ id: \"zone1\", className: \"theme-light\" }];\n\n // Create DOM element\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(IntersectionObserver).toHaveBeenCalledWith(\n expect.any(Function),\n expect.objectContaining({\n rootMargin: \"-64px 0px 0px 0px\",\n threshold: 0,\n })\n );\n });\n\n it(\"observes all scrollpoint elements that exist in DOM\", () => {\n // Create DOM elements\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(mockObserve).toHaveBeenCalledTimes(2);\n expect(mockObserve).toHaveBeenCalledWith(elem1);\n expect(mockObserve).toHaveBeenCalledWith(elem2);\n });\n\n it(\"logs warning for missing DOM elements\", () => {\n const consoleWarn = vi.spyOn(console, \"warn\").mockImplementation(() => {});\n\n const scrollpoints = [{ id: \"non-existent\", className: \"theme\" }];\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(consoleWarn).toHaveBeenCalledWith(\n expect.stringContaining('Element with id \"non-existent\" not found')\n );\n\n consoleWarn.mockRestore();\n });\n\n it(\"observes existing elements and warns about missing ones\", () => {\n const consoleWarn = vi.spyOn(console, \"warn\").mockImplementation(() => {});\n\n // Create only one element\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"missing\", className: \"theme-dark\" },\n ];\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(mockObserve).toHaveBeenCalledTimes(1);\n expect(mockObserve).toHaveBeenCalledWith(elem);\n expect(consoleWarn).toHaveBeenCalledWith(\n expect.stringContaining('Element with id \"missing\" not found')\n );\n\n consoleWarn.mockRestore();\n });\n\n it(\"updates className when intersection occurs\", async () => {\n // Create DOM elements\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n // Initial state\n expect(result.current).toBe(\"theme-light\");\n\n // Simulate intersection with zone2\n observerCallback(\n [\n {\n target: elem2,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n await waitFor(() => {\n expect(result.current).toBe(\"theme-dark\");\n });\n });\n\n it(\"does not update className if same scrollpoint intersects again\", async () => {\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n const scrollpoints = [{ id: \"zone1\", className: \"theme-light\" }];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(result.current).toBe(\"theme-light\");\n\n // Simulate intersection with same element\n const renderCount = result.current;\n observerCallback(\n [\n {\n target: elem,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n // Should not trigger re-render (className unchanged)\n expect(result.current).toBe(renderCount);\n });\n\n it(\"ignores non-intersecting entries\", async () => {\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(result.current).toBe(\"theme-light\");\n\n // Simulate non-intersecting entry\n observerCallback(\n [\n {\n target: elem2,\n isIntersecting: false,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n // Should remain unchanged\n expect(result.current).toBe(\"theme-light\");\n });\n\n it(\"uses first intersecting entry when multiple entries intersect\", async () => {\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n const elem3 = document.createElement(\"div\");\n elem3.id = \"zone3\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n document.body.appendChild(elem3);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n { id: \"zone3\", className: \"theme-blue\" },\n ];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n // Simulate multiple intersections (zone2 and zone3 both intersecting)\n observerCallback(\n [\n {\n target: elem2,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n {\n target: elem3,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n await waitFor(() => {\n // Should use first intersecting entry (zone2)\n expect(result.current).toBe(\"theme-dark\");\n });\n });\n\n it(\"disconnects observer on unmount\", () => {\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n const scrollpoints = [{ id: \"zone1\", className: \"theme-light\" }];\n\n const { unmount } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n unmount();\n\n expect(mockDisconnect).toHaveBeenCalled();\n });\n\n it(\"recreates observer when scrollpoints change\", () => {\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n\n const { rerender } = renderHook(\n ({ scrollpoints }) => useThemedScrollpoints(scrollpoints),\n {\n initialProps: {\n scrollpoints: [{ id: \"zone1\", className: \"theme-light\" }],\n },\n }\n );\n\n expect(IntersectionObserver).toHaveBeenCalledTimes(1);\n expect(mockObserve).toHaveBeenCalledTimes(1);\n\n // Change scrollpoints\n rerender({\n scrollpoints: [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ],\n });\n\n // Should disconnect old observer and create new one\n expect(mockDisconnect).toHaveBeenCalledTimes(1);\n expect(IntersectionObserver).toHaveBeenCalledTimes(2);\n expect(mockObserve).toHaveBeenCalledTimes(3); // 1 from first render + 2 from second\n });\n\n it(\"uses requestAnimationFrame for state updates\", () => {\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n const rafSpy = vi.spyOn(global, \"requestAnimationFrame\");\n\n // Simulate intersection\n observerCallback(\n [\n {\n target: elem,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n expect(rafSpy).toHaveBeenCalled();\n\n rafSpy.mockRestore();\n });\n});\n"],"names":["describe","it","expect","beforeEach","afterEach","vi","renderHook","waitFor","useThemedScrollpoints","observerCallback","mockObserve","mockUnobserve","mockDisconnect","fn","global","IntersectionObserver","callback","observe","unobserve","disconnect","requestAnimationFrame","cb","clearAllMocks","document","body","innerHTML","scrollpoints","id","className","result","current","toBe","not","toHaveBeenCalled","elem","createElement","appendChild","toHaveBeenCalledWith","any","Function","objectContaining","rootMargin","threshold","elem1","elem2","toHaveBeenCalledTimes","consoleWarn","spyOn","console","mockImplementation","stringContaining","mockRestore","target","isIntersecting","renderCount","elem3","unmount","rerender","initialProps","rafSpy"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/hooks/use-themed-scrollpoints.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\n\nimport { describe, it, expect, beforeEach, afterEach, vi } from \"vitest\";\nimport { renderHook, waitFor } from \"@testing-library/react\";\nimport { useThemedScrollpoints } from \"./use-themed-scrollpoints\";\n\ndescribe(\"useThemedScrollpoints\", () => {\n let observerCallback: IntersectionObserverCallback;\n let mockObserve: ReturnType<typeof vi.fn>;\n let mockUnobserve: ReturnType<typeof vi.fn>;\n let mockDisconnect: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n // Mock IntersectionObserver\n mockObserve = vi.fn();\n mockUnobserve = vi.fn();\n mockDisconnect = vi.fn();\n\n global.IntersectionObserver = vi.fn((callback) => {\n observerCallback = callback;\n return {\n observe: mockObserve,\n unobserve: mockUnobserve,\n disconnect: mockDisconnect,\n };\n }) as unknown as typeof IntersectionObserver;\n\n // Mock requestAnimationFrame\n global.requestAnimationFrame = vi.fn((cb) => {\n cb(0);\n return 0;\n });\n });\n\n afterEach(() => {\n vi.clearAllMocks();\n document.body.innerHTML = \"\";\n });\n\n it(\"returns first scrollpoint className on mount\", () => {\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(result.current).toBe(\"theme-light\");\n });\n\n it(\"returns empty string when no scrollpoints provided\", () => {\n const { result } = renderHook(() => useThemedScrollpoints([]));\n expect(result.current).toBe(\"\");\n });\n\n it(\"does not create IntersectionObserver when no scrollpoints provided\", () => {\n renderHook(() => useThemedScrollpoints([]));\n\n expect(IntersectionObserver).not.toHaveBeenCalled();\n });\n\n it(\"creates IntersectionObserver with correct config\", () => {\n const scrollpoints = [{ id: \"zone1\", className: \"theme-light\" }];\n\n // Create DOM element\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(IntersectionObserver).toHaveBeenCalledWith(\n expect.any(Function),\n expect.objectContaining({\n rootMargin: \"-64px 0px 0px 0px\",\n threshold: 0,\n })\n );\n });\n\n it(\"observes all scrollpoint elements that exist in DOM\", () => {\n // Create DOM elements\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(mockObserve).toHaveBeenCalledTimes(2);\n expect(mockObserve).toHaveBeenCalledWith(elem1);\n expect(mockObserve).toHaveBeenCalledWith(elem2);\n });\n\n it(\"logs warning for missing DOM elements\", () => {\n const consoleWarn = vi.spyOn(console, \"warn\").mockImplementation(() => {});\n\n const scrollpoints = [{ id: \"non-existent\", className: \"theme\" }];\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(consoleWarn).toHaveBeenCalledWith(\n expect.stringContaining('Element with id \"non-existent\" not found')\n );\n\n consoleWarn.mockRestore();\n });\n\n it(\"observes existing elements and warns about missing ones\", () => {\n const consoleWarn = vi.spyOn(console, \"warn\").mockImplementation(() => {});\n\n // Create only one element\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"missing\", className: \"theme-dark\" },\n ];\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(mockObserve).toHaveBeenCalledTimes(1);\n expect(mockObserve).toHaveBeenCalledWith(elem);\n expect(consoleWarn).toHaveBeenCalledWith(\n expect.stringContaining('Element with id \"missing\" not found')\n );\n\n consoleWarn.mockRestore();\n });\n\n it(\"updates className when intersection occurs\", async () => {\n // Create DOM elements\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n // Initial state\n expect(result.current).toBe(\"theme-light\");\n\n // Simulate intersection with zone2\n observerCallback(\n [\n {\n target: elem2,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n await waitFor(() => {\n expect(result.current).toBe(\"theme-dark\");\n });\n });\n\n it(\"does not update className if same scrollpoint intersects again\", async () => {\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n const scrollpoints = [{ id: \"zone1\", className: \"theme-light\" }];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(result.current).toBe(\"theme-light\");\n\n // Simulate intersection with same element\n const renderCount = result.current;\n observerCallback(\n [\n {\n target: elem,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n // Should not trigger re-render (className unchanged)\n expect(result.current).toBe(renderCount);\n });\n\n it(\"ignores non-intersecting entries\", async () => {\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n expect(result.current).toBe(\"theme-light\");\n\n // Simulate non-intersecting entry\n observerCallback(\n [\n {\n target: elem2,\n isIntersecting: false,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n // Should remain unchanged\n expect(result.current).toBe(\"theme-light\");\n });\n\n it(\"uses first intersecting entry when multiple entries intersect\", async () => {\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n const elem3 = document.createElement(\"div\");\n elem3.id = \"zone3\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n document.body.appendChild(elem3);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n { id: \"zone3\", className: \"theme-blue\" },\n ];\n\n const { result } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n // Simulate multiple intersections (zone2 and zone3 both intersecting)\n observerCallback(\n [\n {\n target: elem2,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n {\n target: elem3,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n await waitFor(() => {\n // Should use first intersecting entry (zone2)\n expect(result.current).toBe(\"theme-dark\");\n });\n });\n\n it(\"disconnects observer on unmount\", () => {\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n const scrollpoints = [{ id: \"zone1\", className: \"theme-light\" }];\n\n const { unmount } = renderHook(() => useThemedScrollpoints(scrollpoints));\n\n unmount();\n\n expect(mockDisconnect).toHaveBeenCalled();\n });\n\n it(\"recreates observer when scrollpoints change\", () => {\n const elem1 = document.createElement(\"div\");\n elem1.id = \"zone1\";\n const elem2 = document.createElement(\"div\");\n elem2.id = \"zone2\";\n document.body.appendChild(elem1);\n document.body.appendChild(elem2);\n\n const { rerender } = renderHook(\n ({ scrollpoints }) => useThemedScrollpoints(scrollpoints),\n {\n initialProps: {\n scrollpoints: [{ id: \"zone1\", className: \"theme-light\" }],\n },\n }\n );\n\n expect(IntersectionObserver).toHaveBeenCalledTimes(1);\n expect(mockObserve).toHaveBeenCalledTimes(1);\n\n // Change scrollpoints\n rerender({\n scrollpoints: [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ],\n });\n\n // Should disconnect old observer and create new one\n expect(mockDisconnect).toHaveBeenCalledTimes(1);\n expect(IntersectionObserver).toHaveBeenCalledTimes(2);\n expect(mockObserve).toHaveBeenCalledTimes(3); // 1 from first render + 2 from second\n });\n\n it(\"uses requestAnimationFrame for state updates\", () => {\n const elem = document.createElement(\"div\");\n elem.id = \"zone1\";\n document.body.appendChild(elem);\n\n const scrollpoints = [\n { id: \"zone1\", className: \"theme-light\" },\n { id: \"zone2\", className: \"theme-dark\" },\n ];\n\n renderHook(() => useThemedScrollpoints(scrollpoints));\n\n const rafSpy = vi.spyOn(global, \"requestAnimationFrame\");\n\n // Simulate intersection\n observerCallback(\n [\n {\n target: elem,\n isIntersecting: true,\n } as unknown as IntersectionObserverEntry,\n ],\n {} as IntersectionObserver\n );\n\n expect(rafSpy).toHaveBeenCalled();\n\n rafSpy.mockRestore();\n });\n});\n"],"names":["describe","it","expect","beforeEach","afterEach","vi","renderHook","waitFor","useThemedScrollpoints","observerCallback","mockObserve","mockUnobserve","mockDisconnect","fn","global","IntersectionObserver","callback","observe","unobserve","disconnect","requestAnimationFrame","cb","clearAllMocks","document","body","innerHTML","scrollpoints","id","className","result","current","toBe","not","toHaveBeenCalled","elem","createElement","appendChild","toHaveBeenCalledWith","any","Function","objectContaining","rootMargin","threshold","elem1","elem2","toHaveBeenCalledTimes","consoleWarn","spyOn","console","mockImplementation","stringContaining","mockRestore","target","isIntersecting","renderCount","elem3","unmount","rerender","initialProps","rafSpy"],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -5998,6 +5998,21 @@ export const queryIdAll: (val: string, root?: ParentNode) => NodeListOf<Element>
|
|
|
5998
5998
|
//# sourceMappingURL=dom-query.d.ts.map
|
|
5999
5999
|
}
|
|
6000
6000
|
|
|
6001
|
+
declare module '@ably/ui/core/hooks/use-content-height' {
|
|
6002
|
+
import { RefObject } from "react";
|
|
6003
|
+
/**
|
|
6004
|
+
* Custom hook that tracks the content height of an element using ResizeObserver.
|
|
6005
|
+
* This eliminates forced reflows by using the browser's native resize observation API
|
|
6006
|
+
* instead of synchronous clientHeight/getBoundingClientRect queries.
|
|
6007
|
+
*
|
|
6008
|
+
* @param ref - React ref to the element to observe
|
|
6009
|
+
* @param initialHeight - Initial height value (default: 0)
|
|
6010
|
+
* @returns Current content height in pixels
|
|
6011
|
+
*/
|
|
6012
|
+
export function useContentHeight(ref: RefObject<HTMLElement>, initialHeight?: number): number;
|
|
6013
|
+
//# sourceMappingURL=use-content-height.d.ts.map
|
|
6014
|
+
}
|
|
6015
|
+
|
|
6001
6016
|
declare module '@ably/ui/core/hooks/use-rails-ujs-hooks' {
|
|
6002
6017
|
import { RefObject } from "react";
|
|
6003
6018
|
const useRailsUjsLinks: (containerRef: RefObject<HTMLElement>) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ably/ui",
|
|
3
|
-
"version": "17.11.0-dev.
|
|
3
|
+
"version": "17.11.0-dev.672950e8",
|
|
4
4
|
"description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|