@bioturing/components 0.18.0 → 0.20.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/dist/components/{Badge → badge}/component.js.map +1 -1
- package/dist/components/{Breadcrumb → breadcrumb}/component.js.map +1 -1
- package/dist/components/{Breadcrumb → breadcrumb}/useItemRender.js +6 -5
- package/dist/components/breadcrumb/useItemRender.js.map +1 -0
- package/dist/components/button/component.js +46 -0
- package/dist/components/button/component.js.map +1 -0
- package/dist/components/{Button → button}/style.css +1 -1
- package/dist/components/{Checkbox → checkbox}/component.js +1 -0
- package/dist/components/checkbox/component.js.map +1 -0
- package/dist/components/choice-list/component.js +54 -0
- package/dist/components/choice-list/component.js.map +1 -0
- package/dist/components/choice-list/style.css +1 -0
- package/dist/components/cmdk/command-score.js +48 -0
- package/dist/components/cmdk/command-score.js.map +1 -0
- package/dist/components/cmdk/index.js +611 -0
- package/dist/components/cmdk/index.js.map +1 -0
- package/dist/components/{CodeBlock → code-block}/component.js +4 -4
- package/dist/components/code-block/component.js.map +1 -0
- package/dist/components/{Collapse → collapse}/component.js.map +1 -1
- package/dist/components/{ColorSelect → color-select}/component.js +10 -10
- package/dist/components/color-select/component.js.map +1 -0
- package/dist/components/drag-drop/context.js.map +1 -0
- package/dist/components/drag-drop/draggable.js.map +1 -0
- package/dist/components/drag-drop/droppable.js.map +1 -0
- package/dist/components/{DragDrop → drag-drop}/hooks.js +1 -0
- package/dist/components/drag-drop/hooks.js.map +1 -0
- package/dist/components/drag-drop/index.js.map +1 -0
- package/dist/components/{DragDrop → drag-drop}/value.js +4 -4
- package/dist/components/drag-drop/value.js.map +1 -0
- package/dist/components/dropdown-menu/component.js +199 -0
- package/dist/components/dropdown-menu/component.js.map +1 -0
- package/dist/components/dropdown-menu/style.css +1 -0
- package/dist/components/{DSRoot → ds-root}/component.js +3 -3
- package/dist/components/ds-root/component.js.map +1 -0
- package/dist/components/ds-root/context.js.map +1 -0
- package/dist/components/{Empty → empty}/component.js +6 -5
- package/dist/components/empty/component.js.map +1 -0
- package/dist/components/{Field → field}/component.js.map +1 -1
- package/dist/components/{Form → form}/component.js.map +1 -1
- package/dist/components/{Form → form}/item.js +1 -1
- package/dist/components/form/item.js.map +1 -0
- package/dist/components/hooks/useCSSVariables.js +12 -0
- package/dist/components/hooks/useCSSVariables.js.map +1 -0
- package/dist/components/hooks/useCharts.js +1 -1
- package/dist/components/hooks/useCharts.js.map +1 -1
- package/dist/components/{IconButton → icon-button}/component.js +2 -2
- package/dist/components/icon-button/component.js.map +1 -0
- package/dist/components/input/component.js +26 -0
- package/dist/components/input/component.js.map +1 -0
- package/dist/components/{Modal → modal}/Modal.js +3 -3
- package/dist/components/modal/Modal.js.map +1 -0
- package/dist/components/{Modal → modal}/ModalProvider.js.map +1 -1
- package/dist/components/{Modal → modal}/ModalService.js +3 -2
- package/dist/components/modal/ModalService.js.map +1 -0
- package/dist/components/{Modal → modal}/constants.js.map +1 -1
- package/dist/components/{Modal → modal}/functions.js +8 -7
- package/dist/components/modal/functions.js.map +1 -0
- package/dist/components/{Modal → modal}/index.js.map +1 -1
- package/dist/components/{Nav → nav}/context.js.map +1 -1
- package/dist/components/{Nav → nav}/group.js.map +1 -1
- package/dist/components/{Nav → nav}/heading.js.map +1 -1
- package/dist/components/{Nav → nav}/index.js +3 -2
- package/dist/components/nav/index.js.map +1 -0
- package/dist/components/nav/item.js +36 -0
- package/dist/components/nav/item.js.map +1 -0
- package/dist/components/{Popover → popover}/component.js.map +1 -1
- package/dist/components/{PopupPanel → popup-panel}/component.js +47 -47
- package/dist/components/popup-panel/component.js.map +1 -0
- package/dist/components/popup-panel/constants.js.map +1 -0
- package/dist/components/{Radio → radio}/component.js +6 -5
- package/dist/components/radio/component.js.map +1 -0
- package/dist/components/scroll-area/component.js.map +1 -0
- package/dist/components/{Segmented → segmented}/component.js +3 -2
- package/dist/components/segmented/component.js.map +1 -0
- package/dist/components/{Select → select}/component.js +7 -6
- package/dist/components/select/component.js.map +1 -0
- package/dist/components/{Slider → slider}/component.js.map +1 -1
- package/dist/components/{Spin → spin}/component.js +5 -4
- package/dist/components/spin/component.js.map +1 -0
- package/dist/components/{Splitter → splitter}/component.js.map +1 -1
- package/dist/components/{Stack → stack}/Stack.js.map +1 -1
- package/dist/components/stack/StackChild.js +65 -0
- package/dist/components/{Stack → stack}/StackChild.js.map +1 -1
- package/dist/components/{Stack → stack}/index.js.map +1 -1
- package/dist/components/{Switch → switch}/component.js +3 -2
- package/dist/components/switch/component.js.map +1 -0
- package/dist/components/{Table → table}/component.js +1 -1
- package/dist/components/{Table → table}/component.js.map +1 -1
- package/dist/components/{Tag → tag}/component.js.map +1 -1
- package/dist/components/theme-provider/component.js.map +1 -0
- package/dist/components/{Toast → toast}/component.js +14 -14
- package/dist/components/toast/component.js.map +1 -0
- package/dist/components/{Toast → toast}/function.js.map +1 -1
- package/dist/components/{Toast → toast}/style.css +1 -1
- package/dist/components/{Tooltip → tooltip}/component.js.map +1 -1
- package/dist/components/{Tour → tour}/component.js.map +1 -1
- package/dist/components/{Transition → transition}/component.js.map +1 -1
- package/dist/components/{Tree → tree}/components.js.map +1 -1
- package/dist/components/{Tree → tree}/helpers.js.map +1 -1
- package/dist/components/{Tree → tree}/useTreeCommon.js.map +1 -1
- package/dist/components/{Tree → tree}/useUniqueKeysTree.js.map +1 -1
- package/dist/components/{Truncate → truncate}/component.js.map +1 -1
- package/dist/components/{Truncate → truncate}/helpers.js.map +1 -1
- package/dist/components/{Upload → upload}/component.js +1 -1
- package/dist/components/{Upload → upload}/component.js.map +1 -1
- package/dist/components/{Upload → upload}/dragger.js.map +1 -1
- package/dist/components/{Upload → upload}/hooks.js.map +1 -1
- package/dist/components/{Upload → upload}/item.js +7 -6
- package/dist/components/upload/item.js.map +1 -0
- package/dist/components/{Upload → upload}/utils.js.map +1 -1
- package/dist/components/utils/WithRenderProp.js +15 -0
- package/dist/components/utils/WithRenderProp.js.map +1 -0
- package/dist/components/{VerticalCollapsiblePanel → vertical-collapsible-panel}/component.js +9 -9
- package/dist/components/vertical-collapsible-panel/component.js.map +1 -0
- package/dist/index.d.ts +249 -3
- package/dist/index.js +164 -158
- package/dist/index.js.map +1 -1
- package/dist/metadata.js +14 -0
- package/dist/metadata.js.map +1 -1
- package/dist/tokens/and-theme/tokens.js +12 -12
- package/dist/tokens/and-theme/tokens.js.map +1 -1
- package/package.json +6 -2
- package/dist/components/Breadcrumb/useItemRender.js.map +0 -1
- package/dist/components/Button/component.js +0 -36
- package/dist/components/Button/component.js.map +0 -1
- package/dist/components/Checkbox/component.js.map +0 -1
- package/dist/components/CodeBlock/component.js.map +0 -1
- package/dist/components/ColorSelect/component.js.map +0 -1
- package/dist/components/DSRoot/component.js.map +0 -1
- package/dist/components/DSRoot/context.js.map +0 -1
- package/dist/components/DragDrop/context.js.map +0 -1
- package/dist/components/DragDrop/draggable.js.map +0 -1
- package/dist/components/DragDrop/droppable.js.map +0 -1
- package/dist/components/DragDrop/hooks.js.map +0 -1
- package/dist/components/DragDrop/index.js.map +0 -1
- package/dist/components/DragDrop/value.js.map +0 -1
- package/dist/components/DropdownMenu/component.js +0 -156
- package/dist/components/DropdownMenu/component.js.map +0 -1
- package/dist/components/DropdownMenu/style.css +0 -1
- package/dist/components/Empty/component.js.map +0 -1
- package/dist/components/Form/item.js.map +0 -1
- package/dist/components/IconButton/component.js.map +0 -1
- package/dist/components/Input/component.js +0 -25
- package/dist/components/Input/component.js.map +0 -1
- package/dist/components/Modal/Modal.js.map +0 -1
- package/dist/components/Modal/ModalService.js.map +0 -1
- package/dist/components/Modal/functions.js.map +0 -1
- package/dist/components/Nav/index.js.map +0 -1
- package/dist/components/Nav/item.js +0 -36
- package/dist/components/Nav/item.js.map +0 -1
- package/dist/components/PopupPanel/component.js.map +0 -1
- package/dist/components/PopupPanel/constants.js.map +0 -1
- package/dist/components/Radio/component.js.map +0 -1
- package/dist/components/ScrollArea/component.js.map +0 -1
- package/dist/components/Segmented/component.js.map +0 -1
- package/dist/components/Select/component.js.map +0 -1
- package/dist/components/Spin/component.js.map +0 -1
- package/dist/components/Stack/StackChild.js +0 -65
- package/dist/components/Switch/component.js.map +0 -1
- package/dist/components/ThemeProvider/component.js.map +0 -1
- package/dist/components/Toast/component.js.map +0 -1
- package/dist/components/Upload/item.js.map +0 -1
- package/dist/components/VerticalCollapsiblePanel/component.js.map +0 -1
- /package/dist/components/{Badge → badge}/component.js +0 -0
- /package/dist/components/{Badge → badge}/style.css +0 -0
- /package/dist/components/{Breadcrumb → breadcrumb}/component.js +0 -0
- /package/dist/components/{Breadcrumb → breadcrumb}/style.css +0 -0
- /package/dist/components/{Checkbox → checkbox}/style.css +0 -0
- /package/dist/components/{CodeBlock → code-block}/style.css +0 -0
- /package/dist/components/{Collapse → collapse}/component.js +0 -0
- /package/dist/components/{Collapse → collapse}/style.css +0 -0
- /package/dist/components/{ColorSelect → color-select}/style.css +0 -0
- /package/dist/components/{DragDrop → drag-drop}/context.js +0 -0
- /package/dist/components/{DragDrop → drag-drop}/draggable.js +0 -0
- /package/dist/components/{DragDrop → drag-drop}/droppable.js +0 -0
- /package/dist/components/{DragDrop → drag-drop}/index.js +0 -0
- /package/dist/components/{DragDrop → drag-drop}/style.css +0 -0
- /package/dist/components/{DSRoot → ds-root}/context.js +0 -0
- /package/dist/components/{DSRoot → ds-root}/style.css +0 -0
- /package/dist/components/{Empty → empty}/style.css +0 -0
- /package/dist/components/{Field → field}/component.js +0 -0
- /package/dist/components/{Field → field}/style.css +0 -0
- /package/dist/components/{Form → form}/component.js +0 -0
- /package/dist/components/{Form → form}/style.css +0 -0
- /package/dist/components/{IconButton → icon-button}/style.css +0 -0
- /package/dist/components/{Modal → modal}/ModalProvider.js +0 -0
- /package/dist/components/{Modal → modal}/constants.js +0 -0
- /package/dist/components/{Modal → modal}/index.js +0 -0
- /package/dist/components/{Modal → modal}/style.css +0 -0
- /package/dist/components/{Nav → nav}/context.js +0 -0
- /package/dist/components/{Nav → nav}/group.js +0 -0
- /package/dist/components/{Nav → nav}/heading.js +0 -0
- /package/dist/components/{Nav → nav}/style.css +0 -0
- /package/dist/components/{Popover → popover}/component.js +0 -0
- /package/dist/components/{PopupPanel → popup-panel}/constants.js +0 -0
- /package/dist/components/{PopupPanel → popup-panel}/style.css +0 -0
- /package/dist/components/{Radio → radio}/style.css +0 -0
- /package/dist/components/{ScrollArea → scroll-area}/component.js +0 -0
- /package/dist/components/{ScrollArea → scroll-area}/style.css +0 -0
- /package/dist/components/{Segmented → segmented}/style.css +0 -0
- /package/dist/components/{Select → select}/style.css +0 -0
- /package/dist/components/{Slider → slider}/component.js +0 -0
- /package/dist/components/{Spin → spin}/style.css +0 -0
- /package/dist/components/{Splitter → splitter}/component.js +0 -0
- /package/dist/components/{Splitter → splitter}/style.css +0 -0
- /package/dist/components/{Stack → stack}/Stack.js +0 -0
- /package/dist/components/{Stack → stack}/index.js +0 -0
- /package/dist/components/{Stack → stack}/style.css +0 -0
- /package/dist/components/{Switch → switch}/style.css +0 -0
- /package/dist/components/{Table → table}/style.css +0 -0
- /package/dist/components/{Tag → tag}/component.js +0 -0
- /package/dist/components/{Tag → tag}/style.css +0 -0
- /package/dist/components/{ThemeProvider → theme-provider}/component.js +0 -0
- /package/dist/components/{ThemeProvider → theme-provider}/style.css +0 -0
- /package/dist/components/{Toast → toast}/function.js +0 -0
- /package/dist/components/{Tooltip → tooltip}/component.js +0 -0
- /package/dist/components/{Tooltip → tooltip}/style.css +0 -0
- /package/dist/components/{Tour → tour}/component.js +0 -0
- /package/dist/components/{Tour → tour}/style.css +0 -0
- /package/dist/components/{Transition → transition}/component.js +0 -0
- /package/dist/components/{Tree → tree}/components.js +0 -0
- /package/dist/components/{Tree → tree}/helpers.js +0 -0
- /package/dist/components/{Tree → tree}/style.css +0 -0
- /package/dist/components/{Tree → tree}/useTreeCommon.js +0 -0
- /package/dist/components/{Tree → tree}/useUniqueKeysTree.js +0 -0
- /package/dist/components/{Truncate → truncate}/component.js +0 -0
- /package/dist/components/{Truncate → truncate}/helpers.js +0 -0
- /package/dist/components/{Truncate → truncate}/style.css +0 -0
- /package/dist/components/{Upload → upload}/dragger.js +0 -0
- /package/dist/components/{Upload → upload}/hooks.js +0 -0
- /package/dist/components/{Upload → upload}/style.css +0 -0
- /package/dist/components/{Upload → upload}/utils.js +0 -0
- /package/dist/components/{VerticalCollapsiblePanel → vertical-collapsible-panel}/style.css +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUniqueKeysTree.js","sources":["../../../src/components/Tree/useUniqueKeysTree.ts"],"sourcesContent":["import { useCallback, useMemo, type Key } from \"react\";\nimport type { DataNode as AntTreeDataNode, EventDataNode } from \"antd/es/tree\";\nimport { useControlledState } from \"../hooks\";\nimport { processTreeData, getUniqueKeysFromOriginals } from \"./helpers\";\nimport type { CheckInfo, ExpandInfo } from \"./types\";\n\ninterface UseUniqueKeysTreeProps<T extends AntTreeDataNode> {\n treeData: T[] | undefined;\n expandedKeys?: Key[];\n defaultExpandedKeys?: Key[];\n onExpand?: (expandedKeys: Key[], info: ExpandInfo<T>) => void;\n checkedKeys?: Key[] | { checked: Key[]; halfChecked: Key[] };\n defaultCheckedKeys?: Key[];\n onCheck?: (\n checkedKeys: Key[],\n info: CheckInfo<T> & { triggeredOriginalKey?: Key }\n ) => void;\n allowDuplicatedKeys?: boolean;\n}\n\nexport const useUniqueKeysTree = <T extends AntTreeDataNode>({\n treeData: originTreeData,\n expandedKeys,\n defaultExpandedKeys = [],\n onExpand,\n checkedKeys,\n defaultCheckedKeys = [],\n onCheck,\n allowDuplicatedKeys,\n}: UseUniqueKeysTreeProps<T>) => {\n // Always define all hooks at the top level, regardless of allowDuplicatedKeys\n // State hook for ORIGINAL expanded keys\n const [currentOriginalExpandedKeys, setCurrentOriginalExpandedKeys] =\n useControlledState<Key[]>(\n expandedKeys,\n undefined, // Handle onChange manually in handlers\n defaultExpandedKeys\n );\n\n // State hook for ORIGINAL checked keys\n const controlledCheckedKeysValue = useMemo(() => {\n if (!checkedKeys) return undefined;\n return Array.isArray(checkedKeys) ? checkedKeys : checkedKeys.checked;\n }, [checkedKeys]);\n\n const [currentOriginalCheckedKeys, setCurrentOriginalCheckedKeys] =\n useControlledState<Key[]>(\n controlledCheckedKeysValue, // Pass the array of original keys\n undefined, // Handle onChange manually in handlers\n defaultCheckedKeys\n );\n\n // Process tree data to handle duplicated keys (only used when allowDuplicatedKeys is true)\n const { processedTreeData, uniqueToOriginalKeyMap } = useMemo(() => {\n if (!allowDuplicatedKeys) {\n // Return a simple passthrough mapping when not handling duplicates\n return {\n processedTreeData: originTreeData,\n uniqueToOriginalKeyMap: new Map<Key, Key>(),\n };\n }\n\n const map = new Map<Key, Key>();\n const expandedOriginalKeySet = new Set(currentOriginalExpandedKeys);\n const data = processTreeData(\n originTreeData,\n expandedOriginalKeySet,\n \"\",\n map\n );\n return { processedTreeData: data, uniqueToOriginalKeyMap: map };\n }, [originTreeData, currentOriginalExpandedKeys, allowDuplicatedKeys]);\n\n // Create unique keys mappings (only used when allowDuplicatedKeys is true)\n const currentUniqueExpandedKeys = useMemo(() => {\n if (!allowDuplicatedKeys) {\n return currentOriginalExpandedKeys;\n }\n\n const originalKeysSet = new Set(currentOriginalExpandedKeys);\n return getUniqueKeysFromOriginals(\n processedTreeData as AntTreeDataNode[] | undefined,\n originalKeysSet,\n uniqueToOriginalKeyMap\n );\n }, [\n currentOriginalExpandedKeys,\n processedTreeData,\n uniqueToOriginalKeyMap,\n allowDuplicatedKeys,\n ]);\n\n const currentUniqueCheckedKeys = useMemo(() => {\n if (!allowDuplicatedKeys) {\n return currentOriginalCheckedKeys;\n }\n\n const originalKeysSet = new Set(currentOriginalCheckedKeys);\n return getUniqueKeysFromOriginals(\n processedTreeData as AntTreeDataNode[] | undefined,\n originalKeysSet,\n uniqueToOriginalKeyMap\n );\n }, [\n currentOriginalCheckedKeys,\n processedTreeData,\n uniqueToOriginalKeyMap,\n allowDuplicatedKeys,\n ]);\n\n // Simple expand handler for when allowDuplicatedKeys is false\n const handleOriginalExpand = useCallback(\n (\n keys: readonly Key[],\n info: {\n node: EventDataNode<T>;\n expanded: boolean;\n nativeEvent: MouseEvent;\n }\n ) => {\n const keysArray = Array.from(keys);\n setCurrentOriginalExpandedKeys(keysArray);\n\n if (onExpand) {\n onExpand(keysArray, info);\n }\n },\n [onExpand, setCurrentOriginalExpandedKeys]\n );\n\n // Advanced expand handler for when allowDuplicatedKeys is true\n const handleUniqueExpand = useCallback(\n (\n uniqueKeys: readonly Key[],\n info: {\n node: EventDataNode<T>;\n expanded: boolean;\n nativeEvent: MouseEvent;\n }\n ) => {\n const originalKeys = uniqueKeys\n .map((uk) => uniqueToOriginalKeyMap.get(uk))\n .filter((ok): ok is Key => ok !== undefined); // Type guard\n const triggeredOriginalKey = uniqueToOriginalKeyMap.get(info.node.key);\n\n setCurrentOriginalExpandedKeys(originalKeys);\n\n if (onExpand) {\n onExpand(originalKeys, {\n ...info,\n triggeredOriginalKey: triggeredOriginalKey,\n });\n }\n },\n [uniqueToOriginalKeyMap, setCurrentOriginalExpandedKeys, onExpand]\n );\n\n // Simple check handler for when allowDuplicatedKeys is false\n const handleOriginalCheck = useCallback(\n (\n checkedInfoOrKeys:\n | readonly Key[]\n | { checked: readonly Key[]; halfChecked: readonly Key[] },\n info: CheckInfo<T>\n ) => {\n let checkedArray: Key[];\n\n if (Array.isArray(checkedInfoOrKeys)) {\n checkedArray = Array.from(checkedInfoOrKeys);\n } else if (\n checkedInfoOrKeys &&\n typeof checkedInfoOrKeys === \"object\" &&\n \"checked\" in checkedInfoOrKeys\n ) {\n checkedArray = Array.from(checkedInfoOrKeys.checked);\n } else {\n checkedArray = [];\n }\n\n setCurrentOriginalCheckedKeys(checkedArray);\n\n if (onCheck) {\n onCheck(checkedArray, info);\n }\n },\n [onCheck, setCurrentOriginalCheckedKeys]\n );\n\n // Advanced check handler for when allowDuplicatedKeys is true\n const handleUniqueCheck = useCallback(\n (\n checkedInfoOrKeys:\n | readonly Key[]\n | { checked: readonly Key[]; halfChecked: readonly Key[] },\n info: CheckInfo<T> // Contains info about the node that triggered the event\n ) => {\n const triggeredUniqueKey = info.node.key;\n const triggeredOriginalKey =\n uniqueToOriginalKeyMap.get(triggeredUniqueKey);\n\n if (triggeredOriginalKey === undefined) {\n console.error(\n \"Could not find original key for unique key:\",\n triggeredUniqueKey\n );\n return;\n }\n\n // Special handling for unchecking - this is the critical part\n if (!info.checked) {\n // When unchecking, we need to completely rebuild the checked keys list\n // excluding the original key that was unchecked\n\n // 1. Get the current original checked keys\n const currentKeys = [...currentOriginalCheckedKeys];\n\n // 2. Filter out the original key that was unchecked\n const newCheckedKeys = currentKeys.filter(\n (key) => key !== triggeredOriginalKey\n );\n\n // 3. Update the state with the filtered keys\n setCurrentOriginalCheckedKeys(newCheckedKeys);\n\n // 4. Call the user's onCheck callback\n if (onCheck) {\n onCheck(newCheckedKeys, {\n ...info,\n triggeredOriginalKey: triggeredOriginalKey,\n });\n }\n\n // Return early to prevent further processing\n return;\n }\n\n // Handle checking (normal flow for checking items)\n // 1. Extract unique checked keys from Ant Design's final state\n let uniqueCheckedKeys: readonly Key[];\n if (Array.isArray(checkedInfoOrKeys)) {\n uniqueCheckedKeys = checkedInfoOrKeys;\n } else if (\n checkedInfoOrKeys &&\n typeof checkedInfoOrKeys === \"object\" &&\n \"checked\" in checkedInfoOrKeys\n ) {\n uniqueCheckedKeys = checkedInfoOrKeys.checked;\n } else {\n uniqueCheckedKeys = [];\n }\n\n // 2. Map these unique keys to their original keys\n const derivedOriginalKeys = new Set<Key>();\n for (const uniqueKey of uniqueCheckedKeys) {\n const originalKey = uniqueToOriginalKeyMap.get(uniqueKey);\n if (originalKey !== undefined) {\n derivedOriginalKeys.add(originalKey);\n }\n }\n\n // 3. Ensure the triggered original key is included when checking\n derivedOriginalKeys.add(triggeredOriginalKey);\n\n const originalKeysArray = Array.from(derivedOriginalKeys);\n\n // 4. Update the controlled state\n setCurrentOriginalCheckedKeys(originalKeysArray);\n\n // 5. Call the user's onCheck callback\n if (onCheck) {\n onCheck(originalKeysArray, {\n ...info,\n triggeredOriginalKey: triggeredOriginalKey,\n });\n }\n },\n [\n uniqueToOriginalKeyMap,\n setCurrentOriginalCheckedKeys,\n onCheck,\n currentOriginalCheckedKeys,\n ]\n );\n\n // Choose appropriate handlers and data based on allowDuplicatedKeys\n const handleAntTreeExpand = allowDuplicatedKeys\n ? handleUniqueExpand\n : handleOriginalExpand;\n const handleAntTreeCheck = allowDuplicatedKeys\n ? handleUniqueCheck\n : handleOriginalCheck;\n const finalProcessedTreeData = allowDuplicatedKeys\n ? processedTreeData\n : originTreeData;\n\n return {\n processedTreeData: finalProcessedTreeData,\n currentUniqueExpandedKeys,\n currentUniqueCheckedKeys,\n handleAntTreeExpand,\n handleAntTreeCheck,\n };\n};\n"],"names":["useUniqueKeysTree","originTreeData","expandedKeys","defaultExpandedKeys","onExpand","checkedKeys","defaultCheckedKeys","onCheck","allowDuplicatedKeys","currentOriginalExpandedKeys","setCurrentOriginalExpandedKeys","useControlledState","controlledCheckedKeysValue","useMemo","currentOriginalCheckedKeys","setCurrentOriginalCheckedKeys","processedTreeData","uniqueToOriginalKeyMap","map","expandedOriginalKeySet","processTreeData","currentUniqueExpandedKeys","originalKeysSet","getUniqueKeysFromOriginals","currentUniqueCheckedKeys","handleOriginalExpand","useCallback","keys","info","keysArray","handleUniqueExpand","uniqueKeys","originalKeys","uk","ok","triggeredOriginalKey","handleOriginalCheck","checkedInfoOrKeys","checkedArray","handleUniqueCheck","triggeredUniqueKey","newCheckedKeys","key","uniqueCheckedKeys","derivedOriginalKeys","uniqueKey","originalKey","originalKeysArray"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useUniqueKeysTree.js","sources":["../../../src/components/tree/useUniqueKeysTree.ts"],"sourcesContent":["import { useCallback, useMemo, type Key } from \"react\";\nimport type { DataNode as AntTreeDataNode, EventDataNode } from \"antd/es/tree\";\nimport { useControlledState } from \"../hooks\";\nimport { processTreeData, getUniqueKeysFromOriginals } from \"./helpers\";\nimport type { CheckInfo, ExpandInfo } from \"./types\";\n\ninterface UseUniqueKeysTreeProps<T extends AntTreeDataNode> {\n treeData: T[] | undefined;\n expandedKeys?: Key[];\n defaultExpandedKeys?: Key[];\n onExpand?: (expandedKeys: Key[], info: ExpandInfo<T>) => void;\n checkedKeys?: Key[] | { checked: Key[]; halfChecked: Key[] };\n defaultCheckedKeys?: Key[];\n onCheck?: (\n checkedKeys: Key[],\n info: CheckInfo<T> & { triggeredOriginalKey?: Key }\n ) => void;\n allowDuplicatedKeys?: boolean;\n}\n\nexport const useUniqueKeysTree = <T extends AntTreeDataNode>({\n treeData: originTreeData,\n expandedKeys,\n defaultExpandedKeys = [],\n onExpand,\n checkedKeys,\n defaultCheckedKeys = [],\n onCheck,\n allowDuplicatedKeys,\n}: UseUniqueKeysTreeProps<T>) => {\n // Always define all hooks at the top level, regardless of allowDuplicatedKeys\n // State hook for ORIGINAL expanded keys\n const [currentOriginalExpandedKeys, setCurrentOriginalExpandedKeys] =\n useControlledState<Key[]>(\n expandedKeys,\n undefined, // Handle onChange manually in handlers\n defaultExpandedKeys\n );\n\n // State hook for ORIGINAL checked keys\n const controlledCheckedKeysValue = useMemo(() => {\n if (!checkedKeys) return undefined;\n return Array.isArray(checkedKeys) ? checkedKeys : checkedKeys.checked;\n }, [checkedKeys]);\n\n const [currentOriginalCheckedKeys, setCurrentOriginalCheckedKeys] =\n useControlledState<Key[]>(\n controlledCheckedKeysValue, // Pass the array of original keys\n undefined, // Handle onChange manually in handlers\n defaultCheckedKeys\n );\n\n // Process tree data to handle duplicated keys (only used when allowDuplicatedKeys is true)\n const { processedTreeData, uniqueToOriginalKeyMap } = useMemo(() => {\n if (!allowDuplicatedKeys) {\n // Return a simple passthrough mapping when not handling duplicates\n return {\n processedTreeData: originTreeData,\n uniqueToOriginalKeyMap: new Map<Key, Key>(),\n };\n }\n\n const map = new Map<Key, Key>();\n const expandedOriginalKeySet = new Set(currentOriginalExpandedKeys);\n const data = processTreeData(\n originTreeData,\n expandedOriginalKeySet,\n \"\",\n map\n );\n return { processedTreeData: data, uniqueToOriginalKeyMap: map };\n }, [originTreeData, currentOriginalExpandedKeys, allowDuplicatedKeys]);\n\n // Create unique keys mappings (only used when allowDuplicatedKeys is true)\n const currentUniqueExpandedKeys = useMemo(() => {\n if (!allowDuplicatedKeys) {\n return currentOriginalExpandedKeys;\n }\n\n const originalKeysSet = new Set(currentOriginalExpandedKeys);\n return getUniqueKeysFromOriginals(\n processedTreeData as AntTreeDataNode[] | undefined,\n originalKeysSet,\n uniqueToOriginalKeyMap\n );\n }, [\n currentOriginalExpandedKeys,\n processedTreeData,\n uniqueToOriginalKeyMap,\n allowDuplicatedKeys,\n ]);\n\n const currentUniqueCheckedKeys = useMemo(() => {\n if (!allowDuplicatedKeys) {\n return currentOriginalCheckedKeys;\n }\n\n const originalKeysSet = new Set(currentOriginalCheckedKeys);\n return getUniqueKeysFromOriginals(\n processedTreeData as AntTreeDataNode[] | undefined,\n originalKeysSet,\n uniqueToOriginalKeyMap\n );\n }, [\n currentOriginalCheckedKeys,\n processedTreeData,\n uniqueToOriginalKeyMap,\n allowDuplicatedKeys,\n ]);\n\n // Simple expand handler for when allowDuplicatedKeys is false\n const handleOriginalExpand = useCallback(\n (\n keys: readonly Key[],\n info: {\n node: EventDataNode<T>;\n expanded: boolean;\n nativeEvent: MouseEvent;\n }\n ) => {\n const keysArray = Array.from(keys);\n setCurrentOriginalExpandedKeys(keysArray);\n\n if (onExpand) {\n onExpand(keysArray, info);\n }\n },\n [onExpand, setCurrentOriginalExpandedKeys]\n );\n\n // Advanced expand handler for when allowDuplicatedKeys is true\n const handleUniqueExpand = useCallback(\n (\n uniqueKeys: readonly Key[],\n info: {\n node: EventDataNode<T>;\n expanded: boolean;\n nativeEvent: MouseEvent;\n }\n ) => {\n const originalKeys = uniqueKeys\n .map((uk) => uniqueToOriginalKeyMap.get(uk))\n .filter((ok): ok is Key => ok !== undefined); // Type guard\n const triggeredOriginalKey = uniqueToOriginalKeyMap.get(info.node.key);\n\n setCurrentOriginalExpandedKeys(originalKeys);\n\n if (onExpand) {\n onExpand(originalKeys, {\n ...info,\n triggeredOriginalKey: triggeredOriginalKey,\n });\n }\n },\n [uniqueToOriginalKeyMap, setCurrentOriginalExpandedKeys, onExpand]\n );\n\n // Simple check handler for when allowDuplicatedKeys is false\n const handleOriginalCheck = useCallback(\n (\n checkedInfoOrKeys:\n | readonly Key[]\n | { checked: readonly Key[]; halfChecked: readonly Key[] },\n info: CheckInfo<T>\n ) => {\n let checkedArray: Key[];\n\n if (Array.isArray(checkedInfoOrKeys)) {\n checkedArray = Array.from(checkedInfoOrKeys);\n } else if (\n checkedInfoOrKeys &&\n typeof checkedInfoOrKeys === \"object\" &&\n \"checked\" in checkedInfoOrKeys\n ) {\n checkedArray = Array.from(checkedInfoOrKeys.checked);\n } else {\n checkedArray = [];\n }\n\n setCurrentOriginalCheckedKeys(checkedArray);\n\n if (onCheck) {\n onCheck(checkedArray, info);\n }\n },\n [onCheck, setCurrentOriginalCheckedKeys]\n );\n\n // Advanced check handler for when allowDuplicatedKeys is true\n const handleUniqueCheck = useCallback(\n (\n checkedInfoOrKeys:\n | readonly Key[]\n | { checked: readonly Key[]; halfChecked: readonly Key[] },\n info: CheckInfo<T> // Contains info about the node that triggered the event\n ) => {\n const triggeredUniqueKey = info.node.key;\n const triggeredOriginalKey =\n uniqueToOriginalKeyMap.get(triggeredUniqueKey);\n\n if (triggeredOriginalKey === undefined) {\n console.error(\n \"Could not find original key for unique key:\",\n triggeredUniqueKey\n );\n return;\n }\n\n // Special handling for unchecking - this is the critical part\n if (!info.checked) {\n // When unchecking, we need to completely rebuild the checked keys list\n // excluding the original key that was unchecked\n\n // 1. Get the current original checked keys\n const currentKeys = [...currentOriginalCheckedKeys];\n\n // 2. Filter out the original key that was unchecked\n const newCheckedKeys = currentKeys.filter(\n (key) => key !== triggeredOriginalKey\n );\n\n // 3. Update the state with the filtered keys\n setCurrentOriginalCheckedKeys(newCheckedKeys);\n\n // 4. Call the user's onCheck callback\n if (onCheck) {\n onCheck(newCheckedKeys, {\n ...info,\n triggeredOriginalKey: triggeredOriginalKey,\n });\n }\n\n // Return early to prevent further processing\n return;\n }\n\n // Handle checking (normal flow for checking items)\n // 1. Extract unique checked keys from Ant Design's final state\n let uniqueCheckedKeys: readonly Key[];\n if (Array.isArray(checkedInfoOrKeys)) {\n uniqueCheckedKeys = checkedInfoOrKeys;\n } else if (\n checkedInfoOrKeys &&\n typeof checkedInfoOrKeys === \"object\" &&\n \"checked\" in checkedInfoOrKeys\n ) {\n uniqueCheckedKeys = checkedInfoOrKeys.checked;\n } else {\n uniqueCheckedKeys = [];\n }\n\n // 2. Map these unique keys to their original keys\n const derivedOriginalKeys = new Set<Key>();\n for (const uniqueKey of uniqueCheckedKeys) {\n const originalKey = uniqueToOriginalKeyMap.get(uniqueKey);\n if (originalKey !== undefined) {\n derivedOriginalKeys.add(originalKey);\n }\n }\n\n // 3. Ensure the triggered original key is included when checking\n derivedOriginalKeys.add(triggeredOriginalKey);\n\n const originalKeysArray = Array.from(derivedOriginalKeys);\n\n // 4. Update the controlled state\n setCurrentOriginalCheckedKeys(originalKeysArray);\n\n // 5. Call the user's onCheck callback\n if (onCheck) {\n onCheck(originalKeysArray, {\n ...info,\n triggeredOriginalKey: triggeredOriginalKey,\n });\n }\n },\n [\n uniqueToOriginalKeyMap,\n setCurrentOriginalCheckedKeys,\n onCheck,\n currentOriginalCheckedKeys,\n ]\n );\n\n // Choose appropriate handlers and data based on allowDuplicatedKeys\n const handleAntTreeExpand = allowDuplicatedKeys\n ? handleUniqueExpand\n : handleOriginalExpand;\n const handleAntTreeCheck = allowDuplicatedKeys\n ? handleUniqueCheck\n : handleOriginalCheck;\n const finalProcessedTreeData = allowDuplicatedKeys\n ? processedTreeData\n : originTreeData;\n\n return {\n processedTreeData: finalProcessedTreeData,\n currentUniqueExpandedKeys,\n currentUniqueCheckedKeys,\n handleAntTreeExpand,\n handleAntTreeCheck,\n };\n};\n"],"names":["useUniqueKeysTree","originTreeData","expandedKeys","defaultExpandedKeys","onExpand","checkedKeys","defaultCheckedKeys","onCheck","allowDuplicatedKeys","currentOriginalExpandedKeys","setCurrentOriginalExpandedKeys","useControlledState","controlledCheckedKeysValue","useMemo","currentOriginalCheckedKeys","setCurrentOriginalCheckedKeys","processedTreeData","uniqueToOriginalKeyMap","map","expandedOriginalKeySet","processTreeData","currentUniqueExpandedKeys","originalKeysSet","getUniqueKeysFromOriginals","currentUniqueCheckedKeys","handleOriginalExpand","useCallback","keys","info","keysArray","handleUniqueExpand","uniqueKeys","originalKeys","uk","ok","triggeredOriginalKey","handleOriginalCheck","checkedInfoOrKeys","checkedArray","handleUniqueCheck","triggeredUniqueKey","newCheckedKeys","key","uniqueCheckedKeys","derivedOriginalKeys","uniqueKey","originalKey","originalKeysArray"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","sources":["../../../src/components/Truncate/component.tsx"],"sourcesContent":["\"use client\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport { clsx, useCls } from \"../utils\";\nimport { getMiddleTruncatedString } from \"./helpers\";\n\nimport \"./style.css\";\n\nexport type TruncatePosition = \"middle\" | \"end\";\n\nexport type Props = {\n text: string;\n} & React.CSSProperties;\n\nexport interface TruncateProps\n extends Omit<React.ComponentPropsWithoutRef<\"span\">, \"title\"> {\n /** Text content to be truncated */\n children: string;\n /** Where to truncate the text: start, middle, or end */\n position?: TruncatePosition;\n /** Number of lines to display before truncating (default: 1, 'auto' to fit parent height) */\n lines?: number | \"auto\";\n}\n\nexport const Truncate: React.FC<TruncateProps> = ({\n children,\n position = \"end\",\n lines = 1,\n className,\n style,\n ...rest\n}) => {\n const cls = useCls();\n const containerRef = useRef<HTMLElement>(null);\n const [isTruncated, setIsTruncated] = useState(false);\n const [truncatedText, setTruncatedText] = useState(children);\n\n const text = children;\n\n // Get appropriate container styles based on position and lines\n const getContainerStyles = useCallback(() => {\n // For explicit line numbers or single line\n if (lines !== \"auto\") {\n return {\n ...style,\n ...(lines > 1 ? { \"--ds-line-clamp\": lines } : {}),\n } as React.CSSProperties;\n }\n\n // For auto line calculation, we'll let the useLayoutEffect handle it\n return {\n ...style,\n // Set a temporary high value to ensure it fits the parent\n \"--ds-line-clamp\": 999,\n } as React.CSSProperties;\n }, [lines, style]);\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n // Handle auto-height calculation\n if (lines === \"auto\") {\n setTruncatedText(text);\n\n const calculateLines = () => {\n // Get the parent element's height\n const parent = container.parentElement;\n if (!parent) return;\n\n // Calculate the font size and line height\n const styles = window.getComputedStyle(container);\n const fontSize = parseFloat(styles.fontSize);\n const lineHeight =\n styles.lineHeight === \"normal\"\n ? fontSize * 1.2 // Approximate for \"normal\"\n : parseFloat(styles.lineHeight);\n\n // Get parent's padding and border to subtract from available height\n const parentStyles = window.getComputedStyle(parent);\n const paddingTop = parseFloat(parentStyles.paddingTop) || 0;\n const paddingBottom = parseFloat(parentStyles.paddingBottom) || 0;\n const borderTopWidth = parseFloat(parentStyles.borderTopWidth) || 0;\n const borderBottomWidth =\n parseFloat(parentStyles.borderBottomWidth) || 0;\n\n // Calculate how many lines can fit in the available space\n const parentHeight = parent.clientHeight;\n const availableHeight =\n parentHeight -\n paddingTop -\n paddingBottom -\n borderTopWidth -\n borderBottomWidth;\n const maxLines = Math.max(1, Math.floor(availableHeight / lineHeight));\n\n // Apply the calculated line-clamp\n if (container) {\n container.style.setProperty(\"--ds-line-clamp\", String(maxLines));\n }\n\n // Check if the text is truncated\n const clone = document.createElement(\"span\");\n clone.style.visibility = \"hidden\";\n clone.style.position = \"absolute\";\n clone.style.width = `${container.clientWidth}px`;\n clone.style.fontSize = styles.fontSize;\n clone.style.fontFamily = styles.fontFamily;\n clone.style.lineHeight = styles.lineHeight;\n clone.textContent = text;\n document.body.appendChild(clone);\n\n const isTruncated = clone.scrollHeight > availableHeight;\n document.body.removeChild(clone);\n\n setIsTruncated(isTruncated);\n };\n\n window.document.fonts?.ready?.then(calculateLines);\n const observer = new ResizeObserver(() => {\n window.requestAnimationFrame(calculateLines);\n });\n\n observer.observe(container);\n if (container.parentElement) {\n observer.observe(container.parentElement);\n }\n\n return () => observer.disconnect();\n }\n\n // Skip custom truncation logic for multi-line mode\n if (typeof lines === \"number\" && lines > 1) {\n setTruncatedText(text);\n // Check if text is truncated by comparing heights\n const checkIfTruncated = () => {\n const clone = document.createElement(\"span\");\n clone.style.visibility = \"hidden\";\n clone.style.position = \"absolute\";\n clone.style.width = `${container.clientWidth}px`;\n clone.textContent = text;\n document.body.appendChild(clone);\n const isTruncated =\n clone.scrollHeight >\n (container.clientHeight || container.offsetHeight);\n document.body.removeChild(clone);\n setIsTruncated(isTruncated);\n };\n\n window.document.fonts?.ready?.then(checkIfTruncated);\n const observer = new ResizeObserver(() => {\n window.requestAnimationFrame(checkIfTruncated);\n });\n\n observer.observe(container);\n return () => observer.disconnect();\n }\n\n // Original single-line truncation logic\n let cancellationToken = { cancelled: false };\n\n const calculateTruncatedString = () => {\n if (cancellationToken) cancellationToken.cancelled = true;\n\n const requestCancellationToken = { cancelled: false };\n cancellationToken = requestCancellationToken;\n\n const truncated = getMiddleTruncatedString(text, \"\\u2026\", container);\n\n if (requestCancellationToken.cancelled) return;\n\n setTruncatedText(truncated);\n };\n\n if (position == \"middle\") {\n window.document.fonts?.ready?.then(calculateTruncatedString);\n }\n\n if (position == \"end\") {\n setTruncatedText(text);\n }\n\n const observer = new ResizeObserver(() => {\n if (position == \"middle\")\n window.requestAnimationFrame(calculateTruncatedString);\n if (position == \"end\") {\n const isOverflowing = container.scrollWidth > container.clientWidth;\n if (isOverflowing) {\n setIsTruncated(true);\n }\n }\n });\n\n observer.observe(container);\n\n return () => {\n cancellationToken.cancelled = true;\n observer.disconnect();\n };\n }, [text, position, lines]);\n\n return (\n <span\n ref={containerRef}\n style={getContainerStyles()}\n className={clsx(\n lines === 1 ? cls(\"truncate\") : cls(\"truncate-multiline\"),\n position === \"middle\" ? cls(\"truncate-middle\") : cls(\"truncate-end\"),\n className\n )}\n title={isTruncated ? text : undefined}\n {...rest}\n >\n {text === truncatedText ? text : <span>{truncatedText}</span>}\n </span>\n );\n};\n"],"names":["Truncate","children","position","lines","className","style","rest","cls","useCls","containerRef","useRef","isTruncated","setIsTruncated","useState","truncatedText","setTruncatedText","text","getContainerStyles","useCallback","useLayoutEffect","container","calculateLines","parent","styles","fontSize","lineHeight","parentStyles","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","availableHeight","maxLines","clone","_b","_a","observer","checkIfTruncated","_d","_c","cancellationToken","calculateTruncatedString","requestCancellationToken","truncated","getMiddleTruncatedString","_f","_e","jsx","clsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"component.js","sources":["../../../src/components/truncate/component.tsx"],"sourcesContent":["\"use client\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport { clsx, useCls } from \"../utils\";\nimport { getMiddleTruncatedString } from \"./helpers\";\n\nimport \"./style.css\";\n\nexport type TruncatePosition = \"middle\" | \"end\";\n\nexport type Props = {\n text: string;\n} & React.CSSProperties;\n\nexport interface TruncateProps\n extends Omit<React.ComponentPropsWithoutRef<\"span\">, \"title\"> {\n /** Text content to be truncated */\n children: string;\n /** Where to truncate the text: start, middle, or end */\n position?: TruncatePosition;\n /** Number of lines to display before truncating (default: 1, 'auto' to fit parent height) */\n lines?: number | \"auto\";\n}\n\nexport const Truncate: React.FC<TruncateProps> = ({\n children,\n position = \"end\",\n lines = 1,\n className,\n style,\n ...rest\n}) => {\n const cls = useCls();\n const containerRef = useRef<HTMLElement>(null);\n const [isTruncated, setIsTruncated] = useState(false);\n const [truncatedText, setTruncatedText] = useState(children);\n\n const text = children;\n\n // Get appropriate container styles based on position and lines\n const getContainerStyles = useCallback(() => {\n // For explicit line numbers or single line\n if (lines !== \"auto\") {\n return {\n ...style,\n ...(lines > 1 ? { \"--ds-line-clamp\": lines } : {}),\n } as React.CSSProperties;\n }\n\n // For auto line calculation, we'll let the useLayoutEffect handle it\n return {\n ...style,\n // Set a temporary high value to ensure it fits the parent\n \"--ds-line-clamp\": 999,\n } as React.CSSProperties;\n }, [lines, style]);\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n // Handle auto-height calculation\n if (lines === \"auto\") {\n setTruncatedText(text);\n\n const calculateLines = () => {\n // Get the parent element's height\n const parent = container.parentElement;\n if (!parent) return;\n\n // Calculate the font size and line height\n const styles = window.getComputedStyle(container);\n const fontSize = parseFloat(styles.fontSize);\n const lineHeight =\n styles.lineHeight === \"normal\"\n ? fontSize * 1.2 // Approximate for \"normal\"\n : parseFloat(styles.lineHeight);\n\n // Get parent's padding and border to subtract from available height\n const parentStyles = window.getComputedStyle(parent);\n const paddingTop = parseFloat(parentStyles.paddingTop) || 0;\n const paddingBottom = parseFloat(parentStyles.paddingBottom) || 0;\n const borderTopWidth = parseFloat(parentStyles.borderTopWidth) || 0;\n const borderBottomWidth =\n parseFloat(parentStyles.borderBottomWidth) || 0;\n\n // Calculate how many lines can fit in the available space\n const parentHeight = parent.clientHeight;\n const availableHeight =\n parentHeight -\n paddingTop -\n paddingBottom -\n borderTopWidth -\n borderBottomWidth;\n const maxLines = Math.max(1, Math.floor(availableHeight / lineHeight));\n\n // Apply the calculated line-clamp\n if (container) {\n container.style.setProperty(\"--ds-line-clamp\", String(maxLines));\n }\n\n // Check if the text is truncated\n const clone = document.createElement(\"span\");\n clone.style.visibility = \"hidden\";\n clone.style.position = \"absolute\";\n clone.style.width = `${container.clientWidth}px`;\n clone.style.fontSize = styles.fontSize;\n clone.style.fontFamily = styles.fontFamily;\n clone.style.lineHeight = styles.lineHeight;\n clone.textContent = text;\n document.body.appendChild(clone);\n\n const isTruncated = clone.scrollHeight > availableHeight;\n document.body.removeChild(clone);\n\n setIsTruncated(isTruncated);\n };\n\n window.document.fonts?.ready?.then(calculateLines);\n const observer = new ResizeObserver(() => {\n window.requestAnimationFrame(calculateLines);\n });\n\n observer.observe(container);\n if (container.parentElement) {\n observer.observe(container.parentElement);\n }\n\n return () => observer.disconnect();\n }\n\n // Skip custom truncation logic for multi-line mode\n if (typeof lines === \"number\" && lines > 1) {\n setTruncatedText(text);\n // Check if text is truncated by comparing heights\n const checkIfTruncated = () => {\n const clone = document.createElement(\"span\");\n clone.style.visibility = \"hidden\";\n clone.style.position = \"absolute\";\n clone.style.width = `${container.clientWidth}px`;\n clone.textContent = text;\n document.body.appendChild(clone);\n const isTruncated =\n clone.scrollHeight >\n (container.clientHeight || container.offsetHeight);\n document.body.removeChild(clone);\n setIsTruncated(isTruncated);\n };\n\n window.document.fonts?.ready?.then(checkIfTruncated);\n const observer = new ResizeObserver(() => {\n window.requestAnimationFrame(checkIfTruncated);\n });\n\n observer.observe(container);\n return () => observer.disconnect();\n }\n\n // Original single-line truncation logic\n let cancellationToken = { cancelled: false };\n\n const calculateTruncatedString = () => {\n if (cancellationToken) cancellationToken.cancelled = true;\n\n const requestCancellationToken = { cancelled: false };\n cancellationToken = requestCancellationToken;\n\n const truncated = getMiddleTruncatedString(text, \"\\u2026\", container);\n\n if (requestCancellationToken.cancelled) return;\n\n setTruncatedText(truncated);\n };\n\n if (position == \"middle\") {\n window.document.fonts?.ready?.then(calculateTruncatedString);\n }\n\n if (position == \"end\") {\n setTruncatedText(text);\n }\n\n const observer = new ResizeObserver(() => {\n if (position == \"middle\")\n window.requestAnimationFrame(calculateTruncatedString);\n if (position == \"end\") {\n const isOverflowing = container.scrollWidth > container.clientWidth;\n if (isOverflowing) {\n setIsTruncated(true);\n }\n }\n });\n\n observer.observe(container);\n\n return () => {\n cancellationToken.cancelled = true;\n observer.disconnect();\n };\n }, [text, position, lines]);\n\n return (\n <span\n ref={containerRef}\n style={getContainerStyles()}\n className={clsx(\n lines === 1 ? cls(\"truncate\") : cls(\"truncate-multiline\"),\n position === \"middle\" ? cls(\"truncate-middle\") : cls(\"truncate-end\"),\n className\n )}\n title={isTruncated ? text : undefined}\n {...rest}\n >\n {text === truncatedText ? text : <span>{truncatedText}</span>}\n </span>\n );\n};\n"],"names":["Truncate","children","position","lines","className","style","rest","cls","useCls","containerRef","useRef","isTruncated","setIsTruncated","useState","truncatedText","setTruncatedText","text","getContainerStyles","useCallback","useLayoutEffect","container","calculateLines","parent","styles","fontSize","lineHeight","parentStyles","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","availableHeight","maxLines","clone","_b","_a","observer","checkIfTruncated","_d","_c","cancellationToken","calculateTruncatedString","requestCancellationToken","truncated","getMiddleTruncatedString","_f","_e","jsx","clsx"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sources":["../../../src/components/
|
|
1
|
+
{"version":3,"file":"helpers.js","sources":["../../../src/components/truncate/helpers.ts"],"sourcesContent":["export const measureText = (container: HTMLElement) => {\n const span = document.createElement(\"span\");\n span.style.opacity = \"0\";\n span.style.position = \"absolute\";\n span.style.top = \"-1000px\";\n span.style.left = \"-1000px\";\n span.style.whiteSpace = \"nowrap\";\n span.style.pointerEvents = \"none\";\n container.appendChild(span);\n\n return {\n measure: (text: string) => {\n span.innerText = text;\n return span.clientWidth;\n },\n destroy: () => {\n container.removeChild(span);\n },\n };\n};\n\nexport const getMiddleTruncatedString = (\n text: string,\n ellipsis: string,\n container: HTMLElement\n): string => {\n if (!text) return text;\n\n const { measure: getTextWidth, destroy: destroyMeasure } =\n measureText(container);\n\n const textWidth = getTextWidth(text);\n const containerWidth = container.clientWidth;\n const initialOffset = Math.floor((containerWidth / textWidth) * text.length);\n\n if (textWidth <= containerWidth) {\n destroyMeasure();\n return text;\n }\n\n let offset = initialOffset;\n const attempts: Record<number, [number, string]> = {};\n const maxAttempts = 20;\n const buffer = 10;\n\n while (Object.values(attempts).length <= maxAttempts) {\n // If we have already tried this offset, stop\n if (attempts[offset]) break;\n\n // If we are at the beginning of the string, just return the ellipsis\n if (offset <= 1) {\n attempts[0] = [0, ellipsis];\n break;\n }\n\n const start = text\n .slice(0, Math.ceil((offset - ellipsis.length) / 2 - 1))\n .trimEnd();\n const end = text\n .slice(Math.floor((offset - ellipsis.length) / 2) - offset)\n .trimStart();\n const truncatedStr = start + ellipsis + end;\n const width = getTextWidth(truncatedStr);\n\n attempts[offset] = [width, truncatedStr];\n\n if (width >= containerWidth) {\n offset = offset - 2;\n } else {\n // If we are close to the container width, stop\n if (containerWidth - width < buffer) break;\n offset = offset + 2;\n }\n }\n\n // Remove the span element used for measuring text\n destroyMeasure();\n\n // Find the closest attempt that is smaller than the container width\n return (\n Object.values(attempts)\n .reverse()\n .find(([width]) => width < containerWidth)?.[1] ??\n Object.values(attempts)[0][1]\n );\n};\n"],"names":["measureText","container","span","text","getMiddleTruncatedString","ellipsis","_a","getTextWidth","destroyMeasure","textWidth","containerWidth","initialOffset","offset","attempts","maxAttempts","buffer","start","end","truncatedStr","width"],"mappings":"AAAa,MAAAA,IAAc,CAACC,MAA2B;AAC/C,QAAAC,IAAO,SAAS,cAAc,MAAM;AAC1C,SAAAA,EAAK,MAAM,UAAU,KACrBA,EAAK,MAAM,WAAW,YACtBA,EAAK,MAAM,MAAM,WACjBA,EAAK,MAAM,OAAO,WAClBA,EAAK,MAAM,aAAa,UACxBA,EAAK,MAAM,gBAAgB,QAC3BD,EAAU,YAAYC,CAAI,GAEnB;AAAA,IACL,SAAS,CAACC,OACRD,EAAK,YAAYC,GACVD,EAAK;AAAA,IAEd,SAAS,MAAM;AACb,MAAAD,EAAU,YAAYC,CAAI;AAAA,IAAA;AAAA,EAE9B;AACF,GAEaE,IAA2B,CACtCD,GACAE,GACAJ,MACW;AAzBA,MAAAK;AA0BP,MAAA,CAACH,EAAa,QAAAA;AAElB,QAAM,EAAE,SAASI,GAAc,SAASC,EAAe,IACrDR,EAAYC,CAAS,GAEjBQ,IAAYF,EAAaJ,CAAI,GAC7BO,IAAiBT,EAAU,aAC3BU,IAAgB,KAAK,MAAOD,IAAiBD,IAAaN,EAAK,MAAM;AAE3E,MAAIM,KAAaC;AACA,WAAAF,EAAA,GACRL;AAGT,MAAIS,IAASD;AACb,QAAME,IAA6C,CAAC,GAC9CC,IAAc,IACdC,IAAS;AAEf,SAAO,OAAO,OAAOF,CAAQ,EAAE,UAAUC,KAEnC,CAAAD,EAASD,CAAM,KAFiC;AAKpD,QAAIA,KAAU,GAAG;AACf,MAAAC,EAAS,CAAC,IAAI,CAAC,GAAGR,CAAQ;AAC1B;AAAA,IAAA;AAGF,UAAMW,IAAQb,EACX,MAAM,GAAG,KAAK,MAAMS,IAASP,EAAS,UAAU,IAAI,CAAC,CAAC,EACtD,QAAQ,GACLY,IAAMd,EACT,MAAM,KAAK,OAAOS,IAASP,EAAS,UAAU,CAAC,IAAIO,CAAM,EACzD,UAAU,GACPM,IAAeF,IAAQX,IAAWY,GAClCE,IAAQZ,EAAaW,CAAY;AAIvC,QAFAL,EAASD,CAAM,IAAI,CAACO,GAAOD,CAAY,GAEnCC,KAAST;AACX,MAAAE,IAASA,IAAS;AAAA,SACb;AAED,UAAAF,IAAiBS,IAAQJ,EAAQ;AACrC,MAAAH,IAASA,IAAS;AAAA,IAAA;AAAA,EACpB;AAIa,SAAAJ,EAAA,KAIbF,IAAA,OAAO,OAAOO,CAAQ,EACnB,UACA,KAAK,CAAC,CAACM,CAAK,MAAMA,IAAQT,CAAc,MAF3C,gBAAAJ,EAE+C,OAC/C,OAAO,OAAOO,CAAQ,EAAE,CAAC,EAAE,CAAC;AAEhC;"}
|
|
@@ -6,7 +6,7 @@ import { Dragger as d } from "./dragger.js";
|
|
|
6
6
|
import { useUploadItemRender as a } from "./hooks.js";
|
|
7
7
|
import { UploadItem as f } from "./item.js";
|
|
8
8
|
import './style.css';/* empty css */
|
|
9
|
-
import { Button as u } from "../
|
|
9
|
+
import { Button as u } from "../button/component.js";
|
|
10
10
|
import { useCls as U } from "../utils/antdUtils.js";
|
|
11
11
|
import { clsx as g } from "../utils/cn.js";
|
|
12
12
|
const h = ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","sources":["../../../src/components/
|
|
1
|
+
{"version":3,"file":"component.js","sources":["../../../src/components/upload/component.tsx"],"sourcesContent":["\"use client\";\nimport {\n default as AntUpload,\n type UploadFile as AntUploadFile,\n type UploadProps as AntUploadProps,\n type RcFile,\n type UploadChangeParam,\n} from \"antd/es/upload\";\nimport { Button } from \"..\";\nimport { CloudArrowUp } from \"@bioturing/assets\";\nimport { clsx, useCls } from \"../utils\";\nimport { Dragger } from \"./dragger\";\nimport { useUploadItemRender } from \"./hooks\";\nimport { UploadItem } from \"./item\";\n\n// Import component-specific styles\nimport \"./style.css\";\n\n// Re-export UploadFile and other types for consumers\nexport type UploadFile = AntUploadFile;\nexport type { RcFile, UploadChangeParam };\n\nexport type { UploadItemProps, UploadFileStatus } from \"./item\";\n\n// Define props interface extending Ant Design's UploadProps\nexport interface UploadProps extends AntUploadProps {\n /**\n * Show remove button for uploaded files\n * @default true\n */\n showRemoveButton?: boolean;\n // /**\n // * Show file list\n // * @default true\n // */\n // showFileList?: boolean;\n // /**\n // * Custom icon\n // */\n // icon?: React.ReactNode;\n}\n\n// Default icons for file types\nexport const DefaultUpload = ({\n // icon = <CloudArrowUp size={24} />,\n showRemoveButton = true,\n // showFileList = true,\n className,\n fileList,\n children,\n ...restProps\n}: UploadProps) => {\n const cls = useCls();\n const icon = <CloudArrowUp size={24} />;\n\n // Default children if none provided\n const defaultChildren = (\n <Button icon={icon} type=\"default\">\n Upload Files\n </Button>\n );\n const itemRender = useUploadItemRender({ showRemoveButton });\n\n return (\n <AntUpload\n className={clsx(cls(\"upload\"), className)}\n {...restProps}\n fileList={fileList}\n itemRender={itemRender}\n >\n {children || defaultChildren}\n </AntUpload>\n );\n};\n\nexport const Upload = Object.assign(DefaultUpload, {\n // Dragger,\n Dragger: Dragger,\n Item: UploadItem,\n});\n"],"names":["DefaultUpload","showRemoveButton","className","fileList","children","restProps","cls","useCls","defaultChildren","jsx","Button","CloudArrowUp","itemRender","useUploadItemRender","AntUpload","clsx","Upload","Dragger","UploadItem"],"mappings":";;;;;;;;;;;AA2CO,MAAMA,IAAgB,CAAC;AAAA;AAAA,EAE5B,kBAAAC,IAAmB;AAAA;AAAA,EAEnB,WAAAC;AAAA,EACA,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,GAAGC;AACL,MAAmB;AACjB,QAAMC,IAAMC,EAAO,GAIbC,IACH,gBAAAC,EAAAC,GAAA,EAAO,MAJG,gBAAAD,EAACE,GAAa,EAAA,MAAM,GAAI,CAAA,GAIf,MAAK,WAAU,UAEnC,gBAAA,GAEIC,IAAaC,EAAoB,EAAE,kBAAAZ,GAAkB;AAGzD,SAAA,gBAAAQ;AAAA,IAACK;AAAA,IAAA;AAAA,MACC,WAAWC,EAAKT,EAAI,QAAQ,GAAGJ,CAAS;AAAA,MACvC,GAAGG;AAAA,MACJ,UAAAF;AAAA,MACA,YAAAS;AAAA,MAEC,UAAYR,KAAAI;AAAA,IAAA;AAAA,EACf;AAEJ,GAEaQ,IAAS,OAAO,OAAOhB,GAAe;AAAA;AAAA,EAEjD,SAAAiB;AAAA,EACA,MAAMC;AACR,CAAC;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dragger.js","sources":["../../../src/components/
|
|
1
|
+
{"version":3,"file":"dragger.js","sources":["../../../src/components/upload/dragger.tsx"],"sourcesContent":["\"use client\";\nimport {\n default as AntUpload,\n type DraggerProps as AntDraggerProps,\n} from \"antd/es/upload\";\nimport React from \"react\";\nimport { CloudArrowUp } from \"@bioturing/assets\";\nimport { useCls } from \"../utils\";\nimport { useUploadItemRender } from \"./hooks\";\n\nexport interface DraggerProps extends AntDraggerProps {\n /**\n * Custom title for the upload component\n */\n uploadTitle?: React.ReactNode;\n /**\n * Custom description for the upload component\n **/\n uploadDescription?: React.ReactNode;\n}\n\nexport const Dragger = ({\n children,\n uploadTitle = \"Click or drag file to this area to upload\",\n uploadDescription = \"Support for a single or bulk upload.\",\n itemRender,\n ...rest\n}: DraggerProps) => {\n const cls = useCls();\n const renderChildren = () => {\n return (\n <>\n <p className={cls(\"upload-drag-icon\")}>\n <CloudArrowUp size={40} />\n </p>\n <p className={cls(\"upload-text\")}>{uploadTitle}</p>\n <p className={cls(\"upload-hint\")}>{uploadDescription}</p>\n </>\n );\n };\n const defaultItemRender = useUploadItemRender({ showRemoveButton: true });\n return (\n <AntUpload.Dragger itemRender={itemRender || defaultItemRender} {...rest}>\n {children ? children : renderChildren()}\n </AntUpload.Dragger>\n );\n};\n"],"names":["Dragger","children","uploadTitle","uploadDescription","itemRender","rest","cls","useCls","renderChildren","jsxs","Fragment","jsx","CloudArrowUp","defaultItemRender","useUploadItemRender","AntUpload"],"mappings":";;;;;;AAqBO,MAAMA,IAAU,CAAC;AAAA,EACtB,UAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,mBAAAC,IAAoB;AAAA,EACpB,YAAAC;AAAA,EACA,GAAGC;AACL,MAAoB;AAClB,QAAMC,IAAMC,EAAO,GACbC,IAAiB,MAGjB,gBAAAC,EAAAC,GAAA,EAAA,UAAA;AAAA,IAAC,gBAAAC,EAAA,KAAA,EAAE,WAAWL,EAAI,kBAAkB,GAClC,UAAC,gBAAAK,EAAAC,GAAA,EAAa,MAAM,GAAA,CAAI,EAC1B,CAAA;AAAA,sBACC,KAAE,EAAA,WAAWN,EAAI,aAAa,GAAI,UAAYJ,GAAA;AAAA,sBAC9C,KAAE,EAAA,WAAWI,EAAI,aAAa,GAAI,UAAkBH,EAAA,CAAA;AAAA,EAAA,GACvD,GAGEU,IAAoBC,EAAoB,EAAE,kBAAkB,IAAM;AACxE,SACG,gBAAAH,EAAAI,EAAU,SAAV,EAAkB,YAAYX,KAAcS,GAAoB,GAAGR,GACjE,UAAAJ,KAAsBO,EACzB,EAAA,CAAA;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sources":["../../../src/components/
|
|
1
|
+
{"version":3,"file":"hooks.js","sources":["../../../src/components/upload/hooks.tsx"],"sourcesContent":["\"use client\";\nimport { type UploadProps } from \"antd/es/upload\";\nimport { useCallback } from \"react\";\nimport { UploadItem } from \"./item\";\n\nexport type UseUploadItemRenderProps = {\n showRemoveButton?: boolean;\n};\n\nexport const useUploadItemRender: (\n props: UseUploadItemRenderProps\n) => UploadProps[\"itemRender\"] = ({ showRemoveButton = true }) => {\n // If showFileList is false, don't render anything\n // if (!showFileList) return null;\n\n // Custom rendering of file items\n const itemRender: UploadProps[\"itemRender\"] = (\n _originNode,\n file,\n _fileList,\n actions\n ) => {\n return (\n <UploadItem\n fileName={file.name}\n fileType={file.type}\n status={file.status}\n percent={file.percent}\n removable={showRemoveButton}\n onRemove={() => actions.remove()}\n />\n );\n };\n return useCallback(itemRender, [showRemoveButton]);\n};\n"],"names":["useUploadItemRender","showRemoveButton","useCallback","_originNode","file","_fileList","actions","jsx","UploadItem"],"mappings":";;;;AASO,MAAMA,IAEoB,CAAC,EAAE,kBAAAC,IAAmB,SAsB9CC,EAjBuC,CAC5CC,GACAC,GACAC,GACAC,MAGE,gBAAAC;AAAA,EAACC;AAAA,EAAA;AAAA,IACC,UAAUJ,EAAK;AAAA,IACf,UAAUA,EAAK;AAAA,IACf,QAAQA,EAAK;AAAA,IACb,SAASA,EAAK;AAAA,IACd,WAAWH;AAAA,IACX,UAAU,MAAMK,EAAQ,OAAO;AAAA,EAAA;AACjC,GAG2B,CAACL,CAAgB,CAAC;"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as e, jsxs as i } from "react/jsx-runtime";
|
|
2
3
|
import n from "antd/es/flex";
|
|
3
|
-
import
|
|
4
|
-
import { Trash as
|
|
5
|
-
import { Truncate as f } from "../
|
|
4
|
+
import u from "antd/es/progress";
|
|
5
|
+
import { Trash as g } from "@bioturing/assets";
|
|
6
|
+
import { Truncate as f } from "../truncate/component.js";
|
|
6
7
|
import { getUploadFileIcon as h } from "./utils.js";
|
|
7
8
|
import { useCls as x } from "../utils/antdUtils.js";
|
|
8
9
|
import { clsx as N } from "../utils/cn.js";
|
|
9
|
-
import { IconButton as v } from "../
|
|
10
|
+
import { IconButton as v } from "../icon-button/component.js";
|
|
10
11
|
const U = ({
|
|
11
12
|
fileName: t,
|
|
12
13
|
fileType: s,
|
|
@@ -49,7 +50,7 @@ const U = ({
|
|
|
49
50
|
children: [
|
|
50
51
|
/* @__PURE__ */ e(f, { position: "middle", children: t }),
|
|
51
52
|
/* @__PURE__ */ e(
|
|
52
|
-
|
|
53
|
+
u,
|
|
53
54
|
{
|
|
54
55
|
percent: d,
|
|
55
56
|
size: "small",
|
|
@@ -66,7 +67,7 @@ const U = ({
|
|
|
66
67
|
v,
|
|
67
68
|
{
|
|
68
69
|
label: "Remove",
|
|
69
|
-
children: /* @__PURE__ */ e(
|
|
70
|
+
children: /* @__PURE__ */ e(g, { size: 16 }),
|
|
70
71
|
onClick: c,
|
|
71
72
|
size: "small"
|
|
72
73
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item.js","sources":["../../../src/components/upload/item.tsx"],"sourcesContent":["\"use client\";\nimport Flex from \"antd/es/flex\";\nimport Progress from \"antd/es/progress\";\nimport { type ProgressProps } from \"antd/es/progress\";\nimport { Trash } from \"@bioturing/assets\";\nimport { IconButton } from \"../icon-button\";\nimport { Truncate } from \"../truncate/component\";\nimport { clsx, useCls } from \"../utils\";\nimport { getUploadFileIcon } from \"./utils\";\n\nexport type UploadFileStatus =\n | \"error\"\n | \"done\"\n | \"uploading\"\n | \"removed\"\n | \"pending\";\n\nexport interface UploadItemProps {\n fileName: string;\n fileType?: string;\n status?: UploadFileStatus;\n percent?: number;\n removable?: boolean;\n onRemove?: () => void;\n extraActions?: React.ReactNode;\n}\n\nexport const UploadItem = ({\n fileName,\n fileType,\n status = \"pending\",\n percent,\n removable = true,\n onRemove,\n extraActions,\n}: UploadItemProps) => {\n const cls = useCls();\n const showPercent = Math.round(percent || 0);\n const statusWithProgress: Record<UploadFileStatus, ProgressProps[\"status\"]> =\n {\n done: \"success\",\n error: \"exception\",\n uploading: \"active\",\n removed: \"normal\",\n pending: \"normal\",\n };\n return (\n <Flex\n className={clsx(cls(\"upload-item\"))}\n justify=\"space-between\"\n align=\"center\"\n data-error={status === \"error\"}\n >\n <Flex\n align=\"center\"\n gap={16}\n flex={1}\n className={cls(\"upload-item-content\")}\n >\n <span className={cls(\"upload-item-icon\")}>\n {getUploadFileIcon(fileType)}\n </span>\n <Flex\n align=\"start\"\n vertical\n flex={1}\n className={cls(\"upload-item-name-progress\")}\n >\n <Truncate position=\"middle\">{fileName}</Truncate>\n <Progress\n percent={showPercent}\n size=\"small\"\n className={cls(\"upload-item-progress\")}\n status={\n status && status in statusWithProgress\n ? statusWithProgress[status]\n : \"normal\"\n }\n />\n </Flex>\n <Flex gap={8} align=\"center\">\n {extraActions}\n {removable && (\n <IconButton\n label=\"Remove\"\n children={<Trash size={16} />}\n onClick={onRemove}\n size=\"small\"\n />\n )}\n </Flex>\n </Flex>\n </Flex>\n );\n};\n"],"names":["UploadItem","fileName","fileType","status","percent","removable","onRemove","extraActions","cls","useCls","showPercent","statusWithProgress","jsx","Flex","clsx","jsxs","getUploadFileIcon","Truncate","Progress","IconButton","Trash"],"mappings":";;;;;;;;;;AA2BO,MAAMA,IAAa,CAAC;AAAA,EACzB,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,QAAAC,IAAS;AAAA,EACT,SAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,UAAAC;AAAA,EACA,cAAAC;AACF,MAAuB;AACrB,QAAMC,IAAMC,EAAO,GACbC,IAAc,KAAK,MAAMN,KAAW,CAAC,GACrCO,IACJ;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AAEA,SAAA,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,WAAWC,EAAKN,EAAI,aAAa,CAAC;AAAA,MAClC,SAAQ;AAAA,MACR,OAAM;AAAA,MACN,cAAYL,MAAW;AAAA,MAEvB,UAAA,gBAAAY;AAAA,QAACF;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,KAAK;AAAA,UACL,MAAM;AAAA,UACN,WAAWL,EAAI,qBAAqB;AAAA,UAEpC,UAAA;AAAA,YAAA,gBAAAI,EAAC,UAAK,WAAWJ,EAAI,kBAAkB,GACpC,UAAAQ,EAAkBd,CAAQ,GAC7B;AAAA,YACA,gBAAAa;AAAA,cAACF;AAAA,cAAA;AAAA,gBACC,OAAM;AAAA,gBACN,UAAQ;AAAA,gBACR,MAAM;AAAA,gBACN,WAAWL,EAAI,2BAA2B;AAAA,gBAE1C,UAAA;AAAA,kBAAC,gBAAAI,EAAAK,GAAA,EAAS,UAAS,UAAU,UAAShB,GAAA;AAAA,kBACtC,gBAAAW;AAAA,oBAACM;AAAA,oBAAA;AAAA,sBACC,SAASR;AAAA,sBACT,MAAK;AAAA,sBACL,WAAWF,EAAI,sBAAsB;AAAA,sBACrC,QACEL,KAAUA,KAAUQ,IAChBA,EAAmBR,CAAM,IACzB;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAER;AAAA,cAAA;AAAA,YACF;AAAA,YACC,gBAAAY,EAAAF,GAAA,EAAK,KAAK,GAAG,OAAM,UACjB,UAAA;AAAA,cAAAN;AAAA,cACAF,KACC,gBAAAO;AAAA,gBAACO;AAAA,gBAAA;AAAA,kBACC,OAAM;AAAA,kBACN,UAAU,gBAAAP,EAACQ,GAAM,EAAA,MAAM,GAAI,CAAA;AAAA,kBAC3B,SAASd;AAAA,kBACT,MAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,YACP,EAEJ,CAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACF;AAAA,EACF;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/components/
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/components/upload/utils.tsx"],"sourcesContent":["import { File, Folder } from \"@bioturing/assets\";\n\nexport const getUploadFileIcon = (fileType?: string) => {\n return fileType === \"folder\" ? (\n <Folder size={20} weight=\"fill\" />\n ) : (\n <File size={20} weight=\"fill\" />\n );\n};\n"],"names":["getUploadFileIcon","fileType","jsx","Folder","File"],"mappings":";;AAEa,MAAAA,IAAoB,CAACC,MACzBA,MAAa,WACjB,gBAAAC,EAAAC,GAAA,EAAO,MAAM,IAAI,QAAO,OAAO,CAAA,IAE/B,gBAAAD,EAAAE,GAAA,EAAK,MAAM,IAAI,QAAO,QAAO;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as m } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as p } from "react";
|
|
3
|
+
import { useRender as s } from "@base-ui-components/react/use-render";
|
|
4
|
+
const i = (e, r) => {
|
|
5
|
+
const { render: n, as: o = "div", ...t } = e;
|
|
6
|
+
return s({
|
|
7
|
+
render: n || ((d) => /* @__PURE__ */ m(o, { ...d })),
|
|
8
|
+
props: t,
|
|
9
|
+
ref: r
|
|
10
|
+
});
|
|
11
|
+
}, h = p(i);
|
|
12
|
+
export {
|
|
13
|
+
h as WithRenderProp
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=WithRenderProp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WithRenderProp.js","sources":["../../../src/components/utils/WithRenderProp.tsx"],"sourcesContent":["import React, { forwardRef, JSX } from \"react\";\nimport { useRender } from \"@base-ui-components/react/use-render\";\n\n// Utility type to map a tag name to its DOM element type\ntype ElementTypeToDOMType<T extends React.ElementType> =\n T extends keyof JSX.IntrinsicElements\n ? JSX.IntrinsicElements[T] extends React.DetailedHTMLProps<\n infer Props,\n infer Element\n >\n ? Element\n : never\n : never;\n\nexport type WithRenderPropProps<T extends React.ElementType = \"div\"> =\n React.ComponentPropsWithoutRef<T> & {\n render?: useRender.RenderProp;\n as?: T;\n };\n\nconst WithRenderPropInner = <T extends React.ElementType = \"div\">(\n props: WithRenderPropProps<T>,\n ref: React.ForwardedRef<T>\n) => {\n const { render, as: Tag = \"div\", ...etc } = props;\n const renderedElement = useRender({\n render: render || ((props) => <Tag {...props} />),\n props: etc,\n ref: ref as unknown as React.Ref<ElementTypeToDOMType<T>>,\n });\n return renderedElement;\n};\n\nexport const WithRenderProp = forwardRef(WithRenderPropInner) as <\n T extends React.ElementType = \"div\"\n>(\n props: WithRenderPropProps<T> & { ref?: React.Ref<ElementTypeToDOMType<T>> }\n) => ReturnType<typeof WithRenderPropInner>;\n"],"names":["WithRenderPropInner","props","ref","render","Tag","etc","useRender","jsx","WithRenderProp","forwardRef"],"mappings":";;;AAoBA,MAAMA,IAAsB,CAC1BC,GACAC,MACG;AACH,QAAM,EAAE,QAAAC,GAAQ,IAAIC,IAAM,OAAO,GAAGC,MAAQJ;AAMrC,SALiBK,EAAU;AAAA,IAChC,QAAQH,MAAW,CAACF,MAAW,gBAAAM,EAAAH,GAAA,EAAK,GAAGH,EAAO,CAAA;AAAA,IAC9C,OAAOI;AAAA,IACP,KAAAH;AAAA,EAAA,CACD;AAEH,GAEaM,IAAiBC,EAAWT,CAAmB;"}
|
package/dist/components/{VerticalCollapsiblePanel → vertical-collapsible-panel}/component.js
RENAMED
|
@@ -4,13 +4,13 @@ import { useState as I, useRef as g, useEffect as j } from "react";
|
|
|
4
4
|
import { Collapsible as n } from "@base-ui-components/react";
|
|
5
5
|
import { MinusCircle as M, PlusCircle as R } from "@bioturing/assets";
|
|
6
6
|
import { useControlledState as S } from "../hooks/useControlledState.js";
|
|
7
|
-
import { Truncate as A } from "../Truncate/component.js";
|
|
8
7
|
import './style.css';/* empty css */
|
|
9
|
-
import { Transition as
|
|
10
|
-
import { useCls as
|
|
11
|
-
import { useAnimationsFinished as
|
|
8
|
+
import { Transition as A } from "../transition/component.js";
|
|
9
|
+
import { useCls as E } from "../utils/antdUtils.js";
|
|
10
|
+
import { useAnimationsFinished as T } from "../hooks/base-ui.js";
|
|
12
11
|
import { clsx as a } from "../utils/cn.js";
|
|
13
|
-
import {
|
|
12
|
+
import { Truncate as V } from "../truncate/component.js";
|
|
13
|
+
import { IconButton as f } from "../icon-button/component.js";
|
|
14
14
|
const X = ({
|
|
15
15
|
children: h,
|
|
16
16
|
title: i,
|
|
@@ -27,11 +27,11 @@ const X = ({
|
|
|
27
27
|
useTitleAsTrigger: c = !0,
|
|
28
28
|
keepMounted: w = !1
|
|
29
29
|
}) => {
|
|
30
|
-
const e =
|
|
30
|
+
const e = E(), [s, t] = S(
|
|
31
31
|
u,
|
|
32
32
|
N,
|
|
33
33
|
b
|
|
34
|
-
), [k, B] = I(s), m = g(null), d =
|
|
34
|
+
), [k, B] = I(s), m = g(null), d = T(m, {
|
|
35
35
|
waitForNextTick: s
|
|
36
36
|
});
|
|
37
37
|
return j(() => {
|
|
@@ -63,7 +63,7 @@ const X = ({
|
|
|
63
63
|
style: c ? {
|
|
64
64
|
cursor: "pointer"
|
|
65
65
|
} : {},
|
|
66
|
-
children: typeof i == "string" ? /* @__PURE__ */ l(
|
|
66
|
+
children: typeof i == "string" ? /* @__PURE__ */ l(V, { children: i }) : i
|
|
67
67
|
}
|
|
68
68
|
),
|
|
69
69
|
/* @__PURE__ */ r("div", { className: e("collapsible-panel-header-actions"), children: [
|
|
@@ -108,7 +108,7 @@ const X = ({
|
|
|
108
108
|
} : {},
|
|
109
109
|
keepMounted: w,
|
|
110
110
|
children: /* @__PURE__ */ l(
|
|
111
|
-
|
|
111
|
+
A,
|
|
112
112
|
{
|
|
113
113
|
show: k,
|
|
114
114
|
className: a(e("collapsible-panel-body"), v),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.js","sources":["../../../src/components/vertical-collapsible-panel/component.tsx"],"sourcesContent":["\"use client\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { Collapsible } from \"@base-ui-components/react\";\nimport { MinusCircle, PlusCircle } from \"@bioturing/assets\";\nimport { useCls, clsx } from \"../utils\";\nimport { useControlledState } from \"../hooks/useControlledState\";\nimport { Transition } from \"../transition\";\nimport { useAnimationsFinished } from \"../hooks\";\nimport { IconButton } from \"../icon-button\";\nimport { Truncate } from \"../truncate\";\n\n// Import component-specific styles\nimport \"./style.css\";\n\nexport interface VerticalCollapsiblePanelProps {\n /**\n * The content of the panel that will be toggled\n */\n children: React.ReactNode;\n /**\n * The header of the panel\n */\n title?: React.ReactNode;\n /**\n * Indicate if the title should be used as a trigger\n * @default true\n */\n useTitleAsTrigger?: boolean;\n /**\n * Custom Content Padding\n * @default \"24px\"\n */\n contentPadding?: number | string | boolean;\n /**\n * Add more content below the title\n * Only show when panel is open\n */\n afterTitle?: React.ReactNode;\n\n /**\n * Whether the panel is expanded by default\n */\n defaultOpen?: boolean;\n /**\n * Control the open state (makes the component controlled)\n */\n open?: boolean;\n /**\n * Callback when the open state changes\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * Additional class name for the component\n */\n className?: string;\n /**\n * Addtional class name for the header\n */\n headerClassName?: string;\n /**\n * Addtional class name for the header\n */\n headerInnerClassName?: string;\n /**\n * Addtional class name for the body\n * */\n bodyClassName?: string;\n /**\n * Actions to be displayed in the header\n * Only show when panel is open\n */\n actions?: React.ReactNode;\n /**\n * Keeping it as mounted, just hide the content\n */\n keepMounted?: boolean;\n}\n\nexport const VerticalCollapsiblePanel: React.FC<\n VerticalCollapsiblePanelProps\n> = ({\n children,\n title,\n defaultOpen = false,\n open: controlledOpen,\n onOpenChange,\n className,\n headerClassName,\n headerInnerClassName,\n bodyClassName,\n contentPadding = \"16px\",\n afterTitle,\n actions,\n useTitleAsTrigger = true,\n keepMounted = false,\n}) => {\n const cls = useCls();\n // Use useControlledState for open state\n const [isOpen, setIsOpen] = useControlledState(\n controlledOpen,\n onOpenChange,\n defaultOpen\n );\n const [isBodyOpen, setIsBodyOpen] = useState(isOpen);\n const ref = useRef<HTMLDivElement>(null);\n const runOnceAnimationsFinish = useAnimationsFinished(ref, {\n waitForNextTick: isOpen,\n });\n useEffect(() => {\n runOnceAnimationsFinish(() => {\n setIsBodyOpen(isOpen);\n });\n }, [isOpen, runOnceAnimationsFinish]);\n return (\n <Collapsible.Root\n className={clsx(cls(\"collapsible-panel\"), className)}\n open={isOpen}\n onOpenChange={setIsOpen}\n ref={ref}\n >\n <div className={clsx(cls(\"collapsible-panel-header\"), headerClassName)}>\n <div\n className={clsx(\n cls(\"collapsible-panel-header-inner\"),\n headerInnerClassName\n )}\n >\n <div\n className={cls(\"collapsible-panel-header-text\")}\n onClick={\n useTitleAsTrigger ? () => setIsOpen((open) => !open) : undefined\n }\n style={\n useTitleAsTrigger\n ? {\n cursor: \"pointer\",\n }\n : {}\n }\n >\n {typeof title == \"string\" ? <Truncate>{title}</Truncate> : title}\n </div>\n <div className={cls(\"collapsible-panel-header-actions\")}>\n {isOpen && actions}\n <Collapsible.Trigger\n className={cls(\"collapsible-panel-trigger\")}\n render={\n isOpen ? (\n <IconButton>\n <MinusCircle\n weight=\"bold\"\n className={clsx(\n cls(\"collapsible-panel-caret\"),\n isOpen && cls(\"collapsible-panel-caret-open\")\n )}\n />\n </IconButton>\n ) : (\n <IconButton>\n <PlusCircle\n weight=\"bold\"\n className={clsx(\n cls(\"collapsible-panel-caret\"),\n isOpen && cls(\"collapsible-panel-caret-open\")\n )}\n />\n </IconButton>\n )\n }\n ></Collapsible.Trigger>\n </div>\n </div>\n {isOpen && afterTitle && (\n <div className={cls(\"collapsible-panel-header-after\")}>\n {afterTitle}\n </div>\n )}\n </div>\n <Collapsible.Panel\n className={cls(\"collapsible-panel-content\")}\n style={\n (typeof contentPadding != \"undefined\"\n ? {\n \"--ds-content-padding\":\n contentPadding === false || contentPadding === 0\n ? \"0\"\n : typeof contentPadding == \"number\"\n ? `${contentPadding}px`\n : contentPadding,\n }\n : {}) as React.CSSProperties\n }\n keepMounted={keepMounted}\n >\n <Transition\n show={isBodyOpen}\n className={clsx(cls(\"collapsible-panel-body\"), bodyClassName)}\n keepMounted\n >\n <div>{children}</div>\n </Transition>\n </Collapsible.Panel>\n </Collapsible.Root>\n );\n};\n"],"names":["VerticalCollapsiblePanel","children","title","defaultOpen","controlledOpen","onOpenChange","className","headerClassName","headerInnerClassName","bodyClassName","contentPadding","afterTitle","actions","useTitleAsTrigger","keepMounted","cls","useCls","isOpen","setIsOpen","useControlledState","isBodyOpen","setIsBodyOpen","useState","ref","useRef","runOnceAnimationsFinish","useAnimationsFinished","useEffect","jsxs","Collapsible","clsx","jsx","open","Truncate","IconButton","MinusCircle","PlusCircle","Transition"],"mappings":"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"}
|