Browse Source

fix(table-v2): extract timestamp display and align text

dev
hechang27-sprt 3 months ago
parent
commit
e7d26a4991
  1. 93
      packages/base/data/list-table-v2/list-table-v2.vue
  2. 32
      packages/base/data/list-table-v2/types.ts
  3. 19
      packages/base/data/list-table-v2/usePretextColumnWidths.ts
  4. 5
      packages/base/data/list-table-v2/usePretextRowHeights.ts
  5. 59
      packages/base/item/tzDateTime.vue
  6. 1
      plugs/composables/index.ts
  7. 123
      plugs/composables/useTimestampDisplay.ts

93
packages/base/data/list-table-v2/list-table-v2.vue

@ -19,13 +19,7 @@ @@ -19,13 +19,7 @@
<div>Column widths: {{ columnWidths.map((w) => Math.round(w)).join(",") }}</div>
<div>
Column configs:
{{
computedConfigs.map((c) => ({
key: c.key,
flexBasis: Math.round(c.flexBasis),
flexGrow: c.flexGrow.toFixed(1),
}))
}}
{{ computedConfigs }}
</div>
</div>
@ -35,7 +29,7 @@ @@ -35,7 +29,7 @@
<div class="table-header" :style="{ height: `${resolvedHeaderHeight}px` }">
<div v-for="col in visibleColumns" :key="col.key" class="header-cell" :style="getColumnStyle(col)">
<slot :name="`header-${col.key}`">
<span class="header-cell-text">{{ getHeaderText(col) }}</span>
<span class="header-cell-text" :style="getTextStyle(col)">{{ getHeaderText(col) }}</span>
</slot>
</div>
</div>
@ -63,7 +57,9 @@ @@ -63,7 +57,9 @@
@click="handleCellClick(row.index, col)"
>
<slot :name="col.key" :row="getRow(row.index)">
<span class="cell-text">{{ getRow(row.index) ? formatCellValue(getRow(row.index)!, col) : '--' }}</span>
<span class="cell-text" :style="getTextStyle(col)">{{
getRow(row.index) ? formatCellValue(getRow(row.index)!, col) : "--"
}}</span>
</slot>
</div>
</div>
@ -88,18 +84,20 @@ @@ -88,18 +84,20 @@
</template>
<script lang="tsx" setup generic="T">
import { ref, computed, watch, onMounted, onUnmounted, toRef, useSlots, h } from "vue";
import { ref, computed, onMounted, onUnmounted, toRef, StyleValue, CSSProperties } from "vue";
import { useStore } from "vuex";
import { useI18n } from "vue3-i18n";
import * as lodash from "lodash-es";
import type { ListTableColumn, ListTableProps, PageResponse } from "./types";
import { usePretextColumnWidths, type ColumnFlexConfig } from "./usePretextColumnWidths";
import { resolveRowHeights, type RowHeightEntry } from "./usePretextRowHeights";
import type { ListTableColumn, PageResponse } from "./types";
import { usePretextColumnWidths } from "./usePretextColumnWidths";
import { resolveRowHeights } from "./usePretextRowHeights";
import { useVirtualRows } from "./useVirtualRows";
import { formatTimestampFromValue } from "../../../../plugs/composables";
import { match } from "ts-pattern";
const DEFAULT_FONT = "14px sans-serif";
const DEFAULT_TEXT_MAX_WIDTH = 400;
const slots = useSlots();
const { t } = useI18n();
const { state } = useStore();
@ -128,7 +126,6 @@ interface Props { @@ -128,7 +126,6 @@ interface Props {
treeProps?: any;
lazy?: boolean;
border?: boolean;
timestampFormat?: string;
rowHeight?: number;
estimatedRowHeight?: number;
headerHeight?: number;
@ -149,7 +146,6 @@ const props = withDefaults(defineProps<Props>(), { @@ -149,7 +146,6 @@ const props = withDefaults(defineProps<Props>(), {
treeProps: undefined,
lazy: false,
border: false,
timestampFormat: "YYYY-MM-DD HH:mm:ss",
rowHeight: undefined,
estimatedRowHeight: undefined,
headerHeight: 44,
@ -204,7 +200,10 @@ const formatCellValue = (row: T, col: ListTableColumn<T>): string => { @@ -204,7 +200,10 @@ const formatCellValue = (row: T, col: ListTableColumn<T>): string => {
return formatterByDist(col.dict, value);
}
if (col.timestamp) {
return formatStamp(value);
if ((typeof value !== "string" && typeof value !== "number") || value === "") {
return "--";
}
return formatTimestampFromValue(value, col.timestamp);
}
if (col.filesize) {
return formatFileSize(value);
@ -223,16 +222,6 @@ const getValue = (value: any): string => { @@ -223,16 +222,6 @@ const getValue = (value: any): string => {
return value;
};
const formatStamp = (value: any): string => {
const date = new Date(value * 1000);
const month = date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
const day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
const hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
const minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
const second = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return `${date.getFullYear()}-${month}-${day} ${hour}:${minute}:${second}`;
};
const formatFileSize = (value: any): string => {
const k = value / 1024;
if (k < 1) return value + "B";
@ -267,12 +256,19 @@ const { computedConfigs, totalFlexBasis, columnWidths } = usePretextColumnWidths @@ -267,12 +256,19 @@ const { computedConfigs, totalFlexBasis, columnWidths } = usePretextColumnWidths
);
// Row heights via pretext - use actual column widths from flexbox algorithm
const { rowHeights, cellHeights } = resolveRowHeights(pageDataRef, columnsRef, columnWidths, formatCellValue, {
font: props.font,
lineHeight: 20,
debug: props.debug,
fixedRowHeight: props.rowHeight,
});
const { rowHeights, cellHeights } = resolveRowHeights(
pageDataRef,
columnsRef,
columnWidths,
DEFAULT_TEXT_MAX_WIDTH,
formatCellValue,
{
font: props.font,
lineHeight: 20,
debug: props.debug,
fixedRowHeight: props.rowHeight,
}
);
// Virtualizer (needs rowHeights as number[] and viewportHeight)
const virtualizer = useVirtualRows(rowHeights, viewportHeight, { overscan: 5 });
@ -291,7 +287,7 @@ const visibleColumns = computed(() => { @@ -291,7 +287,7 @@ const visibleColumns = computed(() => {
// Computed styles
// =============================================================================
const tableContainerStyle = computed(() => {
const style: Record<string, string> = {
const style: CSSProperties = {
display: "flex",
flexDirection: "column" as const,
width: "100%",
@ -311,15 +307,24 @@ const tableContainerStyle = computed(() => { @@ -311,15 +307,24 @@ const tableContainerStyle = computed(() => {
// =============================================================================
// Column styling
// =============================================================================
function getColumnStyle(col: ListTableColumn<T>): Record<string, string> {
function getColumnStyle(col: ListTableColumn<T>): CSSProperties {
const config = computedConfigs.value.find((c) => c.key === col.key);
const explicitWidth = col.width !== undefined && col.width !== "auto" ? Number(col.width) : undefined;
const explicitMaxWidth =
col.maxWidth !== undefined && Number.isFinite(Number(col.maxWidth)) ? Number(col.maxWidth) : undefined;
const align = match(col.align)
.returnType<CSSProperties>()
.with("left", () => ({ alignSelf: "flex-start", textAlign: "left" }))
.with("right", () => ({ alignSelf: "flex-end", textAlign: "right" }))
.otherwise(() => ({ textAlign: "center" }));
if (explicitWidth !== undefined && Number.isFinite(explicitWidth) && explicitWidth > 0) {
return {
flex: `0 0 ${explicitWidth}px`,
width: `${explicitWidth}px`,
minWidth: `${explicitWidth}px`,
maxWidth: `${explicitWidth}px`,
...align,
...(explicitMaxWidth !== undefined ? { maxWidth: `${explicitMaxWidth}px` } : {}),
};
}
@ -334,7 +339,8 @@ function getColumnStyle(col: ListTableColumn<T>): Record<string, string> { @@ -334,7 +339,8 @@ function getColumnStyle(col: ListTableColumn<T>): Record<string, string> {
flexShrink: "1.1",
flexBasis: `${fallbackBasis}px`,
minWidth: `${Math.max(fallbackBasis, 50)}px`,
maxWidth: "300px",
...align,
...(explicitMaxWidth !== undefined ? { maxWidth: `${explicitMaxWidth}px` } : {}),
};
}
@ -346,7 +352,14 @@ function getColumnStyle(col: ListTableColumn<T>): Record<string, string> { @@ -346,7 +352,14 @@ function getColumnStyle(col: ListTableColumn<T>): Record<string, string> {
flexShrink: `${config.flexShrink}`,
flexBasis: `${flexBasis}px`,
minWidth: `${config.minWidth}px`,
maxWidth: `${config.maxWidth}px`,
...align,
...(explicitMaxWidth !== undefined ? { maxWidth: `${explicitMaxWidth}px` } : {}),
};
}
function getTextStyle(col: ListTableColumn<T>): CSSProperties {
return {
maxWidth: `${col.maxTextWidth ?? DEFAULT_TEXT_MAX_WIDTH}px`,
};
}
@ -484,7 +497,6 @@ onUnmounted(() => { @@ -484,7 +497,6 @@ onUnmounted(() => {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
color: v-bind("state.style.tableColor");
font-weight: bold;
font-size: var(--el-font-size-base);
@ -521,7 +533,9 @@ onUnmounted(() => { @@ -521,7 +533,9 @@ onUnmounted(() => {
.table-cell {
display: flex;
flex: 1 1 120px;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 8px 4px;
box-sizing: border-box;
border-right: 1px solid v-bind("state.style.tableBorderColor");
@ -542,7 +556,6 @@ onUnmounted(() => { @@ -542,7 +556,6 @@ onUnmounted(() => {
text-overflow: clip;
white-space: normal;
word-break: break-word;
text-align: center;
color: v-bind("state.style.tableColor");
font: v-bind("props.font");
}

32
packages/base/data/list-table-v2/types.ts

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
* Type definitions for list-table-v2 component
*/
import type { CellRenderer, HeaderCellRenderer } from "element-plus/es/components/table-v2/src/types.mjs";
import type { TimestampDisplayConfig, TimestampSimpleConfig } from "../../../../plugs/composables";
// =============================================================================
// Column Types
@ -29,9 +30,12 @@ export interface ListTableColumn<T = any> { @@ -29,9 +30,12 @@ export interface ListTableColumn<T = any> {
/** Minimum column width */
minWidth?: string | number;
/** Maximum column width (default 300px) */
/** Maximum column width for the cell container */
maxWidth?: string | number;
/** Maximum width in px for header/body text content before wrapping */
maxTextWidth?: number;
/** Flex grow factor (computed from variance if not set) */
flexGrow?: number;
@ -54,7 +58,7 @@ export interface ListTableColumn<T = any> { @@ -54,7 +58,7 @@ export interface ListTableColumn<T = any> {
dict?: string;
/** Timestamp formatting configuration */
timestamp?: TimestampValue;
timestamp?: TimestampSimpleConfig;
/** Format as file size */
filesize?: boolean;
@ -73,25 +77,8 @@ export interface ListTableColumn<T = any> { @@ -73,25 +77,8 @@ export interface ListTableColumn<T = any> {
// Timestamp Types
// =============================================================================
export type TimestampValue =
| undefined
| boolean
| string
| {
valueFormat?: string;
valueTz?: string;
displayFormat?: string;
locale?: string;
type?: "iso8601" | "unix" | "unixMillis";
};
export interface TzDateTimeConfig {
valueFormat?: string;
valueTz?: string;
displayFormat?: string;
locale?: string;
type?: "iso8601" | "unix" | "unixMillis";
}
export type { TimestampSimpleConfig as TimestampValue };
export type TzDateTimeConfig = TimestampDisplayConfig;
// =============================================================================
// Table Props
@ -137,9 +124,6 @@ export interface ListTableProps<T = any> { @@ -137,9 +124,6 @@ export interface ListTableProps<T = any> {
/** Show border */
border?: boolean;
/** Default timestamp format */
timestampFormat?: string;
/** Fixed row height (enables fixed-height mode) */
rowHeight?: number;

19
packages/base/data/list-table-v2/usePretextColumnWidths.ts

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
* - flexBasis: mean (μ) of measured widths + padding
* - flexGrow/flexShrink: derived from variance (σ²)
* - minWidth: max(μ - 2*σ, 50) + padding
* - maxWidth: 300px
* - maxWidth: unconstrained by default
*
* User can override any parameter via column definition.
*/
@ -17,7 +17,7 @@ const DEFAULT_FONT = "14px Inter, sans-serif"; @@ -17,7 +17,7 @@ const DEFAULT_FONT = "14px Inter, sans-serif";
const DEFAULT_HEADER_FONT = "bold 14px Inter, sans-serif";
const DEFAULT_PADDING = 16;
const CELL_PADDING = DEFAULT_PADDING * 2; // left + right
const MAX_WIDTH = 300;
const MAX_WIDTH = Number.POSITIVE_INFINITY;
const MIN_BASE_WIDTH = 50;
const MIN_AUTO_FLEX = 1.1;
const MAX_AUTO_FLEX = 2;
@ -110,7 +110,7 @@ export function computeFlexWidths(configs: ColumnFlexConfig[], containerWidth: n @@ -110,7 +110,7 @@ export function computeFlexWidths(configs: ColumnFlexConfig[], containerWidth: n
const totalFlexGrow = configs.reduce((sum, c) => sum + c.flexGrow * c.flexBasis, 0);
if (totalFlexGrow > 0) {
widths = widths.map((w, i) => {
const growAmount = (configs[i].flexGrow * configs[i].flexBasis) / totalFlexGrow * remaining;
const growAmount = ((configs[i].flexGrow * configs[i].flexBasis) / totalFlexGrow) * remaining;
return w + growAmount;
});
}
@ -134,7 +134,7 @@ export function computeFlexWidths(configs: ColumnFlexConfig[], containerWidth: n @@ -134,7 +134,7 @@ export function computeFlexWidths(configs: ColumnFlexConfig[], containerWidth: n
// Reduce proportionally based on how much each column can be reduced
widths = widths.map((w, i) => {
const reduction = reducible[i] / totalReducible * overflow;
const reduction = (reducible[i] / totalReducible) * overflow;
return Math.max(w - reduction, configs[i].minWidth);
});
}
@ -162,7 +162,7 @@ function computeRawFlexWidths(configs: ColumnFlexConfig[], containerWidth: numbe @@ -162,7 +162,7 @@ function computeRawFlexWidths(configs: ColumnFlexConfig[], containerWidth: numbe
return configs.map((c) => c.flexBasis);
}
return configs.map((c) => {
const growAmount = (c.flexGrow * c.flexBasis) / totalGrowFactor * availableSpace;
const growAmount = ((c.flexGrow * c.flexBasis) / totalGrowFactor) * availableSpace;
return c.flexBasis + growAmount;
});
} else {
@ -170,11 +170,11 @@ function computeRawFlexWidths(configs: ColumnFlexConfig[], containerWidth: numbe @@ -170,11 +170,11 @@ function computeRawFlexWidths(configs: ColumnFlexConfig[], containerWidth: numbe
const totalShrinkFactor = configs.reduce((sum, c) => sum + c.flexShrink * c.flexBasis, 0);
if (totalShrinkFactor === 0) {
// No shrink - distribute loss evenly
const evenShrink = (-availableSpace) / configs.length;
const evenShrink = -availableSpace / configs.length;
return configs.map((c) => Math.max(0, c.flexBasis - evenShrink));
}
return configs.map((c) => {
const shrinkAmount = (c.flexShrink * c.flexBasis) / totalShrinkFactor * (-availableSpace);
const shrinkAmount = ((c.flexShrink * c.flexBasis) / totalShrinkFactor) * -availableSpace;
return Math.max(0, c.flexBasis - shrinkAmount);
});
}
@ -214,7 +214,8 @@ export function usePretextColumnWidths<T>( @@ -214,7 +214,8 @@ export function usePretextColumnWidths<T>(
const userFlexShrink = col.flexShrink;
const userFlexBasis = col.flexBasis !== undefined && col.flexBasis !== "auto" ? Number(col.flexBasis) : undefined;
const userMinWidth = col.minWidth !== undefined ? Number(col.minWidth) : undefined;
const userMaxWidth = col.maxWidth !== undefined ? Number(col.maxWidth) : undefined;
const userMaxWidth =
col.maxWidth !== undefined && Number.isFinite(Number(col.maxWidth)) ? Number(col.maxWidth) : undefined;
// Measure header width
const headerText = col.name || col.i18n || colKey;
@ -240,7 +241,7 @@ export function usePretextColumnWidths<T>( @@ -240,7 +241,7 @@ export function usePretextColumnWidths<T>(
const minWidth = userMinWidth
? Number(userMinWidth)
: Math.max(mean - 2 * Math.sqrt(variance), MIN_BASE_WIDTH) + CELL_PADDING;
const maxWidth = userMaxWidth ? Number(userMaxWidth) : MAX_WIDTH;
const maxWidth = userMaxWidth ?? MAX_WIDTH;
const flexGrow = userFlexGrow ?? varianceToFlex(mean, variance);
const flexShrink = userFlexShrink ?? varianceToFlex(mean, variance);

5
packages/base/data/list-table-v2/usePretextRowHeights.ts

@ -24,6 +24,7 @@ export function resolveRowHeights<T>( @@ -24,6 +24,7 @@ export function resolveRowHeights<T>(
data: Ref<T[]>,
columns: Ref<ListTableColumn<T>[]>,
columnWidths: Ref<number[]>,
lineMaxWidth: number,
formatCellValue: (row: T, col: ListTableColumn<T>) => string,
options?: {
font?: string;
@ -54,7 +55,7 @@ export function resolveRowHeights<T>( @@ -54,7 +55,7 @@ export function resolveRowHeights<T>(
const col = columns.value[i];
// Use flex basis width for height calculation as an approximation
// of actual column width (CSS flex layout determines actual width)
const colWidth = columnWidths.value[i] ?? 100;
const colWidth = columnWidths.value[i] ?? 120;
// Check if custom renderer exists (we can't measure these with pretext)
const isCustomRenderer = !!(col.cellRenderer || col.slot);
@ -76,7 +77,7 @@ export function resolveRowHeights<T>( @@ -76,7 +77,7 @@ export function resolveRowHeights<T>(
if (!cellText) throw "Invalid Cell Text";
// Calculate available width for text (excluding cell padding)
const availableWidth = colWidth - CELL_VERTICAL_PADDING * 2;
const availableWidth = Math.min(colWidth - CELL_VERTICAL_PADDING * 2, col.maxTextWidth ?? lineMaxWidth);
if (availableWidth <= 0) throw "Invalid Column Width";
rowHeightEntry = {

59
packages/base/item/tzDateTime.vue

@ -3,55 +3,26 @@ @@ -3,55 +3,26 @@
<template v-else>{{ display }}</template>
</template>
<script setup lang="ts">
import dayjs from "dayjs";
import { computed, toRef } from "vue";
import { watchEffectOnce } from "noob-mengyxu";
import {
useTimestampDisplay,
type TimestampDisplayConfig,
type TimestampDisplayType,
} from "../../../plugs/composables";
interface Props {
interface Props extends TimestampDisplayConfig {
value: string | number;
valueFormat?: string;
valueTz?: string;
displayFormat?: string;
locale?: string;
type?: "iso8601" | "unix" | "unixMillis";
type?: TimestampDisplayType;
slot?: boolean;
}
const props = defineProps<Props>();
watchEffectOnce(toRef(props, "valueFormat"), async () => {
const customParseFormat = await import("dayjs/plugin/customParseFormat");
dayjs.extend(customParseFormat.default);
});
watchEffectOnce(toRef(props, "valueTz"), async () => {
const timeZone = await import("dayjs/plugin/timezone");
dayjs.extend(timeZone.default);
});
const parsed = computed(() => {
if (props.type === "unix" || props.type === "unixMillis") {
const value = typeof props.value === "string" ? parseFloat(props.value) : props.value;
return props.type === "unix" ? dayjs.unix(value) : dayjs(value);
} else {
if (props.valueFormat && props.valueTz) {
return dayjs.tz(props.value, props.valueFormat, props.valueTz);
} else if (props.valueTz) {
return dayjs.tz(props.value, props.valueTz);
} else if (props.valueFormat) {
return dayjs(props.value, props.valueFormat);
} else {
return dayjs(props.value);
}
}
});
const display = computed(() => {
let dt = parsed.value;
if (props.locale) {
dt = dt.locale(props.locale);
}
return dt.format(props.displayFormat);
});
const { display } = useTimestampDisplay(() => ({
value: props.value,
valueFormat: props.valueFormat,
valueTz: props.valueTz,
displayFormat: props.displayFormat,
locale: props.locale,
type: props.type,
}));
</script>

1
plugs/composables/index.ts

@ -5,3 +5,4 @@ export * from "./useModifyForm"; @@ -5,3 +5,4 @@ export * from "./useModifyForm";
export * from "./useSysDict";
export * from "./useWatchOnce";
export * from "./useRefreshFlags";
export * from "./useTimestampDisplay";

123
plugs/composables/useTimestampDisplay.ts

@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
import dayjs, { type Dayjs } from "dayjs";
import customParseFormat from "dayjs/plugin/customParseFormat";
import timezone from "dayjs/plugin/timezone";
import utc from "dayjs/plugin/utc";
import { match, P } from "ts-pattern";
import { computed, toValue, type MaybeRefOrGetter } from "vue";
dayjs.extend(customParseFormat);
dayjs.extend(utc);
dayjs.extend(timezone);
export type TimestampDisplayType = "iso8601" | "unix" | "unixMillis";
export interface TimestampDisplayConfig {
valueFormat?: string;
valueTz?: string;
displayFormat?: string;
locale?: string;
type?: TimestampDisplayType;
}
export interface TimestampDisplayInput extends TimestampDisplayConfig {
value: string | number;
}
export type TimestampSimpleConfig = undefined | boolean | string | TimestampDisplayConfig;
export const DEFAULT_TIMESTAMP_DISPLAY_FORMAT = "YYYY-MM-DD HH:mm:ss";
function withDefaultDisplayFormat(
config: TimestampDisplayConfig,
defaultDisplayFormat?: string
): TimestampDisplayConfig {
if (!defaultDisplayFormat || config.displayFormat) {
return config;
}
return {
...config,
displayFormat: defaultDisplayFormat,
};
}
export function normalizeTimestampValue(
timestamp: TimestampSimpleConfig,
defaultDisplayFormat?: string
): TimestampDisplayConfig | null {
return match(timestamp)
.with(P.nullish, () => null)
.with(true, () => withDefaultDisplayFormat({ type: "unixMillis" }, defaultDisplayFormat))
.with(P.union("iso8601", "unix", "unixMillis"), (type) => withDefaultDisplayFormat({ type }, defaultDisplayFormat))
.with(P.string, (valueFormat) => withDefaultDisplayFormat({ valueFormat }, defaultDisplayFormat))
.otherwise((config) => withDefaultDisplayFormat({ ...config }, defaultDisplayFormat));
}
export function parseTimestampValue(value: string | number, config: TimestampDisplayConfig): Dayjs {
const numericValue = match(value)
.with(P.string, parseFloat)
.otherwise((n) => n);
if (!isNaN(numericValue)) {
if (config.type == "unix") return dayjs.unix(numericValue);
if (config.type == "unixMillis") return dayjs(numericValue);
}
if (config.valueFormat && config.valueTz) {
return dayjs.tz(value, config.valueFormat, config.valueTz);
}
if (config.valueTz) {
return dayjs.tz(value, config.valueTz);
}
if (config.valueFormat) {
return dayjs(value, config.valueFormat);
}
return dayjs(value);
}
export function formatTimestampDisplay(value: string | number, config: TimestampDisplayConfig): string {
let parsed = parseTimestampValue(value, config);
if (!parsed.isValid()) {
return String(value);
}
if (config.locale) {
parsed = parsed.locale(config.locale);
}
return config.displayFormat ? parsed.format(config.displayFormat) : parsed.format();
}
export function formatTimestampFromValue(
value: string | number,
timestamp: TimestampSimpleConfig,
defaultDisplayFormat = DEFAULT_TIMESTAMP_DISPLAY_FORMAT
): string {
const config = normalizeTimestampValue(timestamp, defaultDisplayFormat);
if (!config) {
return String(value);
}
return formatTimestampDisplay(value, config);
}
export function useTimestampDisplay(input: MaybeRefOrGetter<TimestampDisplayInput>) {
const parsed = computed(() => {
const resolved = toValue(input);
return parseTimestampValue(resolved.value, resolved);
});
const display = computed(() => {
const resolved = toValue(input);
return formatTimestampDisplay(resolved.value, resolved);
});
return {
parsed,
display,
};
}
Loading…
Cancel
Save