@creekjs/web-components 1.0.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.
Files changed (73) hide show
  1. package/.fatherrc.ts +13 -0
  2. package/.turbo/daemon/deec863de02760ed-turbo.log.2024-11-20 +0 -0
  3. package/README.md +1026 -0
  4. package/dist/bg-center/index.js +28 -0
  5. package/dist/creek-config-provider/CreekConfigContext.js +2 -0
  6. package/dist/creek-config-provider/index.js +14 -0
  7. package/dist/creek-hooks/index.js +1 -0
  8. package/dist/creek-hooks/useViewportHeight.js +147 -0
  9. package/dist/creek-icon/index.js +37 -0
  10. package/dist/creek-keep-alive/index.js +20 -0
  11. package/dist/creek-layout/CollapseButton.js +59 -0
  12. package/dist/creek-layout/Exception/NotFound.js +13 -0
  13. package/dist/creek-layout/Exception/NotFoundPage.js +5 -0
  14. package/dist/creek-layout/Exception/index.js +8 -0
  15. package/dist/creek-layout/HeaderContent/FullScreen.js +50 -0
  16. package/dist/creek-layout/HeaderContent/UserInfo.js +58 -0
  17. package/dist/creek-layout/HeaderContent/index.js +33 -0
  18. package/dist/creek-layout/index.js +86 -0
  19. package/dist/creek-loading/index.js +52 -0
  20. package/dist/creek-search/CreekSearch.js +51 -0
  21. package/dist/creek-search/CreekSearchContext.js +546 -0
  22. package/dist/creek-search/CreekSearchFilterDisplay.js +97 -0
  23. package/dist/creek-search/CreekSearchInput.js +96 -0
  24. package/dist/creek-search/CreekSearchValueSelector.js +422 -0
  25. package/dist/creek-search/index.js +5 -0
  26. package/dist/creek-search/type.js +1 -0
  27. package/dist/creek-table/SearchTable.js +121 -0
  28. package/dist/creek-table/TableOptionRender.js +65 -0
  29. package/dist/creek-table/TableViewContent.js +45 -0
  30. package/dist/creek-table/hooks/index.js +3 -0
  31. package/dist/creek-table/hooks/useAdaptiveToolBar.js +48 -0
  32. package/dist/creek-table/hooks/useAutoAddFilterToColumns.js +93 -0
  33. package/dist/creek-table/hooks/useElementDistance.js +58 -0
  34. package/dist/creek-table/index.js +25 -0
  35. package/dist/creek-table/toolBarRender.js +36 -0
  36. package/dist/creek-table/type.js +1 -0
  37. package/dist/index.js +7 -0
  38. package/package.json +19 -0
  39. package/src/bg-center/index.tsx +26 -0
  40. package/src/creek-config-provider/CreekConfigContext.tsx +7 -0
  41. package/src/creek-config-provider/index.tsx +12 -0
  42. package/src/creek-hooks/index.ts +1 -0
  43. package/src/creek-hooks/useViewportHeight.tsx +154 -0
  44. package/src/creek-icon/index.tsx +34 -0
  45. package/src/creek-keep-alive/index.tsx +11 -0
  46. package/src/creek-layout/CollapseButton.tsx +66 -0
  47. package/src/creek-layout/Exception/NotFound.tsx +12 -0
  48. package/src/creek-layout/Exception/NotFoundPage.tsx +4 -0
  49. package/src/creek-layout/Exception/index.tsx +10 -0
  50. package/src/creek-layout/HeaderContent/FullScreen.tsx +46 -0
  51. package/src/creek-layout/HeaderContent/UserInfo.tsx +54 -0
  52. package/src/creek-layout/HeaderContent/index.tsx +27 -0
  53. package/src/creek-layout/index.tsx +98 -0
  54. package/src/creek-loading/index.tsx +35 -0
  55. package/src/creek-search/CreekSearch.tsx +59 -0
  56. package/src/creek-search/CreekSearchContext.tsx +593 -0
  57. package/src/creek-search/CreekSearchFilterDisplay.tsx +84 -0
  58. package/src/creek-search/CreekSearchInput.tsx +75 -0
  59. package/src/creek-search/CreekSearchValueSelector.tsx +324 -0
  60. package/src/creek-search/index.tsx +5 -0
  61. package/src/creek-search/type.ts +9 -0
  62. package/src/creek-table/SearchTable.tsx +115 -0
  63. package/src/creek-table/TableOptionRender.tsx +57 -0
  64. package/src/creek-table/TableViewContent.tsx +44 -0
  65. package/src/creek-table/hooks/index.ts +4 -0
  66. package/src/creek-table/hooks/useAdaptiveToolBar.tsx +45 -0
  67. package/src/creek-table/hooks/useAutoAddFilterToColumns.tsx +90 -0
  68. package/src/creek-table/hooks/useElementDistance.tsx +64 -0
  69. package/src/creek-table/index.tsx +16 -0
  70. package/src/creek-table/toolBarRender.tsx +28 -0
  71. package/src/creek-table/type.ts +21 -0
  72. package/src/index.tsx +8 -0
  73. package/tsconfig.json +12 -0
