@telescopic-text/react
Version:
A React component for telescopic text.
1 lines • 8.25 kB
Source Map (JSON)
{"version":3,"sources":["../index.tsx"],"sourcesContent":["\"use client\"\n\nimport React, { useState, useEffect } from \"react\";\n\nexport type TelescopicItem = string | React.ReactNode | TelescopicTextNodeData;\n\nexport interface TelescopicTextNodeData {\n id?: string;\n word?: string | React.ReactNode;\n link?: string;\n linkClassName?: string;\n expandableClassName?: string;\n baseClassName?: string;\n expandTo?: TelescopicItem[];\n}\n\ninterface TelescopicTextProps {\n nodes: TelescopicItem[];\n persistenceKey?: string;\n enablePersistence?: boolean;\n baseClassName?: string;\n linkClassName?: string;\n expandableClassName?: string;\n}\n\nfunction useTelescopicState(persistenceKey: string, enablePersistence: boolean) {\n const [expandedKeys, setExpandedKeys] = useState<string[]>([]);\n const [clickedKeys, setClickedKeys] = useState<string[]>([]);\n\n useEffect(() => {\n if (!enablePersistence || typeof window === \"undefined\" || !persistenceKey) return;\n try {\n const savedState = localStorage.getItem(persistenceKey);\n if (savedState) {\n const { expanded, clicked } = JSON.parse(savedState);\n setExpandedKeys(expanded || []);\n setClickedKeys(clicked || []);\n }\n } catch (error) {\n console.error(\"Error loading telescopic text state:\", error);\n localStorage.removeItem(persistenceKey);\n }\n }, [persistenceKey, enablePersistence]);\n\n useEffect(() => {\n if (!enablePersistence || !persistenceKey) return;\n localStorage.setItem(\n persistenceKey,\n JSON.stringify({ expanded: expandedKeys, clicked: clickedKeys })\n );\n }, [expandedKeys, clickedKeys, persistenceKey, enablePersistence]);\n\n const handleExpand = (key: string) => {\n if (!clickedKeys.includes(key)) {\n setExpandedKeys((prev) => [...prev, key]);\n setClickedKeys((prev) => [...prev, key]);\n }\n };\n\n return { expandedKeys, clickedKeys, handleExpand };\n}\n\nconst TelescopicText: React.FC<TelescopicTextProps> = ({\n nodes,\n persistenceKey = \"telescopic-text\",\n enablePersistence = true,\n baseClassName = \"\",\n linkClassName = \"\",\n expandableClassName = \"\",\n}) => {\n const { expandedKeys, clickedKeys, handleExpand } = useTelescopicState(\n persistenceKey,\n enablePersistence\n );\n \n function generateNodeKey(\n parentKey: string | null,\n index: number,\n node: TelescopicTextNodeData\n ): string {\n return parentKey\n ? `${parentKey}-${node.id || index}`\n : `${node.id || index}`;\n }\n\n function renderItems(items: TelescopicItem[], parentKey: string | null = null) {\n return items.map((item, index) => {\n if (typeof item === \"object\" && !React.isValidElement(item)) {\n const data = item as TelescopicTextNodeData;\n const itemKey = generateNodeKey(parentKey, index, data);\n return renderItem(item, itemKey);\n } else {\n const itemKey = parentKey ? `${parentKey}-${index}` : `${index}`;\n return renderItem(item, itemKey);\n }\n });\n }\n\n function renderItem(item: TelescopicItem, key: string): JSX.Element {\n if (typeof item === \"string\") {\n return (\n <span key={key} className={baseClassName}>\n {item}{\" \"}\n </span>\n );\n }\n\n if (React.isValidElement(item)) {\n return (\n <span key={key} className={baseClassName}>\n {item}\n </span>\n );\n }\n\n if (typeof item === 'object' && !Array.isArray(item)) {\n return renderDataNode(item as TelescopicTextNodeData, key);\n }\n\n return (\n <span key={key} className={baseClassName}>\n {String(item)}{\" \"}\n </span>\n );\n }\n \n function renderDataNode(item: TelescopicTextNodeData, key: string): JSX.Element {\n const isExpanded = expandedKeys.includes(key);\n const isClicked = clickedKeys.includes(key);\n\n const currentClassName = item.link\n ? item.linkClassName || linkClassName\n : item.expandTo\n ? item.expandableClassName || expandableClassName\n : item.baseClassName || baseClassName;\n\n const content = item.word || \"\";\n\n if (item.expandTo) {\n return (\n <span key={key}>\n {!isClicked && (\n <span\n role=\"button\"\n tabIndex={0}\n aria-expanded={isExpanded}\n className={currentClassName}\n onClick={() => handleExpand(key)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n handleExpand(key);\n }\n }}\n >\n {content}{\" \"}\n </span>\n )}\n {isExpanded && (\n <span key={`${key}-expanded`} className={`${baseClassName} inline`}>\n {renderItems(item.expandTo, key)}\n </span>\n )}\n </span>\n );\n }\n\n if (item.link) {\n return (\n <a\n key={key}\n href={item.link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={currentClassName}\n >\n {content}\n </a>\n );\n }\n\n return (\n <span key={key} className={baseClassName}>\n {content}\n </span>\n );\n }\n\n return <>{renderItems(nodes)}</>;\n};\n\nexport default TelescopicText;"],"mappings":"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","names":[]}