Skip to main content

Utility Exports

The non-component exports of @vef-framework-react/components — breakpoint, color, and size design-token constants, theme-token access, query metadata symbols, and small helpers. They are the shared foundation the components themselves are built on, exported so application code can stay consistent with the framework instead of redefining the same values.

VEF-specific API. Everything on this page is a plain constant, function, type, or hook — nothing here renders UI. Only exports without a component home live here: hooks and helpers bound to a component (useCodeSetOptionsSelect on Select, useGridCollapsed on Grid, usePaginationProps on Table, …) are documented on their component pages, and the imperative feedback helpers (showSuccessMessage and friends) on Notifications & Messages.

SectionExports
Breakpoints & Responsive Valuesbreakpoints, resolveBreakpointValue, Breakpoint
Colorscolors, presetColors, semanticColors, isPresetColor, isSemanticColor, PresetColor, SemanticColor, Color
Semantic ScenessemanticScenes, semanticSceneLabels, semanticSceneIcons, SemanticScene
Spacing & Sizessizes, fullSizes, getSpacingValue, Size, FullSize, Length, SizeableLength
Theme Tokens & CSS VariablesglobalCssVars, useThemeTokens
Query Metadata SymbolsSYMBOL_PAGINATION, SYMBOL_SORT, OrderSpec, ParamsWithPagination, ParamsWithSort, QueryParams, PaginatedQueryParams
Miscellaneous HelpersemitReloadPage, isFragment
Shared TypesOrientation, Position, PropsWithRef, GetProp, GetProps, GetRef, ActionConfirmMode

Breakpoints & Responsive Values

breakpoints

The framework's named viewport breakpoints — a frozen constant of em-based widths:

KeyValuePixels (at the browser-default 16px font size)
xxs'0em'0px
xs'36em'576px
sm'48em'768px
md'62em'992px
lg'75em'1200px
xl'88em'1408px
xxl'100em'1600px

Breakpoint is the key union: 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'.

These are the breakpoints behind every responsive prop in the library — Grid.Item's span/offset maps and Crud's per-breakpoint form width — and the values framework styles use in media queries:

import { css } from '@emotion/react';
import { breakpoints } from '@vef-framework-react/components';

const toolbarStyle = css({
display: 'flex',
justifyContent: 'space-between',
// Stack vertically below the 768px breakpoint
[`@media (max-width: ${breakpoints.sm})`]: {
flexDirection: 'column',
alignItems: 'flex-start',
},
});

To react to the current breakpoint in JS, pass this constant to useBreakpoints from @vef-framework-react/hooks (see VEF Hooks) — that is exactly how Crud resolves its responsive form width.

resolveBreakpointValue

function resolveBreakpointValue(
breakpointValues: Partial<Record<Breakpoint, Length>>,
breakpoint: Breakpoint
): Length | undefined

Resolves one value out of a partial per-breakpoint map — the lookup rule behind responsive props like Crud's form width:

  1. If the map defines the requested breakpoint, return that value.
  2. Otherwise walk down and return the nearest smaller defined breakpoint (mobile-first fallback).
  3. If nothing smaller is defined, walk up and return the nearest larger one.
  4. Return undefined only when the map is empty.
import { breakpoints, resolveBreakpointValue } from '@vef-framework-react/components';
import { useBreakpoints } from '@vef-framework-react/hooks';

// Sparse map — the gaps are filled by the fallback rule
const drawerWidths = { xs: '90vw', md: '60vw', xl: 720 };

function useDrawerWidth() {
const { current } = useBreakpoints(breakpoints, { initialBreakpoint: 'xxs' });

// 'sm' resolves to '90vw' (nearest smaller), 'xxl' resolves to 720
return resolveBreakpointValue(drawerWidths, current ?? 'xxs');
}

Colors

The color name constants accepted by theme configuration and color props, plus their type guards. All three arrays are readonly as const tuples.

