Update symbols font

This commit is contained in:
Jamie Kyle
2025-09-26 11:10:52 -07:00
committed by GitHub
parent 2fb73bd753
commit 410f53ae57
6 changed files with 921 additions and 249 deletions

View File

@@ -4,7 +4,7 @@ import React, { memo, forwardRef } from 'react';
import type { ButtonHTMLAttributes, FC, ForwardedRef, ReactNode } from 'react';
import type { TailwindStyles } from './tw.js';
import { tw } from './tw.js';
import { AxoSymbol, type AxoSymbolName } from './AxoSymbol.js';
import { AxoSymbol } from './AxoSymbol.js';
import { assert } from './_internal/assert.js';
const Namespace = 'AxoButton';
@@ -143,7 +143,7 @@ type AxoButtonProps = BaseButtonAttrs &
Readonly<{
variant: AxoButtonVariant;
size: AxoButtonSize;
symbol?: AxoSymbolName;
symbol?: AxoSymbol.InlineGlyphName;
arrow?: boolean;
children: ReactNode;
}>;

View File

@@ -4,34 +4,40 @@ import React, { memo, useMemo, useState } from 'react';
import type { Meta } from '@storybook/react';
import { Direction } from 'radix-ui';
import Fuse from 'fuse.js';
import type { AxoSymbolName } from './AxoSymbol.js';
import {
AxoSymbol,
_getAllAxoSymbolNames,
_getAxoSymbol,
} from './AxoSymbol.js';
import { AxoSymbol } from './AxoSymbol.js';
import { tw } from './tw.js';
import {
_getAllAxoSymbolInlineGlyphNames,
getAxoSymbolInlineGlyph,
} from './_internal/AxoSymbolDefs.generated.js';
export default {
title: 'Axo/AxoSymbol',
} satisfies Meta;
const SymbolInfo = memo(function SymbolInfo(props: {
symbolName: AxoSymbolName;
}): JSX.Element {
const ltr = _getAxoSymbol(props.symbolName, 'ltr');
const rtl = _getAxoSymbol(props.symbolName, 'rtl');
const allAxoSymbolNames = _getAllAxoSymbolInlineGlyphNames()
.slice()
.sort((a, b) => a.localeCompare(b));
const fuse = new Fuse(allAxoSymbolNames);
const variants =
const SymbolInfo = memo(function SymbolInfo(props: {
symbolName: AxoSymbol.InlineGlyphName;
}): JSX.Element {
const ltr = getAxoSymbolInlineGlyph(props.symbolName, 'ltr');
const rtl = getAxoSymbolInlineGlyph(props.symbolName, 'rtl');
type Variant = { title: string; dir: 'ltr' | 'rtl'; text: string };
const variants: ReadonlyArray<Variant> =
ltr === rtl
? ([
? [
// same
{ title: 'LTR/RTL', dir: 'ltr', text: ltr },
] as const)
: ([
]
: [
{ title: 'LTR', dir: 'ltr', text: ltr },
{ title: 'RTL', dir: 'rtl', text: rtl },
] as const);
];
return (
<figure
@@ -75,11 +81,6 @@ const SymbolInfo = memo(function SymbolInfo(props: {
);
});
const allAxoSymbolNames = _getAllAxoSymbolNames()
.slice()
.sort((a, b) => a.localeCompare(b));
const fuse = new Fuse(allAxoSymbolNames);
export function All(): JSX.Element {
const [input, setInput] = useState('');

View File

@@ -1,241 +1,61 @@
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { FC } from 'react';
import React, { memo } from 'react';
import React, { memo, useMemo } from 'react';
import { Direction } from 'radix-ui';
import { VisuallyHidden } from 'react-aria';
import { assert } from './_internal/assert.js';
import { tw } from './tw.js';
import {
getAxoSymbolIcon,
getAxoSymbolInlineGlyph,
} from './_internal/AxoSymbolDefs.generated.js';
import type {
AxoSymbolIconName,
AxoSymbolInlineGlyphName,
} from './_internal/AxoSymbolDefs.generated.js';
const { useDirection } = Direction;
const Namespace = 'AxoSymbol';
type AxoSymbolDef = string | { ltr: string; rtl: string };
const AllAxoSymbolDefs = {
logo: '\u{E000}',
album: '\u{E001}',
appearance: '\u{E031}',
'arrow-[start]': { ltr: '\u{2190}', rtl: '\u{2192}' },
'arrow-[end]': { ltr: '\u{2192}', rtl: '\u{2190}' },
'arrow-up': '\u{2191}',
'arrow-down': '\u{2193}',
'arrow-up_[start]': { ltr: '\u{2196}', rtl: '\u{2197}' },
'arrow-up_[end]': { ltr: '\u{2197}', rtl: '\u{2196}' },
'arrow-down_[start]': { ltr: '\u{2199}', rtl: '\u{2198}' },
'arrow-down_[end]': { ltr: '\u{2198}', rtl: '\u{2199}' },
'arrow-circle-[start]': { ltr: '\u{E00B}', rtl: '\u{E00C}' },
'arrow-circle-[end]': { ltr: '\u{E00C}', rtl: '\u{E00B}' },
'arrow-circle-up': '\u{E00D}',
'arrow-circle-down': '\u{E00E}',
'arrow-circle-up_[start]': { ltr: '\u{E00F}', rtl: '\u{E010}' },
'arrow-circle-up_[end]': { ltr: '\u{E010}', rtl: '\u{E00F}' },
'arrow-circle-down_[start]': { ltr: '\u{E011}', rtl: '\u{E012}' },
'arrow-circle-down_[end]': { ltr: '\u{E012}', rtl: '\u{E011}' },
'arrow-square-[start]': { ltr: '\u{E013}', rtl: '\u{E014}' },
'arrow-square-[end]': { ltr: '\u{E014}', rtl: '\u{E013}' },
'arrow-square-up': '\u{E015}',
'arrow-square-down': '\u{E016}',
'arrow-square-up_[start]': { ltr: '\u{E017}', rtl: '\u{E018}' },
'arrow-square-up_[end]': { ltr: '\u{E018}', rtl: '\u{E017}' },
'arrow-square-down_[start]': { ltr: '\u{E019}', rtl: '\u{E01A}' },
'arrow-square-down_[end]': { ltr: '\u{E01A}', rtl: '\u{E019}' },
'arrow-dash-down': '\u{E021}',
'arrow-circle-[start]-fill': { ltr: '\u{E003}', rtl: '\u{E004}' },
'arrow-circle-[end]-fill': { ltr: '\u{E004}', rtl: '\u{E003}' },
'arrow-circle-up-fill': '\u{E005}',
'arrow-circle-down-fill': '\u{E006}',
'arrow-circle-up_[start]-fill': { ltr: '\u{E007}', rtl: '\u{E008}' },
'arrow-circle-up_[end]-fill': { ltr: '\u{E008}', rtl: '\u{E007}' },
'arrow-circle-down_[start]-fill': { ltr: '\u{E009}', rtl: '\u{E00A}' },
'arrow-circle-down_[end]-fill': { ltr: '\u{E00A}', rtl: '\u{E009}' },
'arrow-square-[start]-fill': { ltr: '\u{E08A}', rtl: '\u{E08B}' },
'arrow-square-[end]-fill': { ltr: '\u{E08B}', rtl: '\u{E08A}' },
'arrow-square-up-fill': '\u{E08C}',
'arrow-square-down-fill': '\u{E08D}',
'arrow-square-up_[start]-fill': { ltr: '\u{E08E}', rtl: '\u{E08F}' },
'arrow-square-up_[end]-fill': { ltr: '\u{E08F}', rtl: '\u{E08E}' },
'arrow-square-down_[start]-fill': { ltr: '\u{E090}', rtl: '\u{E091}' },
'arrow-square-down_[end]-fill': { ltr: '\u{E091}', rtl: '\u{E090}' },
at: '\u{E01B}',
attach: '\u{E058}',
audio: '\u{E01C}',
'audio-rectangle': '\u{E01D}',
badge: '\u{E099}',
'badge-fill': '\u{E09A}',
bell: '\u{E01E}',
'bell-slash': '\u{E01F}',
'bell-ring': '\u{E020}',
block: '\u{E002}',
calender: '\u{E0A2}',
'calender-blank': '\u{E0A3}',
check: '\u{2713}',
'check-circle': '\u{E022}',
'check-square': '\u{E023}',
'chevron-[start]': { ltr: '\u{E024}', rtl: '\u{E025}' },
'chevron-[end]': { ltr: '\u{E025}', rtl: '\u{E024}' },
'chevron-up': '\u{E026}',
'chevron-down': '\u{E027}',
'chevron-circle-[start]': { ltr: '\u{E028}', rtl: '\u{E029}' },
'chevron-circle-[end]': { ltr: '\u{E029}', rtl: '\u{E028}' },
'chevron-circle-up': '\u{E02A}',
'chevron-circle-down': '\u{E02B}',
'chevron-square-[start]': { ltr: '\u{E02C}', rtl: '\u{E02D}' },
'chevron-square-[end]': { ltr: '\u{E02D}', rtl: '\u{E02C}' },
'chevron-square-up': '\u{E02E}',
'chevron-square-down': '\u{E02F}',
'dropdown-down': '\u{E07F}',
'dropdown-up': '\u{E080}',
'dropdown-triangle-down': '\u{E082}',
'dropdown-triangle-up': '\u{E083}',
'dropdown-double': '\u{E081}',
edit: '\u{E030}',
emoji: '\u{263A}',
error: '\u{E032}',
'error-triangle': '\u{E092}',
'error-fill': '\u{E093}',
'error-triangle-fill': '\u{E094}',
file: '\u{E034}',
forward: '\u{E035}',
'forward-fill': '\u{E036}',
gif: '\u{E037}',
'gif-rectangle': '\u{E097}',
'gif-rectangle-fill': '\u{E098}',
gift: '\u{E0B5}',
globe: '\u{E0B6}',
group: '\u{E038}',
'group-x': '\u{E0AE}',
heart: '\u{E039}',
help: '\u{E0D8}',
incoming: '\u{E03A}',
info: '\u{E03B}',
leave: { ltr: '\u{E03C}', rtl: '\u{E03D}' },
link: '\u{E03E}',
'link-android': '\u{E03F}',
'link-broken': '\u{E057}',
'link-slash': '\u{E040}',
lock: '\u{E041}',
'lock-open': '\u{E07D}',
megaphone: '\u{E042}',
merge: '\u{E043}',
message: '\u{E0A6}',
'message_status-sending': '\u{E044}',
'message_status-sent': '\u{E045}',
'message_status-read': '\u{E047}',
'message_status-delivered': '\u{E046}',
'message_timer-00': '\u{E048}',
'message_timer-05': '\u{E049}',
'message_timer-10': '\u{E04A}',
'message_timer-15': '\u{E04B}',
'message_timer-20': '\u{E04C}',
'message_timer-25': '\u{E04D}',
'message_timer-30': '\u{E04E}',
'message_timer-35': '\u{E04F}',
'message_timer-40': '\u{E050}',
'message_timer-45': '\u{E051}',
'message_timer-50': '\u{E052}',
'message_timer-55': '\u{E053}',
'message_timer-60': '\u{E054}',
mic: '\u{E055}',
'mic-slash': '\u{E056}',
minus: '\u{2212}',
'minus-circle': '\u{2296}',
'minus-square': '\u{E059}',
'missed-incoming': '\u{E05A}',
'missed-outgoing': '\u{E05B}',
note: { ltr: '\u{E095}', rtl: '\u{E096}' },
official_badge: '\u{E086}',
'official_badge-fill': '\u{E087}',
outgoing: '\u{E05C}',
person: '\u{E05D}',
'person-circle': '\u{E05E}',
'person-check': '\u{E05F}',
'person-x': '\u{E060}',
'person-plus': '\u{E061}',
'person-minus': '\u{E062}',
'person-question': '\u{E06A}',
phone: '\u{E063}',
'phone-fill': '\u{E064}',
photo: '\u{E065}',
'photo-slash': '\u{E066}',
play: '\u{E067}',
'play-circle': '\u{E068}',
'play-square': '\u{E069}',
plus: '\u{002B}',
'plus-circle': '\u{2295}',
'plus-square': '\u{E06C}',
raise_hand: '\u{E07E}',
'raise_hand-fill': '\u{E084}',
refresh: '\u{E0C4}',
reply: '\u{E06D}',
'reply-fill': '\u{E06E}',
safety_number: '\u{E06F}',
spam: '\u{E033}',
sticker: '\u{E070}',
thread: '\u{E071}',
'thread-fill': '\u{E072}',
timer: '\u{E073}',
'timer-slash': '\u{E074}',
video_camera: '\u{E075}',
'video_camera-slash': '\u{E076}',
'video_camera-fill': '\u{E077}',
video: '\u{E088}',
'video-slash': '\u{E089}',
view_once: '\u{E078}',
'view_once-dash': '\u{E079}',
'view_once-viewed': '\u{E07A}',
x: '\u{00D7}',
'x-circle': '\u{2297}',
'x-square': '\u{2327}',
space: '\u{0020}',
} as const satisfies Record<string, AxoSymbolDef>;
export type AxoSymbolName = keyof typeof AllAxoSymbolDefs;
export function _getAllAxoSymbolNames(): ReadonlyArray<AxoSymbolName> {
return Object.keys(AllAxoSymbolDefs) as Array<AxoSymbolName>;
}
export function _getAxoSymbol(
symbolName: AxoSymbolName,
dir: 'ltr' | 'rtl'
): string {
const symbolDef = assert(
AllAxoSymbolDefs[symbolName],
`${Namespace}:Invalid name: ${symbolName}`
);
const symbol = typeof symbolDef === 'string' ? symbolDef : symbolDef[dir];
return symbol;
}
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace AxoSymbol {
const symbolStyles = tw('font-symbols select-none');
const labelStyles = tw('select-none');
// eslint-disable-next-line no-inner-declarations
function useRenderSymbol(glyph: string, label: string | null): JSX.Element {
return useMemo(() => {
return (
<>
<span aria-hidden className={symbolStyles}>
{glyph}
</span>
{label != null && (
<VisuallyHidden className={labelStyles}>{label}</VisuallyHidden>
)}
</>
);
}, [glyph, label]);
}
/**
* Component: <AxoSymbol.InlineGlyph>
* --------------------------------------
*/
export type InlineGlyphName = AxoSymbolInlineGlyphName;
export type InlineGlyphProps = Readonly<{
symbol: AxoSymbolName;
symbol: InlineGlyphName;
label: string | null;
}>;
export const InlineGlyph: FC<InlineGlyphProps> = memo(props => {
const direction = useDirection();
const symbol = _getAxoSymbol(props.symbol, direction);
return (
<>
<span aria-hidden className={tw('font-symbols select-none')}>
{symbol}
</span>
{props.label != null && (
<VisuallyHidden className={tw('select-none')}>
{props.label}
</VisuallyHidden>
)}
</>
);
const glyph = getAxoSymbolInlineGlyph(props.symbol, direction);
const content = useRenderSymbol(glyph, props.label);
return content;
});
InlineGlyph.displayName = `${Namespace}.InlineGlyph`;
@@ -245,21 +65,50 @@ export namespace AxoSymbol {
* --------------------------------------
*/
export type IconName = AxoSymbolIconName;
export type IconSize = 14 | 16 | 20 | 24;
type IconSizeConfig = { size: number; fontSize: number };
const IconSizes: Record<IconSize, IconSizeConfig> = {
14: { size: 14, fontSize: 12 },
16: { size: 16, fontSize: 14 },
20: { size: 20, fontSize: 18 },
24: { size: 24, fontSize: 22 },
};
export function _getAllIconSizes(): ReadonlyArray<IconSize> {
return Object.keys(IconSizes).map(size => Number(size) as IconSize);
}
export type IconProps = Readonly<{
size: 14 | 16 | 20 | 24;
symbol: AxoSymbolName;
size: IconSize;
symbol: AxoSymbolIconName;
label: string | null;
}>;
const iconStyles = tw(
'inline-flex size-[1em] shrink-0 items-center justify-center'
);
export const Icon: FC<IconProps> = memo(props => {
const config = IconSizes[props.size];
const direction = useDirection();
const glyph = getAxoSymbolIcon(props.symbol, direction);
const content = useRenderSymbol(glyph, props.label);
const style = useMemo(() => {
return {
width: config.size,
height: config.size,
fontSize: config.fontSize,
};
}, [config]);
return (
<span
className={tw(
'inline-flex size-[1em] shrink-0 items-center justify-center'
)}
style={{ fontSize: props.size }}
>
<AxoSymbol.InlineGlyph symbol={props.symbol} label={props.label} />
<span className={iconStyles} style={style}>
{content}
</span>
);
});

View File

@@ -3,7 +3,7 @@
import React from 'react';
import type { ReactNode } from 'react';
import { tw } from '../tw.js';
import { AxoSymbol, type AxoSymbolName } from '../AxoSymbol.js';
import { AxoSymbol } from '../AxoSymbol.js';
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace AxoBaseMenu {
@@ -62,7 +62,7 @@ export namespace AxoBaseMenu {
/**
* An icon that should be rendered before the text.
*/
symbol?: AxoSymbolName;
symbol?: AxoSymbol.IconName;
}>;
// <Item/RadioItem/CheckboxItem> (not SubTrigger/Label/Separator)
@@ -138,7 +138,9 @@ export namespace AxoBaseMenu {
return <AxoSymbol.Icon size={14} symbol="check" label={null} />;
}
export function ItemSymbol(props: { symbol: AxoSymbolName }): JSX.Element {
export function ItemSymbol(props: {
symbol: AxoSymbol.IconName;
}): JSX.Element {
return <AxoSymbol.Icon size={16} symbol={props.symbol} label={null} />;
}

View File

@@ -0,0 +1,820 @@
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
// WARNING: This file is automatically generated, do not edit directly
// Can be used in <AxoSymbol.Icon>
export type AxoSymbolIconName =
| 'signal-logo'
| 'album'
| 'appearance'
| 'appearance-fill'
| 'archive'
| 'archive-fill'
| 'archive-down'
| 'archive-down-fill'
| 'archive-up'
| 'archive-up-fill'
| 'arrow-[start]'
| 'arrow-[end]'
| 'arrow-up'
| 'arrow-down'
| 'arrow-up[start]'
| 'arrow-up[end]'
| 'arrow-down[start]'
| 'arrow-down[end]'
| 'arrow-circle-[start]'
| 'arrow-circle-[end]'
| 'arrow-circle-up'
| 'arrow-circle-down'
| 'arrow-circle-up[start]'
| 'arrow-circle-up[end]'
| 'arrow-circle-down[start]'
| 'arrow-circle-down[end]'
| 'arrow-circle-[start]-fill'
| 'arrow-circle-[end]-fill'
| 'arrow-circle-up-fill'
| 'arrow-circle-down-fill'
| 'arrow-circle-up[start]-fill'
| 'arrow-circle-up[end]-fill'
| 'arrow-circle-down[start]-fill'
| 'arrow-circle-down[end]-fill'
| 'arrow-square-[start]'
| 'arrow-square-[end]'
| 'arrow-square-up'
| 'arrow-square-down'
| 'arrow-square-up[start]'
| 'arrow-square-up[end]'
| 'arrow-square-down[start]'
| 'arrow-square-down[end]'
| 'arrow-square-[start]-fill'
| 'arrow-square-[end]-fill'
| 'arrow-square-up-fill'
| 'arrow-square-down-fill'
| 'arrow-square-up[start]-fill'
| 'arrow-square-up[end]-fill'
| 'arrow-square-down[start]-fill'
| 'arrow-square-down[end]-fill'
| 'arrow-rectangle-up'
| 'arrow-rectangle-up-fill'
| 'arrow-circle-dash-down'
| 'aspectratio'
| 'aspectratio-fill'
| 'at'
| 'attach'
| 'audio'
| 'audio-rectangle'
| 'audio-rectangle-fill'
| 'backup'
| 'badge'
| 'badge-fill'
| 'badge-set'
| 'badge-set-fill'
| 'bell'
| 'bell-slash'
| 'bell-ring'
| 'block'
| 'bolt'
| 'boost'
| 'calendar'
| 'calendar-blank'
| 'calendar-week'
| 'calendar-one'
| 'calendar-search'
| 'camera'
| 'camera-fill'
| 'check'
| 'check-circle'
| 'check-circle-fill'
| 'check-square'
| 'check-square-fill'
| 'chevron-[start]'
| 'chevron-[end]'
| 'chevron-up'
| 'chevron-down'
| 'chevron-circle-[start]'
| 'chevron-circle-[end]'
| 'chevron-circle-up'
| 'chevron-circle-down'
| 'chevron-circle-[start]-fill'
| 'chevron-circle-[end]-fill'
| 'chevron-circle-up-fill'
| 'chevron-circle-down-fill'
| 'chevron-square-[start]'
| 'chevron-square-[end]'
| 'chevron-square-up'
| 'chevron-square-down'
| 'chevron-square-[start]-fill'
| 'chevron-square-[end]-fill'
| 'chevron-square-up-fill'
| 'chevron-square-down-fill'
| 'chevron-shallow-[start]'
| 'chevron-shallow-[end]'
| 'chevron-shallow-up'
| 'chevron-shallow-down'
| 'chevron-double-left-right'
| 'chevron-double-up-down'
| 'circle'
| 'circle-fill'
| 'circle-dash'
| 'compose'
| 'connections'
| 'connections-fill'
| 'copy'
| 'copy-alt'
| 'countdown-00'
| 'countdown-05'
| 'countdown-10'
| 'countdown-15'
| 'countdown-20'
| 'countdown-25'
| 'countdown-30'
| 'countdown-35'
| 'countdown-40'
| 'countdown-45'
| 'countdown-50'
| 'countdown-55'
| 'countdown-60'
| 'creditcard'
| 'creditcard-fill'
| 'crop'
| 'crop-rotate'
| 'download'
| 'draghandle'
| 'draghandle-alt'
| 'emoji'
| 'emoji-fill'
| 'emoji-excited'
| 'emoji-sad'
| 'emoji-angry'
| 'emoji-thumbsup'
| 'emoji-surprised'
| 'emoji-animal'
| 'emoji-celebrate'
| 'emoji-food'
| 'emoji-activity'
| 'emoji-travel'
| 'emoji-object'
| 'emoji-symbol'
| 'emoji-flag'
| 'emoticon'
| 'error'
| 'error-fill'
| 'error-triangle'
| 'error-triangle-fill'
| 'error-octagon'
| 'error-octagon-fill'
| 'file'
| 'file-fill'
| 'file-slash'
| 'file-slash-fill'
| 'filter'
| 'filter-circle'
| 'filter-circle-fill'
| 'folder'
| 'forward'
| 'forward-fill'
| 'fullscreen'
| 'gif'
| 'gif-rectangle'
| 'gif-rectangle-fill'
| 'gift'
| 'globe'
| 'grid'
| 'grid-fill'
| 'grid-rectangle'
| 'grid-rectangle-fill'
| 'group'
| 'group-fill'
| 'heart'
| 'heart-plus'
| 'heart-fill'
| 'heart-plus-fill'
| 'help'
| 'help-fill'
| 'info'
| 'info-fill'
| 'invite'
| 'key'
| 'key-slash'
| 'leave'
| 'leave-rtl'
| 'link'
| 'link-alt'
| 'link-broken'
| 'link-slash'
| 'list-bullet'
| 'list-bullet-rtl'
| 'list-circle'
| 'list-circle-rtl'
| 'lock'
| 'lock-open'
| 'lock-fill'
| 'lock-open-fill'
| 'megaphone'
| 'menu'
| 'merge'
| 'message'
| 'message-badge'
| 'message-arrow'
| 'message-check'
| 'message-more'
| 'message-x'
| 'message-fill'
| 'message-badge-fill'
| 'message-arrow-fill'
| 'message-check-fill'
| 'message-more-fill'
| 'message-x-fill'
| 'mic'
| 'mic-fill'
| 'mic-slash'
| 'mic-slash-fill'
| 'minus'
| 'minus-circle'
| 'minus-square'
| 'minus-circle-fill'
| 'minus-square-fill'
| 'missed-incoming'
| 'missed-outgoing'
| 'moon'
| 'moon-slash'
| 'moon-fill'
| 'moon-slash-fill'
| 'more'
| 'more-circle'
| 'more-circle-fill'
| 'note'
| 'note-rtl'
| 'number'
| 'number-square'
| 'number-square-fill'
| 'officialbadge'
| 'officialbadge-fill'
| 'open'
| 'palette'
| 'palette-fill'
| 'pencil'
| 'pencil-fill'
| 'person'
| 'person-fill'
| 'person-circle'
| 'person-square'
| 'person-rectangle'
| 'phone'
| 'phone-fill'
| 'photo'
| 'photo-slash'
| 'piechart'
| 'piechart-fill'
| 'pin'
| 'pin-fill'
| 'pin-slash'
| 'pin-slash-fill'
| 'play'
| 'play-circle'
| 'play-square'
| 'play-fill'
| 'play-circle-fill'
| 'play-square-fill'
| 'plus'
| 'plus-circle'
| 'plus-square'
| 'plus-circle-fill'
| 'plus-square-fill'
| 'poll'
| 'poll-fill'
| 'qrcode'
| 'raisehand'
| 'raisehand-fill'
| 'receipt'
| 'receipt-rtl'
| 'recent'
| 'rectangle'
| 'rectangle-fill'
| 'redo'
| 'refresh'
| 'reply'
| 'reply-fill'
| 'rotate'
| 'scan'
| 'scribble'
| 'search'
| 'send'
| 'send-fill'
| 'settings'
| 'settings-fill'
| 'shield-check'
| 'shield-check-fill'
| 'square'
| 'square-fill'
| 'star'
| 'star-fill'
| 'sticker'
| 'stories'
| 'stories-fill'
| 'sun'
| 'sun-fill'
| 'sun-horizon'
| 'sun-horizon-fill'
| 'swap'
| 'thread'
| 'thread-fill'
| 'ticks'
| 'timer'
| 'timer-fill'
| 'timer-slash'
| 'timer-slash-fill'
| 'trash'
| 'trash-fill'
| 'tune'
| 'undo'
| 'upload'
| 'video'
| 'video-slash'
| 'video-fill'
| 'video-slash-fill'
| 'videocamera'
| 'videocamera-fill'
| 'videocamera-slash'
| 'videocamera-slash-fill'
| 'viewonce'
| 'viewonce-dash'
| 'wifi'
| 'x'
| 'x-circle'
| 'x-circle-fill'
| 'x-circle-dash'
| 'x-square'
| 'x-square-fill';
// Symbols that can only be used in <AxoSymbol.InlineGlyph>
type AxoSymbolInlineGlyphOnlyName =
| 'check-double-circle'
| 'check-double-circle-fill'
| 'group-x'
| 'group-x-fill'
| 'person-check'
| 'person-plus'
| 'person-minus'
| 'person-x'
| 'person-question';
// Symbols with an inline-specific glyph that override the icon glyph
type AxoSymbolInlineGlyphOverrideName =
| 'album'
| 'arrow-rectangle-up'
| 'arrow-rectangle-up-fill'
| 'aspectratio'
| 'aspectratio-fill'
| 'audio-rectangle'
| 'audio-rectangle-fill'
| 'gif-rectangle'
| 'gif-rectangle-fill'
| 'grid-rectangle'
| 'grid-rectangle-fill'
| 'group'
| 'group-fill'
| 'invite'
| 'leave'
| 'leave-rtl'
| 'person-rectangle'
| 'photo'
| 'photo-slash'
| 'rectangle'
| 'rectangle-fill'
| 'video'
| 'video-slash'
| 'video-fill'
| 'video-slash-fill'
| 'videocamera'
| 'videocamera-fill'
| 'videocamera-slash'
| 'videocamera-slash-fill';
// Symbols that can be used in <AxoSymbol.InlineGlyph>
export type AxoSymbolInlineGlyphName =
| AxoSymbolIconName
| AxoSymbolInlineGlyphOnlyName;
type SymbolDef = string | { ltr: string; rtl: string };
type IconDefsName = AxoSymbolIconName;
type InlineDefsName =
| AxoSymbolInlineGlyphOnlyName
| AxoSymbolInlineGlyphOverrideName;
const IconDefs: Record<string, SymbolDef> = {
'signal-logo': '\u{E000}',
album: '\u{E163}',
appearance: '\u{E031}',
'appearance-fill': '\u{E164}',
archive: '\u{E09B}',
'archive-fill': '\u{E165}',
'archive-down': '\u{E205}',
'archive-down-fill': '\u{E206}',
'archive-up': '\u{E09C}',
'archive-up-fill': '\u{E166}',
'arrow-[start]': { ltr: '\u{E169}', rtl: '\u{E16A}' },
'arrow-[end]': { ltr: '\u{E16A}', rtl: '\u{E169}' },
'arrow-up': '\u{E16B}',
'arrow-down': '\u{E16C}',
'arrow-up[start]': { ltr: '\u{E16D}', rtl: '\u{E16E}' },
'arrow-up[end]': { ltr: '\u{E16E}', rtl: '\u{E16D}' },
'arrow-down[start]': { ltr: '\u{E16F}', rtl: '\u{E170}' },
'arrow-down[end]': { ltr: '\u{E170}', rtl: '\u{E16F}' },
'arrow-circle-[start]': { ltr: '\u{E00B}', rtl: '\u{E00C}' },
'arrow-circle-[end]': { ltr: '\u{E00C}', rtl: '\u{E00B}' },
'arrow-circle-up': '\u{E00D}',
'arrow-circle-down': '\u{E00E}',
'arrow-circle-up[start]': { ltr: '\u{E00F}', rtl: '\u{E010}' },
'arrow-circle-up[end]': { ltr: '\u{E010}', rtl: '\u{E00F}' },
'arrow-circle-down[start]': { ltr: '\u{E011}', rtl: '\u{E012}' },
'arrow-circle-down[end]': { ltr: '\u{E012}', rtl: '\u{E011}' },
'arrow-circle-[start]-fill': { ltr: '\u{E003}', rtl: '\u{E004}' },
'arrow-circle-[end]-fill': { ltr: '\u{E004}', rtl: '\u{E003}' },
'arrow-circle-up-fill': '\u{E005}',
'arrow-circle-down-fill': '\u{E006}',
'arrow-circle-up[start]-fill': { ltr: '\u{E007}', rtl: '\u{E008}' },
'arrow-circle-up[end]-fill': { ltr: '\u{E008}', rtl: '\u{E007}' },
'arrow-circle-down[start]-fill': { ltr: '\u{E009}', rtl: '\u{E00A}' },
'arrow-circle-down[end]-fill': { ltr: '\u{E00A}', rtl: '\u{E009}' },
'arrow-square-[start]': { ltr: '\u{E013}', rtl: '\u{E014}' },
'arrow-square-[end]': { ltr: '\u{E014}', rtl: '\u{E013}' },
'arrow-square-up': '\u{E015}',
'arrow-square-down': '\u{E016}',
'arrow-square-up[start]': { ltr: '\u{E017}', rtl: '\u{E018}' },
'arrow-square-up[end]': { ltr: '\u{E018}', rtl: '\u{E017}' },
'arrow-square-down[start]': { ltr: '\u{E019}', rtl: '\u{E01A}' },
'arrow-square-down[end]': { ltr: '\u{E01A}', rtl: '\u{E019}' },
'arrow-square-[start]-fill': { ltr: '\u{E08A}', rtl: '\u{E08B}' },
'arrow-square-[end]-fill': { ltr: '\u{E08B}', rtl: '\u{E08A}' },
'arrow-square-up-fill': '\u{E08C}',
'arrow-square-down-fill': '\u{E08D}',
'arrow-square-up[start]-fill': { ltr: '\u{E08E}', rtl: '\u{E08F}' },
'arrow-square-up[end]-fill': { ltr: '\u{E08F}', rtl: '\u{E08E}' },
'arrow-square-down[start]-fill': { ltr: '\u{E090}', rtl: '\u{E091}' },
'arrow-square-down[end]-fill': { ltr: '\u{E091}', rtl: '\u{E090}' },
'arrow-rectangle-up': '\u{E0CD}',
'arrow-rectangle-up-fill': '\u{E173}',
'arrow-circle-dash-down': '\u{E172}',
aspectratio: '\u{E134}',
'aspectratio-fill': '\u{E176}',
at: '\u{E01B}',
attach: '\u{E058}',
audio: '\u{E01C}',
'audio-rectangle': '\u{E178}',
'audio-rectangle-fill': '\u{E179}',
backup: '\u{E09F}',
badge: '\u{E099}',
'badge-fill': '\u{E09A}',
'badge-set': '\u{E0DA}',
'badge-set-fill': '\u{E17D}',
bell: '\u{E01E}',
'bell-slash': '\u{E01F}',
'bell-ring': '\u{E020}',
block: '\u{E002}',
bolt: '\u{E0B8}',
boost: '\u{E0E2}',
calendar: '\u{E0A2}',
'calendar-blank': '\u{E0A3}',
'calendar-week': '\u{E0A4}',
'calendar-one': '\u{E0A5}',
'calendar-search': '\u{E0E3}',
camera: '\u{E0E4}',
'camera-fill': '\u{E17E}',
check: '\u{E180}',
'check-circle': '\u{E022}',
'check-circle-fill': '\u{E182}',
'check-square': '\u{E023}',
'check-square-fill': '\u{E183}',
'chevron-[start]': { ltr: '\u{E024}', rtl: '\u{E025}' },
'chevron-[end]': { ltr: '\u{E025}', rtl: '\u{E024}' },
'chevron-up': '\u{E026}',
'chevron-down': '\u{E027}',
'chevron-circle-[start]': { ltr: '\u{E028}', rtl: '\u{E029}' },
'chevron-circle-[end]': { ltr: '\u{E029}', rtl: '\u{E028}' },
'chevron-circle-up': '\u{E02A}',
'chevron-circle-down': '\u{E02B}',
'chevron-circle-[start]-fill': { ltr: '\u{E1F2}', rtl: '\u{E1F3}' },
'chevron-circle-[end]-fill': { ltr: '\u{E1F3}', rtl: '\u{E1F2}' },
'chevron-circle-up-fill': '\u{E1F4}',
'chevron-circle-down-fill': '\u{E1F5}',
'chevron-square-[start]': { ltr: '\u{E02C}', rtl: '\u{E02D}' },
'chevron-square-[end]': { ltr: '\u{E02D}', rtl: '\u{E02C}' },
'chevron-square-up': '\u{E02E}',
'chevron-square-down': '\u{E02F}',
'chevron-square-[start]-fill': { ltr: '\u{E1F6}', rtl: '\u{E1F7}' },
'chevron-square-[end]-fill': { ltr: '\u{E1F7}', rtl: '\u{E1F6}' },
'chevron-square-up-fill': '\u{E1F8}',
'chevron-square-down-fill': '\u{E1F9}',
'chevron-shallow-[start]': { ltr: '\u{E0E6}', rtl: '\u{E0E7}' },
'chevron-shallow-[end]': { ltr: '\u{E0E7}', rtl: '\u{E0E6}' },
'chevron-shallow-up': '\u{E0E8}',
'chevron-shallow-down': '\u{E0E9}',
'chevron-double-left-right': '\u{E207}',
'chevron-double-up-down': '\u{E081}',
circle: '\u{E160}',
'circle-fill': '\u{E184}',
'circle-dash': '\u{E07A}',
compose: '\u{E0EA}',
connections: '\u{E0AD}',
'connections-fill': '\u{E185}',
copy: '\u{E0EB}',
'copy-alt': '\u{E0EC}',
'countdown-00': '\u{E048}',
'countdown-05': '\u{E049}',
'countdown-10': '\u{E04A}',
'countdown-15': '\u{E04B}',
'countdown-20': '\u{E04C}',
'countdown-25': '\u{E04D}',
'countdown-30': '\u{E04E}',
'countdown-35': '\u{E04F}',
'countdown-40': '\u{E050}',
'countdown-45': '\u{E051}',
'countdown-50': '\u{E052}',
'countdown-55': '\u{E053}',
'countdown-60': '\u{E054}',
creditcard: '\u{E127}',
'creditcard-fill': '\u{E187}',
crop: '\u{E0ED}',
'crop-rotate': '\u{E0EE}',
download: '\u{E0C8}',
draghandle: '\u{E0F5}',
'draghandle-alt': '\u{E0F6}',
emoji: '\u{E18D}',
'emoji-fill': '\u{E18E}',
'emoji-excited': '\u{E0F9}',
'emoji-sad': '\u{E0FA}',
'emoji-angry': '\u{E0FB}',
'emoji-thumbsup': '\u{E0FC}',
'emoji-surprised': '\u{E0FD}',
'emoji-animal': '\u{E0FE}',
'emoji-celebrate': '\u{E0FF}',
'emoji-food': '\u{E100}',
'emoji-activity': '\u{E101}',
'emoji-travel': '\u{E102}',
'emoji-object': '\u{E103}',
'emoji-symbol': '\u{E104}',
'emoji-flag': '\u{E105}',
emoticon: '\u{E106}',
error: '\u{E032}',
'error-fill': '\u{E093}',
'error-triangle': '\u{E092}',
'error-triangle-fill': '\u{E094}',
'error-octagon': '\u{E033}',
'error-octagon-fill': '\u{E18F}',
file: '\u{E034}',
'file-fill': '\u{E190}',
'file-slash': '\u{E0B1}',
'file-slash-fill': '\u{E191}',
filter: '\u{E107}',
'filter-circle': '\u{E108}',
'filter-circle-fill': '\u{E1FA}',
folder: '\u{E0B2}',
forward: '\u{E035}',
'forward-fill': '\u{E036}',
fullscreen: '\u{E10D}',
gif: '\u{E037}',
'gif-rectangle': '\u{E195}',
'gif-rectangle-fill': '\u{E196}',
gift: '\u{E0B5}',
globe: '\u{E0B6}',
grid: '\u{E10E}',
'grid-fill': '\u{E198}',
'grid-rectangle': '\u{E10F}',
'grid-rectangle-fill': '\u{E199}',
group: '\u{E19B}',
'group-fill': '\u{E19D}',
heart: '\u{E039}',
'heart-plus': '\u{E0B7}',
'heart-fill': '\u{E1A4}',
'heart-plus-fill': '\u{E1A5}',
help: '\u{E0D8}',
'help-fill': '\u{E1A6}',
info: '\u{E03B}',
'info-fill': '\u{E1A7}',
invite: '\u{E0B9}',
key: '\u{E0BA}',
'key-slash': '\u{E0BB}',
leave: '\u{E1AA}',
'leave-rtl': '\u{E1AB}',
link: '\u{E03E}',
'link-alt': '\u{E03F}',
'link-broken': '\u{E057}',
'link-slash': '\u{E040}',
'list-bullet': '\u{E113}',
'list-bullet-rtl': '\u{E115}',
'list-circle': '\u{E114}',
'list-circle-rtl': '\u{E116}',
lock: '\u{E041}',
'lock-open': '\u{E07D}',
'lock-fill': '\u{E1AD}',
'lock-open-fill': '\u{E1AE}',
megaphone: '\u{E042}',
menu: '\u{E11B}',
merge: '\u{E043}',
message: '\u{E0A6}',
'message-badge': '\u{E0A7}',
'message-arrow': '\u{E0A8}',
'message-check': '\u{E0A9}',
'message-more': '\u{E0AA}',
'message-x': '\u{E0AB}',
'message-fill': '\u{E1AF}',
'message-badge-fill': '\u{E1B0}',
'message-arrow-fill': '\u{E1B1}',
'message-check-fill': '\u{E1B2}',
'message-more-fill': '\u{E1B3}',
'message-x-fill': '\u{E1B4}',
mic: '\u{E055}',
'mic-fill': '\u{E1B5}',
'mic-slash': '\u{E056}',
'mic-slash-fill': '\u{E1B6}',
minus: '\u{E1B7}',
'minus-circle': '\u{E1B8}',
'minus-square': '\u{E059}',
'minus-circle-fill': '\u{E1B9}',
'minus-square-fill': '\u{E1BA}',
'missed-incoming': '\u{E05A}',
'missed-outgoing': '\u{E05B}',
moon: '\u{E0BE}',
'moon-slash': '\u{E209}',
'moon-fill': '\u{E0D9}',
'moon-slash-fill': '\u{E20A}',
more: '\u{E120}',
'more-circle': '\u{E121}',
'more-circle-fill': '\u{E208}',
note: '\u{E095}',
'note-rtl': '\u{E096}',
number: '\u{E0BF}',
'number-square': '\u{E0C0}',
'number-square-fill': '\u{E1BC}',
officialbadge: '\u{E086}',
'officialbadge-fill': '\u{E087}',
open: '\u{E0C1}',
palette: '\u{E0AC}',
'palette-fill': '\u{E1BD}',
pencil: '\u{E030}',
'pencil-fill': '\u{E1C1}',
person: '\u{E05D}',
'person-fill': '\u{E1C3}',
'person-circle': '\u{E05E}',
'person-square': '\u{E129}',
'person-rectangle': '\u{E12A}',
phone: '\u{E063}',
'phone-fill': '\u{E064}',
photo: '\u{E1C8}',
'photo-slash': '\u{E1C9}',
piechart: '\u{E0F1}',
'piechart-fill': '\u{E1CA}',
pin: '\u{E12E}',
'pin-fill': '\u{E1CB}',
'pin-slash': '\u{E12F}',
'pin-slash-fill': '\u{E1CC}',
play: '\u{E067}',
'play-circle': '\u{E068}',
'play-square': '\u{E069}',
'play-fill': '\u{E1CD}',
'play-circle-fill': '\u{E1CE}',
'play-square-fill': '\u{E1CF}',
plus: '\u{E1D1}',
'plus-circle': '\u{E1D2}',
'plus-square': '\u{E06C}',
'plus-circle-fill': '\u{E1D3}',
'plus-square-fill': '\u{E1D4}',
poll: '\u{E082}',
'poll-fill': '\u{E083}',
qrcode: '\u{E0C2}',
raisehand: '\u{E07E}',
'raisehand-fill': '\u{E084}',
receipt: '\u{E135}',
'receipt-rtl': '\u{E136}',
recent: '\u{E0C3}',
rectangle: '\u{E162}',
'rectangle-fill': '\u{E1D6}',
redo: '\u{E0C6}',
refresh: '\u{E0C4}',
reply: '\u{E06D}',
'reply-fill': '\u{E06E}',
rotate: '\u{E137}',
scan: '\u{E138}',
scribble: '\u{E0F7}',
search: '\u{E0C7}',
send: '\u{E20B}',
'send-fill': '\u{E0C9}',
settings: '\u{E0CA}',
'settings-fill': '\u{E0CB}',
'shield-check': '\u{E06F}',
'shield-check-fill': '\u{E1D8}',
square: '\u{E161}',
'square-fill': '\u{E1FB}',
star: '\u{E0AF}',
'star-fill': '\u{E0B0}',
sticker: '\u{E070}',
stories: '\u{E0D0}',
'stories-fill': '\u{E0D1}',
sun: '\u{E0D2}',
'sun-fill': '\u{E1DC}',
'sun-horizon': '\u{E0D3}',
'sun-horizon-fill': '\u{E1DD}',
swap: '\u{E0D4}',
thread: '\u{E071}',
'thread-fill': '\u{E072}',
ticks: '\u{E044}',
timer: '\u{E073}',
'timer-fill': '\u{E1E0}',
'timer-slash': '\u{E074}',
'timer-slash-fill': '\u{E1E1}',
trash: '\u{E0D5}',
'trash-fill': '\u{E0D6}',
tune: '\u{E15A}',
undo: '\u{E0C5}',
upload: '\u{E0D7}',
video: '\u{E1E2}',
'video-slash': '\u{E1E3}',
'video-fill': '\u{E1E4}',
'video-slash-fill': '\u{E1E6}',
videocamera: '\u{E1E8}',
'videocamera-fill': '\u{E1EA}',
'videocamera-slash': '\u{E1E9}',
'videocamera-slash-fill': '\u{E1EB}',
viewonce: '\u{E078}',
'viewonce-dash': '\u{E079}',
wifi: '\u{E15D}',
x: '\u{E1ED}',
'x-circle': '\u{E1EE}',
'x-circle-fill': '\u{E1F0}',
'x-circle-dash': '\u{E15F}',
'x-square': '\u{E1EF}',
'x-square-fill': '\u{E1F1}',
} satisfies Record<IconDefsName, SymbolDef>;
const InlineDefs: Record<string, SymbolDef> = {
album: '\u{E001}',
'arrow-rectangle-up': '\u{E171}',
'arrow-rectangle-up-fill': '\u{E174}',
aspectratio: '\u{E175}',
'aspectratio-fill': '\u{E177}',
'audio-rectangle': '\u{E01D}',
'audio-rectangle-fill': '\u{E17A}',
'check-double-circle': '\u{E046}',
'check-double-circle-fill': '\u{E047}',
'gif-rectangle': '\u{E097}',
'gif-rectangle-fill': '\u{E098}',
'grid-rectangle': '\u{E197}',
'grid-rectangle-fill': '\u{E19A}',
group: '\u{E038}',
'group-fill': '\u{E19E}',
'group-x': '\u{E0AE}',
'group-x-fill': '\u{E1A0}',
invite: '\u{E1A8}',
leave: '\u{E03C}',
'leave-rtl': '\u{E03D}',
'person-check': '\u{E05F}',
'person-plus': '\u{E061}',
'person-minus': '\u{E062}',
'person-x': '\u{E060}',
'person-question': '\u{E06A}',
'person-rectangle': '\u{E1C2}',
photo: '\u{E065}',
'photo-slash': '\u{E066}',
rectangle: '\u{E1D5}',
'rectangle-fill': '\u{E1D7}',
video: '\u{E088}',
'video-slash': '\u{E089}',
'video-fill': '\u{E1E5}',
'video-slash-fill': '\u{E1E7}',
videocamera: '\u{E075}',
'videocamera-fill': '\u{E077}',
'videocamera-slash': '\u{E076}',
'videocamera-slash-fill': '\u{E1EC}',
} satisfies Record<InlineDefsName, SymbolDef>;
export function _getAllAxoSymbolIconNames(): ReadonlyArray<AxoSymbolIconName> {
return Object.keys(IconDefs) as Array<AxoSymbolIconName>;
}
export function _getAllAxoSymbolInlineGlyphNames(): ReadonlyArray<AxoSymbolInlineGlyphName> {
return Object.keys(IconDefs) as Array<AxoSymbolIconName>;
}
export function getAxoSymbolIcon(
name: AxoSymbolIconName,
dir: 'ltr' | 'rtl'
): string {
const value = IconDefs[name];
if (value == null) {
throw new TypeError(`Invalid symbol name for icon: ${name}`);
}
return typeof value === 'string' ? value : value[dir];
}
export function getAxoSymbolInlineGlyph(
name: AxoSymbolInlineGlyphName,
dir: 'ltr' | 'rtl'
): string {
const value = InlineDefs[name] ?? IconDefs[name];
if (value == null) {
throw new TypeError(`Invalid symbol name for inline glyph: ${name}`);
}
return typeof value === 'string' ? value : value[dir];
}