@anyknown/ui 0.7.0 → 0.8.1
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/README.md +7 -8
- package/dist/brand.css +101 -214
- package/dist/components/button/Button.d.ts +3 -2
- package/dist/components/button/Button.js +32 -48
- package/dist/components/checkbox/Checkbox.js +24 -48
- package/dist/components/dialog/Dialog.js +1 -1
- package/dist/components/empty-state/EmptyState.js +1 -1
- package/dist/components/ghost/Ghost.d.ts +16 -0
- package/dist/components/ghost/Ghost.js +50 -0
- package/dist/components/group/Group.d.ts +66 -0
- package/dist/components/group/Group.js +166 -0
- package/dist/components/handoff-receipt/HandoffReceipt.js +12 -42
- package/dist/components/icon/Chevron.d.ts +9 -0
- package/dist/components/icon/Chevron.js +6 -0
- package/dist/components/icon/icon.d.ts +35 -0
- package/dist/components/icon/icon.js +10 -0
- package/dist/components/icon-button/IconButton.d.ts +17 -0
- package/dist/components/icon-button/IconButton.js +66 -0
- package/dist/components/input/Input.d.ts +3 -1
- package/dist/components/input/Input.js +3 -2
- package/dist/components/page/Page.d.ts +64 -0
- package/dist/components/page/Page.js +163 -0
- package/dist/components/popover/Popover.js +1 -1
- package/dist/components/progress/Progress.js +49 -104
- package/dist/components/radio/Radio.js +17 -28
- package/dist/components/segmented/Segmented.d.ts +12 -0
- package/dist/components/segmented/Segmented.js +43 -0
- package/dist/components/settings-rows/SettingsRows.d.ts +25 -0
- package/dist/components/settings-rows/SettingsRows.js +63 -0
- package/dist/components/spin/Spin.d.ts +5 -0
- package/dist/components/spin/Spin.js +25 -0
- package/dist/components/status-chip/StatusChip.d.ts +18 -0
- package/dist/components/status-chip/StatusChip.js +68 -0
- package/dist/components/switch/Switch.js +20 -63
- package/dist/components/table/Table.d.ts +39 -0
- package/dist/components/table/Table.js +125 -0
- package/dist/components/table/TableCells.d.ts +52 -0
- package/dist/components/table/TableCells.js +103 -0
- package/dist/components/tabs/Tabs.js +16 -48
- package/dist/components/text/Text.js +2 -2
- package/dist/components/toast/Toast.js +7 -8
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/themes.stylex.d.ts +33 -496
- package/dist/themes.stylex.js +25 -253
- package/dist/tokens.css +53 -126
- package/dist/tokens.stylex.d.ts +36 -54
- package/dist/tokens.stylex.js +62 -90
- package/package.json +1 -1
- package/dist/lib/paths.d.ts +0 -3
- package/dist/lib/paths.js +0 -11
- package/dist/lib/progress.d.ts +0 -2
- package/dist/lib/progress.js +0 -28
- package/dist/lib/silk.d.ts +0 -66
- package/dist/lib/silk.js +0 -337
- package/dist/lib/svgId.d.ts +0 -1
- package/dist/lib/svgId.js +0 -4
- package/dist/lib/weave.d.ts +0 -28
- package/dist/lib/weave.js +0 -83
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as stylex from "@stylexjs/stylex";
|
|
3
|
-
import { useCallback } from "react";
|
|
4
3
|
import { assignRef } from "../../lib/mergeRefs.js";
|
|
5
|
-
import { SilkBody } from "../../lib/silk.js";
|
|
6
4
|
import { styled } from "../../lib/styled.js";
|
|
7
|
-
import { color, font, motion, space, text
|
|
8
|
-
// 織成的實心(TEXTURE-GUIDE):沒有 background,實心由紗織成;
|
|
9
|
-
// 動態全由觸點決定 — 帶動 + 窩 + 掃光(press 全套),幾何在 client 端由
|
|
10
|
-
// SilkBody 以固定種子現織(同尺寸恆定)。reduced-motion 時靜態織紋。
|
|
5
|
+
import { color, corner, font, motion, space, text } from "../../tokens.stylex.js";
|
|
11
6
|
const styles = stylex.create({
|
|
12
7
|
base: {
|
|
13
8
|
position: "relative",
|
|
@@ -19,12 +14,12 @@ const styles = stylex.create({
|
|
|
19
14
|
fontSize: text.sm,
|
|
20
15
|
fontWeight: 500,
|
|
21
16
|
lineHeight: text.leadingTight,
|
|
22
|
-
borderRadius:
|
|
17
|
+
borderRadius: corner.btn,
|
|
23
18
|
borderWidth: 0,
|
|
24
19
|
backgroundColor: "transparent",
|
|
25
20
|
cursor: { default: "pointer", ":disabled": "not-allowed" },
|
|
26
21
|
opacity: { default: 1, ":disabled": 0.5 },
|
|
27
|
-
transitionProperty: "color",
|
|
22
|
+
transitionProperty: "color, background-color",
|
|
28
23
|
transitionDuration: { default: motion.fast, "@media (prefers-reduced-motion: reduce)": "0s" },
|
|
29
24
|
outline: { default: "none", ":focus-visible": `2px solid ${color.focusRing}` },
|
|
30
25
|
outlineOffset: 3,
|
|
@@ -51,48 +46,37 @@ const styles = stylex.create({
|
|
|
51
46
|
iconMd: { paddingInline: 0, width: "2.25rem" },
|
|
52
47
|
iconSm: { paddingInline: 0, width: "1.75rem" },
|
|
53
48
|
iconXs: { paddingInline: 0, width: "1.5rem" },
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
49
|
+
primary: {
|
|
50
|
+
color: color.accentText,
|
|
51
|
+
backgroundColor: {
|
|
52
|
+
default: color.accent,
|
|
53
|
+
":hover": `color-mix(in srgb, ${color.accent} 86%, ${color.bg})`,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
secondary: {
|
|
57
|
+
color: color.text,
|
|
58
|
+
backgroundColor: { default: color.bone, ":hover": color.layer5 },
|
|
59
|
+
},
|
|
60
|
+
ghost: {
|
|
61
|
+
color: color.textMuted,
|
|
62
|
+
backgroundColor: { default: "transparent", ":hover": color.bone },
|
|
63
|
+
},
|
|
64
|
+
danger: {
|
|
65
|
+
color: color.accentText,
|
|
66
|
+
backgroundColor: {
|
|
67
|
+
default: color.danger,
|
|
68
|
+
":hover": `color-mix(in srgb, ${color.danger} 86%, ${color.bg})`,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
// 「白底紅字」:份量走 ghost,語意走 danger token(和 interaction-card 收據列
|
|
72
|
+
// rejected 的 ✓ 同一個 token)
|
|
73
|
+
dangerGhost: {
|
|
74
|
+
color: color.danger,
|
|
75
|
+
backgroundColor: { default: "transparent", ":hover": color.dangerSubtle },
|
|
69
76
|
},
|
|
70
77
|
label: { position: "relative", display: "inline-flex", alignItems: "center", gap: space.xs },
|
|
71
78
|
});
|
|
72
|
-
const RADIUS = 8;
|
|
73
|
-
function palette(vars) {
|
|
74
|
-
return vars;
|
|
75
|
-
}
|
|
76
|
-
const SILK = {
|
|
77
|
-
primary: { palette: palette(yarn), bandMax: 0.75 },
|
|
78
|
-
secondary: { palette: palette(yarnSecondary), bandMax: 0.5 },
|
|
79
|
-
ghost: { palette: palette(yarnGhost), ghost: true, bandMax: 0.5 },
|
|
80
|
-
danger: { palette: palette(yarnDanger), bandMax: 0.75 },
|
|
81
|
-
dangerGhost: { palette: palette(yarnGhost), ghost: true, bandMax: 0.5 },
|
|
82
|
-
};
|
|
83
79
|
const ICON_SIZE = { xs: "iconXs", sm: "iconSm", md: "iconMd" };
|
|
84
80
|
export function Button({ variant = "primary", size = "md", icon = false, children, ref, sx, ...props }) {
|
|
85
|
-
|
|
86
|
-
// useCallback 鎖 identity,只有 variant 變了才重建織體
|
|
87
|
-
const silk = useCallback((node) => {
|
|
88
|
-
if (!node)
|
|
89
|
-
return;
|
|
90
|
-
const body = new SilkBody(node.parentElement, node, {
|
|
91
|
-
...SILK[variant],
|
|
92
|
-
mode: "press",
|
|
93
|
-
radius: RADIUS,
|
|
94
|
-
});
|
|
95
|
-
return () => body.destroy();
|
|
96
|
-
}, [variant]);
|
|
97
|
-
return (_jsxs("button", { type: "button", ...props, ref: (element) => assignRef(ref, element), ...styled(props, styles.base, styles[size], icon && styles[ICON_SIZE[size]], styles[variant], sx), children: [_jsx("svg", { ref: silk, "aria-hidden": "true", ...stylex.props(styles.silk) }), _jsx("span", { ...stylex.props(styles.label), children: children })] }));
|
|
81
|
+
return (_jsx("button", { type: "button", ...props, ref: (element) => assignRef(ref, element), ...styled(props, styles.base, styles[size], icon && styles[ICON_SIZE[size]], styles[variant], sx), children: _jsx("span", { ...stylex.props(styles.label), children: children }) }));
|
|
98
82
|
}
|
|
@@ -3,26 +3,12 @@ import * as stylex from "@stylexjs/stylex";
|
|
|
3
3
|
import { useCallback, useId } from "react";
|
|
4
4
|
import { assignRef } from "../../lib/mergeRefs.js";
|
|
5
5
|
import { styled } from "../../lib/styled.js";
|
|
6
|
-
import { useSvgId } from "../../lib/svgId.js";
|
|
7
6
|
import { useControllableState } from "../../lib/useControllableState.js";
|
|
8
|
-
import {
|
|
9
|
-
import { color, font, motion, radius, space, text, yarn } from "../../tokens.stylex.js";
|
|
7
|
+
import { color, font, motion, radius, space, text } from "../../tokens.stylex.js";
|
|
10
8
|
import { useFieldControl } from "../label/fieldContext.js";
|
|
11
9
|
const REDUCED = "@media (prefers-reduced-motion: reduce)";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// 螢幕上紗的粗細行距與 button 等粗。勾/橫線 = 縫在布上的線,與布共用同一支 rand 序列。
|
|
15
|
-
const rand = weaveRand();
|
|
16
|
-
const CLOTH = buildWeave({ w: 14.8, h: 14.8, s: 24 / 14.8 }, rand);
|
|
17
|
-
const CHECK_D = buildThread([
|
|
18
|
-
[5.83, 12.33],
|
|
19
|
-
[10.05, 16.55],
|
|
20
|
-
[18.18, 7.13],
|
|
21
|
-
], rand);
|
|
22
|
-
const DASH_D = buildThread([
|
|
23
|
-
[6.48, 12],
|
|
24
|
-
[17.53, 12],
|
|
25
|
-
], rand);
|
|
10
|
+
const CHECK_D = "M6 12.4 L10.2 16.6 L18.2 7.4";
|
|
11
|
+
const DASH_D = "M6.5 12 L17.5 12";
|
|
26
12
|
const styles = stylex.create({
|
|
27
13
|
root: {
|
|
28
14
|
display: "flex",
|
|
@@ -35,50 +21,40 @@ const styles = stylex.create({
|
|
|
35
21
|
input: { position: "absolute", opacity: 0, width: "1.05rem", height: "1.05rem", margin: 0 },
|
|
36
22
|
box: {
|
|
37
23
|
flex: "none",
|
|
24
|
+
boxSizing: "border-box",
|
|
38
25
|
width: "1.05rem",
|
|
39
26
|
height: "1.05rem",
|
|
40
27
|
marginTop: "0.16rem",
|
|
41
|
-
borderWidth: 1,
|
|
28
|
+
borderWidth: 1.5,
|
|
42
29
|
borderStyle: "solid",
|
|
43
30
|
borderColor: color.borderStrong,
|
|
44
31
|
borderRadius: radius.sm,
|
|
45
|
-
backgroundColor: color.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
transitionDuration: { default: motion.normal, [REDUCED]: "0s" },
|
|
32
|
+
backgroundColor: color.bg,
|
|
33
|
+
transitionProperty: "border-color, background-color",
|
|
34
|
+
transitionDuration: { default: motion.fast, [REDUCED]: "0s" },
|
|
49
35
|
outline: { default: "none", ":has(:focus-visible)": `2px solid ${color.focusRing}` },
|
|
50
36
|
outlineOffset: 2,
|
|
51
37
|
},
|
|
52
|
-
boxOn: { borderColor: color.accent },
|
|
38
|
+
boxOn: { borderColor: color.accent, backgroundColor: color.accent },
|
|
39
|
+
boxInvalid: { borderColor: color.danger },
|
|
53
40
|
svg: { display: "block", width: "100%", height: "100%" },
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
41
|
+
mark: {
|
|
42
|
+
fill: "none",
|
|
43
|
+
stroke: color.accentText,
|
|
44
|
+
strokeWidth: 2.4,
|
|
45
|
+
strokeLinecap: "round",
|
|
46
|
+
strokeLinejoin: "round",
|
|
47
|
+
strokeDasharray: 32,
|
|
48
|
+
strokeDashoffset: 32,
|
|
49
|
+
transitionProperty: "stroke-dashoffset",
|
|
50
|
+
transitionDuration: { default: "160ms", [REDUCED]: "0s" },
|
|
51
|
+
transitionTimingFunction: "ease-out",
|
|
62
52
|
},
|
|
63
|
-
|
|
64
|
-
cloth: { fill: "none", strokeLinecap: "round" },
|
|
65
|
-
un: { stroke: yarn.un },
|
|
66
|
-
sh: { stroke: yarn.sh, opacity: 0.5 },
|
|
67
|
-
y0: { stroke: yarn.y0 },
|
|
68
|
-
y1: { stroke: yarn.y1 },
|
|
69
|
-
y2: { stroke: yarn.y2 },
|
|
70
|
-
y3: { stroke: yarn.y3 },
|
|
71
|
-
y4: { stroke: yarn.y4 },
|
|
72
|
-
hi: { stroke: yarn.hi, opacity: 0.45 },
|
|
73
|
-
mark: { fill: "none", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
74
|
-
threadShadow: { stroke: "rgba(9, 20, 16, 0.32)" },
|
|
75
|
-
threadCore: { stroke: color.accentText },
|
|
53
|
+
markOn: { strokeDashoffset: 0 },
|
|
76
54
|
labelText: { display: "block", fontWeight: 500, fontSize: text.sm, color: color.text },
|
|
77
55
|
description: { display: "block", fontSize: text.xs, color: color.textMuted },
|
|
78
56
|
});
|
|
79
|
-
const BUCKETS = [styles.y0, styles.y1, styles.y2, styles.y3, styles.y4];
|
|
80
57
|
export function Checkbox({ indeterminate = false, label, description, onCheckedChange, checked, defaultChecked, onChange, ref, sx, ...props }) {
|
|
81
|
-
const clipId = useSvgId("ak-weave");
|
|
82
58
|
const base = useId();
|
|
83
59
|
const labelId = `${base}label`;
|
|
84
60
|
const descriptionId = `${base}description`;
|
|
@@ -95,8 +71,8 @@ export function Checkbox({ indeterminate = false, label, description, onCheckedC
|
|
|
95
71
|
const describedBy = [description != null ? descriptionId : null, field["aria-describedby"]]
|
|
96
72
|
.filter(Boolean)
|
|
97
73
|
.join(" ");
|
|
98
|
-
return (_jsxs("label", { ...stylex.props(styles.root, sx), children: [_jsxs("span", { ...stylex.props(styles.box, filled && styles.boxOn), children: [_jsx("input", { type: "checkbox", ...props, ...field, "aria-invalid": invalid || undefined, "aria-labelledby": label != null ? labelId : undefined, "aria-describedby": describedBy || undefined, ref: setNode, checked: isChecked, onChange: (event) => {
|
|
74
|
+
return (_jsxs("label", { ...stylex.props(styles.root, sx), children: [_jsxs("span", { ...stylex.props(styles.box, filled && styles.boxOn, invalid && styles.boxInvalid), children: [_jsx("input", { type: "checkbox", ...props, ...field, "aria-invalid": invalid || undefined, "aria-labelledby": label != null ? labelId : undefined, "aria-describedby": describedBy || undefined, ref: setNode, checked: isChecked, onChange: (event) => {
|
|
99
75
|
setChecked(event.currentTarget.checked);
|
|
100
76
|
onChange?.(event);
|
|
101
|
-
}, ...styled(props, styles.input) }),
|
|
77
|
+
}, ...styled(props, styles.input) }), _jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", ...stylex.props(styles.svg), children: _jsx("path", { d: indeterminate ? DASH_D : CHECK_D, ...stylex.props(styles.mark, filled && styles.markOn) }) })] }), (label != null || description != null) && (_jsxs("span", { children: [label != null && (_jsx("span", { id: labelId, ...stylex.props(styles.labelText), children: label })), description != null && (_jsx("span", { id: descriptionId, ...stylex.props(styles.description), children: description }))] }))] }));
|
|
102
78
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as stylex from "@stylexjs/stylex";
|
|
2
|
+
import type { ButtonHTMLAttributes, Ref } from "react";
|
|
3
|
+
export type GhostProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type"> & {
|
|
4
|
+
danger?: boolean;
|
|
5
|
+
ref?: Ref<HTMLButtonElement>;
|
|
6
|
+
sx?: stylex.StyleXStyles;
|
|
7
|
+
};
|
|
8
|
+
export declare function Ghost({ danger, sx, ...props }: GhostProps): import("react").JSX.Element;
|
|
9
|
+
export type GhostLinkProps = {
|
|
10
|
+
href: string;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
external?: boolean;
|
|
13
|
+
sx?: stylex.StyleXStyles;
|
|
14
|
+
};
|
|
15
|
+
/** The same word, as a link that leaves the app. */
|
|
16
|
+
export declare function GhostLink({ href, children, external, sx }: GhostLinkProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as stylex from "@stylexjs/stylex";
|
|
3
|
+
import { color, corner, font, motion, space, type } from "../../tokens.stylex.js";
|
|
4
|
+
/** `.ghost`: a word that is a button. 28px, muted until the pointer is on it; `danger` is warning. */
|
|
5
|
+
const REDUCED = "@media (prefers-reduced-motion: reduce)";
|
|
6
|
+
const PHONE = "@media (max-width: 45rem)";
|
|
7
|
+
const styles = stylex.create({
|
|
8
|
+
root: {
|
|
9
|
+
alignItems: "center",
|
|
10
|
+
backgroundColor: { default: "transparent", ":hover": color.layer3 },
|
|
11
|
+
borderRadius: corner.sm,
|
|
12
|
+
borderStyle: "none",
|
|
13
|
+
borderWidth: 0,
|
|
14
|
+
color: { default: color.textMuted, ":hover": color.text },
|
|
15
|
+
cursor: { default: "pointer", ":disabled": "default" },
|
|
16
|
+
display: "inline-flex",
|
|
17
|
+
fontFamily: font.body,
|
|
18
|
+
fontSize: type.t2,
|
|
19
|
+
fontWeight: 400,
|
|
20
|
+
gap: space.xxs,
|
|
21
|
+
height: 28,
|
|
22
|
+
lineHeight: type.body,
|
|
23
|
+
margin: 0,
|
|
24
|
+
minHeight: { default: 0, [PHONE]: 40 },
|
|
25
|
+
opacity: { default: 1, ":disabled": 0.4 },
|
|
26
|
+
outline: { default: "none", ":focus-visible": `2px solid ${color.accent}` },
|
|
27
|
+
outlineOffset: 2,
|
|
28
|
+
paddingBlock: 0,
|
|
29
|
+
paddingInline: space.xs,
|
|
30
|
+
textDecoration: "none",
|
|
31
|
+
transitionDuration: { default: motion.fast, [REDUCED]: "0s" },
|
|
32
|
+
transitionProperty: "background-color, color",
|
|
33
|
+
transitionTimingFunction: motion.easeOut,
|
|
34
|
+
whiteSpace: "nowrap",
|
|
35
|
+
},
|
|
36
|
+
danger: {
|
|
37
|
+
backgroundColor: {
|
|
38
|
+
default: "transparent",
|
|
39
|
+
":hover": `color-mix(in srgb, ${color.warning} 10%, transparent)`,
|
|
40
|
+
},
|
|
41
|
+
color: { default: color.warning, ":hover": color.warning },
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
export function Ghost({ danger = false, sx, ...props }) {
|
|
45
|
+
return _jsx("button", { type: "button", ...props, ...stylex.props(styles.root, danger && styles.danger, sx) });
|
|
46
|
+
}
|
|
47
|
+
/** The same word, as a link that leaves the app. */
|
|
48
|
+
export function GhostLink({ href, children, external = false, sx }) {
|
|
49
|
+
return (_jsx("a", { href: href, ...(external ? { target: "_blank", rel: "noreferrer" } : {}), ...stylex.props(styles.root, sx), children: children }));
|
|
50
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as stylex from "@stylexjs/stylex";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
type Sx = {
|
|
4
|
+
sx?: stylex.StyleXStyles;
|
|
5
|
+
};
|
|
6
|
+
export declare function Group({ children, sx }: {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
} & Sx): import("react").JSX.Element;
|
|
9
|
+
export declare function Item({ children, go, sx }: {
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
go?: boolean;
|
|
12
|
+
} & Sx): import("react").JSX.Element;
|
|
13
|
+
export type MarkProps = {
|
|
14
|
+
letter: string;
|
|
15
|
+
tint: string;
|
|
16
|
+
sx?: stylex.StyleXStyles;
|
|
17
|
+
};
|
|
18
|
+
/** The 22px square with the first letter; `tint` is `<colour> <percent>%` for the mix. */
|
|
19
|
+
export declare function Mark({ letter, tint, sx }: MarkProps): import("react").JSX.Element;
|
|
20
|
+
export type StatusProps = {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
warn?: boolean;
|
|
23
|
+
sx?: stylex.StyleXStyles;
|
|
24
|
+
};
|
|
25
|
+
export declare function Status({ children, warn, sx }: StatusProps): import("react").JSX.Element;
|
|
26
|
+
export declare function Sep(): import("react").JSX.Element;
|
|
27
|
+
export type RowProps = {
|
|
28
|
+
mark?: ReactNode;
|
|
29
|
+
name: ReactNode;
|
|
30
|
+
/** What follows the name after a `·`: a `Status`, a mono value, a tag. */
|
|
31
|
+
children?: ReactNode;
|
|
32
|
+
actions?: ReactNode;
|
|
33
|
+
/** The whole line is the way in; a chevron says so. */
|
|
34
|
+
onPress?: () => void;
|
|
35
|
+
chevron?: boolean;
|
|
36
|
+
sx?: stylex.StyleXStyles;
|
|
37
|
+
};
|
|
38
|
+
export declare function Row({ mark, name, children, actions, onPress, chevron, sx }: RowProps): import("react").JSX.Element;
|
|
39
|
+
export type ExpandProps = {
|
|
40
|
+
open: boolean;
|
|
41
|
+
/** `plain` drops the mark indent, for a form that is not under a row's mark. */
|
|
42
|
+
plain?: boolean;
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
sx?: stylex.StyleXStyles;
|
|
45
|
+
};
|
|
46
|
+
/** `.exp`: what a row opens, unfolding under it in 200ms and taking no room when shut. */
|
|
47
|
+
export declare function Expand({ open, plain, children, sx }: ExpandProps): import("react").JSX.Element;
|
|
48
|
+
export type NoteProps = {
|
|
49
|
+
children: ReactNode;
|
|
50
|
+
faint?: boolean;
|
|
51
|
+
err?: boolean;
|
|
52
|
+
sx?: stylex.StyleXStyles;
|
|
53
|
+
};
|
|
54
|
+
/** A sentence inside an `Expand`: what it means, or what went wrong. */
|
|
55
|
+
export declare function Note({ children, faint, err, sx }: NoteProps): import("react").JSX.Element;
|
|
56
|
+
export declare function Acts({ children, sx }: {
|
|
57
|
+
children: ReactNode;
|
|
58
|
+
} & Sx): import("react").JSX.Element;
|
|
59
|
+
/** `.empty`: nothing here yet, said inside the group in one muted line. */
|
|
60
|
+
export declare function Empty({ children, sx }: {
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
} & Sx): import("react").JSX.Element;
|
|
63
|
+
export declare function Tag({ children, sx }: {
|
|
64
|
+
children: ReactNode;
|
|
65
|
+
} & Sx): import("react").JSX.Element;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import * as stylex from "@stylexjs/stylex";
|
|
3
|
+
import { color, corner, font, motion, space, tone, type } from "../../tokens.stylex.js";
|
|
4
|
+
import { Chevron } from "../icon/Chevron.js";
|
|
5
|
+
import { icon } from "../icon/icon.js";
|
|
6
|
+
/**
|
|
7
|
+
* `.group` / `.item` / `.row`: a bordered list where each line is a thing (a server, a key, a
|
|
8
|
+
* rule) with its name, its state and its one action on the right. What a row opens unfolds under
|
|
9
|
+
* it in an `Expand`, never over the screen.
|
|
10
|
+
*/
|
|
11
|
+
const REDUCED = "@media (prefers-reduced-motion: reduce)";
|
|
12
|
+
const styles = stylex.create({
|
|
13
|
+
group: {
|
|
14
|
+
backgroundColor: color.surface,
|
|
15
|
+
borderRadius: corner.card,
|
|
16
|
+
boxShadow: `inset 0 0 0 1px ${color.border}`,
|
|
17
|
+
color: color.text,
|
|
18
|
+
fontSize: type.t2,
|
|
19
|
+
lineHeight: type.body,
|
|
20
|
+
},
|
|
21
|
+
item: {
|
|
22
|
+
borderRadius: {
|
|
23
|
+
default: 0,
|
|
24
|
+
":first-child": `${corner.card} ${corner.card} 0 0`,
|
|
25
|
+
":last-child": `0 0 ${corner.card} ${corner.card}`,
|
|
26
|
+
},
|
|
27
|
+
boxShadow: { default: "none", ":not(:first-child)": `inset 0 1px 0 ${color.border}` },
|
|
28
|
+
overflow: "hidden",
|
|
29
|
+
},
|
|
30
|
+
go: { backgroundColor: { default: "transparent", ":hover": color.layer3 } },
|
|
31
|
+
row: {
|
|
32
|
+
alignItems: "center",
|
|
33
|
+
columnGap: space.sm,
|
|
34
|
+
display: "grid",
|
|
35
|
+
gridTemplateColumns: "minmax(0, 1fr) auto",
|
|
36
|
+
minHeight: 40,
|
|
37
|
+
paddingBlock: space.xs,
|
|
38
|
+
paddingInline: space.sm,
|
|
39
|
+
},
|
|
40
|
+
rowgo: {
|
|
41
|
+
alignItems: "center",
|
|
42
|
+
backgroundColor: "transparent",
|
|
43
|
+
borderRadius: corner.sm,
|
|
44
|
+
borderStyle: "none",
|
|
45
|
+
borderWidth: 0,
|
|
46
|
+
color: "inherit",
|
|
47
|
+
cursor: "pointer",
|
|
48
|
+
display: "flex",
|
|
49
|
+
flexWrap: "wrap",
|
|
50
|
+
fontFamily: "inherit",
|
|
51
|
+
fontSize: "inherit",
|
|
52
|
+
gap: `0 ${space.xs}`,
|
|
53
|
+
lineHeight: "inherit",
|
|
54
|
+
margin: 0,
|
|
55
|
+
minWidth: 0,
|
|
56
|
+
outline: { default: "none", ":focus-visible": `2px solid ${color.accent}` },
|
|
57
|
+
outlineOffset: 2,
|
|
58
|
+
padding: 0,
|
|
59
|
+
textAlign: "start",
|
|
60
|
+
},
|
|
61
|
+
still: { cursor: "default" },
|
|
62
|
+
mark: {
|
|
63
|
+
alignItems: "center",
|
|
64
|
+
borderRadius: corner.sm,
|
|
65
|
+
color: color.text,
|
|
66
|
+
display: "grid",
|
|
67
|
+
flex: "none",
|
|
68
|
+
fontSize: type.t1,
|
|
69
|
+
fontWeight: 600,
|
|
70
|
+
height: 22,
|
|
71
|
+
justifyItems: "center",
|
|
72
|
+
placeItems: "center",
|
|
73
|
+
width: 22,
|
|
74
|
+
},
|
|
75
|
+
markTint: (tint) => ({ backgroundColor: `color-mix(in srgb, ${tint}, ${color.layer3})` }),
|
|
76
|
+
name: {
|
|
77
|
+
flex: "none",
|
|
78
|
+
fontSize: type.t2,
|
|
79
|
+
fontWeight: 500,
|
|
80
|
+
overflow: "hidden",
|
|
81
|
+
textOverflow: "ellipsis",
|
|
82
|
+
whiteSpace: "nowrap",
|
|
83
|
+
},
|
|
84
|
+
sep: { color: tone.faint, flex: "none", fontSize: type.t2 },
|
|
85
|
+
status: {
|
|
86
|
+
alignItems: "center",
|
|
87
|
+
color: color.textMuted,
|
|
88
|
+
display: "inline-flex",
|
|
89
|
+
fontSize: type.t2,
|
|
90
|
+
gap: space.xs,
|
|
91
|
+
minWidth: 0,
|
|
92
|
+
},
|
|
93
|
+
statusText: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
94
|
+
warn: { color: color.warning },
|
|
95
|
+
dot: { backgroundColor: color.warning, borderRadius: "50%", flex: "none", height: 6, width: 6 },
|
|
96
|
+
tag: { color: color.textMuted, flex: "none", fontFamily: font.mono, fontSize: type.t2 },
|
|
97
|
+
act: { alignItems: "center", display: "flex", gap: space.xs },
|
|
98
|
+
chevron: { color: tone.faint },
|
|
99
|
+
expand: {
|
|
100
|
+
display: "grid",
|
|
101
|
+
gridTemplateRows: "0fr",
|
|
102
|
+
transitionDuration: { default: motion.normal, [REDUCED]: "0s" },
|
|
103
|
+
transitionProperty: "grid-template-rows",
|
|
104
|
+
transitionTimingFunction: motion.easeOut,
|
|
105
|
+
},
|
|
106
|
+
shown: { gridTemplateRows: "1fr" },
|
|
107
|
+
clip: { minHeight: 0, overflow: "hidden" },
|
|
108
|
+
in: {
|
|
109
|
+
alignItems: "flex-start",
|
|
110
|
+
display: "flex",
|
|
111
|
+
flexDirection: "column",
|
|
112
|
+
gap: space.xs,
|
|
113
|
+
paddingBlock: `0 ${space.sm}`,
|
|
114
|
+
paddingInline: `calc(${space.sm} + 22px + ${space.xs}) ${space.sm}`,
|
|
115
|
+
},
|
|
116
|
+
plain: { paddingBlock: `${space.xs} ${space.sm}`, paddingInline: space.sm },
|
|
117
|
+
text: { color: color.textMuted, fontSize: type.t2, lineHeight: type.body, margin: 0 },
|
|
118
|
+
faint: { color: tone.faint },
|
|
119
|
+
err: { color: color.warning },
|
|
120
|
+
acts: { alignItems: "center", display: "flex", gap: space.xs },
|
|
121
|
+
empty: {
|
|
122
|
+
color: color.textMuted,
|
|
123
|
+
fontSize: type.t2,
|
|
124
|
+
lineHeight: type.body,
|
|
125
|
+
margin: 0,
|
|
126
|
+
padding: space.sm,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
export function Group({ children, sx }) {
|
|
130
|
+
return _jsx("div", { ...stylex.props(styles.group, sx), children: children });
|
|
131
|
+
}
|
|
132
|
+
export function Item({ children, go = false, sx }) {
|
|
133
|
+
return _jsx("div", { ...stylex.props(styles.item, go && styles.go, sx), children: children });
|
|
134
|
+
}
|
|
135
|
+
/** The 22px square with the first letter; `tint` is `<colour> <percent>%` for the mix. */
|
|
136
|
+
export function Mark({ letter, tint, sx }) {
|
|
137
|
+
return (_jsx("div", { "aria-hidden": "true", ...stylex.props(styles.mark, styles.markTint(tint), sx), children: letter }));
|
|
138
|
+
}
|
|
139
|
+
export function Status({ children, warn = false, sx }) {
|
|
140
|
+
return (_jsxs("span", { ...stylex.props(styles.status, warn && styles.warn, sx), children: [warn && _jsx("span", { ...stylex.props(styles.dot), "aria-hidden": "true" }), _jsx("span", { ...stylex.props(styles.statusText), children: children })] }));
|
|
141
|
+
}
|
|
142
|
+
export function Sep() {
|
|
143
|
+
return (_jsx("span", { ...stylex.props(styles.sep), "aria-hidden": "true", children: "\u00B7" }));
|
|
144
|
+
}
|
|
145
|
+
export function Row({ mark, name, children, actions, onPress, chevron = false, sx }) {
|
|
146
|
+
const inner = (_jsxs(_Fragment, { children: [mark, _jsx("span", { ...stylex.props(styles.name), children: name }), children !== undefined && _jsx(Sep, {}), children] }));
|
|
147
|
+
return (_jsxs("div", { ...stylex.props(styles.row, sx), children: [onPress ? (_jsx("button", { type: "button", onClick: onPress, ...stylex.props(styles.rowgo), children: inner })) : (_jsx("div", { ...stylex.props(styles.rowgo, styles.still), children: inner })), _jsxs("div", { ...stylex.props(styles.act), children: [actions, chevron && (_jsx(Chevron, { direction: "right", ...stylex.props(icon.sm, styles.chevron), "aria-hidden": "true" }))] })] }));
|
|
148
|
+
}
|
|
149
|
+
/** `.exp`: what a row opens, unfolding under it in 200ms and taking no room when shut. */
|
|
150
|
+
export function Expand({ open, plain = false, children, sx }) {
|
|
151
|
+
return (_jsx("div", { ...(open ? {} : { inert: true }), ...stylex.props(styles.expand, open && styles.shown, sx), children: _jsx("div", { ...stylex.props(styles.clip), children: _jsx("div", { ...stylex.props(styles.in, plain && styles.plain), children: open ? children : null }) }) }));
|
|
152
|
+
}
|
|
153
|
+
/** A sentence inside an `Expand`: what it means, or what went wrong. */
|
|
154
|
+
export function Note({ children, faint = false, err = false, sx }) {
|
|
155
|
+
return (_jsx("p", { role: err ? "alert" : undefined, ...stylex.props(styles.text, faint && styles.faint, err && styles.err, sx), children: children }));
|
|
156
|
+
}
|
|
157
|
+
export function Acts({ children, sx }) {
|
|
158
|
+
return _jsx("div", { ...stylex.props(styles.acts, sx), children: children });
|
|
159
|
+
}
|
|
160
|
+
/** `.empty`: nothing here yet, said inside the group in one muted line. */
|
|
161
|
+
export function Empty({ children, sx }) {
|
|
162
|
+
return _jsx("p", { ...stylex.props(styles.empty, sx), children: children });
|
|
163
|
+
}
|
|
164
|
+
export function Tag({ children, sx }) {
|
|
165
|
+
return _jsx("span", { ...stylex.props(styles.tag, sx), children: children });
|
|
166
|
+
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as stylex from "@stylexjs/stylex";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { SilkBody } from "../../lib/silk.js";
|
|
6
|
-
import { color, font, motion, radius, space, text, yarnSecondary } from "../../tokens.stylex.js";
|
|
3
|
+
import { useId, useState } from "react";
|
|
4
|
+
import { color, corner, font, motion, space, text } from "../../tokens.stylex.js";
|
|
7
5
|
const REDUCED = "@media (prefers-reduced-motion: reduce)";
|
|
8
|
-
// 卡面 = 淺色布(TEXTURE-GUIDE §3、handoff-receipt/NOTES.md):沒有 background,
|
|
9
|
-
// 實心由紗織成;動態取「僅展示面」子集 — hover 帶動 + 光澤帶,無窩、無掃光。
|
|
10
|
-
// 布是固定高度 480 的長布,展開只是露出同一塊布更多 → 高度變化零重織、織紋恆定。
|
|
11
6
|
const styles = stylex.create({
|
|
12
7
|
receipt: {
|
|
13
8
|
position: "relative",
|
|
@@ -15,12 +10,12 @@ const styles = stylex.create({
|
|
|
15
10
|
borderWidth: 1,
|
|
16
11
|
borderStyle: "solid",
|
|
17
12
|
borderColor: color.border,
|
|
18
|
-
borderRadius:
|
|
13
|
+
borderRadius: corner.md,
|
|
14
|
+
backgroundColor: color.surfaceRaised,
|
|
19
15
|
},
|
|
20
|
-
face: { position: "absolute", top: 0, left: 0, pointerEvents: "none" },
|
|
21
16
|
row: {
|
|
22
17
|
// 注意:StyleX 0.19 會靜默丟掉 `all: unset`(編不出任何規則),原生按鈕的
|
|
23
|
-
// buttonface 底色與 outset
|
|
18
|
+
// buttonface 底色與 outset 邊框會留在畫面上 —— 要逐項重設
|
|
24
19
|
appearance: "none",
|
|
25
20
|
backgroundColor: "transparent",
|
|
26
21
|
borderWidth: 0,
|
|
@@ -36,7 +31,7 @@ const styles = stylex.create({
|
|
|
36
31
|
fontFamily: font.body,
|
|
37
32
|
fontSize: text.xs,
|
|
38
33
|
color: { default: color.textMuted, ":hover": color.text },
|
|
39
|
-
borderRadius:
|
|
34
|
+
borderRadius: corner.md,
|
|
40
35
|
outline: { default: "none", ":focus-visible": `2px solid ${color.focusRing}` },
|
|
41
36
|
outlineOffset: -2,
|
|
42
37
|
},
|
|
@@ -52,23 +47,13 @@ const styles = stylex.create({
|
|
|
52
47
|
ruleOpen: { borderTopStyle: "solid", borderTopColor: color.accent },
|
|
53
48
|
label: { whiteSpace: "nowrap", display: "flex", alignItems: "center", gap: space.xxs },
|
|
54
49
|
mono: { fontFamily: font.mono, fontSize: "0.76rem", lineHeight: 1 },
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
transitionProperty: "
|
|
50
|
+
link: {
|
|
51
|
+
flex: "none",
|
|
52
|
+
color: color.textFaint,
|
|
53
|
+
transitionProperty: "color",
|
|
59
54
|
transitionDuration: { default: motion.normal, [REDUCED]: "0s" },
|
|
60
55
|
},
|
|
61
|
-
|
|
62
|
-
loop: {
|
|
63
|
-
stroke: color.accent,
|
|
64
|
-
strokeDasharray: 100,
|
|
65
|
-
strokeDashoffset: 100,
|
|
66
|
-
transitionProperty: "stroke-dashoffset",
|
|
67
|
-
transitionDuration: { default: "500ms", [REDUCED]: "0s" },
|
|
68
|
-
transitionTimingFunction: "ease",
|
|
69
|
-
transitionDelay: { default: "120ms", [REDUCED]: "0s" },
|
|
70
|
-
},
|
|
71
|
-
loopTied: { strokeDashoffset: 0 },
|
|
56
|
+
linkOpen: { color: color.accent },
|
|
72
57
|
chevron: {
|
|
73
58
|
flex: "none",
|
|
74
59
|
color: color.textFaint,
|
|
@@ -128,20 +113,5 @@ function CheckIcon() {
|
|
|
128
113
|
export function HandoffReceipt({ at, ctxPercent, reason = "soft-threshold", memory, ledgerCount, handoffSummary, defaultOpen = false, }) {
|
|
129
114
|
const bodyId = useId();
|
|
130
115
|
const [open, setOpen] = useState(defaultOpen);
|
|
131
|
-
|
|
132
|
-
const face = useCallback((node) => {
|
|
133
|
-
if (!node)
|
|
134
|
-
return;
|
|
135
|
-
const silk = new SilkBody(node.parentElement, node, {
|
|
136
|
-
palette: yarnSecondary,
|
|
137
|
-
mode: "hover",
|
|
138
|
-
bandMax: 0.5,
|
|
139
|
-
pitch: 2,
|
|
140
|
-
hiCount: 12,
|
|
141
|
-
hiSpan: 0.95,
|
|
142
|
-
fixedHeight: 480,
|
|
143
|
-
});
|
|
144
|
-
return () => silk.destroy();
|
|
145
|
-
}, []);
|
|
146
|
-
return (_jsxs("div", { ...stylex.props(styles.receipt), children: [_jsx("svg", { ref: face, "aria-hidden": "true", ...stylex.props(styles.face) }), _jsxs("button", { type: "button", "aria-expanded": open, "aria-controls": bodyId, onClick: () => setOpen((value) => !value), ...stylex.props(styles.row), children: [_jsx("span", { "aria-hidden": "true", ...stylex.props(styles.rule, open && styles.ruleOpen) }), _jsxs("span", { ...stylex.props(styles.label), children: [_jsxs("svg", { width: "15", height: "13", viewBox: "0 0 15 13", fill: "none", strokeWidth: "1.7", strokeLinecap: "round", "aria-hidden": "true", ...stylex.props(styles.knot), children: [_jsx("path", { d: KNOT_LEAD, ...stylex.props(styles.lead, open && styles.leadHidden) }), _jsx("path", { d: KNOT_LOOP, pathLength: "100", ...stylex.props(styles.loop, open && styles.loopTied) })] }), _jsxs("span", { children: ["換班完成 · ", _jsx("span", { ...stylex.props(styles.mono), children: at }), " · ", _jsx("span", { ...stylex.props(styles.mono), children: `ctx ${ctxPercent}%` }), REASON_LABEL[reason], " → 新 session"] })] }), _jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", ...stylex.props(styles.chevron, open && styles.chevronOpen), children: _jsx("path", { d: "m6 9 6 6 6-6" }) }), _jsx("span", { "aria-hidden": "true", ...stylex.props(styles.rule, open && styles.ruleOpen) })] }), _jsx("div", { ...stylex.props(styles.bodyWrap, open && styles.bodyWrapOpen), children: _jsx("div", { ...stylex.props(styles.bodyClip), children: _jsxs("div", { id: bodyId, inert: !open, ...stylex.props(styles.body, open && styles.bodyOpen), children: [_jsxs("p", { ...stylex.props(styles.check), children: [_jsx(CheckIcon, {}), _jsx("b", { ...stylex.props(styles.checkTitle), children: "\u8A18\u61B6" }), _jsxs("span", { ...stylex.props(styles.checkText), children: [`${memory.count} 筆耐久事實已落盤`, memory.items?.length ? `(${memory.items.join("、")})` : "", "\u3002"] })] }), _jsxs("p", { ...stylex.props(styles.check), children: [_jsx(CheckIcon, {}), _jsx("b", { ...stylex.props(styles.checkTitle), children: "\u6458\u8981" }), _jsx("span", { ...stylex.props(styles.checkText), children: "handoff \u5DF2\u4EA4\u7D66\u4E0B\u4E00\u8F2A,\u8B80\u5F8C\u5373\u92B7\u6BC0\u3002" })] }), _jsxs("p", { ...stylex.props(styles.check), children: [_jsx(CheckIcon, {}), _jsx("b", { ...stylex.props(styles.checkTitle), children: "Ledger" }), _jsx("span", { ...stylex.props(styles.checkText), children: `本輪 ${ledgerCount} 條收據可查,不進新 context。` })] }), handoffSummary != null && _jsx("p", { ...stylex.props(styles.summary), children: handoffSummary })] }) }) })] }));
|
|
116
|
+
return (_jsxs("div", { ...stylex.props(styles.receipt), children: [_jsxs("button", { type: "button", "aria-expanded": open, "aria-controls": bodyId, onClick: () => setOpen((value) => !value), ...stylex.props(styles.row), children: [_jsx("span", { "aria-hidden": "true", ...stylex.props(styles.rule, open && styles.ruleOpen) }), _jsxs("span", { ...stylex.props(styles.label), children: [_jsx("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": "true", ...stylex.props(styles.link, open && styles.linkOpen), children: _jsx("path", { d: "M9 17H7A5 5 0 0 1 7 7h2M15 7h2a5 5 0 0 1 0 10h-2M8 12h8" }) }), _jsxs("span", { children: ["換班完成 · ", _jsx("span", { ...stylex.props(styles.mono), children: at }), " · ", _jsx("span", { ...stylex.props(styles.mono), children: `ctx ${ctxPercent}%` }), REASON_LABEL[reason], " → 新 session"] })] }), _jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", ...stylex.props(styles.chevron, open && styles.chevronOpen), children: _jsx("path", { d: "m6 9 6 6 6-6" }) }), _jsx("span", { "aria-hidden": "true", ...stylex.props(styles.rule, open && styles.ruleOpen) })] }), _jsx("div", { ...stylex.props(styles.bodyWrap, open && styles.bodyWrapOpen), children: _jsx("div", { ...stylex.props(styles.bodyClip), children: _jsxs("div", { id: bodyId, inert: !open, ...stylex.props(styles.body, open && styles.bodyOpen), children: [_jsxs("p", { ...stylex.props(styles.check), children: [_jsx(CheckIcon, {}), _jsx("b", { ...stylex.props(styles.checkTitle), children: "\u8A18\u61B6" }), _jsxs("span", { ...stylex.props(styles.checkText), children: [`${memory.count} 筆耐久事實已落盤`, memory.items?.length ? `(${memory.items.join("、")})` : "", "\u3002"] })] }), _jsxs("p", { ...stylex.props(styles.check), children: [_jsx(CheckIcon, {}), _jsx("b", { ...stylex.props(styles.checkTitle), children: "\u6458\u8981" }), _jsx("span", { ...stylex.props(styles.checkText), children: "handoff \u5DF2\u4EA4\u7D66\u4E0B\u4E00\u8F2A,\u8B80\u5F8C\u5373\u92B7\u6BC0\u3002" })] }), _jsxs("p", { ...stylex.props(styles.check), children: [_jsx(CheckIcon, {}), _jsx("b", { ...stylex.props(styles.checkTitle), children: "Ledger" }), _jsx("span", { ...stylex.props(styles.checkText), children: `本輪 ${ledgerCount} 條收據可查,不進新 context。` })] }), handoffSummary != null && _jsx("p", { ...stylex.props(styles.summary), children: handoffSummary })] }) }) })] }));
|
|
147
117
|
}
|