@hkyhy/marsun-components-core 0.1.21 → 0.1.24
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/AgentHub/Chat/Detail/ChatAgentFab/style.module.scss.js +9 -9
- package/dist/components/AgentHub/Chat/utils/index.d.ts +2 -0
- package/dist/components/AgentHub/Chat/utils/smoothScroll.js +51 -0
- package/dist/components/AgentHub/Chat/utils/smoothScroll.js.map +1 -0
- package/dist/components/Empty/Empty.d.ts +16 -0
- package/dist/components/Empty/Empty.js +33 -0
- package/dist/components/Empty/Empty.js.map +1 -0
- package/dist/components/Empty/index.d.ts +2 -0
- package/dist/components/Empty/style.module.scss.js +7 -0
- package/dist/components/Empty/style.module.scss.js.map +1 -0
- package/dist/components/File/FilePreview/FilePreviewContent.js +11 -12
- package/dist/components/File/FilePreview/FilePreviewContent.js.map +1 -1
- package/dist/components/Filter/FilterDatePicker/index.d.ts +31 -0
- package/dist/components/Filter/FilterDatePicker/index.js +128 -0
- package/dist/components/Filter/FilterDatePicker/index.js.map +1 -0
- package/dist/components/Filter/FilterDatePicker/style.module.scss.js +10 -0
- package/dist/components/Filter/FilterDatePicker/style.module.scss.js.map +1 -0
- package/dist/components/Filter/FilterDateRange/index.d.ts +7 -2
- package/dist/components/Filter/FilterDateRange/index.js +96 -68
- package/dist/components/Filter/FilterDateRange/index.js.map +1 -1
- package/dist/components/Filter/index.d.ts +3 -0
- package/dist/components/Form/index.d.ts +6 -0
- package/dist/components/Form/kneFormInfo.d.ts +47 -0
- package/dist/components/Form/kneFormInfo.js +23 -0
- package/dist/components/Form/kneFormInfo.js.map +1 -0
- package/dist/components/Form/kneReactForm.d.ts +8 -0
- package/dist/components/Layout/PageSpin/index.js +5 -5
- package/dist/components/Layout/PageSpin/index.js.map +1 -1
- package/dist/components/TooltipInfo/TooltipInfo.js +11 -10
- package/dist/components/TooltipInfo/TooltipInfo.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +426 -374
- package/dist/index.js.map +1 -1
- package/dist/marsun-components-core.css +1 -1
- package/dist/styles/global.css +1 -1
- package/dist/theme/theme.js +9 -9
- package/dist/theme/theme.js.map +1 -1
- package/dist/theme/tokens.css +12 -0
- package/dist/utils/pickerDate.d.ts +9 -0
- package/dist/utils/pickerDate.js +33 -0
- package/dist/utils/pickerDate.js.map +1 -0
- package/package.json +4 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const a = {
|
|
2
|
-
"chat-agent-fab": "_chat-agent-
|
|
3
|
-
"chat-agent-fab-button": "_chat-agent-fab-
|
|
4
|
-
"chat-agent-fab-button--active": "_chat-agent-fab-button--
|
|
5
|
-
"chat-agent-fab-icon": "_chat-agent-fab-
|
|
6
|
-
"chat-agent-fab-panel": "_chat-agent-fab-
|
|
7
|
-
"chat-agent-fab-panel-body": "_chat-agent-fab-panel-
|
|
8
|
-
"chat-agent-fab-panel--expanded": "_chat-agent-fab-panel--
|
|
9
|
-
"chat-agent-fab-panel--fullscreen": "_chat-agent-fab-panel--
|
|
10
|
-
"chat-agent-fab-panel-body--expanded": "_chat-agent-fab-panel-body--
|
|
2
|
+
"chat-agent-fab": "_chat-agent-fab_14yq1_1",
|
|
3
|
+
"chat-agent-fab-button": "_chat-agent-fab-button_14yq1_9",
|
|
4
|
+
"chat-agent-fab-button--active": "_chat-agent-fab-button--active_14yq1_24",
|
|
5
|
+
"chat-agent-fab-icon": "_chat-agent-fab-icon_14yq1_28",
|
|
6
|
+
"chat-agent-fab-panel": "_chat-agent-fab-panel_14yq1_34",
|
|
7
|
+
"chat-agent-fab-panel-body": "_chat-agent-fab-panel-body_14yq1_45",
|
|
8
|
+
"chat-agent-fab-panel--expanded": "_chat-agent-fab-panel--expanded_14yq1_50",
|
|
9
|
+
"chat-agent-fab-panel--fullscreen": "_chat-agent-fab-panel--fullscreen_14yq1_54",
|
|
10
|
+
"chat-agent-fab-panel-body--expanded": "_chat-agent-fab-panel-body--expanded_14yq1_59"
|
|
11
11
|
};
|
|
12
12
|
export {
|
|
13
13
|
a as default
|
|
@@ -3,3 +3,5 @@ export { hasCitationMarkers, normalizeAssistantMarkdown, normalizeDisplayText, p
|
|
|
3
3
|
export type { ParsedAssistantContent } from './messageContent';
|
|
4
4
|
export { sanitizeMermaidChart, stripProseFromMermaid } from './sanitizeMermaidChart';
|
|
5
5
|
export { extractCitations, formatSessionTime, getSessionDisplayName, isWelcomeOnlyMessages, parseSessionMessages, toDisplayMessages, } from './sessionMessages';
|
|
6
|
+
export { animateScrollFromTopToBottom, animateScrollTo, getScrollBottom } from './smoothScroll';
|
|
7
|
+
export type { AnimateScrollOptions } from './smoothScroll';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const d = (t) => 1 - (1 - t) ** 5, T = (t, n, o = {}) => {
|
|
2
|
+
const { minDuration: i = 420, maxDuration: s = 880, msPerPixel: a = 0.32 } = o, r = Math.max(0, t.scrollHeight - t.clientHeight), c = Math.min(Math.max(0, n), r), l = t.scrollTop, m = c - l;
|
|
3
|
+
if (Math.abs(m) < 1)
|
|
4
|
+
return t.scrollTop = c, () => {
|
|
5
|
+
};
|
|
6
|
+
const f = Math.min(Math.max(Math.abs(m) * a, i), s), g = performance.now();
|
|
7
|
+
let e = 0, u = !1;
|
|
8
|
+
const h = (M) => {
|
|
9
|
+
if (u) return;
|
|
10
|
+
const p = Math.min((M - g) / f, 1);
|
|
11
|
+
t.scrollTop = l + m * d(p), p < 1 && (e = requestAnimationFrame(h));
|
|
12
|
+
};
|
|
13
|
+
return e = requestAnimationFrame(h), () => {
|
|
14
|
+
u = !0, cancelAnimationFrame(e);
|
|
15
|
+
};
|
|
16
|
+
}, x = (t) => Math.max(0, t.scrollHeight - t.clientHeight), F = (t, n = {}) => {
|
|
17
|
+
const o = [];
|
|
18
|
+
t.scrollTop = 0;
|
|
19
|
+
const i = () => {
|
|
20
|
+
o.push(
|
|
21
|
+
T(t, x(t), {
|
|
22
|
+
minDuration: 460,
|
|
23
|
+
maxDuration: 920,
|
|
24
|
+
msPerPixel: 0.34,
|
|
25
|
+
...n
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
const a = window.setTimeout(() => {
|
|
29
|
+
const r = x(t);
|
|
30
|
+
r - t.scrollTop > 6 && o.push(
|
|
31
|
+
T(t, r, {
|
|
32
|
+
minDuration: 180,
|
|
33
|
+
maxDuration: 320,
|
|
34
|
+
msPerPixel: 0.2
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
}, 120);
|
|
38
|
+
o.push(() => window.clearTimeout(a));
|
|
39
|
+
}, s = requestAnimationFrame(() => {
|
|
40
|
+
requestAnimationFrame(i);
|
|
41
|
+
});
|
|
42
|
+
return () => {
|
|
43
|
+
cancelAnimationFrame(s), o.forEach((a) => a());
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
export {
|
|
47
|
+
F as animateScrollFromTopToBottom,
|
|
48
|
+
T as animateScrollTo,
|
|
49
|
+
x as getScrollBottom
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=smoothScroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoothScroll.js","sources":["../../../../../src/components/AgentHub/Chat/utils/smoothScroll.ts"],"sourcesContent":["export interface AnimateScrollOptions {\n minDuration?: number;\n maxDuration?: number;\n msPerPixel?: number;\n}\n\nconst easeOutQuint = (progress: number) => 1 - (1 - progress) ** 5;\n\n/**\n * Smoothly scroll an element with a custom ease-out curve (softer than native smooth).\n */\nexport const animateScrollTo = (\n element: HTMLElement,\n targetTop: number,\n options: AnimateScrollOptions = {},\n): (() => void) => {\n const { minDuration = 420, maxDuration = 880, msPerPixel = 0.32 } = options;\n\n const maxTop = Math.max(0, element.scrollHeight - element.clientHeight);\n const clampedTarget = Math.min(Math.max(0, targetTop), maxTop);\n const startTop = element.scrollTop;\n const distance = clampedTarget - startTop;\n\n if (Math.abs(distance) < 1) {\n element.scrollTop = clampedTarget;\n return () => {};\n }\n\n const duration = Math.min(Math.max(Math.abs(distance) * msPerPixel, minDuration), maxDuration);\n const startTime = performance.now();\n let rafId = 0;\n let cancelled = false;\n\n const step = (now: number) => {\n if (cancelled) return;\n\n const progress = Math.min((now - startTime) / duration, 1);\n element.scrollTop = startTop + distance * easeOutQuint(progress);\n\n if (progress < 1) {\n rafId = requestAnimationFrame(step);\n }\n };\n\n rafId = requestAnimationFrame(step);\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(rafId);\n };\n};\n\nexport const getScrollBottom = (element: HTMLElement) =>\n Math.max(0, element.scrollHeight - element.clientHeight);\n\n/**\n * Session switch: reset to top, then ease to bottom; optional soft correction after layout shifts.\n */\nexport const animateScrollFromTopToBottom = (\n element: HTMLElement,\n options: AnimateScrollOptions = {},\n): (() => void) => {\n const cleanups: Array<() => void> = [];\n\n element.scrollTop = 0;\n\n const start = () => {\n cleanups.push(\n animateScrollTo(element, getScrollBottom(element), {\n minDuration: 460,\n maxDuration: 920,\n msPerPixel: 0.34,\n ...options,\n }),\n );\n\n const correctionTimer = window.setTimeout(() => {\n const bottom = getScrollBottom(element);\n const remaining = bottom - element.scrollTop;\n if (remaining > 6) {\n cleanups.push(\n animateScrollTo(element, bottom, {\n minDuration: 180,\n maxDuration: 320,\n msPerPixel: 0.2,\n }),\n );\n }\n }, 120);\n\n cleanups.push(() => window.clearTimeout(correctionTimer));\n };\n\n const raf = requestAnimationFrame(() => {\n requestAnimationFrame(start);\n });\n\n return () => {\n cancelAnimationFrame(raf);\n cleanups.forEach((cleanup) => cleanup());\n };\n};\n"],"names":["easeOutQuint","progress","animateScrollTo","element","targetTop","options","minDuration","maxDuration","msPerPixel","maxTop","clampedTarget","startTop","distance","duration","startTime","rafId","cancelled","step","now","getScrollBottom","animateScrollFromTopToBottom","cleanups","start","correctionTimer","bottom","raf","cleanup"],"mappings":"AAMA,MAAMA,IAAe,CAACC,MAAqB,KAAK,IAAIA,MAAa,GAKpDC,IAAkB,CAC7BC,GACAC,GACAC,IAAgC,CAAA,MACf;AACjB,QAAM,EAAE,aAAAC,IAAc,KAAK,aAAAC,IAAc,KAAK,YAAAC,IAAa,SAASH,GAE9DI,IAAS,KAAK,IAAI,GAAGN,EAAQ,eAAeA,EAAQ,YAAY,GAChEO,IAAgB,KAAK,IAAI,KAAK,IAAI,GAAGN,CAAS,GAAGK,CAAM,GACvDE,IAAWR,EAAQ,WACnBS,IAAWF,IAAgBC;AAEjC,MAAI,KAAK,IAAIC,CAAQ,IAAI;AACvB,WAAAT,EAAQ,YAAYO,GACb,MAAM;AAAA,IAAC;AAGhB,QAAMG,IAAW,KAAK,IAAI,KAAK,IAAI,KAAK,IAAID,CAAQ,IAAIJ,GAAYF,CAAW,GAAGC,CAAW,GACvFO,IAAY,YAAY,IAAA;AAC9B,MAAIC,IAAQ,GACRC,IAAY;AAEhB,QAAMC,IAAO,CAACC,MAAgB;AAC5B,QAAIF,EAAW;AAEf,UAAMf,IAAW,KAAK,KAAKiB,IAAMJ,KAAaD,GAAU,CAAC;AACzD,IAAAV,EAAQ,YAAYQ,IAAWC,IAAWZ,EAAaC,CAAQ,GAE3DA,IAAW,MACbc,IAAQ,sBAAsBE,CAAI;AAAA,EAEtC;AAEA,SAAAF,IAAQ,sBAAsBE,CAAI,GAE3B,MAAM;AACX,IAAAD,IAAY,IACZ,qBAAqBD,CAAK;AAAA,EAC5B;AACF,GAEaI,IAAkB,CAAChB,MAC9B,KAAK,IAAI,GAAGA,EAAQ,eAAeA,EAAQ,YAAY,GAK5CiB,IAA+B,CAC1CjB,GACAE,IAAgC,OACf;AACjB,QAAMgB,IAA8B,CAAA;AAEpC,EAAAlB,EAAQ,YAAY;AAEpB,QAAMmB,IAAQ,MAAM;AAClB,IAAAD,EAAS;AAAA,MACPnB,EAAgBC,GAASgB,EAAgBhB,CAAO,GAAG;AAAA,QACjD,aAAa;AAAA,QACb,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,GAAGE;AAAA,MAAA,CACJ;AAAA,IAAA;AAGH,UAAMkB,IAAkB,OAAO,WAAW,MAAM;AAC9C,YAAMC,IAASL,EAAgBhB,CAAO;AAEtC,MADkBqB,IAASrB,EAAQ,YACnB,KACdkB,EAAS;AAAA,QACPnB,EAAgBC,GAASqB,GAAQ;AAAA,UAC/B,aAAa;AAAA,UACb,aAAa;AAAA,UACb,YAAY;AAAA,QAAA,CACb;AAAA,MAAA;AAAA,IAGP,GAAG,GAAG;AAEN,IAAAH,EAAS,KAAK,MAAM,OAAO,aAAaE,CAAe,CAAC;AAAA,EAC1D,GAEME,IAAM,sBAAsB,MAAM;AACtC,0BAAsBH,CAAK;AAAA,EAC7B,CAAC;AAED,SAAO,MAAM;AACX,yBAAqBG,CAAG,GACxBJ,EAAS,QAAQ,CAACK,MAAYA,EAAA,CAAS;AAAA,EACzC;AACF;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EmptyProps } from 'antd';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
export type EmptyIconType = 'default' | 'simple';
|
|
4
|
+
export interface MarsunEmptyProps extends Omit<EmptyProps, 'image' | 'description'> {
|
|
5
|
+
/** 是否展示图标,默认 true */
|
|
6
|
+
showIcon?: boolean;
|
|
7
|
+
/** 预设图标:default=antd 默认图,simple=PRESENTED_IMAGE_SIMPLE */
|
|
8
|
+
iconType?: EmptyIconType;
|
|
9
|
+
/** 自定义图标节点,优先级高于 iconType */
|
|
10
|
+
icon?: ReactNode;
|
|
11
|
+
/** 描述文案,不传则不渲染 description */
|
|
12
|
+
description?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
/** 基于 antd Empty 的空态展示,统一 Icon / description 可选语义 */
|
|
15
|
+
declare const MarsunEmpty: React.FC<MarsunEmptyProps>;
|
|
16
|
+
export default MarsunEmpty;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import { Empty as s } from "antd";
|
|
3
|
+
import i from "classnames";
|
|
4
|
+
import u from "./style.module.scss.js";
|
|
5
|
+
function l({
|
|
6
|
+
showIcon: e,
|
|
7
|
+
iconType: m,
|
|
8
|
+
icon: r
|
|
9
|
+
}) {
|
|
10
|
+
if (e === !1) return !1;
|
|
11
|
+
if (r) return r;
|
|
12
|
+
if (m === "simple") return s.PRESENTED_IMAGE_SIMPLE;
|
|
13
|
+
}
|
|
14
|
+
const d = ({
|
|
15
|
+
showIcon: e = !0,
|
|
16
|
+
iconType: m = "default",
|
|
17
|
+
icon: r,
|
|
18
|
+
description: t,
|
|
19
|
+
className: a,
|
|
20
|
+
...f
|
|
21
|
+
}) => /* @__PURE__ */ o(
|
|
22
|
+
s,
|
|
23
|
+
{
|
|
24
|
+
className: i("marsun-empty", u["marsun-empty"], a),
|
|
25
|
+
image: l({ showIcon: e, iconType: m, icon: r }),
|
|
26
|
+
description: t !== void 0 ? t : !1,
|
|
27
|
+
...f
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
export {
|
|
31
|
+
d as default
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=Empty.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Empty.js","sources":["../../../src/components/Empty/Empty.tsx"],"sourcesContent":["import { Empty as AntEmpty } from 'antd';\nimport type { EmptyProps } from 'antd';\nimport classNames from 'classnames';\nimport type { ReactNode } from 'react';\nimport styles from './style.module.scss';\n\nexport type EmptyIconType = 'default' | 'simple';\n\nexport interface MarsunEmptyProps extends Omit<EmptyProps, 'image' | 'description'> {\n /** 是否展示图标,默认 true */\n showIcon?: boolean;\n /** 预设图标:default=antd 默认图,simple=PRESENTED_IMAGE_SIMPLE */\n iconType?: EmptyIconType;\n /** 自定义图标节点,优先级高于 iconType */\n icon?: ReactNode;\n /** 描述文案,不传则不渲染 description */\n description?: ReactNode;\n}\n\nfunction resolveImage({\n showIcon,\n iconType,\n icon,\n}: Pick<MarsunEmptyProps, 'showIcon' | 'iconType' | 'icon'>): EmptyProps['image'] {\n if (showIcon === false) return false;\n if (icon) return icon;\n if (iconType === 'simple') return AntEmpty.PRESENTED_IMAGE_SIMPLE;\n return undefined;\n}\n\n/** 基于 antd Empty 的空态展示,统一 Icon / description 可选语义 */\nconst MarsunEmpty: React.FC<MarsunEmptyProps> = ({\n showIcon = true,\n iconType = 'default',\n icon,\n description,\n className,\n ...rest\n}) => (\n <AntEmpty\n className={classNames('marsun-empty', styles['marsun-empty'], className)}\n image={resolveImage({ showIcon, iconType, icon })}\n description={description !== undefined ? description : false}\n {...rest}\n />\n);\n\nexport default MarsunEmpty;\n"],"names":["resolveImage","showIcon","iconType","icon","AntEmpty","MarsunEmpty","description","className","rest","jsx","classNames","styles"],"mappings":";;;;AAmBA,SAASA,EAAa;AAAA,EACpB,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,MAAAC;AACF,GAAkF;AAChF,MAAIF,MAAa,GAAO,QAAO;AAC/B,MAAIE,EAAM,QAAOA;AACjB,MAAID,MAAa,SAAU,QAAOE,EAAS;AAE7C;AAGA,MAAMC,IAA0C,CAAC;AAAA,EAC/C,UAAAJ,IAAW;AAAA,EACX,UAAAC,IAAW;AAAA,EACX,MAAAC;AAAA,EACA,aAAAG;AAAA,EACA,WAAAC;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC;AAAA,EAACL;AAAAA,EAAA;AAAA,IACC,WAAWM,EAAW,gBAAgBC,EAAO,cAAc,GAAGJ,CAAS;AAAA,IACvE,OAAOP,EAAa,EAAE,UAAAC,GAAU,UAAAC,GAAU,MAAAC,GAAM;AAAA,IAChD,aAAaG,MAAgB,SAAYA,IAAc;AAAA,IACtD,GAAGE;AAAA,EAAA;AACN;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -23,7 +23,7 @@ async function B(r, e) {
|
|
|
23
23
|
const t = s.init(r);
|
|
24
24
|
return await t.preview(e), () => t.destroy();
|
|
25
25
|
}
|
|
26
|
-
async function
|
|
26
|
+
async function M(r, e) {
|
|
27
27
|
const { renderAsync: s } = await import("docx-preview"), a = new Blob([e]);
|
|
28
28
|
await s(a, r, r, {
|
|
29
29
|
inWrapper: !0,
|
|
@@ -32,11 +32,11 @@ async function C(r, e) {
|
|
|
32
32
|
breakPages: !0
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
async function
|
|
35
|
+
async function T(r, e, s) {
|
|
36
36
|
const { init: a } = await import("pptx-preview"), t = a(r, { width: s, height: Math.round(s * 0.5625), mode: "list" });
|
|
37
37
|
return await t.preview(e), () => t.destroy();
|
|
38
38
|
}
|
|
39
|
-
function
|
|
39
|
+
function W(r, e) {
|
|
40
40
|
const s = new TextDecoder("utf-8"), a = document.createElement("pre");
|
|
41
41
|
a.className = o["file-preview-text"], a.textContent = s.decode(e), r.appendChild(a);
|
|
42
42
|
}
|
|
@@ -60,11 +60,11 @@ const D = ({
|
|
|
60
60
|
if (i === "excel")
|
|
61
61
|
t.current = await B(f, c);
|
|
62
62
|
else if (i === "word")
|
|
63
|
-
await
|
|
63
|
+
await M(f, c);
|
|
64
64
|
else if (i === "ppt") {
|
|
65
65
|
const y = f.clientWidth || 852;
|
|
66
|
-
t.current = await
|
|
67
|
-
} else i === "text" &&
|
|
66
|
+
t.current = await T(f, c, y);
|
|
67
|
+
} else i === "text" && W(f, c);
|
|
68
68
|
} catch (c) {
|
|
69
69
|
l || w(c instanceof Error ? c.message : "预览加载失败");
|
|
70
70
|
} finally {
|
|
@@ -75,14 +75,13 @@ const D = ({
|
|
|
75
75
|
var c;
|
|
76
76
|
l = !0, (c = t.current) == null || c.call(t), t.current = void 0, f.innerHTML = "";
|
|
77
77
|
};
|
|
78
|
-
}, [e, i, r.id, r.name]), e ? i === "image" ? /* @__PURE__ */ n("div", { className: o["file-preview-media-wrap"], children: /* @__PURE__ */ n("img", { src: e, alt: r.name, className: o["file-preview-image"] }) }) : i === "pdf" || i === "iframe" ? /* @__PURE__ */ n(
|
|
79
|
-
"
|
|
78
|
+
}, [e, i, r.id, r.name]), e ? i === "image" ? /* @__PURE__ */ n("div", { className: o["file-preview-media-wrap"], children: /* @__PURE__ */ n("img", { src: e, alt: r.name, className: o["file-preview-image"] }) }) : i === "pdf" || i === "iframe" ? /* @__PURE__ */ n("iframe", { src: e, title: r.name, className: o["file-preview-iframe"] }) : i === "video" ? /* @__PURE__ */ n("div", { className: o["file-preview-media-wrap"], children: /* @__PURE__ */ n("video", { src: e, controls: !0, className: o["file-preview-video"] }) }) : i === "audio" ? /* @__PURE__ */ n("div", { className: o["file-preview-audio-wrap"], children: /* @__PURE__ */ n("audio", { src: e, controls: !0, className: o["file-preview-audio"] }) }) : i === "unsupported" ? /* @__PURE__ */ n(u, { description: s }) : P(i) ? /* @__PURE__ */ n(
|
|
79
|
+
"div",
|
|
80
80
|
{
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
className: o["file-preview-iframe"]
|
|
81
|
+
className: b(o["file-preview-office"], o["file-preview-office-wrap"]),
|
|
82
|
+
children: /* @__PURE__ */ n(x, { spinning: d, classNames: { root: o["file-preview-office-spin"] }, children: p ? /* @__PURE__ */ n(u, { description: p }) : /* @__PURE__ */ n("div", { ref: a, className: o["file-preview-office-inner"] }) })
|
|
84
83
|
}
|
|
85
|
-
) :
|
|
84
|
+
) : /* @__PURE__ */ n(u, { description: s }) : /* @__PURE__ */ n(u, { description: "无可预览地址" });
|
|
86
85
|
};
|
|
87
86
|
export {
|
|
88
87
|
D as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewContent.js","sources":["../../../../src/components/File/FilePreview/FilePreviewContent.tsx"],"sourcesContent":["import { Empty, Spin } from 'antd';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { getPreviewKind, needsBlobPreview } from '../previewKind';\nimport type { FileDisplayItem } from '../types';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\ninterface FilePreviewContentProps {\n file: FileDisplayItem;\n previewUrl?: string;\n unsupportedMessage?: string;\n}\n\nasync function fetchPreviewBlob(url: string): Promise<ArrayBuffer> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`预览加载失败 (${res.status})`);\n return res.arrayBuffer();\n}\n\nasync function renderExcel(container: HTMLElement, data: ArrayBuffer) {\n const [{ default: jsPreviewExcel }] = await Promise.all([\n import('@js-preview/excel'),\n import('@js-preview/excel/lib/index.css'),\n ]);\n const height = Math.max(\n container.parentElement?.clientHeight ?? 0,\n Math.round(window.innerHeight * 0.65),\n 480,\n );\n container.style.height = `${height}px`;\n const instance = jsPreviewExcel.init(container);\n await instance.preview(data);\n return () => instance.destroy();\n}\n\nasync function renderWord(container: HTMLElement, data: ArrayBuffer) {\n const { renderAsync } = await import('docx-preview');\n const blob = new Blob([data]);\n await renderAsync(blob, container, container, {\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n breakPages: true,\n });\n}\n\nasync function renderPpt(container: HTMLElement, data: ArrayBuffer, width: number) {\n const { init } = await import('pptx-preview');\n const previewer = init(container, { width, height: Math.round(width * 0.5625), mode: 'list' });\n await previewer.preview(data);\n return () => previewer.destroy();\n}\n\nfunction renderText(container: HTMLElement, data: ArrayBuffer) {\n const decoder = new TextDecoder('utf-8');\n const pre = document.createElement('pre');\n pre.className = styles['file-preview-text'] ?? '';\n pre.textContent = decoder.decode(data);\n container.appendChild(pre);\n}\n\nconst FilePreviewContent: React.FC<FilePreviewContentProps> = ({\n file,\n previewUrl,\n unsupportedMessage = '暂不支持预览此文件类型',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const cleanupRef = useRef<(() => void) | void>(undefined);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const kind = getPreviewKind(file);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !previewUrl) return undefined;\n\n let cancelled = false;\n cleanupRef.current?.();\n cleanupRef.current = undefined;\n container.innerHTML = '';\n setError(null);\n\n const run = async () => {\n if (kind === 'image') return;\n if (kind === 'pdf' || kind === 'iframe') return;\n if (kind === 'video' || kind === 'audio') return;\n if (kind === 'unsupported') return;\n\n setLoading(true);\n try {\n const data = await fetchPreviewBlob(previewUrl);\n if (cancelled) return;\n\n if (kind === 'excel') {\n cleanupRef.current = await renderExcel(container, data);\n } else if (kind === 'word') {\n await renderWord(container, data);\n } else if (kind === 'ppt') {\n const width = container.clientWidth || 852;\n cleanupRef.current = await renderPpt(container, data, width);\n } else if (kind === 'text') {\n renderText(container, data);\n }\n } catch (err) {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : '预览加载失败');\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n\n void run();\n\n return () => {\n cancelled = true;\n cleanupRef.current?.();\n cleanupRef.current = undefined;\n container.innerHTML = '';\n };\n }, [previewUrl, kind, file.id, file.name]);\n\n if (!previewUrl) {\n return <Empty description=\"无可预览地址\" />;\n }\n\n if (kind === 'image') {\n return (\n <div className={styles['file-preview-media-wrap']}>\n <img src={previewUrl} alt={file.name} className={styles['file-preview-image']} />\n </div>\n );\n }\n\n if (kind === 'pdf' || kind === 'iframe') {\n return
|
|
1
|
+
{"version":3,"file":"FilePreviewContent.js","sources":["../../../../src/components/File/FilePreview/FilePreviewContent.tsx"],"sourcesContent":["import { Empty, Spin } from 'antd';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { getPreviewKind, needsBlobPreview } from '../previewKind';\nimport type { FileDisplayItem } from '../types';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\ninterface FilePreviewContentProps {\n file: FileDisplayItem;\n previewUrl?: string;\n unsupportedMessage?: string;\n}\n\nasync function fetchPreviewBlob(url: string): Promise<ArrayBuffer> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`预览加载失败 (${res.status})`);\n return res.arrayBuffer();\n}\n\nasync function renderExcel(container: HTMLElement, data: ArrayBuffer) {\n const [{ default: jsPreviewExcel }] = await Promise.all([\n import('@js-preview/excel'),\n import('@js-preview/excel/lib/index.css'),\n ]);\n const height = Math.max(\n container.parentElement?.clientHeight ?? 0,\n Math.round(window.innerHeight * 0.65),\n 480,\n );\n container.style.height = `${height}px`;\n const instance = jsPreviewExcel.init(container);\n await instance.preview(data);\n return () => instance.destroy();\n}\n\nasync function renderWord(container: HTMLElement, data: ArrayBuffer) {\n const { renderAsync } = await import('docx-preview');\n const blob = new Blob([data]);\n await renderAsync(blob, container, container, {\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n breakPages: true,\n });\n}\n\nasync function renderPpt(container: HTMLElement, data: ArrayBuffer, width: number) {\n const { init } = await import('pptx-preview');\n const previewer = init(container, { width, height: Math.round(width * 0.5625), mode: 'list' });\n await previewer.preview(data);\n return () => previewer.destroy();\n}\n\nfunction renderText(container: HTMLElement, data: ArrayBuffer) {\n const decoder = new TextDecoder('utf-8');\n const pre = document.createElement('pre');\n pre.className = styles['file-preview-text'] ?? '';\n pre.textContent = decoder.decode(data);\n container.appendChild(pre);\n}\n\nconst FilePreviewContent: React.FC<FilePreviewContentProps> = ({\n file,\n previewUrl,\n unsupportedMessage = '暂不支持预览此文件类型',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const cleanupRef = useRef<(() => void) | void>(undefined);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const kind = getPreviewKind(file);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !previewUrl) return undefined;\n\n let cancelled = false;\n cleanupRef.current?.();\n cleanupRef.current = undefined;\n container.innerHTML = '';\n setError(null);\n\n const run = async () => {\n if (kind === 'image') return;\n if (kind === 'pdf' || kind === 'iframe') return;\n if (kind === 'video' || kind === 'audio') return;\n if (kind === 'unsupported') return;\n\n setLoading(true);\n try {\n const data = await fetchPreviewBlob(previewUrl);\n if (cancelled) return;\n\n if (kind === 'excel') {\n cleanupRef.current = await renderExcel(container, data);\n } else if (kind === 'word') {\n await renderWord(container, data);\n } else if (kind === 'ppt') {\n const width = container.clientWidth || 852;\n cleanupRef.current = await renderPpt(container, data, width);\n } else if (kind === 'text') {\n renderText(container, data);\n }\n } catch (err) {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : '预览加载失败');\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n\n void run();\n\n return () => {\n cancelled = true;\n cleanupRef.current?.();\n cleanupRef.current = undefined;\n container.innerHTML = '';\n };\n }, [previewUrl, kind, file.id, file.name]);\n\n if (!previewUrl) {\n return <Empty description=\"无可预览地址\" />;\n }\n\n if (kind === 'image') {\n return (\n <div className={styles['file-preview-media-wrap']}>\n <img src={previewUrl} alt={file.name} className={styles['file-preview-image']} />\n </div>\n );\n }\n\n if (kind === 'pdf' || kind === 'iframe') {\n return <iframe src={previewUrl} title={file.name} className={styles['file-preview-iframe']} />;\n }\n\n if (kind === 'video') {\n return (\n <div className={styles['file-preview-media-wrap']}>\n <video src={previewUrl} controls className={styles['file-preview-video']} />\n </div>\n );\n }\n\n if (kind === 'audio') {\n return (\n <div className={styles['file-preview-audio-wrap']}>\n <audio src={previewUrl} controls className={styles['file-preview-audio']} />\n </div>\n );\n }\n\n if (kind === 'unsupported') {\n return <Empty description={unsupportedMessage} />;\n }\n\n if (needsBlobPreview(kind)) {\n return (\n <div\n className={classNames(styles['file-preview-office'], styles['file-preview-office-wrap'])}\n >\n <Spin spinning={loading} classNames={{ root: styles['file-preview-office-spin'] }}>\n {error ? (\n <Empty description={error} />\n ) : (\n <div ref={containerRef} className={styles['file-preview-office-inner']} />\n )}\n </Spin>\n </div>\n );\n }\n\n return <Empty description={unsupportedMessage} />;\n};\n\nexport default FilePreviewContent;\n"],"names":["fetchPreviewBlob","url","res","renderExcel","container","data","jsPreviewExcel","height","_a","instance","renderWord","renderAsync","blob","renderPpt","width","init","previewer","renderText","decoder","pre","styles","FilePreviewContent","file","previewUrl","unsupportedMessage","containerRef","useRef","cleanupRef","loading","setLoading","useState","error","setError","kind","getPreviewKind","useEffect","cancelled","err","jsx","Empty","needsBlobPreview","classNames","Spin"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Dayjs } from 'dayjs';
|
|
2
|
+
import { default as React } from 'react';
|
|
3
|
+
import { DatePickerGranularity } from '../../../utils/pickerDate';
|
|
4
|
+
import { BaseFilterProps } from '../types';
|
|
5
|
+
/** 单值快捷选项 */
|
|
6
|
+
interface SingleQuickOption {
|
|
7
|
+
key: string;
|
|
8
|
+
label: string;
|
|
9
|
+
getValue: () => Dayjs;
|
|
10
|
+
}
|
|
11
|
+
interface FilterDatePickerProps extends BaseFilterProps {
|
|
12
|
+
value?: string | null;
|
|
13
|
+
onChange?: (value: string | null) => void;
|
|
14
|
+
/** 选择粒度:日 / 月 / 年 */
|
|
15
|
+
picker?: DatePickerGranularity;
|
|
16
|
+
/** 默认值:与默认相同时视为未筛选(除非 showDefaultAsSelected) */
|
|
17
|
+
defaultValue?: string;
|
|
18
|
+
/** 为 true 时,value 等于 defaultValue 仍展示在已选 Tag 中 */
|
|
19
|
+
showDefaultAsSelected?: boolean;
|
|
20
|
+
showQuickOptions?: boolean;
|
|
21
|
+
quickOptions?: SingleQuickOption[];
|
|
22
|
+
placeholder?: string;
|
|
23
|
+
disabledDate?: (current: Dayjs) => boolean;
|
|
24
|
+
}
|
|
25
|
+
declare function getBuiltInQuickOptions(picker: DatePickerGranularity): SingleQuickOption[];
|
|
26
|
+
declare function isSamePickerValue(a?: string | null, b?: string): boolean;
|
|
27
|
+
declare function findMatchingQuickKey(value: string | null | undefined, picker: DatePickerGranularity, opts: SingleQuickOption[]): string | null;
|
|
28
|
+
declare const FilterDatePicker: React.FC<FilterDatePickerProps>;
|
|
29
|
+
export default FilterDatePicker;
|
|
30
|
+
export type { FilterDatePickerProps, SingleQuickOption };
|
|
31
|
+
export { findMatchingQuickKey, getBuiltInQuickOptions, isSamePickerValue };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { jsxs as E, jsx as h } from "react/jsx-runtime";
|
|
2
|
+
import { DatePicker as H } from "antd";
|
|
3
|
+
import I from "dayjs";
|
|
4
|
+
import { useState as O, useMemo as g, useEffect as j } from "react";
|
|
5
|
+
import { parsePickerValue as u, formatPickerValue as K } from "../../../utils/pickerDate.js";
|
|
6
|
+
import L from "../FilterPopover/index.js";
|
|
7
|
+
import { resolveHidden as M } from "../types.js";
|
|
8
|
+
import { useFilterRegister as T } from "../useFilterState.js";
|
|
9
|
+
import c from "./style.module.scss.js";
|
|
10
|
+
import P from "classnames";
|
|
11
|
+
function Y(r) {
|
|
12
|
+
const e = I();
|
|
13
|
+
return r === "year" ? [{ key: "thisYear", label: "今年", getValue: () => e.startOf("year") }] : r === "month" ? [{ key: "thisMonth", label: "本月", getValue: () => e.startOf("month") }] : [{ key: "today", label: "今天", getValue: () => e.startOf("day") }];
|
|
14
|
+
}
|
|
15
|
+
function w(r, e) {
|
|
16
|
+
return !r && !e ? !0 : !r || !e ? !1 : r === e;
|
|
17
|
+
}
|
|
18
|
+
function z(r, e, t) {
|
|
19
|
+
if (!r) return null;
|
|
20
|
+
const i = u(r, e);
|
|
21
|
+
if (!i.isValid()) return null;
|
|
22
|
+
for (const n of t) {
|
|
23
|
+
const m = n.getValue(), d = e === "year" ? "year" : e === "month" ? "month" : "day";
|
|
24
|
+
if (m.isSame(i, d)) return n.key;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const it = ({
|
|
29
|
+
filterKey: r,
|
|
30
|
+
label: e,
|
|
31
|
+
value: t,
|
|
32
|
+
onChange: i,
|
|
33
|
+
picker: n = "date",
|
|
34
|
+
defaultValue: m,
|
|
35
|
+
showDefaultAsSelected: d = !1,
|
|
36
|
+
showQuickOptions: q = !1,
|
|
37
|
+
quickOptions: N,
|
|
38
|
+
placeholder: R,
|
|
39
|
+
disabledDate: S,
|
|
40
|
+
active: A,
|
|
41
|
+
hidden: k
|
|
42
|
+
}) => {
|
|
43
|
+
const [b, p] = O(!1), [y, l] = O(t ? u(t, n) : null), [x, o] = O(null), f = T(), a = g(
|
|
44
|
+
() => N ?? (q ? Y(n) : []),
|
|
45
|
+
[N, q, n]
|
|
46
|
+
), F = (s) => {
|
|
47
|
+
o(z(s, n, a));
|
|
48
|
+
}, Q = () => {
|
|
49
|
+
t ? (l(u(t, n)), F(t)) : (l(null), o(null));
|
|
50
|
+
};
|
|
51
|
+
j(() => {
|
|
52
|
+
t ? (l(u(t, n)), F(t)) : (l(null), o(null));
|
|
53
|
+
}, [t, n, a]);
|
|
54
|
+
const V = d ? !!t : !!t && !w(t, m), D = g(() => !V || !t ? "" : t, [V, t]);
|
|
55
|
+
return j(() => {
|
|
56
|
+
if (f) {
|
|
57
|
+
if (M(k)) {
|
|
58
|
+
f.unregister(r);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
D ? f.register(r, { label: e, valueLabel: D, onRemove: () => i == null ? void 0 : i(null) }) : f.unregister(r);
|
|
62
|
+
}
|
|
63
|
+
}, [D, r, e, k]), M(k) ? null : /* @__PURE__ */ E(
|
|
64
|
+
L,
|
|
65
|
+
{
|
|
66
|
+
label: e,
|
|
67
|
+
active: A || V,
|
|
68
|
+
open: b,
|
|
69
|
+
onOpenChange: (s) => {
|
|
70
|
+
Q(), p(s);
|
|
71
|
+
},
|
|
72
|
+
onConfirm: () => {
|
|
73
|
+
y ? i == null || i(K(y, n)) : i == null || i(null), p(!1);
|
|
74
|
+
},
|
|
75
|
+
onReset: () => {
|
|
76
|
+
Q(), p(!1);
|
|
77
|
+
},
|
|
78
|
+
children: [
|
|
79
|
+
a.length > 0 ? /* @__PURE__ */ h(
|
|
80
|
+
"div",
|
|
81
|
+
{
|
|
82
|
+
className: P(
|
|
83
|
+
"filter-date-picker-quick-options",
|
|
84
|
+
c["filter-date-picker-quick-options"]
|
|
85
|
+
),
|
|
86
|
+
children: a.map((s) => /* @__PURE__ */ h(
|
|
87
|
+
"span",
|
|
88
|
+
{
|
|
89
|
+
className: P(
|
|
90
|
+
"filter-date-picker-quick-option",
|
|
91
|
+
c["filter-date-picker-quick-option"],
|
|
92
|
+
x === s.key && "filter-date-picker-quick-option-active",
|
|
93
|
+
x === s.key && c["filter-date-picker-quick-option-active"]
|
|
94
|
+
),
|
|
95
|
+
onClick: () => {
|
|
96
|
+
const B = s.getValue();
|
|
97
|
+
l(B), o(s.key);
|
|
98
|
+
},
|
|
99
|
+
children: s.label
|
|
100
|
+
},
|
|
101
|
+
s.key
|
|
102
|
+
))
|
|
103
|
+
}
|
|
104
|
+
) : null,
|
|
105
|
+
/* @__PURE__ */ h(
|
|
106
|
+
H,
|
|
107
|
+
{
|
|
108
|
+
className: P("filter-date-picker", c["filter-date-picker"]),
|
|
109
|
+
picker: n,
|
|
110
|
+
value: y,
|
|
111
|
+
placeholder: R,
|
|
112
|
+
disabledDate: S,
|
|
113
|
+
onChange: (s) => {
|
|
114
|
+
l(s), o(null);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
export {
|
|
123
|
+
it as default,
|
|
124
|
+
z as findMatchingQuickKey,
|
|
125
|
+
Y as getBuiltInQuickOptions,
|
|
126
|
+
w as isSamePickerValue
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/Filter/FilterDatePicker/index.tsx"],"sourcesContent":["import { DatePicker } from 'antd';\nimport dayjs, { type Dayjs } from 'dayjs';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport {\n formatPickerValue,\n parsePickerValue,\n type DatePickerGranularity,\n} from '@/utils/pickerDate';\nimport FilterPopover from '../FilterPopover';\nimport type { BaseFilterProps } from '../types';\nimport { resolveHidden } from '../types';\nimport { useFilterRegister } from '../useFilterState';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\n/** 单值快捷选项 */\ninterface SingleQuickOption {\n key: string;\n label: string;\n getValue: () => Dayjs;\n}\n\ninterface FilterDatePickerProps extends BaseFilterProps {\n value?: string | null;\n onChange?: (value: string | null) => void;\n /** 选择粒度:日 / 月 / 年 */\n picker?: DatePickerGranularity;\n /** 默认值:与默认相同时视为未筛选(除非 showDefaultAsSelected) */\n defaultValue?: string;\n /** 为 true 时,value 等于 defaultValue 仍展示在已选 Tag 中 */\n showDefaultAsSelected?: boolean;\n showQuickOptions?: boolean;\n quickOptions?: SingleQuickOption[];\n placeholder?: string;\n disabledDate?: (current: Dayjs) => boolean;\n}\n\nfunction getBuiltInQuickOptions(picker: DatePickerGranularity): SingleQuickOption[] {\n const now = dayjs();\n if (picker === 'year') {\n return [{ key: 'thisYear', label: '今年', getValue: () => now.startOf('year') }];\n }\n if (picker === 'month') {\n return [{ key: 'thisMonth', label: '本月', getValue: () => now.startOf('month') }];\n }\n return [{ key: 'today', label: '今天', getValue: () => now.startOf('day') }];\n}\n\nfunction isSamePickerValue(a?: string | null, b?: string): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n return a === b;\n}\n\nfunction findMatchingQuickKey(\n value: string | null | undefined,\n picker: DatePickerGranularity,\n opts: SingleQuickOption[],\n): string | null {\n if (!value) return null;\n const current = parsePickerValue(value, picker);\n if (!current.isValid()) return null;\n for (const opt of opts) {\n const candidate = opt.getValue();\n const unit = picker === 'year' ? 'year' : picker === 'month' ? 'month' : 'day';\n if (candidate.isSame(current, unit)) return opt.key;\n }\n return null;\n}\n\nconst FilterDatePicker: React.FC<FilterDatePickerProps> = ({\n filterKey,\n label,\n value,\n onChange,\n picker = 'date',\n defaultValue,\n showDefaultAsSelected = false,\n showQuickOptions = false,\n quickOptions,\n placeholder,\n disabledDate,\n active,\n hidden,\n}) => {\n const [open, setOpen] = useState(false);\n const [draft, setDraft] = useState<Dayjs | null>(value ? parsePickerValue(value, picker) : null);\n const [activeQuickKey, setActiveQuickKey] = useState<string | null>(null);\n\n const registerFn = useFilterRegister();\n const opts = useMemo(\n () => quickOptions ?? (showQuickOptions ? getBuiltInQuickOptions(picker) : []),\n [quickOptions, showQuickOptions, picker],\n );\n\n const syncActiveQuickKey = (nextValue: string | null | undefined) => {\n setActiveQuickKey(findMatchingQuickKey(nextValue, picker, opts));\n };\n\n const revertToCommitted = () => {\n if (value) {\n setDraft(parsePickerValue(value, picker));\n syncActiveQuickKey(value);\n } else {\n setDraft(null);\n setActiveQuickKey(null);\n }\n };\n\n useEffect(() => {\n if (value) {\n setDraft(parsePickerValue(value, picker));\n syncActiveQuickKey(value);\n } else {\n setDraft(null);\n setActiveQuickKey(null);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value, picker, opts]);\n\n const hasNonDefaultValue = showDefaultAsSelected\n ? !!value\n : !!value && !isSamePickerValue(value, defaultValue);\n\n const valueLabel = useMemo(() => {\n if (!hasNonDefaultValue || !value) return '';\n return value;\n }, [hasNonDefaultValue, value]);\n\n useEffect(() => {\n if (!registerFn) return;\n if (resolveHidden(hidden)) {\n registerFn.unregister(filterKey);\n return;\n }\n if (valueLabel) {\n registerFn.register(filterKey, { label, valueLabel, onRemove: () => onChange?.(null) });\n } else {\n registerFn.unregister(filterKey);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [valueLabel, filterKey, label, hidden]);\n\n if (resolveHidden(hidden)) return null;\n\n const handleConfirm = () => {\n if (draft) {\n onChange?.(formatPickerValue(draft, picker));\n } else {\n onChange?.(null);\n }\n setOpen(false);\n };\n\n const handleDiscardDraft = () => {\n revertToCommitted();\n setOpen(false);\n };\n\n const handleOpenChange = (nextOpen: boolean) => {\n revertToCommitted();\n setOpen(nextOpen);\n };\n\n return (\n <FilterPopover\n label={label}\n active={active || hasNonDefaultValue}\n open={open}\n onOpenChange={handleOpenChange}\n onConfirm={handleConfirm}\n onReset={handleDiscardDraft}\n >\n {opts.length > 0 ? (\n <div\n className={classNames(\n 'filter-date-picker-quick-options',\n styles['filter-date-picker-quick-options'],\n )}\n >\n {opts.map((opt) => (\n <span\n key={opt.key}\n className={classNames(\n 'filter-date-picker-quick-option',\n styles['filter-date-picker-quick-option'],\n activeQuickKey === opt.key && 'filter-date-picker-quick-option-active',\n activeQuickKey === opt.key && styles['filter-date-picker-quick-option-active'],\n )}\n onClick={() => {\n const next = opt.getValue();\n setDraft(next);\n setActiveQuickKey(opt.key);\n }}\n >\n {opt.label}\n </span>\n ))}\n </div>\n ) : null}\n <DatePicker\n className={classNames('filter-date-picker', styles['filter-date-picker'])}\n picker={picker}\n value={draft}\n placeholder={placeholder}\n disabledDate={disabledDate}\n onChange={(next) => {\n setDraft(next);\n setActiveQuickKey(null);\n }}\n />\n </FilterPopover>\n );\n};\n\nexport default FilterDatePicker;\nexport type { FilterDatePickerProps, SingleQuickOption };\nexport { findMatchingQuickKey, getBuiltInQuickOptions, isSamePickerValue };\n"],"names":["getBuiltInQuickOptions","picker","now","dayjs","isSamePickerValue","a","b","findMatchingQuickKey","value","opts","current","parsePickerValue","opt","candidate","unit","FilterDatePicker","filterKey","label","onChange","defaultValue","showDefaultAsSelected","showQuickOptions","quickOptions","placeholder","disabledDate","active","hidden","open","setOpen","useState","draft","setDraft","activeQuickKey","setActiveQuickKey","registerFn","useFilterRegister","useMemo","syncActiveQuickKey","nextValue","revertToCommitted","useEffect","hasNonDefaultValue","valueLabel","resolveHidden","jsxs","FilterPopover","nextOpen","formatPickerValue","jsx","classNames","styles","next","DatePicker"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const i = {
|
|
2
|
+
"filter-date-picker-quick-options": "_filter-date-picker-quick-options_9zz2f_1",
|
|
3
|
+
"filter-date-picker-quick-option": "_filter-date-picker-quick-option_9zz2f_1",
|
|
4
|
+
"filter-date-picker-quick-option-active": "_filter-date-picker-quick-option-active_9zz2f_18",
|
|
5
|
+
"filter-date-picker": "_filter-date-picker_9zz2f_1"
|
|
6
|
+
};
|
|
7
|
+
export {
|
|
8
|
+
i as default
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=style.module.scss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Dayjs } from 'dayjs';
|
|
2
2
|
import { default as React } from 'react';
|
|
3
|
+
import { DatePickerGranularity } from '../../../utils/pickerDate';
|
|
3
4
|
import { BaseFilterProps } from '../types';
|
|
4
5
|
/** 快捷选项配置类型 */
|
|
5
6
|
interface QuickOption {
|
|
@@ -7,19 +8,23 @@ interface QuickOption {
|
|
|
7
8
|
label: string;
|
|
8
9
|
getValue: () => [Dayjs, Dayjs] | null;
|
|
9
10
|
}
|
|
11
|
+
declare function getBuiltInMonthOptions(): QuickOption[];
|
|
10
12
|
interface FilterDateRangeProps extends BaseFilterProps {
|
|
11
13
|
value?: [string, string] | null;
|
|
12
14
|
onChange?: (value: [string, string] | null) => void;
|
|
15
|
+
/** 选择粒度:日 / 月 / 年 */
|
|
16
|
+
picker?: DatePickerGranularity;
|
|
13
17
|
/** 默认区间:与默认相同时视为未筛选(除非 showDefaultAsSelected) */
|
|
14
18
|
defaultValue?: [string, string];
|
|
15
19
|
/** 为 true 时,value 等于 defaultValue 仍展示在已选 Tag 中 */
|
|
16
20
|
showDefaultAsSelected?: boolean;
|
|
17
21
|
showQuickOptions?: boolean;
|
|
18
22
|
quickOptions?: QuickOption[];
|
|
23
|
+
disabledDate?: (current: Dayjs) => boolean;
|
|
19
24
|
}
|
|
20
25
|
declare function isSameRange(a?: [string, string] | null, b?: [string, string]): boolean;
|
|
21
|
-
declare function findMatchingQuickKey(range: [string, string] | null | undefined, opts: QuickOption[]): string | null;
|
|
26
|
+
declare function findMatchingQuickKey(range: [string, string] | null | undefined, opts: QuickOption[], picker: DatePickerGranularity): string | null;
|
|
22
27
|
declare const FilterDateRange: React.FC<FilterDateRangeProps>;
|
|
23
28
|
export default FilterDateRange;
|
|
24
29
|
export type { FilterDateRangeProps, QuickOption };
|
|
25
|
-
export { findMatchingQuickKey, isSameRange };
|
|
30
|
+
export { findMatchingQuickKey, isSameRange, getBuiltInMonthOptions };
|