mm
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
import { ComponentPropsWithRef, forwardRef, ReactNode } from "react";
|
||||
|
||||
export type ButtonState = {
|
||||
loading?: boolean;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export type ButtonProps = {
|
||||
size?: "xs" | "sm" | "md" | "lg";
|
||||
shape?: "circle" | "rounded" | "square";
|
||||
iconSvg?: ReactNode;
|
||||
iconOnly?: boolean;
|
||||
hideIcon?: boolean;
|
||||
loadingIconSvg?: ReactNode;
|
||||
} & ButtonState &
|
||||
ComponentPropsWithRef<"button">;
|
||||
|
||||
export const Button = forwardRef();
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ComponentPropsWithRef } from "react";
|
||||
|
||||
type ButtonIconProps = ComponentPropsWithRef<"span">;
|
||||
|
||||
export const ButtonIcon = (props: ButtonIconProps) => {
|
||||
const { children, ...rest } = props;
|
||||
return <span {...rest}>{children}</span>;
|
||||
};
|
||||
ButtonIcon.displayName = "ButtonIcon";
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ComponentPropsWithRef } from "react";
|
||||
|
||||
type ButtonLoadingProps = ComponentPropsWithRef<"span">;
|
||||
|
||||
export const ButtonLoading = (props: ButtonLoadingProps) => {
|
||||
const { children, ...rest } = props;
|
||||
return <span {...rest}>{children}</span>;
|
||||
};
|
||||
ButtonLoading.displayName = "ButtonLoading";
|
||||
38
packages/ui-web-headless/componnets/button/ButtonRoot.tsx
Normal file
38
packages/ui-web-headless/componnets/button/ButtonRoot.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import { ComponentPropsWithoutRef, forwardRef } from "react";
|
||||
import { useButtonSlot } from "./useButtonSlots";
|
||||
|
||||
export type ButtonRootOwnProps = {
|
||||
iconOnly?: boolean;
|
||||
hideIcon?: boolean;
|
||||
};
|
||||
|
||||
export type ButtonRootStateProps = {
|
||||
loading?: boolean;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export type ButtonRootPrimitiveProps = Omit<
|
||||
ComponentPropsWithoutRef<"button">,
|
||||
keyof ButtonRootStateProps
|
||||
>;
|
||||
|
||||
export type ButtonRootProps = ButtonRootOwnProps &
|
||||
ButtonRootStateProps &
|
||||
ButtonRootPrimitiveProps;
|
||||
|
||||
export const ButtonRoot = forwardRef<HTMLButtonElement, ButtonRootProps>(
|
||||
(props, ref) => {
|
||||
const { children, loading, iconOnly, hideIcon, ...rest } = props;
|
||||
const { iconNode, loadingNode } = useButtonSlot(children);
|
||||
|
||||
return (
|
||||
<button ref={ref} {...rest}>
|
||||
{loadingNode ?? loadingNode}
|
||||
{!loadingNode && iconNode ? (hideIcon ? null : iconNode) : null}
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
},
|
||||
);
|
||||
ButtonRoot.displayName = "ButtonRoot";
|
||||
// 我需要一个通用hook方法 useProps<ownProps,stateProps,primitiveProps>(props),返一个对象 { ownProps,stateProps,primitiveProps}
|
||||
9
packages/ui-web-headless/componnets/button/index.ts
Normal file
9
packages/ui-web-headless/componnets/button/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ButtonIcon } from "./ButtonIcon";
|
||||
import { ButtonLoading } from "./ButtonLoading";
|
||||
import { ButtonRoot } from "./ButtonRoot";
|
||||
|
||||
export namespace Button {
|
||||
export const Root = ButtonRoot;
|
||||
export const Icon = ButtonIcon;
|
||||
export const Loading = ButtonLoading;
|
||||
}
|
||||
29
packages/ui-web-headless/componnets/button/useButtonSlots.ts
Normal file
29
packages/ui-web-headless/componnets/button/useButtonSlots.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import React, { ReactNode, isValidElement, Children } from "react";
|
||||
import { ButtonIcon } from "./ButtonIcon";
|
||||
import { ButtonLoading } from "./ButtonLoading";
|
||||
|
||||
export function useButtonSlot(children: ReactNode) {
|
||||
const iconNodes: React.ReactElement[] = [];
|
||||
const loadingNodes: React.ReactElement[] = [];
|
||||
|
||||
const collectNodes = (nodes: ReactNode) => {
|
||||
Children.forEach(nodes, (child) => {
|
||||
if (!isValidElement(child)) return;
|
||||
|
||||
if (child.type === ButtonIcon) {
|
||||
iconNodes.push(child);
|
||||
} else if (child.type === ButtonLoading) {
|
||||
loadingNodes.push(child);
|
||||
} else if ((child as any).props.children) {
|
||||
collectNodes((child as any).props.children);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
collectNodes(children);
|
||||
|
||||
return {
|
||||
iconNode: iconNodes.at(-1),
|
||||
loadingNode: loadingNodes.at(-1),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user