@superad/ui 0.1.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/LICENSE +21 -0
- package/README.md +42 -0
- package/es/Button/Button.d.mts +7 -0
- package/es/Button/Button.mjs +29 -0
- package/es/Button/Button.mjs.map +1 -0
- package/es/Button/index.d.mts +3 -0
- package/es/Button/index.d.ts +1 -0
- package/es/Button/index.js +1 -0
- package/es/Button/index.mjs +2 -0
- package/es/Button/style.mjs +33 -0
- package/es/Button/style.mjs.map +1 -0
- package/es/Button/type.d.mts +21 -0
- package/es/ConfigProvider/index.d.mts +9 -0
- package/es/ConfigProvider/index.d.ts +1 -0
- package/es/ConfigProvider/index.js +1 -0
- package/es/ConfigProvider/index.mjs +82 -0
- package/es/ConfigProvider/index.mjs.map +1 -0
- package/es/ConfigProvider/type.d.mts +24 -0
- package/es/DraggablePanel/DraggablePanel.d.mts +6 -0
- package/es/DraggablePanel/DraggablePanel.mjs +104 -0
- package/es/DraggablePanel/DraggablePanel.mjs.map +1 -0
- package/es/DraggablePanel/index.d.mts +3 -0
- package/es/DraggablePanel/index.d.ts +1 -0
- package/es/DraggablePanel/index.js +1 -0
- package/es/DraggablePanel/index.mjs +3 -0
- package/es/DraggablePanel/style.mjs +86 -0
- package/es/DraggablePanel/style.mjs.map +1 -0
- package/es/DraggablePanel/type.d.mts +27 -0
- package/es/Flex/Center.d.mts +7 -0
- package/es/Flex/Center.mjs +14 -0
- package/es/Flex/Center.mjs.map +1 -0
- package/es/Flex/FlexBasic.d.mts +6 -0
- package/es/Flex/FlexBasic.mjs +46 -0
- package/es/Flex/FlexBasic.mjs.map +1 -0
- package/es/Flex/Flexbox.d.mts +2 -0
- package/es/Flex/index.d.mts +5 -0
- package/es/Flex/index.d.ts +1 -0
- package/es/Flex/index.js +1 -0
- package/es/Flex/index.mjs +3 -0
- package/es/Flex/type.d.mts +35 -0
- package/es/Flex/utils.mjs +24 -0
- package/es/Flex/utils.mjs.map +1 -0
- package/es/FontLoader/index.d.mts +9 -0
- package/es/FontLoader/index.d.ts +1 -0
- package/es/FontLoader/index.js +1 -0
- package/es/FontLoader/index.mjs +23 -0
- package/es/FontLoader/index.mjs.map +1 -0
- package/es/GlobalFocusRing/index.d.mts +6 -0
- package/es/GlobalFocusRing/index.d.ts +1 -0
- package/es/GlobalFocusRing/index.js +1 -0
- package/es/GlobalFocusRing/index.mjs +204 -0
- package/es/GlobalFocusRing/index.mjs.map +1 -0
- package/es/GlobalFocusRing/style.mjs +35 -0
- package/es/GlobalFocusRing/style.mjs.map +1 -0
- package/es/Provider.d.mts +5 -0
- package/es/Table/canvas/canvasPalette.mjs +11 -0
- package/es/Table/canvas/canvasPalette.mjs.map +1 -0
- package/es/Table/canvas/chipPainters.mjs +408 -0
- package/es/Table/canvas/chipPainters.mjs.map +1 -0
- package/es/Table/canvas/controlPainters.mjs +193 -0
- package/es/Table/canvas/controlPainters.mjs.map +1 -0
- package/es/Table/canvas/groupTitle.mjs +181 -0
- package/es/Table/canvas/groupTitle.mjs.map +1 -0
- package/es/Table/canvas/paintUtils.mjs +70 -0
- package/es/Table/canvas/paintUtils.mjs.map +1 -0
- package/es/Table/canvas/rowSeries.mjs +130 -0
- package/es/Table/canvas/rowSeries.mjs.map +1 -0
- package/es/Table/canvas/textPainters.mjs +97 -0
- package/es/Table/canvas/textPainters.mjs.map +1 -0
- package/es/Table/canvas/theme.d.mts +14 -0
- package/es/Table/canvas/theme.mjs +276 -0
- package/es/Table/canvas/theme.mjs.map +1 -0
- package/es/Table/core/cellValue.d.mts +1 -0
- package/es/Table/core/cellValue.mjs +240 -0
- package/es/Table/core/cellValue.mjs.map +1 -0
- package/es/Table/core/rowSelection.mjs +138 -0
- package/es/Table/core/rowSelection.mjs.map +1 -0
- package/es/Table/core/size.mjs +60 -0
- package/es/Table/core/size.mjs.map +1 -0
- package/es/Table/core/tableI18n.d.mts +11 -0
- package/es/Table/core/tableI18n.mjs +123 -0
- package/es/Table/core/tableI18n.mjs.map +1 -0
- package/es/Table/core/tagTone.mjs +245 -0
- package/es/Table/core/tagTone.mjs.map +1 -0
- package/es/Table/core/zIndex.mjs +7 -0
- package/es/Table/core/zIndex.mjs.map +1 -0
- package/es/Table/index.d.mts +6 -0
- package/es/Table/index.d.ts +1 -0
- package/es/Table/index.js +1 -0
- package/es/Table/index.mjs +6 -0
- package/es/Table/react/Table.d.mts +9 -0
- package/es/Table/react/Table.mjs +407 -0
- package/es/Table/react/Table.mjs.map +1 -0
- package/es/Table/react/TableColumnSettings.mjs +65 -0
- package/es/Table/react/TableColumnSettings.mjs.map +1 -0
- package/es/Table/react/a11y.mjs +72 -0
- package/es/Table/react/a11y.mjs.map +1 -0
- package/es/Table/react/editors/base.mjs +427 -0
- package/es/Table/react/editors/base.mjs.map +1 -0
- package/es/Table/react/editors/inline.mjs +225 -0
- package/es/Table/react/editors/inline.mjs.map +1 -0
- package/es/Table/react/editors/picker.mjs +368 -0
- package/es/Table/react/editors/picker.mjs.map +1 -0
- package/es/Table/react/overlayChips.mjs +50 -0
- package/es/Table/react/overlayChips.mjs.map +1 -0
- package/es/Table/react/sameRenderInputs.mjs +50 -0
- package/es/Table/react/sameRenderInputs.mjs.map +1 -0
- package/es/Table/react/style.mjs +650 -0
- package/es/Table/react/style.mjs.map +1 -0
- package/es/Table/react/useTableCellEvents.mjs +32 -0
- package/es/Table/react/useTableCellEvents.mjs.map +1 -0
- package/es/Table/react/useTableColumnSettings.mjs +107 -0
- package/es/Table/react/useTableColumnSettings.mjs.map +1 -0
- package/es/Table/react/useTableEditorSync.mjs +41 -0
- package/es/Table/react/useTableEditorSync.mjs.map +1 -0
- package/es/Table/react/useTableHoverHint.mjs +62 -0
- package/es/Table/react/useTableHoverHint.mjs.map +1 -0
- package/es/Table/react/useTableKeyboard.mjs +41 -0
- package/es/Table/react/useTableKeyboard.mjs.map +1 -0
- package/es/Table/react/useTableRenderState.mjs +194 -0
- package/es/Table/react/useTableRenderState.mjs.map +1 -0
- package/es/Table/react/useTableScroll.mjs +33 -0
- package/es/Table/react/useTableScroll.mjs.map +1 -0
- package/es/Table/react/useTableSelectionInfo.mjs +48 -0
- package/es/Table/react/useTableSelectionInfo.mjs.map +1 -0
- package/es/Table/react/useTableVTableEvents.mjs +132 -0
- package/es/Table/react/useTableVTableEvents.mjs.map +1 -0
- package/es/Table/type.d.mts +279 -0
- package/es/Table/type.mjs +34 -0
- package/es/Table/type.mjs.map +1 -0
- package/es/Table/vtable/columns.d.mts +17 -0
- package/es/Table/vtable/columns.mjs +381 -0
- package/es/Table/vtable/columns.mjs.map +1 -0
- package/es/Table/vtable/frozenShadow.mjs +27 -0
- package/es/Table/vtable/frozenShadow.mjs.map +1 -0
- package/es/Table/vtable/interaction.mjs +175 -0
- package/es/Table/vtable/interaction.mjs.map +1 -0
- package/es/Table/vtable/option.d.mts +39 -0
- package/es/Table/vtable/option.mjs +232 -0
- package/es/Table/vtable/option.mjs.map +1 -0
- package/es/Table/vtable/seriesSelection.mjs +374 -0
- package/es/Table/vtable/seriesSelection.mjs.map +1 -0
- package/es/Table/vtable/vtableAdapter.mjs +96 -0
- package/es/Table/vtable/vtableAdapter.mjs.map +1 -0
- package/es/ThemeProvider/AppElementContext.d.mts +5 -0
- package/es/ThemeProvider/AppElementContext.mjs +10 -0
- package/es/ThemeProvider/AppElementContext.mjs.map +1 -0
- package/es/ThemeProvider/ConfigProvider.mjs +29 -0
- package/es/ThemeProvider/ConfigProvider.mjs.map +1 -0
- package/es/ThemeProvider/GlobalStyle/antdOverride.mjs +73 -0
- package/es/ThemeProvider/GlobalStyle/antdOverride.mjs.map +1 -0
- package/es/ThemeProvider/GlobalStyle/essential.mjs +50 -0
- package/es/ThemeProvider/GlobalStyle/essential.mjs.map +1 -0
- package/es/ThemeProvider/GlobalStyle/global.mjs +90 -0
- package/es/ThemeProvider/GlobalStyle/global.mjs.map +1 -0
- package/es/ThemeProvider/GlobalStyle/index.mjs +14 -0
- package/es/ThemeProvider/GlobalStyle/index.mjs.map +1 -0
- package/es/ThemeProvider/Meta.d.mts +7 -0
- package/es/ThemeProvider/Meta.mjs +48 -0
- package/es/ThemeProvider/Meta.mjs.map +1 -0
- package/es/ThemeProvider/ThemeProvider.d.mts +6 -0
- package/es/ThemeProvider/ThemeProvider.mjs +89 -0
- package/es/ThemeProvider/ThemeProvider.mjs.map +1 -0
- package/es/ThemeProvider/constants.d.mts +5 -0
- package/es/ThemeProvider/constants.mjs +6 -0
- package/es/ThemeProvider/constants.mjs.map +1 -0
- package/es/ThemeProvider/index.d.mts +6 -0
- package/es/ThemeProvider/index.d.ts +1 -0
- package/es/ThemeProvider/index.js +1 -0
- package/es/ThemeProvider/index.mjs +5 -0
- package/es/ThemeProvider/type.d.mts +48 -0
- package/es/_virtual/_rolldown/runtime.mjs +13 -0
- package/es/color/colors/blue.d.mts +6 -0
- package/es/color/colors/blue.mjs +67 -0
- package/es/color/colors/blue.mjs.map +1 -0
- package/es/color/colors/cyan.d.mts +6 -0
- package/es/color/colors/cyan.mjs +67 -0
- package/es/color/colors/cyan.mjs.map +1 -0
- package/es/color/colors/geekblue.d.mts +6 -0
- package/es/color/colors/geekblue.mjs +67 -0
- package/es/color/colors/geekblue.mjs.map +1 -0
- package/es/color/colors/gold.d.mts +6 -0
- package/es/color/colors/gold.mjs +67 -0
- package/es/color/colors/gold.mjs.map +1 -0
- package/es/color/colors/gray.d.mts +6 -0
- package/es/color/colors/gray.mjs +67 -0
- package/es/color/colors/gray.mjs.map +1 -0
- package/es/color/colors/green.d.mts +6 -0
- package/es/color/colors/green.mjs +67 -0
- package/es/color/colors/green.mjs.map +1 -0
- package/es/color/colors/index.d.mts +22 -0
- package/es/color/colors/index.mjs +35 -0
- package/es/color/colors/index.mjs.map +1 -0
- package/es/color/colors/lime.d.mts +6 -0
- package/es/color/colors/lime.mjs +67 -0
- package/es/color/colors/lime.mjs.map +1 -0
- package/es/color/colors/magenta.d.mts +6 -0
- package/es/color/colors/magenta.mjs +67 -0
- package/es/color/colors/magenta.mjs.map +1 -0
- package/es/color/colors/orange.d.mts +6 -0
- package/es/color/colors/orange.mjs +67 -0
- package/es/color/colors/orange.mjs.map +1 -0
- package/es/color/colors/primary.d.mts +6 -0
- package/es/color/colors/primary.mjs +67 -0
- package/es/color/colors/primary.mjs.map +1 -0
- package/es/color/colors/purple.d.mts +6 -0
- package/es/color/colors/purple.mjs +67 -0
- package/es/color/colors/purple.mjs.map +1 -0
- package/es/color/colors/red.d.mts +6 -0
- package/es/color/colors/red.mjs +67 -0
- package/es/color/colors/red.mjs.map +1 -0
- package/es/color/colors/volcano.d.mts +6 -0
- package/es/color/colors/volcano.mjs +67 -0
- package/es/color/colors/volcano.mjs.map +1 -0
- package/es/color/colors/yellow.d.mts +6 -0
- package/es/color/colors/yellow.mjs +67 -0
- package/es/color/colors/yellow.mjs.map +1 -0
- package/es/color/index.d.mts +23 -0
- package/es/color/index.d.ts +1 -0
- package/es/color/index.js +1 -0
- package/es/color/index.mjs +22 -0
- package/es/color/neutrals/index.d.mts +13 -0
- package/es/color/neutrals/index.mjs +17 -0
- package/es/color/neutrals/index.mjs.map +1 -0
- package/es/color/neutrals/mauve.d.mts +6 -0
- package/es/color/neutrals/mauve.mjs +67 -0
- package/es/color/neutrals/mauve.mjs.map +1 -0
- package/es/color/neutrals/olive.d.mts +6 -0
- package/es/color/neutrals/olive.mjs +67 -0
- package/es/color/neutrals/olive.mjs.map +1 -0
- package/es/color/neutrals/sage.d.mts +6 -0
- package/es/color/neutrals/sage.mjs +67 -0
- package/es/color/neutrals/sage.mjs.map +1 -0
- package/es/color/neutrals/sand.d.mts +6 -0
- package/es/color/neutrals/sand.mjs +67 -0
- package/es/color/neutrals/sand.mjs.map +1 -0
- package/es/color/neutrals/slate.d.mts +6 -0
- package/es/color/neutrals/slate.mjs +67 -0
- package/es/color/neutrals/slate.mjs.map +1 -0
- package/es/color/types.d.mts +16 -0
- package/es/eslint/index.d.mts +26 -0
- package/es/eslint/index.d.ts +1 -0
- package/es/eslint/index.js +1 -0
- package/es/eslint/index.mjs +11 -0
- package/es/eslint/index.mjs.map +1 -0
- package/es/hooks/useIsClient.d.mts +8 -0
- package/es/hooks/useIsClient.mjs +13 -0
- package/es/hooks/useIsClient.mjs.map +1 -0
- package/es/i18n/context.d.mts +7 -0
- package/es/i18n/context.mjs +16 -0
- package/es/i18n/context.mjs.map +1 -0
- package/es/i18n/index.d.mts +6 -0
- package/es/i18n/index.d.ts +1 -0
- package/es/i18n/index.js +1 -0
- package/es/i18n/index.mjs +5 -0
- package/es/i18n/resources/en/common.d.mts +35 -0
- package/es/i18n/resources/en/common.mjs +36 -0
- package/es/i18n/resources/en/common.mjs.map +1 -0
- package/es/i18n/resources/en/index.d.mts +7 -0
- package/es/i18n/resources/en/index.mjs +8 -0
- package/es/i18n/resources/en/index.mjs.map +1 -0
- package/es/i18n/resources/zhCn/common.d.mts +35 -0
- package/es/i18n/resources/zhCn/common.mjs +36 -0
- package/es/i18n/resources/zhCn/common.mjs.map +1 -0
- package/es/i18n/resources/zhCn/index.d.mts +7 -0
- package/es/i18n/resources/zhCn/index.mjs +8 -0
- package/es/i18n/resources/zhCn/index.mjs.map +1 -0
- package/es/i18n/types.d.mts +22 -0
- package/es/i18n/useTranslation.d.mts +12 -0
- package/es/i18n/useTranslation.mjs +22 -0
- package/es/i18n/useTranslation.mjs.map +1 -0
- package/es/index.d.mts +43 -0
- package/es/index.mjs +26 -0
- package/es/storybook/StoryBook/StoryBook.d.mts +7 -0
- package/es/storybook/StoryBook/StoryBook.mjs +52 -0
- package/es/storybook/StoryBook/StoryBook.mjs.map +1 -0
- package/es/storybook/StoryBook/index.d.mts +3 -0
- package/es/storybook/StoryBook/style.mjs +97 -0
- package/es/storybook/StoryBook/style.mjs.map +1 -0
- package/es/storybook/StoryBook/type.d.mts +13 -0
- package/es/storybook/index.d.mts +4 -0
- package/es/storybook/index.d.ts +1 -0
- package/es/storybook/index.js +1 -0
- package/es/storybook/index.mjs +2 -0
- package/es/styles/classNames.d.mts +11 -0
- package/es/styles/classNames.mjs +12 -0
- package/es/styles/classNames.mjs.map +1 -0
- package/es/styles/customTheme.d.mts +36 -0
- package/es/styles/customTheme.mjs +71 -0
- package/es/styles/customTheme.mjs.map +1 -0
- package/es/styles/index.d.mts +6 -0
- package/es/styles/index.d.ts +1 -0
- package/es/styles/index.js +1 -0
- package/es/styles/index.mjs +6 -0
- package/es/styles/theme/algorithms/darkAlgorithm.mjs +18 -0
- package/es/styles/theme/algorithms/darkAlgorithm.mjs.map +1 -0
- package/es/styles/theme/algorithms/lightAlgorithm.mjs +18 -0
- package/es/styles/theme/algorithms/lightAlgorithm.mjs.map +1 -0
- package/es/styles/theme/algorithms/resolveScales.mjs +25 -0
- package/es/styles/theme/algorithms/resolveScales.mjs.map +1 -0
- package/es/styles/theme/antdTheme.mjs +31 -0
- package/es/styles/theme/antdTheme.mjs.map +1 -0
- package/es/styles/theme/customStylish.d.mts +7 -0
- package/es/styles/theme/customStylish.mjs +158 -0
- package/es/styles/theme/customStylish.mjs.map +1 -0
- package/es/styles/theme/customStylishStatic.d.mts +6 -0
- package/es/styles/theme/customStylishStatic.mjs +156 -0
- package/es/styles/theme/customStylishStatic.mjs.map +1 -0
- package/es/styles/theme/customToken.d.mts +7 -0
- package/es/styles/theme/customToken.mjs +127 -0
- package/es/styles/theme/customToken.mjs.map +1 -0
- package/es/styles/theme/generateColorPalette.d.mts +16 -0
- package/es/styles/theme/generateColorPalette.mjs +170 -0
- package/es/styles/theme/generateColorPalette.mjs.map +1 -0
- package/es/styles/theme/token/base.mjs +64 -0
- package/es/styles/theme/token/base.mjs.map +1 -0
- package/es/styles/theme/token/dark.mjs +37 -0
- package/es/styles/theme/token/dark.mjs.map +1 -0
- package/es/styles/theme/token/light.mjs +37 -0
- package/es/styles/theme/token/light.mjs.map +1 -0
- package/es/types/customStylish.d.mts +28 -0
- package/es/types/customToken.d.mts +34 -0
- package/es/types/customToken.mjs +32 -0
- package/es/types/customToken.mjs.map +1 -0
- package/es/types/index.d.mts +15 -0
- package/es/types/index.d.ts +1 -0
- package/es/types/index.js +1 -0
- package/es/types/index.mjs +2 -0
- package/es/utils/composeEventHandlers.d.mts +5 -0
- package/es/utils/composeEventHandlers.mjs +10 -0
- package/es/utils/composeEventHandlers.mjs.map +1 -0
- package/es/utils/copyToClipboard.d.mts +5 -0
- package/es/utils/copyToClipboard.mjs +28 -0
- package/es/utils/copyToClipboard.mjs.map +1 -0
- package/es/utils/dom.d.mts +15 -0
- package/es/utils/dom.mjs +16 -0
- package/es/utils/dom.mjs.map +1 -0
- package/es/utils/genCdnUrl.d.mts +12 -0
- package/es/utils/genCdnUrl.mjs +17 -0
- package/es/utils/genCdnUrl.mjs.map +1 -0
- package/es/utils/safeReadableColor.mjs +6 -0
- package/es/utils/safeReadableColor.mjs.map +1 -0
- package/package.json +96 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { toneFor } from "../core/tagTone.mjs";
|
|
3
|
+
import { getCanvasPalette } from "./canvasPalette.mjs";
|
|
4
|
+
import { formatDuration, formatLinkLabel, resolveDurationRange, resolveOption, resolveUser, toValueList } from "../core/cellValue.mjs";
|
|
5
|
+
import { editHintGutterFor, fitLabel, measureArrayChipWidth, measureLabelWidth, measureLinkPillWidth, measureOverflowBadgeWidth, measureTagWidth, overflowBadgeWidth, packItems } from "./paintUtils.mjs";
|
|
6
|
+
import { createEmptyCellText } from "./textPainters.mjs";
|
|
7
|
+
import { CustomLayout } from "@visactor/vtable";
|
|
8
|
+
//#region src/Table/canvas/chipPainters.ts
|
|
9
|
+
/**
|
|
10
|
+
* "+N" badge shown when chips do not fit. Shared by every chip layout so the badge
|
|
11
|
+
* keeps one size, colour and baseline.
|
|
12
|
+
*/
|
|
13
|
+
const createOverflowText = (count, palette, height, x) => new CustomLayout.Text({
|
|
14
|
+
fontFamily: palette.fontFamily,
|
|
15
|
+
fill: palette.text,
|
|
16
|
+
fontSize: 13,
|
|
17
|
+
pickable: false,
|
|
18
|
+
text: `+${count}`,
|
|
19
|
+
textAlign: "left",
|
|
20
|
+
textBaseline: "middle",
|
|
21
|
+
x,
|
|
22
|
+
y: height / 2
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* 打包用的可用宽度。绘制是从 `palette.paddingX` 起笔的,不减掉左右内边距的话,最后一个
|
|
26
|
+
* chip 会顶到甚至越过单元格右边界 —— 自定义容器没有 clip,会盖到相邻单元格上。
|
|
27
|
+
* 文本 painter 早就是这么算的(`width - paddingX * 2`)。
|
|
28
|
+
*/
|
|
29
|
+
const availableWidth = (width, paddingX) => Math.max(width - paddingX * 2, 48);
|
|
30
|
+
/**
|
|
31
|
+
* 各个 chip 布局共用的排布:打包 → 按可用宽截断 → 从左往右累加 x。
|
|
32
|
+
*
|
|
33
|
+
* 抽成自由函数是因为**画布与 DOM 悬停浮层必须共用同一份计算**:浮层要在画布画出来的 chip
|
|
34
|
+
* 正上方盖一个 ×,两边各算一次就会错位。用到的度量(`measureLabelWidth` / `fitLabel` /
|
|
35
|
+
* `packItems`)都是纯函数、不依赖 canvas 上下文,所以 DOM 这边也能直接调。
|
|
36
|
+
*
|
|
37
|
+
* `Extra` 让调用方带上自己的载荷(标签带 option、人员带 user),排布本身不关心那是什么。
|
|
38
|
+
*/
|
|
39
|
+
const layoutChips = (items, widthOf, overflowOf, { paddingX, width }) => {
|
|
40
|
+
const available = availableWidth(width, paddingX);
|
|
41
|
+
const packed = packItems(items.map(({ label }) => widthOf(label)), available, overflowOf);
|
|
42
|
+
const boxes = [];
|
|
43
|
+
let x = paddingX;
|
|
44
|
+
items.slice(0, packed.visible).forEach((item) => {
|
|
45
|
+
const label = fitLabel(item.label, available - overflowBadgeWidth(packed.overflow), widthOf);
|
|
46
|
+
const chipWidth = widthOf(label);
|
|
47
|
+
boxes.push({
|
|
48
|
+
...item,
|
|
49
|
+
label,
|
|
50
|
+
width: chipWidth,
|
|
51
|
+
x
|
|
52
|
+
});
|
|
53
|
+
x += chipWidth + 4;
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
boxes,
|
|
57
|
+
overflow: packed.overflow,
|
|
58
|
+
overflowX: x
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* 标签 chip 的排布。供悬停浮层在画布画出来的 chip 上盖 × 用。
|
|
63
|
+
*
|
|
64
|
+
* 值的容器类型不同(数组 / 单个字符串)不影响排布 —— `packed.visible` 之外的那些由 +N 徽标
|
|
65
|
+
* 代表,`index` 始终是**原始数组下标**。
|
|
66
|
+
*/
|
|
67
|
+
/**
|
|
68
|
+
* 状态 chip 外标注的时长文案与它占的宽度。**画布与悬停浮层必须用同一份**:打包预算要把它
|
|
69
|
+
* 预留掉,两边各算一遍截断点就会漂移。
|
|
70
|
+
*/
|
|
71
|
+
const tagDurationSuffix = (record, duration) => {
|
|
72
|
+
const text = formatDuration(resolveDurationRange(record, duration));
|
|
73
|
+
if (text === "") return {
|
|
74
|
+
suffix: "",
|
|
75
|
+
width: 0
|
|
76
|
+
};
|
|
77
|
+
const suffix = ` ${text}`;
|
|
78
|
+
return {
|
|
79
|
+
suffix,
|
|
80
|
+
width: 4 + measureLabelWidth(suffix, 13)
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
const layoutTagChips = ({ options, paddingX, reserve = 0, value, width }) => layoutChips(toValueList(value).map((item) => resolveOption(item, options)).map((option, index) => ({
|
|
84
|
+
index,
|
|
85
|
+
label: option.label,
|
|
86
|
+
option
|
|
87
|
+
})), measureTagWidth, (rest) => measureOverflowBadgeWidth(`+${rest}`), {
|
|
88
|
+
paddingX,
|
|
89
|
+
width: width - reserve
|
|
90
|
+
});
|
|
91
|
+
const createTagLayout = (options, placeholder, duration) => (args) => {
|
|
92
|
+
const palette = getCanvasPalette(args.table);
|
|
93
|
+
const width = args.rect?.width ?? 120;
|
|
94
|
+
const height = args.rect?.height ?? 40;
|
|
95
|
+
const record = args.table?.getCellOriginRecord?.(args.col, args.row);
|
|
96
|
+
const { suffix, width: suffixWidth } = tagDurationSuffix(record, duration);
|
|
97
|
+
const root = new CustomLayout.Group({
|
|
98
|
+
height,
|
|
99
|
+
pickable: false,
|
|
100
|
+
width
|
|
101
|
+
});
|
|
102
|
+
const { boxes, overflow, overflowX } = layoutTagChips({
|
|
103
|
+
options,
|
|
104
|
+
paddingX: palette.paddingX,
|
|
105
|
+
reserve: suffixWidth + editHintGutterFor(args.table, args.col, args.row),
|
|
106
|
+
value: args.value,
|
|
107
|
+
width
|
|
108
|
+
});
|
|
109
|
+
if (boxes.length === 0) {
|
|
110
|
+
if (placeholder) root.add(createEmptyCellText(placeholder, palette, height, args.table));
|
|
111
|
+
return {
|
|
112
|
+
enableCellPadding: false,
|
|
113
|
+
renderDefault: false,
|
|
114
|
+
rootContainer: root
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const chipHeight = 24;
|
|
118
|
+
const chipTop = Math.max(0, (height - chipHeight) / 2);
|
|
119
|
+
boxes.forEach(({ label, option, width: chipWidth, x }) => {
|
|
120
|
+
const tone = toneFor(option.value, option.color, palette.isDarkMode, palette.checkboxBg);
|
|
121
|
+
const textFill = palette.isDarkMode ? tone.color : palette.text;
|
|
122
|
+
root.add(new CustomLayout.Rect({
|
|
123
|
+
cornerRadius: 6,
|
|
124
|
+
fill: tone.bg,
|
|
125
|
+
height: chipHeight,
|
|
126
|
+
lineWidth: tone.border ? 1 : 0,
|
|
127
|
+
pickable: false,
|
|
128
|
+
stroke: tone.border,
|
|
129
|
+
width: chipWidth,
|
|
130
|
+
x,
|
|
131
|
+
y: chipTop
|
|
132
|
+
}));
|
|
133
|
+
root.add(new CustomLayout.Text({
|
|
134
|
+
fontFamily: palette.fontFamily,
|
|
135
|
+
fill: textFill,
|
|
136
|
+
fontSize: 13,
|
|
137
|
+
pickable: false,
|
|
138
|
+
text: label,
|
|
139
|
+
textAlign: "left",
|
|
140
|
+
textBaseline: "middle",
|
|
141
|
+
x: x + 14,
|
|
142
|
+
y: height / 2
|
|
143
|
+
}));
|
|
144
|
+
});
|
|
145
|
+
let after = overflowX;
|
|
146
|
+
if (suffix !== "") {
|
|
147
|
+
const remaining = Math.max(0, width - palette.paddingX - (overflowX + 4));
|
|
148
|
+
const drawnSuffix = remaining >= suffixWidth ? suffix : fitLabel(suffix, remaining, (label) => measureLabelWidth(label, 13));
|
|
149
|
+
root.add(new CustomLayout.Text({
|
|
150
|
+
fontFamily: palette.fontFamily,
|
|
151
|
+
fill: palette.textMuted,
|
|
152
|
+
fontSize: 13,
|
|
153
|
+
pickable: false,
|
|
154
|
+
text: drawnSuffix,
|
|
155
|
+
textAlign: "left",
|
|
156
|
+
textBaseline: "middle",
|
|
157
|
+
x: overflowX + 4,
|
|
158
|
+
y: height / 2
|
|
159
|
+
}));
|
|
160
|
+
after += suffixWidth;
|
|
161
|
+
}
|
|
162
|
+
if (overflow > 0) root.add(createOverflowText(overflow, palette, height, after));
|
|
163
|
+
return {
|
|
164
|
+
enableCellPadding: false,
|
|
165
|
+
renderDefault: false,
|
|
166
|
+
rootContainer: root
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* 人员 chip 的排布。
|
|
171
|
+
*
|
|
172
|
+
* 抽成自由函数是因为**画布与 DOM 悬停浮层必须共用同一份计算**:浮层要在画布画出来的 chip
|
|
173
|
+
* 正上方盖一个 ×,两边各算一次就会错位。用到的度量(`measureLabelWidth` / `fitLabel` /
|
|
174
|
+
* `packItems`)都是纯函数、不依赖 canvas 上下文,所以 DOM 这边也能直接调。
|
|
175
|
+
*/
|
|
176
|
+
const layoutUserChips = ({ paddingX, users, width }) => layoutChips(users.map(({ index, user }) => ({
|
|
177
|
+
index,
|
|
178
|
+
label: user.name,
|
|
179
|
+
user
|
|
180
|
+
})), (label) => 18 + measureLabelWidth(label, 13) + 22, () => 24, {
|
|
181
|
+
paddingX,
|
|
182
|
+
width
|
|
183
|
+
});
|
|
184
|
+
/** 值的每一项解析成人员并保留**原始下标**;没有可用名字的(`{}` / `{ id }` / `{ name: 42 }`)
|
|
185
|
+
* 一律丢掉 —— `isEmptyCellValue({})` 判它是空值,两条路径口径必须一致。 */
|
|
186
|
+
const resolveUserEntries = (value) => toValueList(value).map(resolveUser).map((user, index) => ({
|
|
187
|
+
index,
|
|
188
|
+
user
|
|
189
|
+
})).filter(({ user }) => user.name !== "");
|
|
190
|
+
const createUserLayout = (placeholder) => (args) => {
|
|
191
|
+
const palette = getCanvasPalette(args.table);
|
|
192
|
+
const width = args.rect?.width ?? 140;
|
|
193
|
+
const height = args.rect?.height ?? 40;
|
|
194
|
+
const entries = resolveUserEntries(args.value);
|
|
195
|
+
const root = new CustomLayout.Group({
|
|
196
|
+
height,
|
|
197
|
+
pickable: false,
|
|
198
|
+
width
|
|
199
|
+
});
|
|
200
|
+
if (entries.length === 0) {
|
|
201
|
+
if (placeholder) root.add(createEmptyCellText(placeholder, palette, height, args.table));
|
|
202
|
+
return {
|
|
203
|
+
enableCellPadding: false,
|
|
204
|
+
renderDefault: false,
|
|
205
|
+
rootContainer: root
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const chipTop = Math.max(0, (height - 24) / 2);
|
|
209
|
+
const { boxes, overflow, overflowX } = layoutUserChips({
|
|
210
|
+
paddingX: palette.paddingX,
|
|
211
|
+
users: entries,
|
|
212
|
+
width: width - editHintGutterFor(args.table, args.col, args.row)
|
|
213
|
+
});
|
|
214
|
+
boxes.forEach(({ label, user, width: chipWidth, x }) => {
|
|
215
|
+
const tone = toneFor(user.name, void 0, palette.isDarkMode, palette.checkboxBg);
|
|
216
|
+
const initials = user.name.trim().slice(0, 1) || "?";
|
|
217
|
+
root.add(new CustomLayout.Rect({
|
|
218
|
+
cornerRadius: 4,
|
|
219
|
+
fill: palette.pillBg,
|
|
220
|
+
height: 24,
|
|
221
|
+
pickable: false,
|
|
222
|
+
width: chipWidth,
|
|
223
|
+
x,
|
|
224
|
+
y: chipTop
|
|
225
|
+
}));
|
|
226
|
+
if (user.avatar) root.add(new CustomLayout.Image({
|
|
227
|
+
cornerRadius: 999,
|
|
228
|
+
height: 14,
|
|
229
|
+
pickable: false,
|
|
230
|
+
shape: "square",
|
|
231
|
+
src: user.avatar,
|
|
232
|
+
width: 14,
|
|
233
|
+
x: x + 4,
|
|
234
|
+
y: chipTop + 5
|
|
235
|
+
}));
|
|
236
|
+
else {
|
|
237
|
+
root.add(new CustomLayout.Rect({
|
|
238
|
+
cornerRadius: 999,
|
|
239
|
+
fill: tone.bg,
|
|
240
|
+
height: 14,
|
|
241
|
+
pickable: false,
|
|
242
|
+
width: 14,
|
|
243
|
+
x: x + 4,
|
|
244
|
+
y: chipTop + 5
|
|
245
|
+
}));
|
|
246
|
+
root.add(new CustomLayout.Text({
|
|
247
|
+
fontFamily: palette.fontFamily,
|
|
248
|
+
fill: tone.color,
|
|
249
|
+
fontSize: 9,
|
|
250
|
+
pickable: false,
|
|
251
|
+
text: initials,
|
|
252
|
+
textAlign: "center",
|
|
253
|
+
textBaseline: "middle",
|
|
254
|
+
x: x + 4 + 7,
|
|
255
|
+
y: chipTop + 5 + 7
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
root.add(new CustomLayout.Text({
|
|
259
|
+
fontFamily: palette.fontFamily,
|
|
260
|
+
fill: palette.text,
|
|
261
|
+
fontSize: 13,
|
|
262
|
+
pickable: false,
|
|
263
|
+
text: label,
|
|
264
|
+
textAlign: "left",
|
|
265
|
+
textBaseline: "middle",
|
|
266
|
+
x: x + 4 + 14 + 4,
|
|
267
|
+
y: height / 2
|
|
268
|
+
}));
|
|
269
|
+
});
|
|
270
|
+
if (overflow > 0) root.add(createOverflowText(overflow, palette, height, overflowX));
|
|
271
|
+
return {
|
|
272
|
+
enableCellPadding: false,
|
|
273
|
+
renderDefault: false,
|
|
274
|
+
rootContainer: root
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
/** 值 → 文本项,保留**原始下标**;空串不画(与 painter 原先的 `filter(Boolean)` 同口径)。
|
|
278
|
+
* 下标必须是原始的:记录是 `['', '核心']` 时画面上只有一枚 chip,点它的 × 要删掉「核心」。 */
|
|
279
|
+
const resolveTextEntries = (value) => toValueList(value).map((item) => String(item)).map((label, index) => ({
|
|
280
|
+
index,
|
|
281
|
+
label
|
|
282
|
+
})).filter(({ label }) => label !== "");
|
|
283
|
+
/** 链接 pill 的排布。文案与画布同源:`kind === 'link'` 时要一起剥掉 scheme。 */
|
|
284
|
+
const layoutLinkChips = ({ kind, paddingX, value, width }) => layoutChips(resolveTextEntries(value).map(({ index, label }) => ({
|
|
285
|
+
index,
|
|
286
|
+
label: kind === "link" ? formatLinkLabel(label) : label
|
|
287
|
+
})), measureLinkPillWidth, () => 24, {
|
|
288
|
+
paddingX,
|
|
289
|
+
width
|
|
290
|
+
});
|
|
291
|
+
const createLinkLayout = (kind, placeholder) => (args) => {
|
|
292
|
+
const palette = getCanvasPalette(args.table);
|
|
293
|
+
const width = args.rect?.width ?? 140;
|
|
294
|
+
const height = args.rect?.height ?? 40;
|
|
295
|
+
const root = new CustomLayout.Group({
|
|
296
|
+
height,
|
|
297
|
+
pickable: false,
|
|
298
|
+
width
|
|
299
|
+
});
|
|
300
|
+
const { boxes, overflow, overflowX } = layoutLinkChips({
|
|
301
|
+
kind,
|
|
302
|
+
paddingX: palette.paddingX,
|
|
303
|
+
value: args.value,
|
|
304
|
+
width: width - editHintGutterFor(args.table, args.col, args.row)
|
|
305
|
+
});
|
|
306
|
+
if (boxes.length === 0) {
|
|
307
|
+
if (placeholder) root.add(createEmptyCellText(placeholder, palette, height, args.table));
|
|
308
|
+
return {
|
|
309
|
+
enableCellPadding: false,
|
|
310
|
+
renderDefault: false,
|
|
311
|
+
rootContainer: root
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
const pillHeight = 24;
|
|
315
|
+
const pillTop = Math.max(0, (height - pillHeight) / 2);
|
|
316
|
+
boxes.forEach(({ label, width: pillWidth, x }) => {
|
|
317
|
+
root.add(new CustomLayout.Rect({
|
|
318
|
+
cornerRadius: 999,
|
|
319
|
+
fill: palette.pillBg,
|
|
320
|
+
height: pillHeight,
|
|
321
|
+
lineWidth: 1,
|
|
322
|
+
pickable: false,
|
|
323
|
+
stroke: palette.overlayBorder,
|
|
324
|
+
width: pillWidth,
|
|
325
|
+
x,
|
|
326
|
+
y: pillTop
|
|
327
|
+
}));
|
|
328
|
+
root.add(new CustomLayout.Text({
|
|
329
|
+
fontFamily: palette.fontFamily,
|
|
330
|
+
fill: palette.text,
|
|
331
|
+
fontSize: 13,
|
|
332
|
+
pickable: false,
|
|
333
|
+
text: label,
|
|
334
|
+
textAlign: "left",
|
|
335
|
+
textBaseline: "middle",
|
|
336
|
+
x: x + 14,
|
|
337
|
+
y: height / 2
|
|
338
|
+
}));
|
|
339
|
+
});
|
|
340
|
+
if (overflow > 0) root.add(createOverflowText(overflow, palette, height, overflowX));
|
|
341
|
+
return {
|
|
342
|
+
enableCellPadding: false,
|
|
343
|
+
renderDefault: false,
|
|
344
|
+
rootContainer: root
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
/** 数组 chip 的排布。内边距与标签 / 链接同为 CHIP_PAD —— 右内边距要整颗装下悬停的 ×。 */
|
|
348
|
+
const layoutArrayChips = ({ paddingX, value, width }) => layoutChips(resolveTextEntries(value), measureArrayChipWidth, () => 24, {
|
|
349
|
+
paddingX,
|
|
350
|
+
width
|
|
351
|
+
});
|
|
352
|
+
const createArrayLayout = (placeholder) => (args) => {
|
|
353
|
+
const palette = getCanvasPalette(args.table);
|
|
354
|
+
const width = args.rect?.width ?? 140;
|
|
355
|
+
const height = args.rect?.height ?? 40;
|
|
356
|
+
const root = new CustomLayout.Group({
|
|
357
|
+
height,
|
|
358
|
+
pickable: false,
|
|
359
|
+
width
|
|
360
|
+
});
|
|
361
|
+
const { boxes, overflow, overflowX } = layoutArrayChips({
|
|
362
|
+
paddingX: palette.paddingX,
|
|
363
|
+
value: args.value,
|
|
364
|
+
width: width - editHintGutterFor(args.table, args.col, args.row)
|
|
365
|
+
});
|
|
366
|
+
if (boxes.length === 0) {
|
|
367
|
+
if (placeholder) root.add(createEmptyCellText(placeholder, palette, height, args.table));
|
|
368
|
+
return {
|
|
369
|
+
enableCellPadding: false,
|
|
370
|
+
renderDefault: false,
|
|
371
|
+
rootContainer: root
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
const chipHeight = 24;
|
|
375
|
+
const chipTop = Math.max(0, (height - chipHeight) / 2);
|
|
376
|
+
boxes.forEach(({ label, width: chipWidth, x }) => {
|
|
377
|
+
root.add(new CustomLayout.Rect({
|
|
378
|
+
cornerRadius: 4,
|
|
379
|
+
fill: palette.pillBg,
|
|
380
|
+
height: chipHeight,
|
|
381
|
+
pickable: false,
|
|
382
|
+
width: chipWidth,
|
|
383
|
+
x,
|
|
384
|
+
y: chipTop
|
|
385
|
+
}));
|
|
386
|
+
root.add(new CustomLayout.Text({
|
|
387
|
+
fontFamily: palette.fontFamily,
|
|
388
|
+
fill: palette.text,
|
|
389
|
+
fontSize: 13,
|
|
390
|
+
pickable: false,
|
|
391
|
+
text: label,
|
|
392
|
+
textAlign: "left",
|
|
393
|
+
textBaseline: "middle",
|
|
394
|
+
x: x + 14,
|
|
395
|
+
y: height / 2
|
|
396
|
+
}));
|
|
397
|
+
});
|
|
398
|
+
if (overflow > 0) root.add(createOverflowText(overflow, palette, height, overflowX));
|
|
399
|
+
return {
|
|
400
|
+
enableCellPadding: false,
|
|
401
|
+
renderDefault: false,
|
|
402
|
+
rootContainer: root
|
|
403
|
+
};
|
|
404
|
+
};
|
|
405
|
+
//#endregion
|
|
406
|
+
export { createArrayLayout, createLinkLayout, createTagLayout, createUserLayout, layoutArrayChips, layoutLinkChips, layoutTagChips, layoutUserChips, resolveUserEntries, tagDurationSuffix };
|
|
407
|
+
|
|
408
|
+
//# sourceMappingURL=chipPainters.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chipPainters.mjs","names":[],"sources":["../../../src/Table/canvas/chipPainters.ts"],"sourcesContent":["'use client';\n\nimport { CustomLayout } from '@visactor/vtable';\nimport type { ICustomLayoutFuc } from '@visactor/vtable/es/ts-types/customLayout';\n\nimport {\n formatDuration,\n formatLinkLabel,\n type LinkKind,\n resolveDurationRange,\n resolveOption,\n resolveUser,\n toValueList,\n} from '../core/cellValue';\nimport { toneFor } from '../core/tagTone';\nimport type { TableSelectOption, TableUser } from '../type';\nimport { type CanvasPalette, getCanvasPalette } from './canvasPalette';\nimport {\n ARRAY_PAD_LEFT,\n editHintGutterFor,\n fitLabel,\n LINK_PAD_LEFT,\n measureArrayChipWidth,\n measureLabelWidth,\n measureLinkPillWidth,\n measureOverflowBadgeWidth,\n measureTagWidth,\n overflowBadgeWidth,\n packItems,\n TAG_FONT_SIZE,\n TAG_GAP,\n TAG_PAD_LEFT,\n} from './paintUtils';\nimport { createEmptyCellText } from './textPainters';\n\nexport { EDIT_HINT_GUTTER, editHintGutterFor } from './paintUtils';\n\n/**\n * \"+N\" badge shown when chips do not fit. Shared by every chip layout so the badge\n * keeps one size, colour and baseline.\n */\nconst createOverflowText = (count: number, palette: CanvasPalette, height: number, x: number) =>\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: palette.text,\n fontSize: 13,\n pickable: false,\n text: `+${count}`,\n textAlign: 'left',\n textBaseline: 'middle',\n x,\n y: height / 2,\n } as never);\n\n/**\n * 打包用的可用宽度。绘制是从 `palette.paddingX` 起笔的,不减掉左右内边距的话,最后一个\n * chip 会顶到甚至越过单元格右边界 —— 自定义容器没有 clip,会盖到相邻单元格上。\n * 文本 painter 早就是这么算的(`width - paddingX * 2`)。\n */\nconst availableWidth = (width: number, paddingX: number): number =>\n Math.max(width - paddingX * 2, 48);\n\n/** 画布与 DOM 悬停浮层共用的 chip 排布结果。 */\nexport interface ChipBox {\n /** 在**记录原始数组**里的下标 —— 移除时按它 splice,不能用过滤后的位置。 */\n index: number;\n /** 画进 chip 的文字(可能已被截断)。 */\n label: string;\n width: number;\n /** 相对单元格左边界的起点,与 painter 的落笔位置同源。 */\n x: number;\n}\n\n/**\n * 各个 chip 布局共用的排布:打包 → 按可用宽截断 → 从左往右累加 x。\n *\n * 抽成自由函数是因为**画布与 DOM 悬停浮层必须共用同一份计算**:浮层要在画布画出来的 chip\n * 正上方盖一个 ×,两边各算一次就会错位。用到的度量(`measureLabelWidth` / `fitLabel` /\n * `packItems`)都是纯函数、不依赖 canvas 上下文,所以 DOM 这边也能直接调。\n *\n * `Extra` 让调用方带上自己的载荷(标签带 option、人员带 user),排布本身不关心那是什么。\n */\nconst layoutChips = <Extra>(\n items: ({ index: number; label: string } & Extra)[],\n widthOf: (label: string) => number,\n overflowOf: (rest: number) => number,\n { paddingX, width }: { paddingX: number; width: number },\n): { boxes: (ChipBox & Extra)[]; overflow: number; overflowX: number } => {\n const available = availableWidth(width, paddingX);\n const packed = packItems(\n items.map(({ label }) => widthOf(label)),\n available,\n overflowOf,\n );\n const boxes: (ChipBox & Extra)[] = [];\n let x = paddingX;\n\n items.slice(0, packed.visible).forEach((item) => {\n // 截断必须发生在**算宽度之前**:只截文本节点的话矩形仍按完整标签算宽,照样越界。\n const label = fitLabel(item.label, available - overflowBadgeWidth(packed.overflow), widthOf);\n const chipWidth = widthOf(label);\n\n boxes.push({ ...item, label, width: chipWidth, x });\n x += chipWidth + TAG_GAP;\n });\n\n // `x` 已经停在下一枚 chip 该落笔的位置,正好是 +N 徽标的起点。\n return { boxes, overflow: packed.overflow, overflowX: x };\n};\n\n/**\n * 标签 chip 的排布。供悬停浮层在画布画出来的 chip 上盖 × 用。\n *\n * 值的容器类型不同(数组 / 单个字符串)不影响排布 —— `packed.visible` 之外的那些由 +N 徽标\n * 代表,`index` 始终是**原始数组下标**。\n */\n/**\n * 状态 chip 外标注的时长文案与它占的宽度。**画布与悬停浮层必须用同一份**:打包预算要把它\n * 预留掉,两边各算一遍截断点就会漂移。\n */\nexport const tagDurationSuffix = (\n record: unknown,\n duration?: string | { from: string; to: string },\n): { suffix: string; width: number } => {\n const text = formatDuration(resolveDurationRange(record, duration));\n if (text === '') return { suffix: '', width: 0 };\n\n const suffix = ` ${text}`;\n return { suffix, width: TAG_GAP + measureLabelWidth(suffix, TAG_FONT_SIZE) };\n};\n\nexport const layoutTagChips = ({\n options,\n paddingX,\n reserve = 0,\n value,\n width,\n}: {\n options: TableSelectOption[] | undefined;\n paddingX: number;\n /** chip 之后还要放独立文字(「5天」这类时长)时预留的宽度(含间距)。 */\n reserve?: number;\n value: unknown;\n width: number;\n}): {\n boxes: (ChipBox & { option: TableSelectOption })[];\n overflow: number;\n overflowX: number;\n} =>\n layoutChips(\n toValueList(value)\n .map((item) => resolveOption(item, options))\n .map((option, index) => ({ index, label: option.label, option })),\n measureTagWidth,\n (rest) => measureOverflowBadgeWidth(`+${rest}`),\n { paddingX, width: width - reserve },\n );\n\nexport const createTagLayout =\n (\n options: TableSelectOption[] | undefined,\n placeholder?: string,\n duration?: string | { from: string; to: string },\n ): ICustomLayoutFuc =>\n (args) => {\n const palette = getCanvasPalette(args.table);\n const width = args.rect?.width ?? 120;\n const height = args.rect?.height ?? 40;\n // 状态标题后跟的时长(「5天 / 1个月」):`duration` 指名记录里存日期范围的字段,时长现算,\n // 作为 chip **外面**的独立文字画出来 —— 参考图里它就是 chip 后面的标注,不是 chip 的一部分。\n const record = (args.table as any)?.getCellOriginRecord?.(args.col, args.row);\n const { suffix, width: suffixWidth } = tagDurationSuffix(record, duration);\n const root = new CustomLayout.Group({ height, pickable: false, width });\n const { boxes, overflow, overflowX } = layoutTagChips({\n options,\n paddingX: palette.paddingX,\n reserve: suffixWidth + editHintGutterFor(args.table as never, args.col, args.row),\n value: args.value,\n width,\n });\n\n if (boxes.length === 0) {\n if (placeholder) {\n root.add(createEmptyCellText(placeholder, palette, height, args.table));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n }\n\n const chipHeight = 24;\n const chipTop = Math.max(0, (height - chipHeight) / 2);\n\n boxes.forEach(({ label, option, width: chipWidth, x }) => {\n const tone = toneFor(option.value, option.color, palette.isDarkMode, palette.checkboxBg);\n // 文字是主题文字色而不是 tone.color:浅底 + 统一近黑字是「状态」参考图的样式,也正好是\n // antd Tag 默认的「浅底 + colorText 字」。tone.color 仍是色相源(hex 吸附、暗色提亮都靠\n // 它),暗色下 chip 底是彩色半透明,白字对比度没有保证,所以暗色继续用 tone 的提亮色。\n const textFill = palette.isDarkMode ? tone.color : palette.text;\n\n root.add(\n new CustomLayout.Rect({\n cornerRadius: 6,\n fill: tone.bg,\n height: chipHeight,\n lineWidth: tone.border ? 1 : 0,\n pickable: false,\n stroke: tone.border,\n width: chipWidth,\n x,\n y: chipTop,\n } as never),\n );\n root.add(\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: textFill,\n fontSize: TAG_FONT_SIZE,\n pickable: false,\n text: label,\n textAlign: 'left',\n textBaseline: 'middle',\n x: x + TAG_PAD_LEFT,\n y: height / 2,\n } as never),\n );\n });\n\n // 时长文字画在**最后一枚 chip 的外面**(参考图里「4天」是 chip 后面的标注),\n // 用弱色 —— 它是补充信息,不能与 chip 标题同权重。已通过 `reserve` 参与打包预算。\n // 极窄列 + 长时长时剩余宽度装不下完整标注,按剩余宽度截断 —— 不能顶出单元格。\n let after = overflowX;\n if (suffix !== '') {\n const remaining = Math.max(0, width - palette.paddingX - (overflowX + TAG_GAP));\n const drawnSuffix =\n remaining >= suffixWidth\n ? suffix\n : fitLabel(suffix, remaining, (label) => measureLabelWidth(label, TAG_FONT_SIZE));\n root.add(\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: palette.textMuted,\n fontSize: TAG_FONT_SIZE,\n pickable: false,\n text: drawnSuffix,\n textAlign: 'left',\n textBaseline: 'middle',\n x: overflowX + TAG_GAP,\n y: height / 2,\n } as never),\n );\n after += suffixWidth;\n }\n\n if (overflow > 0) {\n root.add(createOverflowText(overflow, palette, height, after));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n };\n\n/** 人员 chip 的固定尺寸,画布与 DOM 悬停浮层共用。 */\nexport const USER_CHIP_HEIGHT = 24;\nexport const USER_CHIP_AVATAR = 14;\n/**\n * chip 右侧留白。**不是纯装饰**:悬停时要在这一格里盖一个 14px 的移除按钮。\n *\n * 取值有下界:文字从 `x + 22` 起笔,按钮是「贴右 + margin-inline-end 2px」,所以留白必须\n * ≥ 4 + 2 + 14 = 20 才不压到字上。留 8px 时按钮整个盖在最后一个字上 —— 近黑的 × 叠在近黑的\n * 笔画上等于没画,实测截图里完全看不见。22 是 20 再加 2px 余量。\n */\nexport const USER_CHIP_TRAILING = 22;\n\nexport interface UserChipBox extends ChipBox {\n user: TableUser;\n}\n\n/**\n * 人员 chip 的排布。\n *\n * 抽成自由函数是因为**画布与 DOM 悬停浮层必须共用同一份计算**:浮层要在画布画出来的 chip\n * 正上方盖一个 ×,两边各算一次就会错位。用到的度量(`measureLabelWidth` / `fitLabel` /\n * `packItems`)都是纯函数、不依赖 canvas 上下文,所以 DOM 这边也能直接调。\n */\nexport const layoutUserChips = ({\n paddingX,\n users,\n width,\n}: {\n paddingX: number;\n users: { index: number; user: TableUser }[];\n width: number;\n}): { boxes: UserChipBox[]; overflow: number; overflowX: number } =>\n layoutChips(\n users.map(({ index, user }) => ({ index, label: user.name, user })),\n // Packing and drawing must share one expression: the avatar's width is what makes them\n // differ, and a mismatch would shift the +N overflow count.\n (label) => USER_CHIP_AVATAR + 4 + measureLabelWidth(label, 13) + USER_CHIP_TRAILING,\n () => 24,\n { paddingX, width },\n );\n\n/** 值的每一项解析成人员并保留**原始下标**;没有可用名字的(`{}` / `{ id }` / `{ name: 42 }`)\n * 一律丢掉 —— `isEmptyCellValue({})` 判它是空值,两条路径口径必须一致。 */\nexport const resolveUserEntries = (value: unknown): { index: number; user: TableUser }[] =>\n toValueList(value)\n .map(resolveUser)\n .map((user, index) => ({ index, user }))\n .filter(({ user }) => user.name !== '');\n\nexport const createUserLayout =\n (placeholder?: string): ICustomLayoutFuc =>\n (args) => {\n const palette = getCanvasPalette(args.table);\n const width = args.rect?.width ?? 140;\n const height = args.rect?.height ?? 40;\n const entries = resolveUserEntries(args.value);\n const root = new CustomLayout.Group({ height, pickable: false, width });\n\n if (entries.length === 0) {\n if (placeholder) {\n root.add(createEmptyCellText(placeholder, palette, height, args.table));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n }\n\n const chipTop = Math.max(0, (height - USER_CHIP_HEIGHT) / 2);\n const { boxes, overflow, overflowX } = layoutUserChips({\n paddingX: palette.paddingX,\n users: entries,\n width: width - editHintGutterFor(args.table as never, args.col, args.row),\n });\n\n boxes.forEach(({ label, user, width: chipWidth, x }) => {\n const tone = toneFor(user.name, undefined, palette.isDarkMode, palette.checkboxBg);\n const initials = user.name.trim().slice(0, 1) || '?';\n\n root.add(\n new CustomLayout.Rect({\n cornerRadius: 4,\n fill: palette.pillBg,\n height: USER_CHIP_HEIGHT,\n pickable: false,\n width: chipWidth,\n x,\n y: chipTop,\n } as never),\n );\n if (user.avatar) {\n root.add(\n new CustomLayout.Image({\n cornerRadius: 999,\n height: USER_CHIP_AVATAR,\n pickable: false,\n shape: 'square',\n src: user.avatar,\n width: USER_CHIP_AVATAR,\n x: x + 4,\n y: chipTop + (USER_CHIP_HEIGHT - USER_CHIP_AVATAR) / 2,\n } as never),\n );\n } else {\n root.add(\n new CustomLayout.Rect({\n // 圆形:人员头像一律是圆的(参考图里单元格 chip 与选择面板同形)。\n cornerRadius: 999,\n fill: tone.bg,\n height: USER_CHIP_AVATAR,\n pickable: false,\n width: USER_CHIP_AVATAR,\n x: x + 4,\n y: chipTop + (USER_CHIP_HEIGHT - USER_CHIP_AVATAR) / 2,\n } as never),\n );\n root.add(\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: tone.color,\n fontSize: 9,\n pickable: false,\n text: initials,\n textAlign: 'center',\n textBaseline: 'middle',\n x: x + 4 + USER_CHIP_AVATAR / 2,\n y: chipTop + (USER_CHIP_HEIGHT - USER_CHIP_AVATAR) / 2 + USER_CHIP_AVATAR / 2,\n } as never),\n );\n }\n root.add(\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: palette.text,\n fontSize: 13,\n pickable: false,\n text: label,\n textAlign: 'left',\n textBaseline: 'middle',\n x: x + 4 + USER_CHIP_AVATAR + 4,\n y: height / 2,\n } as never),\n );\n });\n\n if (overflow > 0) {\n root.add(createOverflowText(overflow, palette, height, overflowX));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n };\n\n/** 值 → 文本项,保留**原始下标**;空串不画(与 painter 原先的 `filter(Boolean)` 同口径)。\n * 下标必须是原始的:记录是 `['', '核心']` 时画面上只有一枚 chip,点它的 × 要删掉「核心」。 */\nconst resolveTextEntries = (value: unknown): { index: number; label: string }[] =>\n toValueList(value)\n .map((item) => String(item))\n .map((label, index) => ({ index, label }))\n .filter(({ label }) => label !== '');\n\n/** 链接 pill 的排布。文案与画布同源:`kind === 'link'` 时要一起剥掉 scheme。 */\nexport const layoutLinkChips = ({\n kind,\n paddingX,\n value,\n width,\n}: {\n kind: LinkKind;\n paddingX: number;\n value: unknown;\n width: number;\n}): { boxes: ChipBox[]; overflow: number; overflowX: number } =>\n layoutChips(\n resolveTextEntries(value).map(({ index, label }) => ({\n index,\n label: kind === 'link' ? formatLinkLabel(label) : label,\n })),\n measureLinkPillWidth,\n () => 24,\n { paddingX, width },\n );\n\nexport const createLinkLayout =\n (kind: LinkKind, placeholder?: string): ICustomLayoutFuc =>\n (args) => {\n const palette = getCanvasPalette(args.table);\n const width = args.rect?.width ?? 140;\n const height = args.rect?.height ?? 40;\n const root = new CustomLayout.Group({ height, pickable: false, width });\n const { boxes, overflow, overflowX } = layoutLinkChips({\n kind,\n paddingX: palette.paddingX,\n value: args.value,\n width: width - editHintGutterFor(args.table as never, args.col, args.row),\n });\n\n if (boxes.length === 0) {\n if (placeholder) {\n root.add(createEmptyCellText(placeholder, palette, height, args.table));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n }\n\n const pillHeight = 24;\n const pillTop = Math.max(0, (height - pillHeight) / 2);\n\n boxes.forEach(({ label, width: pillWidth, x }) => {\n root.add(\n new CustomLayout.Rect({\n cornerRadius: 999,\n fill: palette.pillBg,\n height: pillHeight,\n lineWidth: 1,\n pickable: false,\n stroke: palette.overlayBorder,\n width: pillWidth,\n x,\n y: pillTop,\n } as never),\n );\n root.add(\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: palette.text,\n fontSize: 13,\n pickable: false,\n text: label,\n textAlign: 'left',\n textBaseline: 'middle',\n x: x + LINK_PAD_LEFT,\n y: height / 2,\n } as never),\n );\n });\n\n if (overflow > 0) {\n root.add(createOverflowText(overflow, palette, height, overflowX));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n };\n\n/** 数组 chip 的排布。内边距与标签 / 链接同为 CHIP_PAD —— 右内边距要整颗装下悬停的 ×。 */\nexport const layoutArrayChips = ({\n paddingX,\n value,\n width,\n}: {\n paddingX: number;\n value: unknown;\n width: number;\n}): { boxes: ChipBox[]; overflow: number; overflowX: number } =>\n layoutChips(resolveTextEntries(value), measureArrayChipWidth, () => 24, { paddingX, width });\n\nexport const createArrayLayout =\n (placeholder?: string): ICustomLayoutFuc =>\n (args) => {\n const palette = getCanvasPalette(args.table);\n const width = args.rect?.width ?? 140;\n const height = args.rect?.height ?? 40;\n const root = new CustomLayout.Group({ height, pickable: false, width });\n const { boxes, overflow, overflowX } = layoutArrayChips({\n paddingX: palette.paddingX,\n value: args.value,\n width: width - editHintGutterFor(args.table as never, args.col, args.row),\n });\n\n if (boxes.length === 0) {\n if (placeholder) {\n root.add(createEmptyCellText(placeholder, palette, height, args.table));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n }\n\n const chipHeight = 24;\n const chipTop = Math.max(0, (height - chipHeight) / 2);\n\n boxes.forEach(({ label, width: chipWidth, x }) => {\n root.add(\n new CustomLayout.Rect({\n cornerRadius: 4,\n fill: palette.pillBg,\n height: chipHeight,\n pickable: false,\n width: chipWidth,\n x,\n y: chipTop,\n } as never),\n );\n root.add(\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: palette.text,\n fontSize: 13,\n pickable: false,\n text: label,\n textAlign: 'left',\n textBaseline: 'middle',\n x: x + ARRAY_PAD_LEFT,\n y: height / 2,\n } as never),\n );\n });\n\n if (overflow > 0) {\n root.add(createOverflowText(overflow, palette, height, overflowX));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { resolveOnAccent } from "./theme.mjs";
|
|
3
|
+
import { getCanvasPalette } from "./canvasPalette.mjs";
|
|
4
|
+
import { toBoolean, toRating } from "../core/cellValue.mjs";
|
|
5
|
+
import { CustomLayout } from "@visactor/vtable";
|
|
6
|
+
//#region src/Table/canvas/controlPainters.ts
|
|
7
|
+
const CHECK_MARK_POINTS = [
|
|
8
|
+
{
|
|
9
|
+
x: 3,
|
|
10
|
+
y: 7.2
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
x: 5.8,
|
|
14
|
+
y: 10
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
x: 11,
|
|
18
|
+
y: 4
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
const drawCheckMark = (root, centerX, centerY, size, color) => {
|
|
22
|
+
const scale = size / 14;
|
|
23
|
+
const left = centerX - size / 2;
|
|
24
|
+
const top = centerY - size / 2;
|
|
25
|
+
root.add(new CustomLayout.Line({
|
|
26
|
+
lineCap: "round",
|
|
27
|
+
lineJoin: "round",
|
|
28
|
+
lineWidth: 1.6 * scale,
|
|
29
|
+
pickable: false,
|
|
30
|
+
points: CHECK_MARK_POINTS.map((point) => ({
|
|
31
|
+
x: left + point.x * scale,
|
|
32
|
+
y: top + point.y * scale
|
|
33
|
+
})),
|
|
34
|
+
stroke: color
|
|
35
|
+
}));
|
|
36
|
+
};
|
|
37
|
+
const CROSS_MARK_SEGMENTS = [[{
|
|
38
|
+
x: 4,
|
|
39
|
+
y: 4
|
|
40
|
+
}, {
|
|
41
|
+
x: 10,
|
|
42
|
+
y: 10
|
|
43
|
+
}], [{
|
|
44
|
+
x: 10,
|
|
45
|
+
y: 4
|
|
46
|
+
}, {
|
|
47
|
+
x: 4,
|
|
48
|
+
y: 10
|
|
49
|
+
}]];
|
|
50
|
+
const drawCrossMark = (root, centerX, centerY, size, color) => {
|
|
51
|
+
const scale = size / 14;
|
|
52
|
+
const left = centerX - size / 2;
|
|
53
|
+
const top = centerY - size / 2;
|
|
54
|
+
CROSS_MARK_SEGMENTS.forEach((segment) => {
|
|
55
|
+
root.add(new CustomLayout.Line({
|
|
56
|
+
lineCap: "round",
|
|
57
|
+
lineWidth: 1.6 * scale,
|
|
58
|
+
pickable: false,
|
|
59
|
+
points: segment.map((point) => ({
|
|
60
|
+
x: left + point.x * scale,
|
|
61
|
+
y: top + point.y * scale
|
|
62
|
+
})),
|
|
63
|
+
stroke: color
|
|
64
|
+
}));
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
const createCheckboxLayout = () => (args) => {
|
|
68
|
+
const palette = getCanvasPalette(args.table);
|
|
69
|
+
const width = args.rect?.width ?? 64;
|
|
70
|
+
const height = args.rect?.height ?? 40;
|
|
71
|
+
const checked = toBoolean(args.value) === true;
|
|
72
|
+
const size = 16;
|
|
73
|
+
const x = palette.paddingX;
|
|
74
|
+
const y = (height - size) / 2;
|
|
75
|
+
const root = new CustomLayout.Group({
|
|
76
|
+
height,
|
|
77
|
+
pickable: false,
|
|
78
|
+
width
|
|
79
|
+
});
|
|
80
|
+
root.add(new CustomLayout.Rect({
|
|
81
|
+
cornerRadius: 4,
|
|
82
|
+
fill: checked ? palette.accent : palette.checkboxBg,
|
|
83
|
+
height: size,
|
|
84
|
+
lineWidth: 1,
|
|
85
|
+
pickable: false,
|
|
86
|
+
stroke: checked ? palette.accent : palette.overlayBorder,
|
|
87
|
+
width: size,
|
|
88
|
+
x,
|
|
89
|
+
y
|
|
90
|
+
}));
|
|
91
|
+
if (checked) drawCheckMark(root, x + size / 2, height / 2, 12, resolveOnAccent(palette.accent));
|
|
92
|
+
return {
|
|
93
|
+
enableCellPadding: false,
|
|
94
|
+
renderDefault: false,
|
|
95
|
+
rootContainer: root
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
const createRatingLayout = () => (args) => {
|
|
99
|
+
const palette = getCanvasPalette(args.table);
|
|
100
|
+
const width = args.rect?.width ?? 96;
|
|
101
|
+
const height = args.rect?.height ?? 40;
|
|
102
|
+
const rating = toRating(args.value);
|
|
103
|
+
const root = new CustomLayout.Group({
|
|
104
|
+
height,
|
|
105
|
+
pickable: false,
|
|
106
|
+
width
|
|
107
|
+
});
|
|
108
|
+
const starSize = 16;
|
|
109
|
+
for (let star = 1; star <= 5; star += 1) {
|
|
110
|
+
const active = star <= rating;
|
|
111
|
+
root.add(new CustomLayout.Text({
|
|
112
|
+
fontFamily: palette.fontFamily,
|
|
113
|
+
fill: active ? palette.starOn : palette.starOff,
|
|
114
|
+
fontSize: 14,
|
|
115
|
+
pickable: false,
|
|
116
|
+
text: active ? "★" : "☆",
|
|
117
|
+
textAlign: "left",
|
|
118
|
+
textBaseline: "middle",
|
|
119
|
+
x: palette.paddingX + (star - 1) * starSize,
|
|
120
|
+
y: height / 2
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
enableCellPadding: false,
|
|
125
|
+
renderDefault: false,
|
|
126
|
+
rootContainer: root
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
const createBooleanLayout = (editable) => (args) => {
|
|
130
|
+
const palette = getCanvasPalette(args.table);
|
|
131
|
+
const width = args.rect?.width ?? 80;
|
|
132
|
+
const height = args.rect?.height ?? 40;
|
|
133
|
+
const flag = toBoolean(args.value);
|
|
134
|
+
const root = new CustomLayout.Group({
|
|
135
|
+
height,
|
|
136
|
+
pickable: false,
|
|
137
|
+
width
|
|
138
|
+
});
|
|
139
|
+
if (flag == null && editable === false) return {
|
|
140
|
+
enableCellPadding: false,
|
|
141
|
+
renderDefault: false,
|
|
142
|
+
rootContainer: root
|
|
143
|
+
};
|
|
144
|
+
const checked = flag === true;
|
|
145
|
+
if (checked) drawCheckMark(root, palette.paddingX + 7, height / 2, 13, palette.success);
|
|
146
|
+
else drawCrossMark(root, palette.paddingX + 7, height / 2, 13, palette.textMuted);
|
|
147
|
+
root.add(new CustomLayout.Text({
|
|
148
|
+
fontFamily: palette.fontFamily,
|
|
149
|
+
fill: palette.text,
|
|
150
|
+
fontSize: 13,
|
|
151
|
+
pickable: false,
|
|
152
|
+
text: checked ? "是" : "否",
|
|
153
|
+
textAlign: "left",
|
|
154
|
+
textBaseline: "middle",
|
|
155
|
+
x: palette.paddingX + 14,
|
|
156
|
+
y: height / 2
|
|
157
|
+
}));
|
|
158
|
+
return {
|
|
159
|
+
enableCellPadding: false,
|
|
160
|
+
renderDefault: false,
|
|
161
|
+
rootContainer: root
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
const drawSeriesCheckbox = (root, centerX, centerY, size, checked, indeterminate, palette) => {
|
|
165
|
+
const x = centerX - size / 2;
|
|
166
|
+
const y = centerY - size / 2;
|
|
167
|
+
const active = checked || indeterminate;
|
|
168
|
+
root.add(new CustomLayout.Rect({
|
|
169
|
+
cornerRadius: 4,
|
|
170
|
+
fill: active ? palette.accent : palette.checkboxBg,
|
|
171
|
+
height: size,
|
|
172
|
+
lineWidth: 1,
|
|
173
|
+
pickable: false,
|
|
174
|
+
stroke: active ? palette.accent : palette.overlayBorder,
|
|
175
|
+
width: size,
|
|
176
|
+
x,
|
|
177
|
+
y
|
|
178
|
+
}));
|
|
179
|
+
if (checked) drawCheckMark(root, centerX, centerY, size - 4, resolveOnAccent(palette.accent));
|
|
180
|
+
else if (indeterminate) root.add(new CustomLayout.Rect({
|
|
181
|
+
cornerRadius: 999,
|
|
182
|
+
fill: resolveOnAccent(palette.accent),
|
|
183
|
+
height: 2,
|
|
184
|
+
pickable: false,
|
|
185
|
+
width: 8,
|
|
186
|
+
x: centerX - 4,
|
|
187
|
+
y: centerY - 1
|
|
188
|
+
}));
|
|
189
|
+
};
|
|
190
|
+
//#endregion
|
|
191
|
+
export { createBooleanLayout, createCheckboxLayout, createRatingLayout, drawSeriesCheckbox };
|
|
192
|
+
|
|
193
|
+
//# sourceMappingURL=controlPainters.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controlPainters.mjs","names":[],"sources":["../../../src/Table/canvas/controlPainters.ts"],"sourcesContent":["'use client';\n\nimport { CustomLayout } from '@visactor/vtable';\nimport type { ICustomLayoutFuc } from '@visactor/vtable/es/ts-types/customLayout';\n\nimport { toBoolean, toRating } from '../core/cellValue';\nimport { type CanvasPalette, getCanvasPalette } from './canvasPalette';\nimport { resolveOnAccent } from './theme';\n\nconst CHECK_MARK_POINTS = [\n { x: 3, y: 7.2 },\n { x: 5.8, y: 10 },\n { x: 11, y: 4 },\n];\n\nconst drawCheckMark = (\n root: any,\n centerX: number,\n centerY: number,\n size: number,\n color: string,\n): void => {\n const scale = size / 14;\n const left = centerX - size / 2;\n const top = centerY - size / 2;\n\n root.add(\n new CustomLayout.Line({\n lineCap: 'round',\n lineJoin: 'round',\n lineWidth: 1.6 * scale,\n pickable: false,\n points: CHECK_MARK_POINTS.map((point) => ({\n x: left + point.x * scale,\n y: top + point.y * scale,\n })),\n stroke: color,\n } as never),\n );\n};\n\nconst CROSS_MARK_SEGMENTS = [\n [\n { x: 4, y: 4 },\n { x: 10, y: 10 },\n ],\n [\n { x: 10, y: 4 },\n { x: 4, y: 10 },\n ],\n];\n\nconst drawCrossMark = (\n root: any,\n centerX: number,\n centerY: number,\n size: number,\n color: string,\n): void => {\n const scale = size / 14;\n const left = centerX - size / 2;\n const top = centerY - size / 2;\n\n CROSS_MARK_SEGMENTS.forEach((segment) => {\n root.add(\n new CustomLayout.Line({\n lineCap: 'round',\n lineWidth: 1.6 * scale,\n pickable: false,\n points: segment.map((point) => ({\n x: left + point.x * scale,\n y: top + point.y * scale,\n })),\n stroke: color,\n } as never),\n );\n });\n};\n\nexport const createCheckboxLayout = (): ICustomLayoutFuc => (args) => {\n const palette = getCanvasPalette(args.table);\n const width = args.rect?.width ?? 64;\n const height = args.rect?.height ?? 40;\n const checked = toBoolean(args.value) === true;\n const size = 16;\n const x = palette.paddingX;\n const y = (height - size) / 2;\n const root = new CustomLayout.Group({ height, pickable: false, width });\n\n root.add(\n new CustomLayout.Rect({\n cornerRadius: 4,\n fill: checked ? palette.accent : palette.checkboxBg,\n height: size,\n lineWidth: 1,\n pickable: false,\n stroke: checked ? palette.accent : palette.overlayBorder,\n width: size,\n x,\n y,\n } as never),\n );\n\n if (checked) {\n drawCheckMark(root, x + size / 2, height / 2, size - 4, resolveOnAccent(palette.accent));\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n};\n\nexport const createRatingLayout = (): ICustomLayoutFuc => (args) => {\n const palette = getCanvasPalette(args.table);\n const width = args.rect?.width ?? 96;\n const height = args.rect?.height ?? 40;\n const rating = toRating(args.value);\n const root = new CustomLayout.Group({ height, pickable: false, width });\n const starSize = 16;\n\n for (let star = 1; star <= 5; star += 1) {\n const active = star <= rating;\n\n root.add(\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: active ? palette.starOn : palette.starOff,\n fontSize: 14,\n pickable: false,\n text: active ? '★' : '☆',\n textAlign: 'left',\n textBaseline: 'middle',\n x: palette.paddingX + (star - 1) * starSize,\n y: height / 2,\n } as never),\n );\n }\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n};\n\nexport const createBooleanLayout =\n (editable?: boolean): ICustomLayoutFuc =>\n (args) => {\n const palette = getCanvasPalette(args.table);\n const width = args.rect?.width ?? 80;\n const height = args.rect?.height ?? 40;\n const flag = toBoolean(args.value);\n const root = new CustomLayout.Group({ height, pickable: false, width });\n\n if (flag == null && editable === false) {\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n }\n\n const checked = flag === true;\n\n if (checked) {\n drawCheckMark(root, palette.paddingX + 7, height / 2, 13, palette.success);\n } else {\n drawCrossMark(root, palette.paddingX + 7, height / 2, 13, palette.textMuted);\n }\n root.add(\n new CustomLayout.Text({\n fontFamily: palette.fontFamily,\n fill: palette.text,\n fontSize: 13,\n pickable: false,\n text: checked ? '是' : '否',\n textAlign: 'left',\n textBaseline: 'middle',\n x: palette.paddingX + 14,\n y: height / 2,\n } as never),\n );\n\n return { enableCellPadding: false, renderDefault: false, rootContainer: root };\n };\n\nexport const drawSeriesCheckbox = (\n root: any,\n centerX: number,\n centerY: number,\n size: number,\n checked: boolean,\n indeterminate: boolean,\n palette: CanvasPalette,\n): void => {\n const x = centerX - size / 2;\n const y = centerY - size / 2;\n const active = checked || indeterminate;\n\n root.add(\n new CustomLayout.Rect({\n cornerRadius: 4,\n fill: active ? palette.accent : palette.checkboxBg,\n height: size,\n lineWidth: 1,\n pickable: false,\n stroke: active ? palette.accent : palette.overlayBorder,\n width: size,\n x,\n y,\n } as never),\n );\n\n if (checked) {\n drawCheckMark(root, centerX, centerY, size - 4, resolveOnAccent(palette.accent));\n } else if (indeterminate) {\n root.add(\n new CustomLayout.Rect({\n cornerRadius: 999,\n fill: resolveOnAccent(palette.accent),\n height: 2,\n pickable: false,\n width: 8,\n x: centerX - 4,\n y: centerY - 1,\n } as never),\n );\n }\n};\n"],"mappings":"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"}
|