@bioturing/components 0.37.1 → 0.38.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/hooks/useResizable.d.ts +50 -0
- package/dist/components/hooks/useResizable.d.ts.map +1 -0
- package/dist/components/hooks/useResizable.js +148 -0
- package/dist/components/hooks/useResizable.js.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/popup-panel/component.d.ts.map +1 -1
- package/dist/components/popup-panel/component.js +119 -112
- package/dist/components/popup-panel/component.js.map +1 -1
- package/dist/components/popup-panel/utils.d.ts +10 -0
- package/dist/components/popup-panel/utils.d.ts.map +1 -0
- package/dist/components/popup-panel/utils.js +13 -0
- package/dist/components/popup-panel/utils.js.map +1 -0
- package/dist/components/resizable/component.d.ts +2 -8
- package/dist/components/resizable/component.d.ts.map +1 -1
- package/dist/components/resizable/component.js +250 -248
- package/dist/components/resizable/component.js.map +1 -1
- package/dist/components/window-portal/component.d.ts +24 -0
- package/dist/components/window-portal/component.d.ts.map +1 -0
- package/dist/components/window-portal/component.js +120 -0
- package/dist/components/window-portal/component.js.map +1 -0
- package/dist/components/window-portal/index.d.ts +3 -0
- package/dist/components/window-portal/index.d.ts.map +1 -0
- package/dist/components/window-portal/types.d.ts +77 -0
- package/dist/components/window-portal/types.d.ts.map +1 -0
- package/dist/index.js +81 -79
- package/dist/index.js.map +1 -1
- package/dist/metadata.d.ts +8 -0
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +18 -0
- package/dist/metadata.js.map +1 -1
- package/dist/stats.html +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","sources":["../../../src/components/resizable/component.tsx"],"sourcesContent":["\"use client\";\nimport React, { useCallback, useEffect, useState, isValidElement } from \"react\";\nimport {\n useResizable,\n type MoveValues,\n ResizableProps as UseResizableProps,\n} from \"react-use-resizable\";\nimport mergeRefs from \"merge-refs\";\nimport {\n useCls,\n clsx,\n WithRenderProp,\n WithRenderPropProps,\n cn,\n getReactElementProp,\n} from \"../utils\";\nimport { mergeProps } from \"@base-ui-components/react\";\n\nimport \"./style.css\";\nimport { on } from \"node:stream\";\n\nexport interface ResizableProps\n extends Omit<WithRenderPropProps, keyof UseResizableProps>,\n UseResizableProps {\n /**\n * Single React element child that will be enhanced with resize handles\n */\n children: React.ReactNode;\n /**\n * Whether the component should be resizable\n * @default false\n */\n resizable?: boolean;\n /**\n * Configure which resize handles to show\n * @default { bottom: true, right: true, left: true, top: true }\n */\n handles?: {\n bottom?: boolean;\n right?: boolean;\n left?: boolean;\n top?: boolean;\n };\n /**\n * Whether to use absolute positioning for left handle resizing\n * Set to true when used in absolutely positioned containers like PopupPanel\n * @default false\n */\n absolutePositioning?: boolean;\n /**\n * Custom class names for different parts of the resizable component\n */\n classNames?: {\n root?: string;\n resizeHandle?: string;\n };\n /**\n * Key to reset dimensions to current element size\n * When this value changes, the component will recalculate its dimensions\n * Similar to React's key prop pattern for forcing component resets\n */\n resetKey?: React.Key;\n /**\n * Maximum width the component can be resized to\n */\n maxWidth?: number;\n /**\n * Maximum height the component can be resized to\n */\n maxHeight?: number;\n /**\n * Minimum width the component can be resized to\n */\n minWidth?: number;\n /**\n * Minimum height the component can be resized to\n */\n minHeight?: number;\n /**\n * Callback fired during resize operations\n */\n onResize?: (values: MoveValues) => void;\n /**\n * Whether to maintain aspect ratio during resize\n * @default false\n */\n maintainAspectRatio?: boolean;\n}\n\nexport const Resizable = ({\n children,\n resizable = false,\n handles = { bottom: true, right: true, left: true, top: true },\n absolutePositioning = false,\n classNames,\n className: containerClassName,\n style: containerStyle,\n resetKey,\n\n // Use Resizable Props\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n lockHorizontal,\n lockVertical,\n onResize,\n onDragEnd: onDragEndProp,\n onDragStart: onDragStartProp,\n disabled,\n maintainAspectRatio = false,\n interval,\n initialHeight: initialHeightProp,\n initialWidth: initialWidthProp,\n // other With Render Props\n ...rest\n}: ResizableProps) => {\n // Validate that children is a single React element\n // if (!isValidElement(children)) {\n // throw new Error(\n // \"Resizable component expects a single React element as children\"\n // );\n // }\n\n const cls = useCls();\n const [panelRef, setPanelRef] = useState<HTMLDivElement | null>(null);\n const [width, setWidth] = useState<number>();\n const [height, setHeight] = useState<number>();\n const [resizing, setResizing] = useState(false);\n\n const callbackRef = useCallback(\n (node: HTMLDivElement) => {\n setPanelRef(node);\n\n // Get initial dimensions only once when ref is set\n // For aspect ratio maintenance, we need initial dimensions immediately\n // Otherwise, preserve natural width/height behavior\n if (node && !width && !height) {\n const rect = node.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) {\n if (maintainAspectRatio) {\n // Need dimensions for aspect ratio calculation\n setWidth(rect.width);\n setHeight(rect.height);\n }\n // For non-aspect-ratio cases, don't set dimensions to preserve natural behavior\n }\n }\n },\n [width, height, maintainAspectRatio],\n );\n\n // Reset dimensions when resetKey changes\n useEffect(() => {\n if (resetKey !== undefined && panelRef) {\n // Clear the hook's inline styles to reset to natural size\n panelRef.style.width = \"\";\n panelRef.style.height = \"\";\n\n // Force a reflow to get natural dimensions\n const rect = panelRef.getBoundingClientRect();\n\n if (rect.width > 0 && rect.height > 0) {\n if (maintainAspectRatio) {\n // For aspect ratio maintenance, re-measure and set dimensions\n setWidth(rect.width);\n setHeight(rect.height);\n } else {\n // Reset state to allow natural dimensions again\n setWidth(undefined);\n setHeight(undefined);\n }\n\n // Don't apply any explicit dimensions - let them remain natural\n // panelRef.style.width = `${rect.width}px`;\n // panelRef.style.height = `${rect.height}px`;\n }\n }\n }, [resetKey, panelRef, maintainAspectRatio]);\n\n // Initialize useResizable with current dimensions (or undefined if not ready)\n // For aspect ratio maintenance, we need initial dimensions\n // Otherwise, preserve natural width/height behavior until user starts resizing\n const resizableHook = useResizable({\n initialWidth: maintainAspectRatio ? width : initialWidthProp,\n initialHeight: maintainAspectRatio ? height : initialHeightProp,\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n lockHorizontal,\n lockVertical,\n onResize,\n disabled,\n maintainAspectRatio,\n interval,\n onDragStart: (values) => {\n setResizing(true);\n // Capture natural dimensions when user starts resizing\n if (panelRef) {\n const rect = panelRef.getBoundingClientRect();\n if (rect.width > 0 && !width) {\n setWidth(rect.width);\n }\n if (rect.height > 0 && !height) {\n setHeight(rect.height);\n }\n }\n if (onDragStartProp) onDragStartProp(values);\n },\n onDragEnd: (values) => {\n setResizing(false);\n if (onDragEndProp) onDragEndProp(values);\n },\n });\n\n const isChildrenValidElement = isValidElement(children);\n\n useEffect(() => {\n if (resizing) {\n document.body.style.userSelect = \"none\";\n } else {\n document.body.style.userSelect = \"\";\n }\n }, [resizing]);\n\n // Get resizable props - useResizable hook handles cases where dimensions aren't ready\n const { ref: rootRefProp, ...rootPropsWithoutRef } =\n resizableHook.getRootProps();\n const getHandleProps = resizableHook.getHandleProps;\n const rootRef = resizableHook.rootRef;\n\n // Handle reverse handle change for horizontal resizing (only for absolute positioning)\n const onReverseHandleChangeHorizontal = (\n parent: React.RefObject<HTMLDivElement>,\n values: MoveValues,\n ) => {\n if (!parent.current || !absolutePositioning) return;\n const { widthDiff } = values;\n parent.current.style.left = `${\n parseInt(parent.current.style.left || \"0\") - widthDiff\n }px`;\n };\n\n // Handle reverse handle change for vertical resizing (only for absolute positioning)\n const onReverseHandleChangeVertical = (\n parent: React.RefObject<HTMLDivElement>,\n values: MoveValues,\n ) => {\n if (!parent.current || !absolutePositioning) return;\n const { heightDiff } = values;\n parent.current.style.top = `${\n parseInt(parent.current.style.top || \"0\") - heightDiff\n }px`;\n };\n\n const resizeHandles = resizable\n ? [\n handles.top && !maintainAspectRatio && (\n <div\n key=\"top\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle,\n )}\n data-placement=\"top-center\"\n {...getHandleProps({\n reverse: true,\n lockHorizontal: true,\n onResize: (values) =>\n onReverseHandleChangeVertical(rootRef, values),\n })}\n />\n ),\n handles.bottom && !maintainAspectRatio && (\n <div\n key=\"bottom\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle,\n )}\n data-placement=\"bottom-left\"\n {...getHandleProps({\n lockHorizontal: true,\n })}\n />\n ),\n handles.left && !maintainAspectRatio && (\n <div\n key=\"left\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle,\n )}\n data-placement=\"top-left\"\n {...getHandleProps({\n reverse: true,\n lockVertical: true,\n onResize: (values) =>\n onReverseHandleChangeHorizontal(rootRef, values),\n })}\n />\n ),\n handles.right && !maintainAspectRatio && (\n <div\n key=\"right\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle,\n )}\n data-placement=\"top-right\"\n {...getHandleProps({\n lockVertical: true,\n })}\n />\n ),\n // For aspect ratio maintenance, add corner handles that can resize both dimensions\n handles.right && handles.bottom && (\n <div\n key=\"bottom-right-corner\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle,\n )}\n data-placement=\"bottom-right-corner\"\n {...getHandleProps({\n // No locks - allow both horizontal and vertical resizing\n })}\n />\n ),\n maintainAspectRatio && handles.left && handles.bottom && (\n <div\n key=\"bottom-left-corner\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle,\n )}\n data-placement=\"bottom-left-corner\"\n {...getHandleProps({\n reverse: true,\n onResize: (values) =>\n onReverseHandleChangeHorizontal(rootRef, values),\n })}\n />\n ),\n maintainAspectRatio && handles.right && handles.top && (\n <div\n key=\"top-right-corner\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle,\n )}\n data-placement=\"top-right-corner\"\n {...getHandleProps({\n reverse: true,\n onResize: (values) =>\n onReverseHandleChangeVertical(rootRef, values),\n })}\n />\n ),\n handles.left && handles.top && (\n <div\n key=\"top-left-corner\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle,\n )}\n data-placement=\"top-left-corner\"\n {...getHandleProps({\n reverse: true,\n onResize: (values) => {\n onReverseHandleChangeHorizontal(rootRef, values);\n onReverseHandleChangeVertical(rootRef, values);\n },\n })}\n />\n ),\n ]\n : [];\n\n const childElement = children as React.ReactElement & {\n ref?: React.Ref<HTMLDivElement>;\n };\n\n const childElementProps = {\n className: getReactElementProp<string>(childElement, \"className\"),\n style: getReactElementProp<React.CSSProperties>(childElement, \"style\"),\n children: getReactElementProp<React.ReactNode>(childElement, \"children\"),\n ref: childElement.ref,\n };\n\n const childProps = {\n className: cn(\n resizable && cls(\"resizable\"),\n classNames?.root,\n childElementProps.className,\n containerClassName,\n ),\n ref: mergeRefs(\n resizable ? rootRefProp : undefined,\n callbackRef, // Always need this for dimension measurement\n childElement?.ref,\n ),\n style: { ...childElementProps.style, ...containerStyle },\n ...(resizing ? { \"data-resizing\": true } : {}),\n ...(resizable ? { \"data-resizable\": true } : {}),\n children: isChildrenValidElement\n ? [\n ...(Array.isArray(childElementProps.children)\n ? childElementProps.children\n : [childElementProps.children]),\n ...resizeHandles.filter(Boolean),\n ]\n : children,\n };\n\n return (\n <WithRenderProp\n render={(props) => {\n // Merge the props from WithRenderProp with our childProps\n const mergedProps = mergeProps(\n props,\n childProps,\n resizable ? rootPropsWithoutRef : {},\n );\n if (isChildrenValidElement) {\n return React.cloneElement(childElement, mergedProps);\n } else {\n return <div {...mergedProps}>{children}</div>;\n }\n }}\n {...rest}\n />\n );\n};\n"],"names":["Resizable","children","resizable","handles","absolutePositioning","classNames","containerClassName","containerStyle","resetKey","maxHeight","maxWidth","minHeight","minWidth","lockHorizontal","lockVertical","onResize","onDragEndProp","onDragStartProp","disabled","maintainAspectRatio","interval","initialHeightProp","initialWidthProp","rest","cls","useCls","panelRef","setPanelRef","useState","width","setWidth","height","setHeight","resizing","setResizing","callbackRef","useCallback","node","rect","useEffect","resizableHook","useResizable","values","isChildrenValidElement","isValidElement","rootRefProp","rootPropsWithoutRef","getHandleProps","rootRef","onReverseHandleChangeHorizontal","parent","widthDiff","onReverseHandleChangeVertical","heightDiff","resizeHandles","jsx","clsx","childElement","childElementProps","getReactElementProp","childProps","cn","mergeRefs","WithRenderProp","props","mergedProps","mergeProps","React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"component.js","sources":["../../../src/components/resizable/component.tsx"],"sourcesContent":["\"use client\";\nimport React, {\n useCallback,\n useEffect,\n useState,\n isValidElement,\n forwardRef,\n} from \"react\";\nimport {\n useResizable,\n type MoveValues,\n ResizableProps as UseResizableProps,\n} from \"../hooks/useResizable\";\nimport mergeRefs from \"merge-refs\";\nimport {\n useCls,\n clsx,\n WithRenderProp,\n WithRenderPropProps,\n cn,\n getReactElementProp,\n} from \"../utils\";\nimport { mergeProps } from \"@base-ui-components/react\";\n\nimport \"./style.css\";\n// import { on } from \"node:stream\";\n\nexport interface ResizableProps\n extends Omit<WithRenderPropProps, keyof UseResizableProps>,\n UseResizableProps {\n /**\n * Single React element child that will be enhanced with resize handles\n */\n children: React.ReactNode;\n /**\n * Whether the component should be resizable\n * @default false\n */\n resizable?: boolean;\n /**\n * Configure which resize handles to show\n * @default { bottom: true, right: true, left: true, top: true }\n */\n handles?: {\n bottom?: boolean;\n right?: boolean;\n left?: boolean;\n top?: boolean;\n };\n // /**\n // * Whether to use absolute positioning for left handle resizing\n // * Set to true when used in absolutely positioned containers like PopupPanel\n // * @default false\n // */\n // absolutePositioning?: boolean;\n /**\n * Custom class names for different parts of the resizable component\n */\n classNames?: {\n root?: string;\n resizeHandle?: string;\n };\n /**\n * Key to reset dimensions to current element size\n * When this value changes, the component will recalculate its dimensions\n * Similar to React's key prop pattern for forcing component resets\n */\n resetKey?: React.Key;\n /**\n * Maximum width the component can be resized to\n */\n maxWidth?: number;\n /**\n * Maximum height the component can be resized to\n */\n maxHeight?: number;\n /**\n * Minimum width the component can be resized to\n */\n minWidth?: number;\n /**\n * Minimum height the component can be resized to\n */\n minHeight?: number;\n /**\n * Callback fired during resize operations\n */\n onResize?: (values: MoveValues) => void;\n /**\n * Whether to maintain aspect ratio during resize\n * @default false\n */\n maintainAspectRatio?: boolean;\n}\n\nexport const Resizable = forwardRef<HTMLDivElement, ResizableProps>(\n (\n {\n children,\n resizable = false,\n handles = { bottom: true, right: true, left: true, top: true },\n classNames,\n className: containerClassName,\n style: containerStyle,\n resetKey,\n\n // Use Resizable Props\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n lockHorizontal,\n lockVertical,\n onResize,\n onDragEnd: onDragEndProp,\n onDragStart: onDragStartProp,\n disabled,\n maintainAspectRatio = false,\n interval,\n initialHeight: initialHeightProp,\n initialWidth: initialWidthProp,\n // other With Render Props\n ...rest\n },\n ref\n ) => {\n // Validate that children is a single React element\n // if (!isValidElement(children)) {\n // throw new Error(\n // \"Resizable component expects a single React element as children\"\n // );\n // }\n\n const cls = useCls();\n const [panelRef, setPanelRef] = useState<HTMLDivElement | null>(null);\n const [width, setWidth] = useState<number>();\n const [height, setHeight] = useState<number>();\n const [resizing, setResizing] = useState(false);\n\n const callbackRef = useCallback(\n (node: HTMLDivElement) => {\n setPanelRef(node);\n\n // Get initial dimensions only once when ref is set\n // For aspect ratio maintenance, we need initial dimensions immediately\n // Otherwise, preserve natural width/height behavior\n if (node && !width && !height) {\n const rect = node.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) {\n if (maintainAspectRatio) {\n // Need dimensions for aspect ratio calculation\n setWidth(rect.width);\n setHeight(rect.height);\n }\n // For non-aspect-ratio cases, don't set dimensions to preserve natural behavior\n }\n }\n },\n [width, height, maintainAspectRatio]\n );\n\n // Reset dimensions when resetKey changes\n useEffect(() => {\n if (resetKey !== undefined && panelRef) {\n // Clear the hook's inline styles to reset to natural size\n panelRef.style.width = \"\";\n panelRef.style.height = \"\";\n\n // Force a reflow to get natural dimensions\n const rect = panelRef.getBoundingClientRect();\n\n if (rect.width > 0 && rect.height > 0) {\n if (maintainAspectRatio) {\n // For aspect ratio maintenance, re-measure and set dimensions\n setWidth(rect.width);\n setHeight(rect.height);\n } else {\n // Reset state to allow natural dimensions again\n setWidth(undefined);\n setHeight(undefined);\n }\n\n // Don't apply any explicit dimensions - let them remain natural\n // panelRef.style.width = `${rect.width}px`;\n // panelRef.style.height = `${rect.height}px`;\n }\n }\n }, [resetKey, panelRef, maintainAspectRatio]);\n\n // Initialize useResizable with current dimensions (or undefined if not ready)\n // For aspect ratio maintenance, we need initial dimensions\n // Otherwise, preserve natural width/height behavior until user starts resizing\n const resizableHook = useResizable({\n initialWidth: maintainAspectRatio ? width : initialWidthProp,\n initialHeight: maintainAspectRatio ? height : initialHeightProp,\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n lockHorizontal,\n lockVertical,\n onResize,\n disabled,\n maintainAspectRatio,\n interval,\n onDragStart: (values) => {\n setResizing(true);\n // Capture natural dimensions when user starts resizing\n if (panelRef) {\n const rect = panelRef.getBoundingClientRect();\n if (rect.width > 0 && !width) {\n setWidth(rect.width);\n }\n if (rect.height > 0 && !height) {\n setHeight(rect.height);\n }\n }\n if (onDragStartProp) onDragStartProp(values);\n },\n onDragEnd: (values) => {\n setResizing(false);\n if (onDragEndProp) onDragEndProp(values);\n },\n });\n\n const isChildrenValidElement = isValidElement(children);\n\n useEffect(() => {\n if (resizing) {\n document.body.style.userSelect = \"none\";\n } else {\n document.body.style.userSelect = \"\";\n }\n }, [resizing]);\n\n // Get resizable props - useResizable hook handles cases where dimensions aren't ready\n const { ref: rootRefProp, ...rootPropsWithoutRef } =\n resizableHook.getRootProps();\n const getHandleProps = resizableHook.getHandleProps;\n\n // // Handle reverse handle change for horizontal resizing (only for absolute positioning)\n // const onReverseHandleChangeHorizontal = (\n // parent: React.RefObject<HTMLDivElement>,\n // values: MoveValues\n // ) => {\n // if (!parent.current || !absolutePositioning) return;\n // const { widthDiff } = values;\n // parent.current.style.left = `${\n // parseInt(parent.current.style.left || \"0\") - widthDiff\n // }px`;\n // };\n\n // // Handle reverse handle change for vertical resizing (only for absolute positioning)\n // const onReverseHandleChangeVertical = (\n // parent: React.RefObject<HTMLDivElement>,\n // values: MoveValues\n // ) => {\n // if (!parent.current || !absolutePositioning) return;\n // const { heightDiff } = values;\n // console.log({\n // parentStyleTop: parent.current.style.top,\n // computedStyleTop: window.getComputedStyle(parent.current).top,\n // });\n // parent.current.style.top = `${\n // parseInt(parent.current.style.top || \"0\") - heightDiff\n // }px`;\n // };\n\n const resizeHandles = resizable\n ? [\n handles.top && !maintainAspectRatio && (\n <div\n key=\"top\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle\n )}\n data-placement=\"top-center\"\n {...getHandleProps({\n reverse: true,\n lockHorizontal: true,\n // onResize: (values) =>\n // onReverseHandleChangeVertical(rootRef, values),\n })}\n />\n ),\n handles.bottom && !maintainAspectRatio && (\n <div\n key=\"bottom\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle\n )}\n data-placement=\"bottom-left\"\n {...getHandleProps({\n lockHorizontal: true,\n })}\n />\n ),\n handles.left && !maintainAspectRatio && (\n <div\n key=\"left\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle\n )}\n data-placement=\"top-left\"\n {...getHandleProps({\n reverse: true,\n lockVertical: true,\n // onResize: (values) =>\n // onReverseHandleChangeHorizontal(rootRef, values),\n })}\n />\n ),\n handles.right && !maintainAspectRatio && (\n <div\n key=\"right\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle\n )}\n data-placement=\"top-right\"\n {...getHandleProps({\n lockVertical: true,\n })}\n />\n ),\n handles.right && handles.bottom && (\n <div\n key=\"bottom-right-corner\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle\n )}\n data-placement=\"bottom-right-corner\"\n {...getHandleProps({\n // No locks - allow both horizontal and vertical resizing\n corner: \"bottom-right\",\n })}\n />\n ),\n handles.left && handles.top && (\n <div\n key=\"top-left-corner\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle\n )}\n data-placement=\"top-left-corner\"\n {...getHandleProps({\n corner: \"top-left\",\n // onResize: (values) => {\n // onReverseHandleChangeHorizontal(rootRef, values);\n // onReverseHandleChangeVertical(rootRef, values);\n // },\n })}\n />\n ),\n handles.right && handles.top && (\n <div\n key=\"top-right-corner\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle\n )}\n data-placement=\"top-right-corner\"\n {...getHandleProps({\n corner: \"top-right\",\n // onResize: (values) => {\n // onReverseHandleChangeVertical(rootRef, values);\n // },\n })}\n />\n ),\n handles.left && handles.bottom && (\n <div\n key=\"bottom-left-corner\"\n className={clsx(\n cls(\"resizable-resize-handle\"),\n classNames?.resizeHandle\n )}\n data-placement=\"bottom-left-corner\"\n {...getHandleProps({\n corner: \"bottom-left\",\n // onResize: (values) => {\n // onReverseHandleChangeHorizontal(rootRef, values);\n // onReverseHandleChangeVertical(rootRef, values);\n // },\n })}\n />\n ),\n ]\n : [];\n\n const childElement = children as React.ReactElement & {\n ref?: React.Ref<HTMLDivElement>;\n };\n\n const childElementProps = {\n className: getReactElementProp<string>(childElement, \"className\"),\n style: getReactElementProp<React.CSSProperties>(childElement, \"style\"),\n children: getReactElementProp<React.ReactNode>(childElement, \"children\"),\n ref: childElement.ref,\n };\n\n const childProps = {\n className: cn(\n resizable && cls(\"resizable\"),\n classNames?.root,\n childElementProps.className,\n containerClassName\n ),\n ref: mergeRefs(\n resizable ? rootRefProp : undefined,\n callbackRef, // Always need this for dimension measurement\n childElement?.ref,\n ref\n ),\n style: { ...childElementProps.style, ...containerStyle },\n ...(resizing ? { \"data-resizing\": true } : {}),\n ...(resizable ? { \"data-resizable\": true } : {}),\n children: isChildrenValidElement\n ? [\n ...(Array.isArray(childElementProps.children)\n ? childElementProps.children\n : [childElementProps.children]),\n ...resizeHandles.filter(Boolean),\n ]\n : children,\n };\n\n return (\n <WithRenderProp\n render={(props) => {\n // Merge the props from WithRenderProp with our childProps\n const mergedProps = mergeProps(\n props,\n childProps,\n resizable ? rootPropsWithoutRef : {}\n );\n if (isChildrenValidElement) {\n return React.cloneElement(childElement, mergedProps);\n } else {\n return <div {...mergedProps}>{children}</div>;\n }\n }}\n {...rest}\n />\n );\n }\n);\n"],"names":["Resizable","forwardRef","children","resizable","handles","classNames","containerClassName","containerStyle","resetKey","maxHeight","maxWidth","minHeight","minWidth","lockHorizontal","lockVertical","onResize","onDragEndProp","onDragStartProp","disabled","maintainAspectRatio","interval","initialHeightProp","initialWidthProp","rest","ref","cls","useCls","panelRef","setPanelRef","useState","width","setWidth","height","setHeight","resizing","setResizing","callbackRef","useCallback","node","rect","useEffect","resizableHook","useResizable","values","isChildrenValidElement","isValidElement","rootRefProp","rootPropsWithoutRef","getHandleProps","resizeHandles","jsx","clsx","childElement","childElementProps","getReactElementProp","childProps","cn","mergeRefs","WithRenderProp","props","mergedProps","mergeProps","React"],"mappings":";;;;;;;;;;;AA+FO,MAAMA,KAAYC;AAAA,EACvB,CACE;AAAA,IACE,UAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,SAAAC,IAAU,EAAE,QAAQ,IAAM,OAAO,IAAM,MAAM,IAAM,KAAK,GAAA;AAAA,IACxD,YAAAC;AAAA,IACA,WAAWC;AAAA,IACX,OAAOC;AAAA,IACP,UAAAC;AAAA;AAAA,IAGA,WAAAC;AAAA,IACA,UAAAC;AAAA,IACA,WAAAC;AAAA,IACA,UAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,cAAAC;AAAA,IACA,UAAAC;AAAA,IACA,WAAWC;AAAA,IACX,aAAaC;AAAA,IACb,UAAAC;AAAA,IACA,qBAAAC,IAAsB;AAAA,IACtB,UAAAC;AAAA,IACA,eAAeC;AAAA,IACf,cAAcC;AAAA;AAAA,IAEd,GAAGC;AAAA,EAAA,GAELC,MACG;AAQH,UAAMC,IAAMC,GAAA,GACN,CAACC,GAAUC,CAAW,IAAIC,EAAgC,IAAI,GAC9D,CAACC,GAAOC,CAAQ,IAAIF,EAAA,GACpB,CAACG,GAAQC,CAAS,IAAIJ,EAAA,GACtB,CAACK,GAAUC,CAAW,IAAIN,EAAS,EAAK,GAExCO,IAAcC;AAAA,MAClB,CAACC,MAAyB;AAMxB,YALAV,EAAYU,CAAI,GAKZA,KAAQ,CAACR,KAAS,CAACE,GAAQ;AAC7B,gBAAMO,IAAOD,EAAK,sBAAA;AAClB,UAAIC,EAAK,QAAQ,KAAKA,EAAK,SAAS,KAC9BpB,MAEFY,EAASQ,EAAK,KAAK,GACnBN,EAAUM,EAAK,MAAM;AAAA,QAI3B;AAAA,MACF;AAAA,MACA,CAACT,GAAOE,GAAQb,CAAmB;AAAA,IAAA;AAIrC,IAAAqB,EAAU,MAAM;AACd,UAAIhC,MAAa,UAAamB,GAAU;AAEtC,QAAAA,EAAS,MAAM,QAAQ,IACvBA,EAAS,MAAM,SAAS;AAGxB,cAAMY,IAAOZ,EAAS,sBAAA;AAEtB,QAAIY,EAAK,QAAQ,KAAKA,EAAK,SAAS,MAC9BpB,KAEFY,EAASQ,EAAK,KAAK,GACnBN,EAAUM,EAAK,MAAM,MAGrBR,EAAS,MAAS,GAClBE,EAAU,MAAS;AAAA,MAOzB;AAAA,IACF,GAAG,CAACzB,GAAUmB,GAAUR,CAAmB,CAAC;AAK5C,UAAMsB,IAAgBC,EAAa;AAAA,MACjC,cAAcvB,IAAsBW,IAAQR;AAAA,MAC5C,eAAeH,IAAsBa,IAASX;AAAA,MAC9C,WAAAZ;AAAA,MACA,UAAAC;AAAA,MACA,WAAAC;AAAA,MACA,UAAAC;AAAA,MACA,gBAAAC;AAAA,MACA,cAAAC;AAAA,MACA,UAAAC;AAAA,MACA,UAAAG;AAAA,MACA,qBAAAC;AAAA,MACA,UAAAC;AAAA,MACA,aAAa,CAACuB,MAAW;AAGvB,YAFAR,EAAY,EAAI,GAEZR,GAAU;AACZ,gBAAMY,IAAOZ,EAAS,sBAAA;AACtB,UAAIY,EAAK,QAAQ,KAAK,CAACT,KACrBC,EAASQ,EAAK,KAAK,GAEjBA,EAAK,SAAS,KAAK,CAACP,KACtBC,EAAUM,EAAK,MAAM;AAAA,QAEzB;AACA,QAAItB,OAAiC0B,CAAM;AAAA,MAC7C;AAAA,MACA,WAAW,CAACA,MAAW;AACrB,QAAAR,EAAY,EAAK,GACbnB,OAA6B2B,CAAM;AAAA,MACzC;AAAA,IAAA,CACD,GAEKC,IAAyBC,EAAe3C,CAAQ;AAEtD,IAAAsC,EAAU,MAAM;AACd,MAAIN,IACF,SAAS,KAAK,MAAM,aAAa,SAEjC,SAAS,KAAK,MAAM,aAAa;AAAA,IAErC,GAAG,CAACA,CAAQ,CAAC;AAGb,UAAM,EAAE,KAAKY,GAAa,GAAGC,EAAA,IAC3BN,EAAc,aAAA,GACVO,IAAiBP,EAAc,gBA8B/BQ,IAAgB9C,IAClB;AAAA,MACEC,EAAQ,OAAO,CAACe,KACd,gBAAA+B;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWC;AAAA,YACT1B,EAAI,yBAAyB;AAAA,YAC7BpB,GAAY;AAAA,UAAA;AAAA,UAEd,kBAAe;AAAA,UACd,GAAG2C,EAAe;AAAA,YACjB,SAAS;AAAA,YACT,gBAAgB;AAAA;AAAA;AAAA,UAAA,CAGjB;AAAA,QAAA;AAAA,QAXG;AAAA,MAAA;AAAA,MAcR5C,EAAQ,UAAU,CAACe,KACjB,gBAAA+B;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWC;AAAA,YACT1B,EAAI,yBAAyB;AAAA,YAC7BpB,GAAY;AAAA,UAAA;AAAA,UAEd,kBAAe;AAAA,UACd,GAAG2C,EAAe;AAAA,YACjB,gBAAgB;AAAA,UAAA,CACjB;AAAA,QAAA;AAAA,QARG;AAAA,MAAA;AAAA,MAWR5C,EAAQ,QAAQ,CAACe,KACf,gBAAA+B;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWC;AAAA,YACT1B,EAAI,yBAAyB;AAAA,YAC7BpB,GAAY;AAAA,UAAA;AAAA,UAEd,kBAAe;AAAA,UACd,GAAG2C,EAAe;AAAA,YACjB,SAAS;AAAA,YACT,cAAc;AAAA;AAAA;AAAA,UAAA,CAGf;AAAA,QAAA;AAAA,QAXG;AAAA,MAAA;AAAA,MAcR5C,EAAQ,SAAS,CAACe,KAChB,gBAAA+B;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWC;AAAA,YACT1B,EAAI,yBAAyB;AAAA,YAC7BpB,GAAY;AAAA,UAAA;AAAA,UAEd,kBAAe;AAAA,UACd,GAAG2C,EAAe;AAAA,YACjB,cAAc;AAAA,UAAA,CACf;AAAA,QAAA;AAAA,QARG;AAAA,MAAA;AAAA,MAWR5C,EAAQ,SAASA,EAAQ,UACvB,gBAAA8C;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWC;AAAA,YACT1B,EAAI,yBAAyB;AAAA,YAC7BpB,GAAY;AAAA,UAAA;AAAA,UAEd,kBAAe;AAAA,UACd,GAAG2C,EAAe;AAAA;AAAA,YAEjB,QAAQ;AAAA,UAAA,CACT;AAAA,QAAA;AAAA,QATG;AAAA,MAAA;AAAA,MAYR5C,EAAQ,QAAQA,EAAQ,OACtB,gBAAA8C;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWC;AAAA,YACT1B,EAAI,yBAAyB;AAAA,YAC7BpB,GAAY;AAAA,UAAA;AAAA,UAEd,kBAAe;AAAA,UACd,GAAG2C,EAAe;AAAA,YACjB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,UAAA,CAKT;AAAA,QAAA;AAAA,QAZG;AAAA,MAAA;AAAA,MAeR5C,EAAQ,SAASA,EAAQ,OACvB,gBAAA8C;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWC;AAAA,YACT1B,EAAI,yBAAyB;AAAA,YAC7BpB,GAAY;AAAA,UAAA;AAAA,UAEd,kBAAe;AAAA,UACd,GAAG2C,EAAe;AAAA,YACjB,QAAQ;AAAA;AAAA;AAAA;AAAA,UAAA,CAIT;AAAA,QAAA;AAAA,QAXG;AAAA,MAAA;AAAA,MAcR5C,EAAQ,QAAQA,EAAQ,UACtB,gBAAA8C;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWC;AAAA,YACT1B,EAAI,yBAAyB;AAAA,YAC7BpB,GAAY;AAAA,UAAA;AAAA,UAEd,kBAAe;AAAA,UACd,GAAG2C,EAAe;AAAA,YACjB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,UAAA,CAKT;AAAA,QAAA;AAAA,QAZG;AAAA,MAAA;AAAA,IAaN,IAGJ,CAAA,GAEEI,IAAelD,GAIfmD,IAAoB;AAAA,MACxB,WAAWC,EAA4BF,GAAc,WAAW;AAAA,MAChE,OAAOE,EAAyCF,GAAc,OAAO;AAAA,MACrE,UAAUE,EAAqCF,GAAc,UAAU;AAAA,IAEzE,GAEMG,IAAa;AAAA,MACjB,WAAWC;AAAA,QACTrD,KAAasB,EAAI,WAAW;AAAA,QAC5BpB,GAAY;AAAA,QACZgD,EAAkB;AAAA,QAClB/C;AAAA,MAAA;AAAA,MAEF,KAAKmD;AAAAA,QACHtD,IAAY2C,IAAc;AAAA,QAC1BV;AAAA;AAAA,QACAgB,GAAc;AAAA,QACd5B;AAAA,MAAA;AAAA,MAEF,OAAO,EAAE,GAAG6B,EAAkB,OAAO,GAAG9C,EAAA;AAAA,MACxC,GAAI2B,IAAW,EAAE,iBAAiB,GAAA,IAAS,CAAA;AAAA,MAC3C,GAAI/B,IAAY,EAAE,kBAAkB,GAAA,IAAS,CAAA;AAAA,MAC7C,UAAUyC,IACN;AAAA,QACE,GAAI,MAAM,QAAQS,EAAkB,QAAQ,IACxCA,EAAkB,WAClB,CAACA,EAAkB,QAAQ;AAAA,QAC/B,GAAGJ,EAAc,OAAO,OAAO;AAAA,MAAA,IAEjC/C;AAAA,IAAA;AAGN,WACE,gBAAAgD;AAAA,MAACQ;AAAA,MAAA;AAAA,QACC,QAAQ,CAACC,MAAU;AAEjB,gBAAMC,IAAcC;AAAA,YAClBF;AAAA,YACAJ;AAAA,YACApD,IAAY4C,IAAsB,CAAA;AAAA,UAAC;AAErC,iBAAIH,IACKkB,EAAM,aAAaV,GAAcQ,CAAW,IAE5C,gBAAAV,EAAC,OAAA,EAAK,GAAGU,GAAc,UAAA1D,EAAA,CAAS;AAAA,QAE3C;AAAA,QACC,GAAGqB;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { WindowPortalProps } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* WindowPortal - Renders content in a separate browser window
|
|
4
|
+
*
|
|
5
|
+
* This component creates a new browser window and renders its children inside it.
|
|
6
|
+
* It automatically copies parent window styles for consistent theming and handles
|
|
7
|
+
* cleanup when the component unmounts or the window is closed.
|
|
8
|
+
*
|
|
9
|
+
* **Performance Note**: Rapid state updates (e.g., text input) may have slight latency
|
|
10
|
+
* due to React reconciliation across different window contexts. This is expected behavior
|
|
11
|
+
* when using portals across window boundaries.
|
|
12
|
+
*
|
|
13
|
+
* **Theme Synchronization**: The component automatically syncs theme changes (light/dark mode)
|
|
14
|
+
* from the parent window to the popup window using a MutationObserver.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <WindowPortal width={800} height={600} title="My Window">
|
|
19
|
+
* <div>Content rendered in separate window</div>
|
|
20
|
+
* </WindowPortal>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function WindowPortal({ children, width, height, left, top, title, copyStyles, onClose, windowFeatures, }: WindowPortalProps): import('react').ReactPortal;
|
|
24
|
+
//# sourceMappingURL=component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../src/components/window-portal/component.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAW,EACX,MAAY,EACZ,IAAU,EACV,GAAS,EACT,KAAU,EACV,UAAiB,EACjB,OAAO,EACP,cAAmB,GACpB,EAAE,iBAAiB,+BAiOnB"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState as C, useRef as g, useCallback as I, useEffect as i } from "react";
|
|
3
|
+
import { createPortal as P } from "react-dom";
|
|
4
|
+
function z({
|
|
5
|
+
children: w,
|
|
6
|
+
width: $ = 600,
|
|
7
|
+
height: N = 400,
|
|
8
|
+
left: W = 200,
|
|
9
|
+
top: k = 200,
|
|
10
|
+
title: d = "",
|
|
11
|
+
copyStyles: f = !0,
|
|
12
|
+
onClose: y,
|
|
13
|
+
windowFeatures: x = {}
|
|
14
|
+
}) {
|
|
15
|
+
const [l, S] = C(null), c = g(null), [h, E] = C(!1), b = I((e) => {
|
|
16
|
+
if (!e || e.closed) return;
|
|
17
|
+
e.document.head.querySelectorAll("style, link[rel='stylesheet']").forEach((o) => o.remove()), Array.from(document.styleSheets).forEach((o) => {
|
|
18
|
+
try {
|
|
19
|
+
if (o.cssRules) {
|
|
20
|
+
const t = e.document.createElement("style");
|
|
21
|
+
Array.from(o.cssRules).forEach((r) => {
|
|
22
|
+
t.appendChild(
|
|
23
|
+
e.document.createTextNode(r.cssText)
|
|
24
|
+
);
|
|
25
|
+
}), e.document.head.appendChild(t);
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
if (o.href) {
|
|
29
|
+
const r = e.document.createElement("link");
|
|
30
|
+
r.rel = "stylesheet", r.href = o.href, e.document.head.appendChild(r);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}), Array.from(document.querySelectorAll("style")).forEach((o) => {
|
|
34
|
+
const t = e.document.createElement("style");
|
|
35
|
+
t.textContent = o.textContent, e.document.head.appendChild(t);
|
|
36
|
+
});
|
|
37
|
+
}, []);
|
|
38
|
+
return i(() => {
|
|
39
|
+
const e = document.createElement("div");
|
|
40
|
+
S(e);
|
|
41
|
+
}, []), i(() => {
|
|
42
|
+
if (!l || c.current && !c.current.closed)
|
|
43
|
+
return;
|
|
44
|
+
const {
|
|
45
|
+
resizable: e = !0,
|
|
46
|
+
scrollbars: u = !0,
|
|
47
|
+
toolbar: o = !1,
|
|
48
|
+
menubar: t = !1,
|
|
49
|
+
location: r = !1,
|
|
50
|
+
status: s = !1
|
|
51
|
+
} = x, m = [
|
|
52
|
+
`width=${$}`,
|
|
53
|
+
`height=${N}`,
|
|
54
|
+
`left=${W}`,
|
|
55
|
+
`top=${k}`,
|
|
56
|
+
`resizable=${e ? "yes" : "no"}`,
|
|
57
|
+
`scrollbars=${u ? "yes" : "no"}`,
|
|
58
|
+
`toolbar=${o ? "yes" : "no"}`,
|
|
59
|
+
`menubar=${t ? "yes" : "no"}`,
|
|
60
|
+
`location=${r ? "yes" : "no"}`,
|
|
61
|
+
`status=${s ? "yes" : "no"}`
|
|
62
|
+
].join(","), n = window.open("", "", m);
|
|
63
|
+
if (!n) {
|
|
64
|
+
console.warn(
|
|
65
|
+
"WindowPortal: Failed to open new window. It may have been blocked by a popup blocker."
|
|
66
|
+
);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (c.current = n, d && (n.document.title = d), f) {
|
|
70
|
+
b(n);
|
|
71
|
+
const v = document.documentElement.className;
|
|
72
|
+
v && (n.document.documentElement.className = v), Array.from(document.documentElement.attributes).forEach((a) => {
|
|
73
|
+
a.name.startsWith("data-") && n.document.documentElement.setAttribute(a.name, a.value);
|
|
74
|
+
});
|
|
75
|
+
const A = document.body.className;
|
|
76
|
+
A && (n.document.body.className = A), Array.from(document.body.attributes).forEach((a) => {
|
|
77
|
+
a.name.startsWith("data-") && n.document.body.setAttribute(a.name, a.value);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
n.document.body.appendChild(l), E(!0);
|
|
81
|
+
const R = () => {
|
|
82
|
+
y && y();
|
|
83
|
+
}, p = setInterval(() => {
|
|
84
|
+
n.closed && (clearInterval(p), R());
|
|
85
|
+
}, 500);
|
|
86
|
+
return () => {
|
|
87
|
+
clearInterval(p), E(!1), n && !n.closed && n.close();
|
|
88
|
+
};
|
|
89
|
+
}, [l]), i(() => {
|
|
90
|
+
c.current && !c.current.closed && (c.current.document.title = d);
|
|
91
|
+
}, [d]), i(() => {
|
|
92
|
+
if (!f || !h || !c.current || c.current.closed)
|
|
93
|
+
return;
|
|
94
|
+
const e = c.current, u = new MutationObserver((t) => {
|
|
95
|
+
t.forEach((r) => {
|
|
96
|
+
if (r.type === "attributes") {
|
|
97
|
+
const s = r.attributeName;
|
|
98
|
+
if (!s) return;
|
|
99
|
+
if (s === "class")
|
|
100
|
+
e.document.documentElement.className = document.documentElement.className, b(e);
|
|
101
|
+
else if (s.startsWith("data-")) {
|
|
102
|
+
const m = document.documentElement.getAttribute(s);
|
|
103
|
+
m !== null ? e.document.documentElement.setAttribute(s, m) : e.document.documentElement.removeAttribute(s);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}), o = Array.from(document.documentElement.attributes).filter((t) => t.name.startsWith("data-")).map((t) => t.name);
|
|
108
|
+
return u.observe(document.documentElement, {
|
|
109
|
+
attributes: !0,
|
|
110
|
+
attributeFilter: ["class", ...o],
|
|
111
|
+
attributeOldValue: !1
|
|
112
|
+
}), () => {
|
|
113
|
+
u.disconnect();
|
|
114
|
+
};
|
|
115
|
+
}, [f, b, h]), l ? P(w, l) : null;
|
|
116
|
+
}
|
|
117
|
+
export {
|
|
118
|
+
z as WindowPortal
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.js","sources":["../../../src/components/window-portal/component.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { WindowPortalProps } from \"./types\";\n\n/**\n * WindowPortal - Renders content in a separate browser window\n *\n * This component creates a new browser window and renders its children inside it.\n * It automatically copies parent window styles for consistent theming and handles\n * cleanup when the component unmounts or the window is closed.\n *\n * **Performance Note**: Rapid state updates (e.g., text input) may have slight latency\n * due to React reconciliation across different window contexts. This is expected behavior\n * when using portals across window boundaries.\n *\n * **Theme Synchronization**: The component automatically syncs theme changes (light/dark mode)\n * from the parent window to the popup window using a MutationObserver.\n *\n * @example\n * ```tsx\n * <WindowPortal width={800} height={600} title=\"My Window\">\n * <div>Content rendered in separate window</div>\n * </WindowPortal>\n * ```\n */\nexport function WindowPortal({\n children,\n width = 600,\n height = 400,\n left = 200,\n top = 200,\n title = \"\",\n copyStyles = true,\n onClose,\n windowFeatures = {},\n}: WindowPortalProps) {\n const [container, setContainer] = useState<HTMLElement | null>(null);\n const newWindow = useRef<Window | null>(null);\n const [windowReady, setWindowReady] = useState(false);\n\n // Function to copy styles from parent to popup window\n const copyStylesToWindow = useCallback((win: Window) => {\n if (!win || win.closed) return;\n\n // Clear existing styles in popup window\n const existingStyles = win.document.head.querySelectorAll(\"style, link[rel='stylesheet']\");\n existingStyles.forEach((style) => style.remove());\n\n // Copy all stylesheets\n Array.from(document.styleSheets).forEach((stylesheet) => {\n try {\n // Try to copy via cssRules (for same-origin stylesheets)\n if (stylesheet.cssRules) {\n const newStyleElement = win.document.createElement(\"style\");\n Array.from(stylesheet.cssRules).forEach((rule) => {\n newStyleElement.appendChild(\n win.document.createTextNode(rule.cssText)\n );\n });\n win.document.head.appendChild(newStyleElement);\n }\n } catch (e) {\n // If cssRules is not accessible (CORS), copy via link element\n if (stylesheet.href) {\n const link = win.document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = stylesheet.href;\n win.document.head.appendChild(link);\n }\n }\n });\n\n // Copy inline style elements\n Array.from(document.querySelectorAll(\"style\")).forEach((style) => {\n const newStyle = win.document.createElement(\"style\");\n newStyle.textContent = style.textContent;\n win.document.head.appendChild(newStyle);\n });\n }, []);\n\n useEffect(() => {\n // Create container element on client-side\n const div = document.createElement(\"div\");\n setContainer(div);\n }, []);\n\n useEffect(() => {\n // When container is ready\n if (!container) return;\n\n // Only create the window once - don't recreate on every render\n if (newWindow.current && !newWindow.current.closed) {\n return;\n }\n\n // Build window features string\n const {\n resizable = true,\n scrollbars = true,\n toolbar = false,\n menubar = false,\n location = false,\n status = false,\n } = windowFeatures;\n\n const features = [\n `width=${width}`,\n `height=${height}`,\n `left=${left}`,\n `top=${top}`,\n `resizable=${resizable ? \"yes\" : \"no\"}`,\n `scrollbars=${scrollbars ? \"yes\" : \"no\"}`,\n `toolbar=${toolbar ? \"yes\" : \"no\"}`,\n `menubar=${menubar ? \"yes\" : \"no\"}`,\n `location=${location ? \"yes\" : \"no\"}`,\n `status=${status ? \"yes\" : \"no\"}`,\n ].join(\",\");\n\n // Create window\n const win = window.open(\"\", \"\", features);\n\n if (!win) {\n console.warn(\n \"WindowPortal: Failed to open new window. It may have been blocked by a popup blocker.\"\n );\n return;\n }\n\n newWindow.current = win;\n\n // Set initial window title\n if (title) {\n win.document.title = title;\n }\n\n // Copy styles from parent window\n if (copyStyles) {\n copyStylesToWindow(win);\n\n // Copy theme classes from html element to maintain dark/light mode\n const htmlClasses = document.documentElement.className;\n if (htmlClasses) {\n win.document.documentElement.className = htmlClasses;\n }\n\n // Copy data attributes from html element (for theme)\n Array.from(document.documentElement.attributes).forEach((attr) => {\n if (attr.name.startsWith(\"data-\")) {\n win.document.documentElement.setAttribute(attr.name, attr.value);\n }\n });\n\n // Also copy body classes and attributes\n const bodyClasses = document.body.className;\n if (bodyClasses) {\n win.document.body.className = bodyClasses;\n }\n\n Array.from(document.body.attributes).forEach((attr) => {\n if (attr.name.startsWith(\"data-\")) {\n win.document.body.setAttribute(attr.name, attr.value);\n }\n });\n }\n\n // Append container to new window's body\n win.document.body.appendChild(container);\n\n // Mark window as ready for theme sync\n setWindowReady(true);\n\n // Set up cleanup handler\n const handleClose = () => {\n if (onClose) {\n onClose();\n }\n };\n\n // Poll for window closure (since 'beforeunload' doesn't always work reliably)\n const checkClosed = setInterval(() => {\n if (win.closed) {\n clearInterval(checkClosed);\n handleClose();\n }\n }, 500);\n\n // Return cleanup function\n return () => {\n clearInterval(checkClosed);\n setWindowReady(false);\n if (win && !win.closed) {\n win.close();\n }\n };\n // Only depend on container - window should only be created once\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [container]);\n\n // Update window title when it changes\n useEffect(() => {\n if (newWindow.current && !newWindow.current.closed) {\n newWindow.current.document.title = title;\n }\n }, [title]);\n\n // Sync theme changes from parent to popup window\n useEffect(() => {\n if (!copyStyles || !windowReady || !newWindow.current || newWindow.current.closed) {\n return;\n }\n\n const win = newWindow.current;\n\n // Create a MutationObserver to watch for class and data attribute changes on html element\n // Theme classes (light/dark) are applied to the html element in this design system\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (mutation.type === \"attributes\") {\n const attrName = mutation.attributeName;\n if (!attrName) return;\n\n // Sync class changes from html element (this is where theme classes are applied)\n if (attrName === \"class\") {\n win.document.documentElement.className = document.documentElement.className;\n\n // Re-copy all styles to get the updated theme-specific CSS\n // This ensures CSS variables and theme-specific rules are updated\n copyStylesToWindow(win);\n }\n // Sync data attributes (for theme)\n else if (attrName.startsWith(\"data-\")) {\n const value = document.documentElement.getAttribute(attrName);\n if (value !== null) {\n win.document.documentElement.setAttribute(attrName, value);\n } else {\n win.document.documentElement.removeAttribute(attrName);\n }\n }\n }\n });\n });\n\n // Collect all data-* attributes to watch\n const allDataAttrs = Array.from(document.documentElement.attributes)\n .filter((attr) => attr.name.startsWith(\"data-\"))\n .map((attr) => attr.name);\n\n // Observe the parent window's html element for attribute changes\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", ...allDataAttrs],\n attributeOldValue: false,\n });\n\n return () => {\n observer.disconnect();\n };\n }, [copyStyles, copyStylesToWindow, windowReady]);\n\n return container ? createPortal(children, container) : null;\n}\n"],"names":["WindowPortal","children","width","height","left","top","title","copyStyles","onClose","windowFeatures","container","setContainer","useState","newWindow","useRef","windowReady","setWindowReady","copyStylesToWindow","useCallback","win","style","stylesheet","newStyleElement","rule","link","newStyle","useEffect","div","resizable","scrollbars","toolbar","menubar","location","status","features","htmlClasses","attr","bodyClasses","handleClose","checkClosed","observer","mutations","mutation","attrName","value","allDataAttrs","createPortal"],"mappings":";;;AA0BO,SAASA,EAAa;AAAA,EAC3B,UAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,QAAAC,IAAS;AAAA,EACT,MAAAC,IAAO;AAAA,EACP,KAAAC,IAAM;AAAA,EACN,OAAAC,IAAQ;AAAA,EACR,YAAAC,IAAa;AAAA,EACb,SAAAC;AAAA,EACA,gBAAAC,IAAiB,CAAA;AACnB,GAAsB;AACpB,QAAM,CAACC,GAAWC,CAAY,IAAIC,EAA6B,IAAI,GAC7DC,IAAYC,EAAsB,IAAI,GACtC,CAACC,GAAaC,CAAc,IAAIJ,EAAS,EAAK,GAG9CK,IAAqBC,EAAY,CAACC,MAAgB;AACtD,QAAI,CAACA,KAAOA,EAAI,OAAQ;AAIxB,IADuBA,EAAI,SAAS,KAAK,iBAAiB,+BAA+B,EAC1E,QAAQ,CAACC,MAAUA,EAAM,QAAQ,GAGhD,MAAM,KAAK,SAAS,WAAW,EAAE,QAAQ,CAACC,MAAe;AACvD,UAAI;AAEF,YAAIA,EAAW,UAAU;AACvB,gBAAMC,IAAkBH,EAAI,SAAS,cAAc,OAAO;AAC1D,gBAAM,KAAKE,EAAW,QAAQ,EAAE,QAAQ,CAACE,MAAS;AAChD,YAAAD,EAAgB;AAAA,cACdH,EAAI,SAAS,eAAeI,EAAK,OAAO;AAAA,YAAA;AAAA,UAE5C,CAAC,GACDJ,EAAI,SAAS,KAAK,YAAYG,CAAe;AAAA,QAC/C;AAAA,MACF,QAAY;AAEV,YAAID,EAAW,MAAM;AACnB,gBAAMG,IAAOL,EAAI,SAAS,cAAc,MAAM;AAC9C,UAAAK,EAAK,MAAM,cACXA,EAAK,OAAOH,EAAW,MACvBF,EAAI,SAAS,KAAK,YAAYK,CAAI;AAAA,QACpC;AAAA,MACF;AAAA,IACF,CAAC,GAGD,MAAM,KAAK,SAAS,iBAAiB,OAAO,CAAC,EAAE,QAAQ,CAACJ,MAAU;AAChE,YAAMK,IAAWN,EAAI,SAAS,cAAc,OAAO;AACnD,MAAAM,EAAS,cAAcL,EAAM,aAC7BD,EAAI,SAAS,KAAK,YAAYM,CAAQ;AAAA,IACxC,CAAC;AAAA,EACH,GAAG,CAAA,CAAE;AAEL,SAAAC,EAAU,MAAM;AAEd,UAAMC,IAAM,SAAS,cAAc,KAAK;AACxC,IAAAhB,EAAagB,CAAG;AAAA,EAClB,GAAG,CAAA,CAAE,GAELD,EAAU,MAAM;AAKd,QAHI,CAAChB,KAGDG,EAAU,WAAW,CAACA,EAAU,QAAQ;AAC1C;AAIF,UAAM;AAAA,MACJ,WAAAe,IAAY;AAAA,MACZ,YAAAC,IAAa;AAAA,MACb,SAAAC,IAAU;AAAA,MACV,SAAAC,IAAU;AAAA,MACV,UAAAC,IAAW;AAAA,MACX,QAAAC,IAAS;AAAA,IAAA,IACPxB,GAEEyB,IAAW;AAAA,MACf,SAAShC,CAAK;AAAA,MACd,UAAUC,CAAM;AAAA,MAChB,QAAQC,CAAI;AAAA,MACZ,OAAOC,CAAG;AAAA,MACV,aAAauB,IAAY,QAAQ,IAAI;AAAA,MACrC,cAAcC,IAAa,QAAQ,IAAI;AAAA,MACvC,WAAWC,IAAU,QAAQ,IAAI;AAAA,MACjC,WAAWC,IAAU,QAAQ,IAAI;AAAA,MACjC,YAAYC,IAAW,QAAQ,IAAI;AAAA,MACnC,UAAUC,IAAS,QAAQ,IAAI;AAAA,IAAA,EAC/B,KAAK,GAAG,GAGJd,IAAM,OAAO,KAAK,IAAI,IAAIe,CAAQ;AAExC,QAAI,CAACf,GAAK;AACR,cAAQ;AAAA,QACN;AAAA,MAAA;AAEF;AAAA,IACF;AAUA,QARAN,EAAU,UAAUM,GAGhBb,MACFa,EAAI,SAAS,QAAQb,IAInBC,GAAY;AACd,MAAAU,EAAmBE,CAAG;AAGtB,YAAMgB,IAAc,SAAS,gBAAgB;AAC7C,MAAIA,MACFhB,EAAI,SAAS,gBAAgB,YAAYgB,IAI3C,MAAM,KAAK,SAAS,gBAAgB,UAAU,EAAE,QAAQ,CAACC,MAAS;AAChE,QAAIA,EAAK,KAAK,WAAW,OAAO,KAC9BjB,EAAI,SAAS,gBAAgB,aAAaiB,EAAK,MAAMA,EAAK,KAAK;AAAA,MAEnE,CAAC;AAGD,YAAMC,IAAc,SAAS,KAAK;AAClC,MAAIA,MACFlB,EAAI,SAAS,KAAK,YAAYkB,IAGhC,MAAM,KAAK,SAAS,KAAK,UAAU,EAAE,QAAQ,CAACD,MAAS;AACrD,QAAIA,EAAK,KAAK,WAAW,OAAO,KAC9BjB,EAAI,SAAS,KAAK,aAAaiB,EAAK,MAAMA,EAAK,KAAK;AAAA,MAExD,CAAC;AAAA,IACH;AAGA,IAAAjB,EAAI,SAAS,KAAK,YAAYT,CAAS,GAGvCM,EAAe,EAAI;AAGnB,UAAMsB,IAAc,MAAM;AACxB,MAAI9B,KACFA,EAAA;AAAA,IAEJ,GAGM+B,IAAc,YAAY,MAAM;AACpC,MAAIpB,EAAI,WACN,cAAcoB,CAAW,GACzBD,EAAA;AAAA,IAEJ,GAAG,GAAG;AAGN,WAAO,MAAM;AACX,oBAAcC,CAAW,GACzBvB,EAAe,EAAK,GAChBG,KAAO,CAACA,EAAI,UACdA,EAAI,MAAA;AAAA,IAER;AAAA,EAGF,GAAG,CAACT,CAAS,CAAC,GAGdgB,EAAU,MAAM;AACd,IAAIb,EAAU,WAAW,CAACA,EAAU,QAAQ,WAC1CA,EAAU,QAAQ,SAAS,QAAQP;AAAA,EAEvC,GAAG,CAACA,CAAK,CAAC,GAGVoB,EAAU,MAAM;AACd,QAAI,CAACnB,KAAc,CAACQ,KAAe,CAACF,EAAU,WAAWA,EAAU,QAAQ;AACzE;AAGF,UAAMM,IAAMN,EAAU,SAIhB2B,IAAW,IAAI,iBAAiB,CAACC,MAAc;AACnD,MAAAA,EAAU,QAAQ,CAACC,MAAa;AAC9B,YAAIA,EAAS,SAAS,cAAc;AAClC,gBAAMC,IAAWD,EAAS;AAC1B,cAAI,CAACC,EAAU;AAGf,cAAIA,MAAa;AACf,YAAAxB,EAAI,SAAS,gBAAgB,YAAY,SAAS,gBAAgB,WAIlEF,EAAmBE,CAAG;AAAA,mBAGfwB,EAAS,WAAW,OAAO,GAAG;AACrC,kBAAMC,IAAQ,SAAS,gBAAgB,aAAaD,CAAQ;AAC5D,YAAIC,MAAU,OACZzB,EAAI,SAAS,gBAAgB,aAAawB,GAAUC,CAAK,IAEzDzB,EAAI,SAAS,gBAAgB,gBAAgBwB,CAAQ;AAAA,UAEzD;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,CAAC,GAGKE,IAAe,MAAM,KAAK,SAAS,gBAAgB,UAAU,EAChE,OAAO,CAACT,MAASA,EAAK,KAAK,WAAW,OAAO,CAAC,EAC9C,IAAI,CAACA,MAASA,EAAK,IAAI;AAG1B,WAAAI,EAAS,QAAQ,SAAS,iBAAiB;AAAA,MACzC,YAAY;AAAA,MACZ,iBAAiB,CAAC,SAAS,GAAGK,CAAY;AAAA,MAC1C,mBAAmB;AAAA,IAAA,CACpB,GAEM,MAAM;AACX,MAAAL,EAAS,WAAA;AAAA,IACX;AAAA,EACF,GAAG,CAACjC,GAAYU,GAAoBF,CAAW,CAAC,GAEzCL,IAAYoC,EAAa7C,GAAUS,CAAS,IAAI;AACzD;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/window-portal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface WindowPortalProps {
|
|
3
|
+
/**
|
|
4
|
+
* Content to render in the new window
|
|
5
|
+
*/
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Width of the new window in pixels
|
|
9
|
+
* @default 600
|
|
10
|
+
*/
|
|
11
|
+
width?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Height of the new window in pixels
|
|
14
|
+
* @default 400
|
|
15
|
+
*/
|
|
16
|
+
height?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Left position of the new window in pixels from the screen's left edge
|
|
19
|
+
* @default 200
|
|
20
|
+
*/
|
|
21
|
+
left?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Top position of the new window in pixels from the screen's top edge
|
|
24
|
+
* @default 200
|
|
25
|
+
*/
|
|
26
|
+
top?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Title of the new window
|
|
29
|
+
* @default ""
|
|
30
|
+
*/
|
|
31
|
+
title?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Whether to copy parent window's stylesheets to the new window
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
copyStyles?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Callback fired when the window is closed
|
|
39
|
+
*/
|
|
40
|
+
onClose?: () => void;
|
|
41
|
+
/**
|
|
42
|
+
* Native window features configuration
|
|
43
|
+
*/
|
|
44
|
+
windowFeatures?: {
|
|
45
|
+
/**
|
|
46
|
+
* Whether the window should be resizable
|
|
47
|
+
* @default true
|
|
48
|
+
*/
|
|
49
|
+
resizable?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Whether to show scrollbars
|
|
52
|
+
* @default true
|
|
53
|
+
*/
|
|
54
|
+
scrollbars?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Whether to show the toolbar
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
toolbar?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Whether to show the menubar
|
|
62
|
+
* @default false
|
|
63
|
+
*/
|
|
64
|
+
menubar?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Whether to show the location bar
|
|
67
|
+
* @default false
|
|
68
|
+
*/
|
|
69
|
+
location?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Whether to show the status bar
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
status?: boolean;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/window-portal/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,cAAc,CAAC,EAAE;QACf;;;WAGG;QACH,SAAS,CAAC,EAAE,OAAO,CAAC;QAEpB;;;WAGG;QACH,UAAU,CAAC,EAAE,OAAO,CAAC;QAErB;;;WAGG;QACH,OAAO,CAAC,EAAE,OAAO,CAAC;QAElB;;;WAGG;QACH,OAAO,CAAC,EAAE,OAAO,CAAC;QAElB;;;WAGG;QACH,QAAQ,CAAC,EAAE,OAAO,CAAC;QAEnB;;;WAGG;QACH,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;CACH"}
|