listpage-next 0.0.234 → 0.0.236

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.
@@ -2,28 +2,11 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "antd";
3
3
  import { useMemo } from "react";
4
4
  import { styled } from "styled-components";
5
- import { CloseOutlined } from "@ant-design/icons";
6
5
  import { AsyncButton } from "../../../AsyncButton/index.js";
6
+ import { useCloseButton } from "./useCloseButton.js";
7
7
  function useActions(props) {
8
- const { actionPosition = 'bottom', okText, cancelText, onOk, icon, title, onCancel, extraActions, closable = true } = props;
9
- const closeButton = useMemo(()=>{
10
- if (true === closable) return /*#__PURE__*/ jsx(CloseButton, {
11
- type: "text",
12
- icon: /*#__PURE__*/ jsx(CloseOutlined, {}),
13
- onClick: onCancel
14
- });
15
- if (false === closable) return null;
16
- const { closeIcon, disabled } = closable;
17
- return /*#__PURE__*/ jsx(CloseButton, {
18
- type: "text",
19
- disabled: disabled,
20
- icon: closeIcon || /*#__PURE__*/ jsx(CloseOutlined, {}),
21
- onClick: onCancel
22
- });
23
- }, [
24
- closable,
25
- onCancel
26
- ]);
8
+ const { actionPosition = 'bottom', okText, cancelText, onOk, icon, title, onCancel, extraActions } = props;
9
+ const { closeButton } = useCloseButton(props);
27
10
  const actions = 'none' === actionPosition ? null : /*#__PURE__*/ jsxs(Fragment, {
28
11
  children: [
29
12
  /*#__PURE__*/ jsx(Button, {
@@ -39,12 +22,12 @@ function useActions(props) {
39
22
  ]
40
23
  });
41
24
  const footer = useMemo(()=>{
42
- if ('bottom' === actionPosition) return /*#__PURE__*/ jsxs(ExtraContainer, {
25
+ if ('bottom' === actionPosition) return /*#__PURE__*/ jsxs(Fragment, {
43
26
  children: [
44
- /*#__PURE__*/ jsx(Fragment, {
27
+ /*#__PURE__*/ jsx(FlexContainer, {
45
28
  children: extraActions
46
29
  }),
47
- /*#__PURE__*/ jsx(Fragment, {
30
+ /*#__PURE__*/ jsx(ExtraContainer, {
48
31
  children: actions
49
32
  })
50
33
  ]
@@ -88,12 +71,20 @@ function useActions(props) {
88
71
  })
89
72
  ]
90
73
  });
91
- return /*#__PURE__*/ jsxs(FlexContainer, {
74
+ if ('bottom' === actionPosition) return /*#__PURE__*/ jsxs(HeaderContainer, {
92
75
  children: [
93
- icon,
94
- title
76
+ /*#__PURE__*/ jsxs(FlexContainer, {
77
+ children: [
78
+ icon,
79
+ title
80
+ ]
81
+ }),
82
+ /*#__PURE__*/ jsx(ExtraContainer, {
83
+ children: closeButton
84
+ })
95
85
  ]
96
86
  });
87
+ return /*#__PURE__*/ jsx(Fragment, {});
97
88
  }, [
98
89
  actionPosition,
99
90
  icon,
@@ -126,10 +117,4 @@ const ExtraContainer = styled.div`
126
117
  gap: 8px;
127
118
  justify-content: flex-end;
128
119
  `;
129
- const CloseButton = styled(Button)`
130
- color: rgba(0, 0, 0, 0.45);
131
- :hover {
132
- color: rgba(0, 0, 0, 0.88);
133
- }
134
- `;
135
120
  export { useActions };
@@ -0,0 +1,4 @@
1
+ import type { PageModalProps } from '.';
2
+ export declare function useCloseButton(props: PageModalProps): {
3
+ closeButton: import("react/jsx-runtime").JSX.Element | null;
4
+ };
@@ -0,0 +1,36 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
3
+ import { CloseOutlined } from "@ant-design/icons";
4
+ import { styled } from "styled-components";
5
+ import { Button } from "antd";
6
+ function useCloseButton(props) {
7
+ const { onCancel, closable = true } = props;
8
+ const closeButton = useMemo(()=>{
9
+ if (true === closable) return /*#__PURE__*/ jsx(CloseButton, {
10
+ type: "text",
11
+ icon: /*#__PURE__*/ jsx(CloseOutlined, {}),
12
+ onClick: onCancel
13
+ });
14
+ if (false === closable) return null;
15
+ const { closeIcon, disabled } = closable;
16
+ return /*#__PURE__*/ jsx(CloseButton, {
17
+ type: "text",
18
+ disabled: disabled,
19
+ icon: closeIcon || /*#__PURE__*/ jsx(CloseOutlined, {}),
20
+ onClick: onCancel
21
+ });
22
+ }, [
23
+ closable,
24
+ onCancel
25
+ ]);
26
+ return {
27
+ closeButton
28
+ };
29
+ }
30
+ const CloseButton = styled(Button)`
31
+ color: rgba(0, 0, 0, 0.45);
32
+ :hover {
33
+ color: rgba(0, 0, 0, 0.88);
34
+ }
35
+ `;
36
+ export { useCloseButton };
@@ -12,7 +12,7 @@ export declare const FloatProvider: (props: {
12
12
  export type FloatComponentProps<T extends Record<string, any> = any> = {
13
13
  record: T;
14
14
  visible: boolean;
15
- onClose: () => void;
15
+ onClose: (code?: number) => void;
16
16
  };
17
17
  export type PageFloatProps<T extends Record<string, any> = any> = {
18
18
  key: string;
@@ -1,12 +1,15 @@
1
1
  type BaseConversation = {
2
2
  id: string;
3
3
  title: string;
4
+ updatedAt?: string | number | Date;
5
+ createdAt?: string | number | Date;
4
6
  };
5
7
  export interface ConversationDropdownMenuProps<T extends BaseConversation = BaseConversation> {
6
8
  request: () => Promise<{
7
9
  list: T[];
8
10
  }>;
9
11
  onSelect?: (item: T) => void;
12
+ onDelete?: (item: T) => void | Promise<void>;
10
13
  activeKey?: string;
11
14
  }
12
15
  export declare const ConversationDropdownMenu: <T extends BaseConversation = any>(props: ConversationDropdownMenuProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -1,28 +1,94 @@
1
- import { jsx } from "react/jsx-runtime";
2
- import { HistoryOutlined } from "@ant-design/icons";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { DeleteOutlined, HistoryOutlined } from "@ant-design/icons";
3
3
  import { PageLoading } from "../../../../components/index.js";
4
4
  import { useRequest } from "ahooks";
5
5
  import { Button, Dropdown, Tooltip } from "antd";
6
6
  import styled_components from "styled-components";
7
+ import dayjs from "dayjs";
7
8
  const ConversationDropdownMenu = (props)=>{
8
- const { request, onSelect, activeKey } = props;
9
- const { data, run: refresh, loading } = useRequest(()=>request(), {
9
+ const { request, onSelect, onDelete, activeKey } = props;
10
+ const { data, run: refresh, loading, mutate } = useRequest(()=>request(), {
10
11
  manual: true
11
12
  });
12
- const menus = [
13
- {
14
- label: '历史会话',
15
- type: 'group'
16
- },
17
- ...(data?.list ?? []).map((item)=>({
18
- key: item.id,
19
- label: item.title || item,
20
- type: 'item',
21
- onClick: ()=>{
22
- if (item.id !== activeKey) onSelect?.(item);
23
- }
24
- }))
25
- ];
13
+ const toMenuItem = (item)=>({
14
+ key: item.id,
15
+ label: /*#__PURE__*/ jsxs(MenuItemLabel, {
16
+ children: [
17
+ /*#__PURE__*/ jsx("span", {
18
+ children: item.title || item
19
+ }),
20
+ /*#__PURE__*/ jsx(Button, {
21
+ type: "text",
22
+ size: "small",
23
+ danger: true,
24
+ icon: /*#__PURE__*/ jsx(DeleteOutlined, {}),
25
+ onClick: async (e)=>{
26
+ e.preventDefault();
27
+ e.stopPropagation();
28
+ await onDelete?.(item);
29
+ const list = (data?.list ?? []).filter((x)=>x.id !== item.id);
30
+ mutate?.({
31
+ list
32
+ });
33
+ },
34
+ className: "delete-btn"
35
+ })
36
+ ]
37
+ }),
38
+ type: 'item',
39
+ onClick: ()=>{
40
+ if (item.id !== activeKey) onSelect?.(item);
41
+ }
42
+ });
43
+ const now = dayjs();
44
+ const startOfWeek = now.startOf('day').subtract(now.day(), 'day');
45
+ const getTime = (it)=>it.updatedAt || it.createdAt || it.time || it.date || void 0;
46
+ const list = data?.list ?? [];
47
+ const isToday = (t)=>dayjs(t).isSame(now, 'day');
48
+ const isYesterday = (t)=>dayjs(t).isSame(now.clone().subtract(1, 'day'), 'day');
49
+ const inWeek = (t)=>{
50
+ const d = dayjs(t);
51
+ return d.isAfter(startOfWeek) || d.isSame(startOfWeek, 'day');
52
+ };
53
+ const inMonth = (t)=>dayjs(t).isSame(now, 'month');
54
+ const today = list.filter((it)=>{
55
+ const t = getTime(it);
56
+ if (!t) return false;
57
+ return isToday(t);
58
+ });
59
+ const yesterday = list.filter((it)=>{
60
+ const t = getTime(it);
61
+ if (!t) return false;
62
+ return isYesterday(t);
63
+ });
64
+ const week = list.filter((it)=>{
65
+ const t = getTime(it);
66
+ if (!t) return false;
67
+ return inWeek(t) && !isToday(t) && !isYesterday(t);
68
+ });
69
+ const month = list.filter((it)=>{
70
+ const t = getTime(it);
71
+ if (!t) return false;
72
+ return inMonth(t) && !inWeek(t) && !isToday(t) && !isYesterday(t);
73
+ });
74
+ const groups = {
75
+ 今天: today,
76
+ 昨天: yesterday,
77
+ 本周内: week,
78
+ 本月内: month
79
+ };
80
+ const groupEntries = Object.entries(groups).filter(([_, arr])=>arr.length);
81
+ const menus = [];
82
+ groupEntries.forEach(([label, arr], index)=>{
83
+ menus.push({
84
+ type: 'group',
85
+ label,
86
+ children: arr.map((it)=>toMenuItem(it))
87
+ });
88
+ if (index < groupEntries.length - 1) menus.push({
89
+ type: 'divider'
90
+ });
91
+ });
26
92
  return /*#__PURE__*/ jsx(Tooltip, {
27
93
  title: "历史会话",
28
94
  children: /*#__PURE__*/ jsx(Dropdown, {
@@ -36,11 +102,15 @@ const ConversationDropdownMenu = (props)=>{
36
102
  popupRender: (originNode)=>{
37
103
  if (loading || !data?.list?.length) {
38
104
  const content = loading ? /*#__PURE__*/ jsx(PageLoading, {}) : '暂无历史会话';
39
- return /*#__PURE__*/ jsx(DefaultPanelContainer, {
40
- children: content
105
+ return /*#__PURE__*/ jsx(MenuPanelContainer, {
106
+ children: /*#__PURE__*/ jsx(DefaultPanelContainer, {
107
+ children: content
108
+ })
41
109
  });
42
110
  }
43
- return originNode;
111
+ return /*#__PURE__*/ jsx(MenuPanelContainer, {
112
+ children: originNode
113
+ });
44
114
  },
45
115
  children: /*#__PURE__*/ jsx(Button, {
46
116
  onClick: refresh,
@@ -59,6 +129,36 @@ const DefaultPanelContainer = styled_components.div`
59
129
  border-radius: 8px;
60
130
  min-height: 100px;
61
131
  min-width: 200px;
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ box-shadow:
136
+ 0px 0px 4px 0px rgba(0, 0, 0, 0.02),
137
+ 0px 6px 12px 0px rgba(47, 53, 64, 0.12);
138
+ `;
139
+ const MenuItemLabel = styled_components.div`
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: space-between;
143
+ gap: 8px;
144
+ width: 100%;
145
+ .delete-btn {
146
+ opacity: 0;
147
+ visibility: hidden;
148
+ transition: opacity 0.2s ease;
149
+ }
150
+ &:hover .delete-btn {
151
+ opacity: 1;
152
+ visibility: visible;
153
+ }
154
+ `;
155
+ const MenuPanelContainer = styled_components.div`
156
+ max-height: 450px;
157
+ overflow: auto;
158
+ min-width: 200px;
159
+ background: #fff;
160
+ border: 1px solid rgba(5, 5, 5, 0.06);
161
+ border-radius: 8px;
62
162
  box-shadow:
63
163
  0px 0px 4px 0px rgba(0, 0, 0, 0.02),
64
164
  0px 6px 12px 0px rgba(47, 53, 64, 0.12);
@@ -8,10 +8,11 @@ function useFloat() {
8
8
  const Component = store.floats.find((f)=>f.key === visibleFloat?.key)?.render;
9
9
  const props = {
10
10
  record: visibleFloat?.record,
11
- onClose: ()=>{
11
+ onClose: (code)=>{
12
12
  store.hideFloat();
13
- if (visibleFloat?.onCloseCallback === true) store.refreshTable();
14
- else visibleFloat?.onCloseCallback?.();
13
+ if (visibleFloat?.onCloseCallback === true) {
14
+ if (-1 !== code) store.refreshTable();
15
+ } else visibleFloat?.onCloseCallback?.();
15
16
  },
16
17
  visible: true
17
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "listpage-next",
3
- "version": "0.0.234",
3
+ "version": "0.0.236",
4
4
  "description": "A React component library for creating filter forms with Ant Design",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",