@@ -0,0 +1,34 @@
1
+ import Icon, { createFromIconfontCN } from '@ant-design/icons';
2
+ import type { GetProps } from 'antd';
3
+ import { isEmpty } from 'lodash';
4
+ import { useContext } from 'react';
5
+
6
+ import { CreekConfigProvider, CreekConfigProviderProps } from '../creek-config-provider';
7
+
8
+ type CustomIconComponentProps = GetProps<typeof Icon>;
9
+
10
+ export type CreekIconProps = CustomIconComponentProps & {
11
+ iconFontCNs?: CreekConfigProviderProps['iconFontCNs'];
12
+ type?: string;
13
+ component?: CustomIconComponentProps['component'];
14
+ };
15
+
16
+ export const CreekIcon = (props: CreekIconProps) => {
17
+ const { iconFontCNs: iconFontCNsContext } = useContext(CreekConfigProvider.CreekConfigContext);
18
+ const { component, type, iconFontCNs, ...more } = props;
19
+
20
+ const _iconFontCNs = iconFontCNs || iconFontCNsContext;
21
+
22
+ if (component) {
23
+ return <Icon component={component} {...more} />;
24
+ }
25
+
26
+ if (type && !isEmpty(_iconFontCNs)) {
27
+ const IconFont = createFromIconfontCN({
28
+ scriptUrl: _iconFontCNs,
29
+ });
30
+ return <IconFont type={type} {...more} />;
31
+ }
32
+
33
+ return null;
34
+ };
@@ -0,0 +1,11 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ export const CreekKeepAlive = () => {
4
+ const [isMounted, setIsMounted] = useState(false);
5
+
6
+ useEffect(() => {
7
+ setIsMounted(true);
8
+ }, []);
9
+
10
+ return <div>KeepAlive</div>;
11
+ };
@@ -0,0 +1,66 @@
1
+ import { ArrowLeftOutlined, ArrowRightOutlined } from "@ant-design/icons";
2
+ import { createStyles } from "antd-style";
3
+ import { useEffect } from "react";
4
+ import { create } from "zustand";
5
+
6
+ export type CollapsedButtonProps = {
7
+ collapsed?: boolean;
8
+ };
9
+
10
+ export type CollapsedButtonStore = {
11
+ collapsed: boolean;
12
+ changeCollapsed: () => void;
13
+ };
14
+
15
+ const useStyles = createStyles(({ token }) => ({
16
+ buttonContainer: {
17
+ padding: token.padding,
18
+ },
19
+ iconContainer: {
20
+ width: "24px",
21
+ height: "24px",
22
+ background: "#f3f3f3",
23
+ display: "flex",
24
+ alignItems: "center",
25
+ justifyContent: "center",
26
+ cursor: "pointer",
27
+ },
28
+ }));
29
+
30
+ export const useCollapsedStore = create<CollapsedButtonStore>((set, get) => {
31
+ return {
32
+ collapsed: false,
33
+ changeCollapsed: () => {
34
+ const _collapsed = get().collapsed;
35
+ set({
36
+ collapsed: !_collapsed,
37
+ });
38
+ },
39
+ };
40
+ });
41
+
42
+ export const CollapsedButton = (props: CollapsedButtonProps) => {
43
+ const { collapsed: defaultCollapsed = false } = props;
44
+ const { styles } = useStyles();
45
+
46
+ const { collapsed, changeCollapsed } = useCollapsedStore.getState();
47
+
48
+ useEffect(() => {
49
+ if (defaultCollapsed !== collapsed) {
50
+ useCollapsedStore.setState({ collapsed: defaultCollapsed });
51
+ }
52
+ }, [defaultCollapsed]);
53
+
54
+ return (
55
+ <div
56
+ className={styles.buttonContainer}
57
+ onClick={() => {
58
+ changeCollapsed();
59
+ }}
60
+ >
61
+ <div className={styles.iconContainer}>
62
+ {collapsed ? <ArrowRightOutlined /> : <ArrowLeftOutlined />}
63
+ </div>
64
+ </div>
65
+ );
66
+ };
@@ -0,0 +1,12 @@
1
+ import { Button, Result } from "antd";
2
+
3
+ export const NotFound = () => {
4
+ return (
5
+ <Result
6
+ status="404"
7
+ title="404"
8
+ subTitle="Sorry, the page you visited does not exist."
9
+ extra={<Button type="primary">Back Home</Button>}
10
+ />
11
+ );
12
+ };
@@ -0,0 +1,4 @@
1
+ import { NotFound } from "./NotFound";
2
+ export default () => {
3
+ return <NotFound />;
4
+ };
@@ -0,0 +1,10 @@
1
+ export * from "./NotFound";
2
+
3
+ export type ExceptionProps = {
4
+ children?: React.ReactNode;
5
+ };
6
+
7
+ export const Exception = (props: ExceptionProps) => {
8
+ const { children } = props;
9
+ return <div>{children}</div>;
10
+ };
@@ -0,0 +1,46 @@
1
+ import { FullscreenExitOutlined, FullscreenOutlined } from "@ant-design/icons";
2
+ import { useFullscreen, useMemoizedFn } from "ahooks";
3
+ import { Tooltip } from "antd";
4
+ import { create } from "zustand";
5
+
6
+ export type FullScreenStore = {
7
+ isFullScreen: boolean;
8
+ changeFullScreen: () => void;
9
+ };
10
+
11
+ export const useFullScreenStore = create<FullScreenStore>((set, get) => {
12
+ return {
13
+ isFullScreen: false,
14
+ changeFullScreen: () => {
15
+ const _isFullScreen = get().isFullScreen;
16
+ set({
17
+ isFullScreen: !_isFullScreen,
18
+ });
19
+ },
20
+ };
21
+ });
22
+
23
+ export const FullScreen = () => {
24
+ const [, { toggleFullscreen }] = useFullscreen(document.body);
25
+
26
+ const { isFullScreen, changeFullScreen } = useFullScreenStore.getState();
27
+
28
+ const handleFullScreen = useMemoizedFn(() => {
29
+ toggleFullscreen();
30
+ changeFullScreen();
31
+ });
32
+
33
+ return (
34
+ <>
35
+ {isFullScreen ? (
36
+ <Tooltip title="退出全屏" placement="top">
37
+ <FullscreenExitOutlined onClick={handleFullScreen} />
38
+ </Tooltip>
39
+ ) : (
40
+ <Tooltip title="全屏" placement="top">
41
+ <FullscreenOutlined onClick={handleFullScreen} />
42
+ </Tooltip>
43
+ )}
44
+ </>
45
+ );
46
+ };
@@ -0,0 +1,54 @@
1
+ import { LogoutOutlined } from "@ant-design/icons";
2
+ import { Avatar, Dropdown, DropDownProps, Space } from "antd";
3
+ import { createStyles } from "antd-style";
4
+
5
+ const useStyles = createStyles(({ token }) => ({
6
+ avatarContainer: {
7
+ backgroundColor: token.colorPrimary,
8
+ width: 24,
9
+ height: 24,
10
+ },
11
+ userInfoDropdownOverlay: {
12
+ ".ant-dropdown-menu": {
13
+ padding: "8px 0",
14
+ },
15
+ ".ant-dropdown-menu-item": {
16
+ ".ant-dropdown-menu-item-icon": {
17
+ fontSize: "18px",
18
+ marginRight: "8px",
19
+ },
20
+ },
21
+ },
22
+ }));
23
+
24
+ export const UserInfo = () => {
25
+ const { styles } = useStyles();
26
+
27
+ const userInfoMenu: DropDownProps["menu"] = {
28
+ items: [
29
+ {
30
+ key: "logout",
31
+ label: (
32
+ <Space size={8}>
33
+ <LogoutOutlined />
34
+ <span>退出登录</span>
35
+ </Space>
36
+ ),
37
+ onClick: () => {},
38
+ },
39
+ ],
40
+ };
41
+ return (
42
+ <Dropdown
43
+ arrow
44
+ placement="bottom"
45
+ overlayClassName={styles.userInfoDropdownOverlay}
46
+ menu={userInfoMenu}
47
+ >
48
+ <Space size={4} align="center">
49
+ <Avatar className={styles.avatarContainer}>C</Avatar>
50
+ <span>Creek</span>
51
+ </Space>
52
+ </Dropdown>
53
+ );
54
+ };
@@ -0,0 +1,27 @@
1
+ import { Divider, Flex, Space } from 'antd';
2
+ import { createStyles } from 'antd-style';
3
+
4
+ import { FullScreen } from './FullScreen';
5
+ import { UserInfo } from './UserInfo';
6
+
7
+ const useStyles = createStyles(({}) => ({
8
+ headerContentContainer: {
9
+ color: '#fff',
10
+ },
11
+ dividerContainer: {
12
+ backgroundColor: '#9b9999',
13
+ },
14
+ }));
15
+
16
+ export const HeaderContent = () => {
17
+ const { styles } = useStyles();
18
+ return (
19
+ <Flex justify="space-between" className={styles.headerContentContainer}>
20
+ <span />
21
+ <Space split={<Divider type="vertical" className={styles.dividerContainer} />}>
22
+ <FullScreen />
23
+ <UserInfo />
24
+ </Space>
25
+ </Flex>
26
+ );
27
+ };
@@ -0,0 +1,98 @@
1
+ import { ProLayout, ProLayoutProps } from "@ant-design/pro-components";
2
+ import { useMemoizedFn } from "ahooks";
3
+ import { theme } from "antd";
4
+ import classnames from "classnames";
5
+
6
+ import { CollapsedButton, useCollapsedStore } from "./CollapseButton";
7
+ import { Exception } from "./Exception";
8
+ import { HeaderContent } from "./HeaderContent";
9
+
10
+ export type LayoutProps = ProLayoutProps & {
11
+ runtimeConfig: ProLayoutProps;
12
+ userConfig?: ProLayoutProps;
13
+ navigate?: (path?: string | number) => void;
14
+ initialInfo?: {
15
+ initialState: any;
16
+ loading: boolean;
17
+ setInitialState: () => void;
18
+ };
19
+ };
20
+
21
+ export const CreekLayout = (props: LayoutProps) => {
22
+ const {
23
+ route,
24
+ userConfig,
25
+ runtimeConfig,
26
+ children,
27
+ location,
28
+ navigate,
29
+ ...more
30
+ } = props;
31
+
32
+ const { useToken } = theme;
33
+ const { token } = useToken();
34
+
35
+ const { collapsed } = useCollapsedStore();
36
+
37
+ const menuItemRender: ProLayoutProps["menuItemRender"] = useMemoizedFn(
38
+ (itemProps, defaultDom) => {
39
+ return (
40
+ <span
41
+ onClick={() => {
42
+ if (navigate) {
43
+ navigate(itemProps.path);
44
+ }
45
+ }}
46
+ >
47
+ {defaultDom}
48
+ </span>
49
+ );
50
+ }
51
+ );
52
+
53
+ return (
54
+ <ProLayout
55
+ className={classnames("creek-layout-container", userConfig?.className)}
56
+ layout="mix"
57
+ route={route}
58
+ title={userConfig?.title}
59
+ siderWidth={212}
60
+ location={location}
61
+ menuItemRender={menuItemRender}
62
+ headerContentRender={() => {
63
+ return <HeaderContent />;
64
+ }}
65
+ token={{
66
+ header: {
67
+ colorBgHeader: "#2c2c2c",
68
+ colorHeaderTitle: "#fff",
69
+ colorTextMenuSelected: "#fff",
70
+ heightLayoutHeader: 48,
71
+ },
72
+ sider: {
73
+ colorMenuBackground: "#fff",
74
+ colorBgMenuItemSelected: "transparent",
75
+ colorTextMenuActive: token.colorPrimary,
76
+ colorTextMenuSelected: token.colorPrimary,
77
+ colorTextMenuItemHover: token.colorPrimary,
78
+ colorTextMenu: "#333",
79
+ },
80
+ pageContainer: {
81
+ paddingBlockPageContainerContent: 0,
82
+ paddingInlinePageContainerContent: 0,
83
+ },
84
+ }}
85
+ fixSiderbar
86
+ fixedHeader
87
+ collapsed={collapsed}
88
+ collapsedButtonRender={(collapsed) => {
89
+ return <CollapsedButton collapsed={collapsed} />;
90
+ }}
91
+ {...more}
92
+ >
93
+ <Exception>{children}</Exception>
94
+ </ProLayout>
95
+ );
96
+ };
97
+
98
+ export * from "./Exception";
@@ -0,0 +1,35 @@
1
+ import { Spin } from 'antd';
2
+ import React from 'react';
3
+ import { createRoot } from 'react-dom/client';
4
+
5
+ export class Loading {
6
+ private static container: HTMLDivElement | null = null;
7
+ private static root: ReturnType<typeof createRoot> | null = null;
8
+
9
+ private static createContainer() {
10
+ if (this.container) return this.container;
11
+
12
+ this.container = document.createElement('div');
13
+ document.body.appendChild(this.container);
14
+ this.root = createRoot(this.container);
15
+ return this.container;
16
+ }
17
+
18
+ static open(config?: React.ComponentProps<typeof Spin>) {
19
+ this.createContainer();
20
+
21
+ this.root?.render(<Spin {...config} fullscreen></Spin>);
22
+ }
23
+
24
+ static close() {
25
+ if (this.root) {
26
+ this.root.unmount();
27
+
28
+ if (this.container) {
29
+ document.body.removeChild(this.container);
30
+ this.container = null;
31
+ this.root = null;
32
+ }
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,59 @@
1
+ import { ParamsType, ProColumnType } from '@ant-design/pro-components';
2
+ import { createStyles } from 'antd-style';
3
+ import classnames from 'classnames';
4
+
5
+ import { CreekSearchProvider } from './CreekSearchContext';
6
+ import { CreekFilterDisplay } from './CreekSearchFilterDisplay';
7
+ import { CreekSearchInput } from './CreekSearchInput';
8
+
9
+ const useStyles = createStyles(
10
+ (
11
+ { token, prefixCls },
12
+ props: {
13
+ justify: 'start' | 'end';
14
+ },
15
+ ) => {
16
+ return {
17
+ creekSearchContainer: {
18
+ padding: '20px 20px 0 20px',
19
+ width: '100%',
20
+ display: 'flex',
21
+ flexDirection: 'column',
22
+ alignItems: props.justify === 'end' ? 'flex-end' : 'flex-start',
23
+ },
24
+
25
+ creekSearchContainerEnd: {
26
+ [`& .${prefixCls}-tag`]: {
27
+ marginInlineEnd: 0,
28
+ },
29
+ },
30
+
31
+ creekSearchFilterDisplay: {
32
+ marginTop: '10px',
33
+ },
34
+ };
35
+ },
36
+ );
37
+
38
+ export type CreekSearchProps<T> = {
39
+ columns: ProColumnType<T>[];
40
+ onSubmit?: (values: Record<string, any>) => void;
41
+ justify?: 'start' | 'end';
42
+ };
43
+
44
+ export const CreekSearch = <T extends ParamsType>(props: CreekSearchProps<T>) => {
45
+ const { columns = [], onSubmit, justify = 'start' } = props;
46
+
47
+ const { styles } = useStyles({
48
+ justify,
49
+ });
50
+
51
+ return (
52
+ <CreekSearchProvider columns={columns} onSubmit={onSubmit}>
53
+ <div className={classnames(styles.creekSearchContainer, justify === 'end' && styles.creekSearchContainerEnd)}>
54
+ <CreekSearchInput />
55
+ <CreekFilterDisplay className={styles.creekSearchFilterDisplay} />
56
+ </div>
57
+ </CreekSearchProvider>
58
+ );
59
+ };