ExportTypeDescription
presetColorsreadonly PresetColor[]The 13 Ant Design palette names: 'blue', 'purple', 'cyan', 'green', 'magenta', 'pink', 'red', 'orange', 'yellow', 'volcano', 'geekblue', 'lime', 'gold' (re-exported from antd)
semanticColorsreadonly SemanticColor[]The 5 semantic roles: 'primary', 'success', 'info', 'warning', 'error''primary' plus the semantic scenes
colorsreadonly Color[]All 18 names — presetColors followed by semanticColors
isPresetColor(color: string) => color is PresetColortrue when the string is one of the 13 preset names
isSemanticColor(color: string) => color is SemanticColortrue when the string is one of the 5 semantic roles

The matching types are PresetColor, SemanticColor, and Color (= PresetColor | SemanticColor).

Preset names are resolved to concrete values by ConfigProvider — its theme.colors map accepts a preset name or any CSS color per semantic role, and each name also exists as a CSS variable (--vef-blue, --vef-color-primary, …; see Theming). Use the arrays to enumerate options and the guards to validate free-form input:

import { isPresetColor, presetColors } from '@vef-framework-react/components';

// Offer the full preset palette in a theme-settings select
const colorOptions = presetColors.map(color => ({ label: color, value: color }));

// Restrict a tenant-configured brand color to the preset palette,
// falling back to the framework default for anything unrecognized
function resolvePrimary(configured: string): string {
return isPresetColor(configured) ? configured : 'blue';
}

Semantic Scenes

The four feedback severities used across the framework — by Notifications & Messages, Alert, Result, and status-driven UI in general.

ExportTypeDescription
semanticScenesreadonly SemanticScene[]'success', 'info', 'warning', 'error'
semanticSceneLabelsRecord<SemanticScene, string>Default display titles: '成功' / '提示' / '警告' / '错误'
semanticSceneIconsRecord<SemanticScene, ReactElement>Default icons from @ant-design/icons: <CheckCircleOutlined /> / <InfoCircleOutlined /> / <ExclamationCircleOutlined /> / <CloseCircleOutlined />

SemanticScene is the union 'success' | 'info' | 'warning' | 'error'. Note that semanticColors = 'primary' + semanticScenes: a scene is always a valid color name, but 'primary' is not a scene.

semanticSceneLabels supplies the default title of every notification and alert/confirm dialog helper (see the NotificationOptions defaults). semanticSceneIcons is not consumed internally — it is exported so custom scene-driven UI can match the built-ins:

import {
semanticSceneIcons,
semanticSceneLabels,
type SemanticScene,
} from '@vef-framework-react/components';

// A status chip that stays visually consistent with framework feedback
function SceneChip({ scene }: { scene: SemanticScene }) {
return (
<span style={{ color: `var(--vef-color-${scene})` }}>
{semanticSceneIcons[scene]} {semanticSceneLabels[scene]}
</span>
);
}

Spacing & Sizes

sizes and fullSizes

The named size scales used by component size-style props, as readonly as const tuples:

ExportValuesType union
sizes'small', 'medium', 'large'Size
fullSizes'extra-small', 'small', 'medium', 'large', 'extra-large'FullSize

Size is the three-step scale of control-density props (ProTable/Table size, IconPicker, GenericSelect, CodeEditor, …). FullSize extends it at both ends for spacing-style props — Grid's gap maps the five names onto the theme's margin tokens (marginXSmarginLG), so named gaps track the active theme. Iterate the arrays when building settings UI (for example a density switcher offering every Size).

getSpacingValue

function getSpacingValue(value: Length): string

Normalizes a Length (string | number) into a CSS length string: numbers become px (16'16px'), strings pass through unchanged ('2rem''2rem'). This is how components like Page, ScrollArea, and CodeEditor interpret their Length props, so use it when forwarding such values into your own styles:

import { getSpacingValue, type Length } from '@vef-framework-react/components';
import type { ReactNode } from 'react';

interface PanelProps {
// Same contract as framework length props: 8 → '8px', '1rem' → '1rem'
gap?: Length;
children?: ReactNode;
}

function Panel({ gap = 8, children }: PanelProps) {
return <div style={{ display: 'flex', gap: getSpacingValue(gap) }}>{children}</div>;
}

SizeableLength<TSize> combines both worlds: a prop typed SizeableLength<Size> accepts the named sizes of TSize or any free-form Length (with the names still suggested by autocompletion).

Theme Tokens & CSS Variables

Two access paths to the same design language — see Theming for the full decision guide on when to use which.

globalCssVars

A frozen constant with one camelCase key per global VEF CSS custom property — 671 entries — whose values are var(--vef-…) reference strings, not resolved values:

globalCssVars.colorPrimary // 'var(--vef-color-primary)'
globalCssVars.spacingMd // 'var(--vef-spacing-md)'
globalCssVars.borderRadiusLg // 'var(--vef-border-radius-lg)'

It spans every variable family: semantic colors and their state ramps (colorPrimary*, colorSuccess*, …), preset palettes (blue1blue10, …), extended Tailwind-style ramps (colorBlue50colorBlue950, …), neutral surfaces (colorText*, colorBg*, colorFill*, colorBorder*), typography, spacing/padding/margin, radii, shadows, motion, sizing, z-index, breakpoints, and animation shorthands. The full generated catalog with default values is the CSS Variables Reference.

Use it in Emotion or other JS object styles to avoid repeating raw var() strings — the values stay live CSS variables, so styles adapt to theme and dark-mode changes without re-rendering:

import { css } from '@emotion/react';
import { globalCssVars } from '@vef-framework-react/components';

const cardStyle = css({
padding: globalCssVars.spacingMd,
borderRadius: globalCssVars.borderRadiusLg,
border: `1px solid ${globalCssVars.colorBorderSecondary}`,
backgroundColor: globalCssVars.colorBgContainer,
boxShadow: globalCssVars.shadowSm,
});

The variables are emitted onto :root by ConfigProvider (already in place when the app is bootstrapped through the starter). ConfigProvider's theme.globalCssVars option — a map for injecting additional --vef-* variables — is a different thing from this constant, which reads the built-in ones.

useThemeTokens

function useThemeTokens(): GlobalToken

Returns Ant Design's resolved token object (GlobalToken from antd) for the currently active theme — concrete values like colorPrimary: '#2b7fff' or margin: 16, recomputed when the theme or dark mode changes. Must be called under ConfigProvider.

Reach for it when a runtime consumer needs real values rather than var() strings — chart palettes, canvas drawing, third-party library options:

import { useThemeTokens } from '@vef-framework-react/components';

function MetricsChart() {
// Resolved hex values, safe to hand to ECharts
const { colorPrimary, colorTextSecondary } = useThemeTokens();

return <Chart option={{ color: [colorPrimary, colorTextSecondary] }} />;
}

Its sibling useIsDarkMode() is documented on the ConfigProvider page.

Query Metadata Symbols

SYMBOL_PAGINATION and SYMBOL_SORT

const SYMBOL_PAGINATION: unique symbol; // Symbol.for('__vef_pagination')
const SYMBOL_SORT: unique symbol; // Symbol.for('__vef_sort')

Well-known symbols under which ProTable and Crud attach pagination and sort metadata to the params object passed to your queryFn (and spread into the TanStack Query key). Symbol keys cannot collide with real search fields, and JSON.stringify drops them — so the metadata never leaks into a request body serialized from the same object. Both are registered via Symbol.for, so identity holds even across duplicated module instances.

The attached value shapes:

SymbolValue typeShape
SYMBOL_PAGINATIONPaginationParams (from @vef-framework-react/core){ page?: number; size?: number } — 1-based page, defaults page: 1 / size: 15
SYMBOL_SORTOrderSpec[]Each OrderSpec is { column: string; direction: 'asc' | 'desc' }

The exported param types describe both directions of that contract:

TypeDefinitionDescription
ParamsWithPagination<TParams>TParams & { [SYMBOL_PAGINATION]?: PaginationParams }Params carrying pagination metadata
ParamsWithSort<TParams>TParams & { [SYMBOL_SORT]?: OrderSpec[] }Params carrying sort metadata
QueryParams<TSearch, TParams = never>ParamsWithSort<TSearch & If<IsNever<TParams>, EmptyObject, TParams>>What a non-paginated Crud queryFn receives — the never default is guarded so omitting TParams leaves plain TSearch intact
PaginatedQueryParams<TSearch, TParams = never>ParamsWithPagination<ParamsWithSort<TSearch & If<IsNever<TParams>, EmptyObject, TParams>>>What a paginated Crud/ProTable queryFn receives — same never guard as QueryParams

A typical queryFn splits the symbols off before building the request:

import {
SYMBOL_PAGINATION,
SYMBOL_SORT,
type PaginatedQueryParams,
} from '@vef-framework-react/components';

interface UserSearch {
name?: string;
status?: string;
}

async function findUserPage(params: PaginatedQueryParams<UserSearch>) {
// Destructure the symbol-keyed metadata away from the plain search fields
const { [SYMBOL_PAGINATION]: pagination, [SYMBOL_SORT]: sort, ...search } = params;

return post('/api/users/page', {
...search,
page: pagination?.page ?? 1,
pageSize: pagination?.size ?? 15,
orderBy: sort?.map(({ column, direction }) => `${column} ${direction}`),
});
}

API layers built on the framework RPC convention (the approval / cron / integration engines, the starter's extractQueryParams) ship ready-made splitters following this exact pattern.

Miscellaneous Helpers

emitReloadPage

function emitReloadPage(key: string): void

Broadcasts a page-reload event on an internal event bus. Every mounted Page listens and bumps its internal render key, remounting its entire subtree — local component state resets, the entrance animation replays, and mount-time queries refetch. This is what the starter layout's tab-bar refresh button calls, passing the route's full path as key.

Note that the current implementation remounts every mounted Page regardless of key — still pass a meaningful key (the route path by convention), as it documents intent and keeps callers forward-compatible. There is no exported subscribe counterpart; the listening side is internal to Page.

import { emitReloadPage } from '@vef-framework-react/components';

// After switching tenant, remount the page content with fresh state
async function handleTenantSwitch(tenantId: string, routeFullPath: string) {
await switchTenant(tenantId);
emitReloadPage(routeFullPath);
}

isFragment

function isFragment(node: ReactNode): node is ReactElement<FragmentProps>

Type guard returning true when a node is a React <Fragment> element (including the <>…</> shorthand) — isValidElement(node) && node.type === Fragment. After narrowing, node.props.children is typed and accessible, which is the usual reason to need it: unwrapping fragment children before decorating each one.

import { isFragment, Keyboard } from '@vef-framework-react/components';
import { Children, type ReactNode } from 'react';

// Accepts <>⌘K</> as well as a single key node
function ShortcutHint({ keys }: { keys: ReactNode }) {
const nodes = isFragment(keys) ? Children.toArray(keys.props.children) : [keys];

return nodes.map((node, index) => <Keyboard key={index}>{node}</Keyboard>);
}

Shared Types

Small foundation types used throughout the component props, exported for application code:

ExportTypeDescription
Lengthstring | numberA CSS length — numbers mean pixels (see getSpacingValue)
SizeableLength<TSize>LiteralUnion<TSize, Length>A named size from TSize or any free-form Length
Orientation'horizontal' | 'vertical'Layout direction — e.g. the starter's menu layout mode is Orientation | 'mixed'
Position{ x: number; y: number }A 2D coordinate — e.g. ScrollArea's scroll offset callbacks
PropsWithRef<TRef, TProps>TProps & { ref?: Ref<TRef> }Adds a typed ref prop (React 19 style, no forwardRef)
GetProp, GetProps, GetRefantd re-exportsExtract a single prop type, the full props type, or the ref instance type of a component
ActionConfirmMode'popover' | 'dialog'Confirmation UI style behind ActionButton's confirmMode prop

Types that belong to a specific feature are documented with it: Breakpoint, Color/PresetColor/SemanticColor, SemanticScene, Size/FullSize, and OrderSpec in the sections above; ActionButtonConfig on ActionGroup; NotificationOptions/AlertOptions/ConfirmOptions on Notifications & Messages; the form types on Form.