@salemcobalt/ui 0.2.0-rc.20 → 0.2.0-rc.22

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/dist/editor.d.ts CHANGED
@@ -1,8 +1,15 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, Ref } from 'react';
3
3
 
4
4
  type TextEditorLanguage = 'yaml' | 'json' | 'markdown' | 'text';
5
5
 
6
+ /** What `ref` gives you: focus and line selection, on the Textarea before CodeMirror loads and on CodeMirror after. */
7
+ interface TextEditorHandle {
8
+ /** Focuses the editor. */
9
+ focus(): void;
10
+ /** Selects line `line` (1-based, clamped to the text), scrolls it into view and focuses the editor. */
11
+ selectLine(line: number): void;
12
+ }
6
13
  interface TextEditorProps {
7
14
  /** Required. The visible label. */
8
15
  label: ReactNode;
@@ -34,13 +41,15 @@ interface TextEditorProps {
34
41
  id?: string | undefined;
35
42
  /** Class on the wrapper. */
36
43
  className?: string | undefined;
44
+ /** Focus and select a line from outside, such as "Show line 12". */
45
+ ref?: Ref<TextEditorHandle> | undefined;
37
46
  }
38
47
  /**
39
48
  * A code and text editor on CodeMirror 6, with inline word diffs against `base`. Client-only: the server and the
40
49
  * first client render show a code `<textarea>` in the same field chrome, and CodeMirror replaces it once its chunk
41
50
  * has loaded, keeping focus and the selection.
42
51
  */
43
- declare function TextEditor({ label, description, error, value, onValueChange, base, language, liveDiff, disabled, readOnly, rows, id: idProp, className, }: TextEditorProps): react.JSX.Element;
52
+ declare function TextEditor({ label, description, error, value, onValueChange, base, language, liveDiff, disabled, readOnly, rows, id: idProp, className, ref, }: TextEditorProps): react.JSX.Element;
44
53
 
45
54
  export { TextEditor };
46
- export type { TextEditorLanguage, TextEditorProps };
55
+ export type { TextEditorHandle, TextEditorLanguage, TextEditorProps };
package/dist/editor.js CHANGED
@@ -5,6 +5,7 @@ import { Field } from "@base-ui/react/field";
5
5
  import {
6
6
  useEffect,
7
7
  useId,
8
+ useImperativeHandle,
8
9
  useLayoutEffect,
9
10
  useRef,
10
11
  useState
@@ -17,8 +18,14 @@ function cx(...parts) {
17
18
 
18
19
  // src/components/TextEditor/TextEditor.tsx
19
20
  import { jsx, jsxs } from "react/jsx-runtime";
20
- var load = () => import("./codemirror-D3Z4MYFA.js");
21
+ var load = () => import("./codemirror-6REE3TUN.js");
21
22
  var isProse = (language) => language === "markdown" || language === "text";
23
+ function lineRange(text, line) {
24
+ const lines = text.split("\n");
25
+ const n = Math.min(Math.max(Math.trunc(line), 1), lines.length);
26
+ const start = lines.slice(0, n - 1).reduce((at, l) => at + l.length + 1, 0);
27
+ return [start, start + lines[n - 1].length];
28
+ }
22
29
  function TextEditor({
23
30
  label,
24
31
  description,
@@ -32,7 +39,8 @@ function TextEditor({
32
39
  readOnly = false,
33
40
  rows = 8,
34
41
  id: idProp,
35
- className
42
+ className,
43
+ ref
36
44
  }) {
37
45
  const [module, setModule] = useState(null);
38
46
  const textareaRef = useRef(null);
@@ -94,6 +102,23 @@ function TextEditor({
94
102
  useLayoutEffect(() => {
95
103
  handleRef.current?.update(options);
96
104
  });
105
+ useImperativeHandle(
106
+ ref,
107
+ () => ({
108
+ focus() {
109
+ if (handleRef.current) return handleRef.current.focus();
110
+ if (!optionsRef.current.disabled) textareaRef.current?.focus();
111
+ },
112
+ selectLine(line) {
113
+ if (handleRef.current) return handleRef.current.selectLine(line);
114
+ const ta = textareaRef.current;
115
+ if (!ta || optionsRef.current.disabled) return;
116
+ ta.focus();
117
+ ta.setSelectionRange(...lineRange(ta.value, line));
118
+ }
119
+ }),
120
+ []
121
+ );
97
122
  const prose = isProse(language);
98
123
  return /* @__PURE__ */ jsxs(
99
124
  Field.Root,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/TextEditor/TextEditor.tsx","../src/utils/cx.ts"],"sourcesContent":["import { Field } from '@base-ui/react/field';\nimport {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from 'react';\nimport { cx } from '../../utils/cx';\nimport type * as CodeMirror from './codemirror';\nimport type { EditorHandle, EditorOptions, TextEditorLanguage } from './codemirror';\n\nexport type { TextEditorLanguage };\n\nexport interface TextEditorProps {\n /** Required. The visible label. */\n label: ReactNode;\n /** Help text under the editor, wired with `aria-describedby`. */\n description?: ReactNode | undefined;\n /** The error message. When given the editor is invalid and the message is announced. */\n error?: ReactNode | undefined;\n /** The text. Controlled: feed `onValueChange`'s value back. */\n value: string;\n onValueChange: (value: string) => void;\n /** The text to compare against, such as the saved version. With a base, changes show inline; without, no diff. */\n base?: string | undefined;\n /**\n * Syntax highlighting, loaded per language. `markdown` and `text` (default) keep the phone's autocorrect,\n * capitals and spellcheck; `yaml` and `json` turn them off.\n */\n language?: TextEditorLanguage | undefined;\n /**\n * Keep showing changes while the editor has focus, updated 300ms after the last keystroke. Default false: the\n * diff hides while you type, so nothing moves under the caret, and shows again on blur.\n */\n liveDiff?: boolean | undefined;\n disabled?: boolean | undefined;\n /** Focusable and selectable, not editable. The phone's keyboard stays down. */\n readOnly?: boolean | undefined;\n /** Minimum visible lines; the editor grows with its content. Default 8. */\n rows?: number | undefined;\n /** The editable element's id (the Textarea's before CodeMirror loads). */\n id?: string | undefined;\n /** Class on the wrapper. */\n className?: string | undefined;\n}\n\ntype CodeMirrorModule = typeof CodeMirror;\n// The only path to CodeMirror: a dynamic import, so it lands in its own chunk and never in the server render.\nconst load = (): Promise<CodeMirrorModule> => import('./codemirror');\n\nconst isProse = (language: TextEditorLanguage) => language === 'markdown' || language === 'text';\n\n/**\n * A code and text editor on CodeMirror 6, with inline word diffs against `base`. Client-only: the server and the\n * first client render show a code `<textarea>` in the same field chrome, and CodeMirror replaces it once its chunk\n * has loaded, keeping focus and the selection.\n */\nexport function TextEditor({\n label,\n description,\n error,\n value,\n onValueChange,\n base,\n language = 'text',\n liveDiff = false,\n disabled = false,\n readOnly = false,\n rows = 8,\n id: idProp,\n className,\n}: TextEditorProps) {\n const [module, setModule] = useState<CodeMirrorModule | null>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const hostRef = useRef<HTMLDivElement>(null);\n const handleRef = useRef<EditorHandle | null>(null);\n // The Textarea's focus and selection at the moment of the swap.\n const handoffRef = useRef<[number, number] | null>(null);\n const onChangeRef = useRef(onValueChange);\n useLayoutEffect(() => {\n onChangeRef.current = onValueChange;\n });\n const generatedId = useId();\n const id = idProp ?? generatedId;\n const labelId = `${id}-label`;\n const descriptionId = `${id}-description`;\n const errorId = `${id}-error`;\n const invalid = error != null;\n const describedBy = [description != null && descriptionId, invalid && errorId].filter(Boolean).join(' ');\n const options: EditorOptions = {\n value,\n base,\n liveDiff,\n language,\n disabled,\n readOnly,\n invalid,\n attributes: {\n id,\n 'aria-labelledby': labelId,\n ...(describedBy ? { 'aria-describedby': describedBy } : {}),\n },\n };\n const optionsRef = useRef(options);\n useLayoutEffect(() => {\n optionsRef.current = options;\n });\n\n useEffect(() => {\n let live = true;\n void load().then((m) => {\n if (!live) return;\n const ta = textareaRef.current;\n if (ta && document.activeElement === ta) handoffRef.current = [ta.selectionStart, ta.selectionEnd];\n setModule(() => m);\n });\n return () => {\n live = false;\n };\n }, []);\n\n useLayoutEffect(() => {\n if (!module || !hostRef.current) return;\n const handle = module.mountEditor(hostRef.current, optionsRef.current, (v) => onChangeRef.current(v));\n handleRef.current = handle;\n if (handoffRef.current) handle.focus(...handoffRef.current);\n handoffRef.current = null;\n return () => {\n handle.destroy();\n handleRef.current = null;\n };\n }, [module]);\n\n useLayoutEffect(() => {\n handleRef.current?.update(options);\n });\n\n const prose = isProse(language);\n return (\n <Field.Root\n className={cx('sc-field', className)}\n disabled={disabled}\n invalid={invalid}\n data-size=\"md\"\n data-editor={module ? 'codemirror' : 'fallback'}\n >\n {/* A <label> can't point at a contenteditable, so once CodeMirror is in, a click focuses it by hand. */}\n <Field.Label\n id={labelId}\n htmlFor={id}\n className=\"sc-field__label\"\n onClick={() => handleRef.current?.focus()}\n >\n {label}\n </Field.Label>\n {module ? (\n <div ref={hostRef} style={{ '--_rows': rows } as CSSProperties} />\n ) : (\n <Field.Control\n id={id}\n render={\n <textarea\n ref={textareaRef}\n // Grows to its content like the editor (text-editor.css), so the swap moves the layout only by the diff.\n rows={Math.max(rows, value.split('\\n').length)}\n style={{ '--_rows': rows } as CSSProperties}\n readOnly={readOnly}\n spellCheck={prose}\n autoCorrect={prose ? 'on' : 'off'}\n autoCapitalize={prose ? 'sentences' : 'off'}\n />\n }\n className=\"sc-input sc-textarea\"\n data-variant=\"code\"\n data-resize=\"none\"\n value={value}\n onValueChange={(v) => onValueChange(v)}\n />\n )}\n {description != null ? (\n <Field.Description id={descriptionId} className=\"sc-field__description\">\n {description}\n </Field.Description>\n ) : null}\n {invalid ? (\n <Field.Error id={errorId} className=\"sc-field__error\" match>\n {error}\n </Field.Error>\n ) : null}\n </Field.Root>\n );\n}\n","/** Joins class names, dropping falsy entries. */\nexport function cx(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(' ');\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/components/TextEditor/TextEditor.tsx","../src/utils/cx.ts"],"sourcesContent":["import { Field } from '@base-ui/react/field';\nimport {\n useEffect,\n useId,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { cx } from '../../utils/cx';\nimport type * as CodeMirror from './codemirror';\nimport type { EditorHandle, EditorOptions, TextEditorLanguage } from './codemirror';\n\nexport type { TextEditorLanguage };\n\n/** What `ref` gives you: focus and line selection, on the Textarea before CodeMirror loads and on CodeMirror after. */\nexport interface TextEditorHandle {\n /** Focuses the editor. */\n focus(): void;\n /** Selects line `line` (1-based, clamped to the text), scrolls it into view and focuses the editor. */\n selectLine(line: number): void;\n}\n\nexport interface TextEditorProps {\n /** Required. The visible label. */\n label: ReactNode;\n /** Help text under the editor, wired with `aria-describedby`. */\n description?: ReactNode | undefined;\n /** The error message. When given the editor is invalid and the message is announced. */\n error?: ReactNode | undefined;\n /** The text. Controlled: feed `onValueChange`'s value back. */\n value: string;\n onValueChange: (value: string) => void;\n /** The text to compare against, such as the saved version. With a base, changes show inline; without, no diff. */\n base?: string | undefined;\n /**\n * Syntax highlighting, loaded per language. `markdown` and `text` (default) keep the phone's autocorrect,\n * capitals and spellcheck; `yaml` and `json` turn them off.\n */\n language?: TextEditorLanguage | undefined;\n /**\n * Keep showing changes while the editor has focus, updated 300ms after the last keystroke. Default false: the\n * diff hides while you type, so nothing moves under the caret, and shows again on blur.\n */\n liveDiff?: boolean | undefined;\n disabled?: boolean | undefined;\n /** Focusable and selectable, not editable. The phone's keyboard stays down. */\n readOnly?: boolean | undefined;\n /** Minimum visible lines; the editor grows with its content. Default 8. */\n rows?: number | undefined;\n /** The editable element's id (the Textarea's before CodeMirror loads). */\n id?: string | undefined;\n /** Class on the wrapper. */\n className?: string | undefined;\n /** Focus and select a line from outside, such as \"Show line 12\". */\n ref?: Ref<TextEditorHandle> | undefined;\n}\n\ntype CodeMirrorModule = typeof CodeMirror;\n// The only path to CodeMirror: a dynamic import, so it lands in its own chunk and never in the server render.\nconst load = (): Promise<CodeMirrorModule> => import('./codemirror');\n\nconst isProse = (language: TextEditorLanguage) => language === 'markdown' || language === 'text';\n\n/** Line `line`'s start and end offsets in `text`, without its line break; clamped like CodeMirror's. */\nfunction lineRange(text: string, line: number): [number, number] {\n const lines = text.split('\\n');\n const n = Math.min(Math.max(Math.trunc(line), 1), lines.length);\n const start = lines.slice(0, n - 1).reduce((at, l) => at + l.length + 1, 0);\n return [start, start + lines[n - 1]!.length];\n}\n\n/**\n * A code and text editor on CodeMirror 6, with inline word diffs against `base`. Client-only: the server and the\n * first client render show a code `<textarea>` in the same field chrome, and CodeMirror replaces it once its chunk\n * has loaded, keeping focus and the selection.\n */\nexport function TextEditor({\n label,\n description,\n error,\n value,\n onValueChange,\n base,\n language = 'text',\n liveDiff = false,\n disabled = false,\n readOnly = false,\n rows = 8,\n id: idProp,\n className,\n ref,\n}: TextEditorProps) {\n const [module, setModule] = useState<CodeMirrorModule | null>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const hostRef = useRef<HTMLDivElement>(null);\n const handleRef = useRef<EditorHandle | null>(null);\n // The Textarea's focus and selection at the moment of the swap.\n const handoffRef = useRef<[number, number] | null>(null);\n const onChangeRef = useRef(onValueChange);\n useLayoutEffect(() => {\n onChangeRef.current = onValueChange;\n });\n const generatedId = useId();\n const id = idProp ?? generatedId;\n const labelId = `${id}-label`;\n const descriptionId = `${id}-description`;\n const errorId = `${id}-error`;\n const invalid = error != null;\n const describedBy = [description != null && descriptionId, invalid && errorId].filter(Boolean).join(' ');\n const options: EditorOptions = {\n value,\n base,\n liveDiff,\n language,\n disabled,\n readOnly,\n invalid,\n attributes: {\n id,\n 'aria-labelledby': labelId,\n ...(describedBy ? { 'aria-describedby': describedBy } : {}),\n },\n };\n const optionsRef = useRef(options);\n useLayoutEffect(() => {\n optionsRef.current = options;\n });\n\n useEffect(() => {\n let live = true;\n void load().then((m) => {\n if (!live) return;\n const ta = textareaRef.current;\n if (ta && document.activeElement === ta) handoffRef.current = [ta.selectionStart, ta.selectionEnd];\n setModule(() => m);\n });\n return () => {\n live = false;\n };\n }, []);\n\n useLayoutEffect(() => {\n if (!module || !hostRef.current) return;\n const handle = module.mountEditor(hostRef.current, optionsRef.current, (v) => onChangeRef.current(v));\n handleRef.current = handle;\n if (handoffRef.current) handle.focus(...handoffRef.current);\n handoffRef.current = null;\n return () => {\n handle.destroy();\n handleRef.current = null;\n };\n }, [module]);\n\n useLayoutEffect(() => {\n handleRef.current?.update(options);\n });\n\n useImperativeHandle(\n ref,\n () => ({\n focus() {\n if (handleRef.current) return handleRef.current.focus();\n if (!optionsRef.current.disabled) textareaRef.current?.focus();\n },\n selectLine(line) {\n if (handleRef.current) return handleRef.current.selectLine(line);\n const ta = textareaRef.current;\n if (!ta || optionsRef.current.disabled) return;\n ta.focus();\n ta.setSelectionRange(...lineRange(ta.value, line));\n },\n }),\n [],\n );\n\n const prose = isProse(language);\n return (\n <Field.Root\n className={cx('sc-field', className)}\n disabled={disabled}\n invalid={invalid}\n data-size=\"md\"\n data-editor={module ? 'codemirror' : 'fallback'}\n >\n {/* A <label> can't point at a contenteditable, so once CodeMirror is in, a click focuses it by hand. */}\n <Field.Label\n id={labelId}\n htmlFor={id}\n className=\"sc-field__label\"\n onClick={() => handleRef.current?.focus()}\n >\n {label}\n </Field.Label>\n {module ? (\n <div ref={hostRef} style={{ '--_rows': rows } as CSSProperties} />\n ) : (\n <Field.Control\n id={id}\n render={\n <textarea\n ref={textareaRef}\n // Grows to its content like the editor (text-editor.css), so the swap moves the layout only by the diff.\n rows={Math.max(rows, value.split('\\n').length)}\n style={{ '--_rows': rows } as CSSProperties}\n readOnly={readOnly}\n spellCheck={prose}\n autoCorrect={prose ? 'on' : 'off'}\n autoCapitalize={prose ? 'sentences' : 'off'}\n />\n }\n className=\"sc-input sc-textarea\"\n data-variant=\"code\"\n data-resize=\"none\"\n value={value}\n onValueChange={(v) => onValueChange(v)}\n />\n )}\n {description != null ? (\n <Field.Description id={descriptionId} className=\"sc-field__description\">\n {description}\n </Field.Description>\n ) : null}\n {invalid ? (\n <Field.Error id={errorId} className=\"sc-field__error\" match>\n {error}\n </Field.Error>\n ) : null}\n </Field.Root>\n );\n}\n","/** Joins class names, dropping falsy entries. */\nexport function cx(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(' ');\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -3299,7 +3299,44 @@ interface QuoteProps extends ComponentPropsWithRef<'figure'> {
3299
3299
  */
3300
3300
  declare function Quote({ label, className, children, ...rest }: QuoteProps): react.JSX.Element;
3301
3301
 
3302
+ type AvatarSize = 'xs' | 'sm' | 'md' | 'lg';
3303
+ /**
3304
+ * One or two capital letters for a person: the first letters of the first and last words of a name, or, for an email
3305
+ * address, of its local part split on `.`, `_`, `+`, `-` and digits. Empty when there is nothing to take a letter from.
3306
+ */
3307
+ declare function avatarInitials(name: string | null | undefined): string;
3308
+ interface AvatarLookProps {
3309
+ /** The person's name, or their email address when there is no name. The initials come from it. (On AvatarButton it is not the form `name` attribute.) */
3310
+ name?: string | null | undefined;
3311
+ /** Overrides the initials taken from `name`. Shown as given, up to two characters. */
3312
+ initials?: string | undefined;
3313
+ /** A picture. The initials show until it loads, and stay if it fails. */
3314
+ src?: string | undefined;
3315
+ /** `xs` 24px (beside text), `sm` 32, `md` 40 (default) and `lg` 48 follow the control heights, compact density included. */
3316
+ size?: AvatarSize | undefined;
3317
+ }
3318
+ interface AvatarProps extends AvatarLookProps, Omit<ComponentPropsWithRef<'span'>, 'children'> {
3319
+ /** Gives the avatar an accessible name (`role="img"`), e.g. the person's name where it is not written next to it. Without it the avatar is decorative and hidden from assistive tech. */
3320
+ label?: string | undefined;
3321
+ }
3322
+ /**
3323
+ * A person: their picture, else their initials on a brand tint inside a 1px ring (the ring is what keeps the circle
3324
+ * visible on every surface). Decorative unless `label` is given. For a clickable avatar use `AvatarButton`.
3325
+ */
3326
+ declare function Avatar({ name, initials, src, size, label, className, ...rest }: AvatarProps): react.JSX.Element;
3327
+ interface AvatarButtonProps extends AvatarLookProps, Omit<useRender.ComponentProps<'button'>, 'children' | 'aria-label' | 'name'> {
3328
+ /** Required. The button's accessible name, e.g. `Account: Robin Test`; the avatar inside is decorative. */
3329
+ label: string;
3330
+ }
3331
+ /**
3332
+ * A round button that is an Avatar, for an account menu or a profile link. The ring thickens on hover and while its
3333
+ * popup is open; the focus ring is the system's; on touch the hit area is at least 44px. Compose it as a trigger:
3334
+ * `<Menu.Trigger render={<AvatarButton label="Account: Robin Test" name="Robin Test" size="sm" />} />`, or make it a
3335
+ * link with `render={<a href="/profile" />}`.
3336
+ */
3337
+ declare function AvatarButton({ label, name, initials, src, size, type, className, render, ref, ...rest }: AvatarButtonProps): react.ReactElement<unknown, string | react.JSXElementConstructor<any>>;
3338
+
3302
3339
  declare const version = "0.1.1";
3303
3340
 
3304
- export { ArchiveIcon, ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowUpIcon, Badge, Banner, BellIcon, BriefcaseIcon, BroomIcon, Button, CalendarIcon, Card, CheckIcon, Checkbox, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, Chip, CircleCheckIcon, CircleXIcon, ClockIcon, CopyIcon, Dialog, Disclosure, DocumentIcon, DownloadIcon, EditIcon, EmptyState, ExternalLinkIcon, EyeIcon, FileInput, FilePreviewDialog, FilterIcon, FlagIcon, FullScreenFlow, Heading, Icon, IconButton, InboxIcon, InfoIcon, Inline, Input, Kbd, LinkIcon, MailIcon, MapPinIcon, Menu, MenuIcon, MinusIcon, MoonIcon, MoreHorizontalIcon, MoreVerticalIcon, PauseIcon, PlayIcon, PlusIcon, Popover, PriorityNav, Progress$1 as Progress, Quote, ReasonList, RefreshIcon, Score, SearchIcon, Select, SelectionBar, SettingsIcon, Skeleton, Spinner, Stack, StarIcon, Stat, SunIcon, Switch, Table, Tabs, Text, Textarea, ThumbsDownIcon, ThumbsUpIcon, Toast, Toolbar, Tooltip, TrashIcon, UndoIcon, UserIcon, WarningIcon, WordDiff, XIcon, iconNames, useRowSelection, useToast, version };
3305
- export type { BadgeProps, BadgeSize, BadgeTone, BadgeVariant, BannerProps, BannerTone, BroomIconProps, ButtonProps, ButtonSize, ButtonVariant, CardElement, CardPadding, CardProps, CardVariant, CheckboxProps, ChipProps, ChipSize, ChipTone, ControlSize, DialogActionsProps, DialogBodyProps, DialogCloseProps, DialogCloseRequestReason, DialogContentProps, DialogDescriptionProps, DialogRootProps, DialogSize, DialogTitleProps, DialogVariant, DisclosureProps, EmptyStateElement, EmptyStateProps, EmptyStateSize, FieldProps, FileInputProps, FilePreviewDialogProps, FlowChapter, FlowCloseRequestReason, FlowDirection, FullScreenFlowBodyProps, FullScreenFlowFooterProps, FullScreenFlowHeaderProps, FullScreenFlowProgressProps, FullScreenFlowRailGroupProps, FullScreenFlowRailItemProps, FullScreenFlowRailProps, FullScreenFlowRootProps, FullScreenFlowStepProps, FullScreenFlowViewportProps, HeadingElement, HeadingLevel, HeadingProps, HeadingSize, IconButtonDotTone, IconButtonProps, IconGlyphProps, IconName, IconProps, IconSize, InlineAlign, InlineElement, InlineJustify, InlineProps, InputProps, KbdGroupProps, KbdProps, MenuAlign, MenuCheckboxItemProps, MenuContentProps, MenuGroupProps, MenuItemProps, MenuItemTone, MenuLinkItemProps, MenuRadioGroupProps, MenuRadioItemProps, MenuRootProps, MenuSeparatorProps, MenuSide, MenuTriggerProps, PopoverAlign, PopoverCloseProps, PopoverContentProps, PopoverDescriptionProps, PopoverRootProps, PopoverSide, PopoverTitleProps, PopoverTriggerProps, PriorityNavItem, PriorityNavLinkProps, PriorityNavProps, ProgressProps, ProgressSize, ProgressTone, ProgressVariant, QuoteProps, ReasonListItemProps, ReasonListProps, ReasonListSize, ReasonTone, RowSelection, RowSelectionHeaderState, ScoreProps, ScoreSize, ScoreTone, ScoreVariant, SelectGroup, SelectOption, SelectProps, SelectionBarProps, SkeletonProps, SkeletonVariant, SpacingSize, SpinnerProps, StackAlign, StackElement, StackJustify, StackProps, StatDeltaTone, StatElement, StatProps, StatSize, StatTrend, StatVariant, SwitchProps, TableAlign, TableBodyProps, TableCaptionProps, TableCellProps, TableDensity, TableFootProps, TableHeadProps, TableHeaderProps, TableRootProps, TableRowProps, TableSelectionCellProps, TableSelectionHeaderProps, TableSortDirection, TabsListProps, TabsListVariant, TabsPanelProps, TabsRootProps, TabsTabProps, TextAlign, TextElement, TextFamily, TextProps, TextSize, TextTone, TextWeight, TextareaProps, TextareaVariant, ToastApi, ToastOptions, ToastProviderProps, ToastTone, ToolbarButtonProps, ToolbarGroupProps, ToolbarLinkProps, ToolbarRootProps, ToolbarSeparatorProps, ToolbarSpacerProps, TooltipAlign, TooltipProps, TooltipSide, WordDiffElement, WordDiffKind, WordDiffPart, WordDiffProps, WordDiffSize };
3341
+ export { ArchiveIcon, ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowUpIcon, Avatar, AvatarButton, Badge, Banner, BellIcon, BriefcaseIcon, BroomIcon, Button, CalendarIcon, Card, CheckIcon, Checkbox, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, Chip, CircleCheckIcon, CircleXIcon, ClockIcon, CopyIcon, Dialog, Disclosure, DocumentIcon, DownloadIcon, EditIcon, EmptyState, ExternalLinkIcon, EyeIcon, FileInput, FilePreviewDialog, FilterIcon, FlagIcon, FullScreenFlow, Heading, Icon, IconButton, InboxIcon, InfoIcon, Inline, Input, Kbd, LinkIcon, MailIcon, MapPinIcon, Menu, MenuIcon, MinusIcon, MoonIcon, MoreHorizontalIcon, MoreVerticalIcon, PauseIcon, PlayIcon, PlusIcon, Popover, PriorityNav, Progress$1 as Progress, Quote, ReasonList, RefreshIcon, Score, SearchIcon, Select, SelectionBar, SettingsIcon, Skeleton, Spinner, Stack, StarIcon, Stat, SunIcon, Switch, Table, Tabs, Text, Textarea, ThumbsDownIcon, ThumbsUpIcon, Toast, Toolbar, Tooltip, TrashIcon, UndoIcon, UserIcon, WarningIcon, WordDiff, XIcon, avatarInitials, iconNames, useRowSelection, useToast, version };
3342
+ export type { AvatarButtonProps, AvatarProps, AvatarSize, BadgeProps, BadgeSize, BadgeTone, BadgeVariant, BannerProps, BannerTone, BroomIconProps, ButtonProps, ButtonSize, ButtonVariant, CardElement, CardPadding, CardProps, CardVariant, CheckboxProps, ChipProps, ChipSize, ChipTone, ControlSize, DialogActionsProps, DialogBodyProps, DialogCloseProps, DialogCloseRequestReason, DialogContentProps, DialogDescriptionProps, DialogRootProps, DialogSize, DialogTitleProps, DialogVariant, DisclosureProps, EmptyStateElement, EmptyStateProps, EmptyStateSize, FieldProps, FileInputProps, FilePreviewDialogProps, FlowChapter, FlowCloseRequestReason, FlowDirection, FullScreenFlowBodyProps, FullScreenFlowFooterProps, FullScreenFlowHeaderProps, FullScreenFlowProgressProps, FullScreenFlowRailGroupProps, FullScreenFlowRailItemProps, FullScreenFlowRailProps, FullScreenFlowRootProps, FullScreenFlowStepProps, FullScreenFlowViewportProps, HeadingElement, HeadingLevel, HeadingProps, HeadingSize, IconButtonDotTone, IconButtonProps, IconGlyphProps, IconName, IconProps, IconSize, InlineAlign, InlineElement, InlineJustify, InlineProps, InputProps, KbdGroupProps, KbdProps, MenuAlign, MenuCheckboxItemProps, MenuContentProps, MenuGroupProps, MenuItemProps, MenuItemTone, MenuLinkItemProps, MenuRadioGroupProps, MenuRadioItemProps, MenuRootProps, MenuSeparatorProps, MenuSide, MenuTriggerProps, PopoverAlign, PopoverCloseProps, PopoverContentProps, PopoverDescriptionProps, PopoverRootProps, PopoverSide, PopoverTitleProps, PopoverTriggerProps, PriorityNavItem, PriorityNavLinkProps, PriorityNavProps, ProgressProps, ProgressSize, ProgressTone, ProgressVariant, QuoteProps, ReasonListItemProps, ReasonListProps, ReasonListSize, ReasonTone, RowSelection, RowSelectionHeaderState, ScoreProps, ScoreSize, ScoreTone, ScoreVariant, SelectGroup, SelectOption, SelectProps, SelectionBarProps, SkeletonProps, SkeletonVariant, SpacingSize, SpinnerProps, StackAlign, StackElement, StackJustify, StackProps, StatDeltaTone, StatElement, StatProps, StatSize, StatTrend, StatVariant, SwitchProps, TableAlign, TableBodyProps, TableCaptionProps, TableCellProps, TableDensity, TableFootProps, TableHeadProps, TableHeaderProps, TableRootProps, TableRowProps, TableSelectionCellProps, TableSelectionHeaderProps, TableSortDirection, TabsListProps, TabsListVariant, TabsPanelProps, TabsRootProps, TabsTabProps, TextAlign, TextElement, TextFamily, TextProps, TextSize, TextTone, TextWeight, TextareaProps, TextareaVariant, ToastApi, ToastOptions, ToastProviderProps, ToastTone, ToolbarButtonProps, ToolbarGroupProps, ToolbarLinkProps, ToolbarRootProps, ToolbarSeparatorProps, ToolbarSpacerProps, TooltipAlign, TooltipProps, TooltipSide, WordDiffElement, WordDiffKind, WordDiffPart, WordDiffProps, WordDiffSize };
package/dist/index.js CHANGED
@@ -3640,6 +3640,66 @@ function Quote({ label, className, children, ...rest }) {
3640
3640
  ] });
3641
3641
  }
3642
3642
 
3643
+ // src/components/Avatar/Avatar.tsx
3644
+ import { Avatar as BaseAvatar } from "@base-ui/react/avatar";
3645
+ import { useRender as useRender3 } from "@base-ui/react/use-render";
3646
+ import { jsx as jsx39, jsxs as jsxs33 } from "react/jsx-runtime";
3647
+ function avatarInitials(name) {
3648
+ const value = name?.trim() ?? "";
3649
+ const words = (value.includes("@") ? (value.split("@")[0] ?? "").split(/[._+\-\d]+/) : value.split(/\s+/)).filter(Boolean);
3650
+ const first = (w) => w ? Array.from(w)[0] ?? "" : "";
3651
+ const letters = words.length > 1 ? first(words[0]) + first(words[words.length - 1]) : first(words[0]);
3652
+ return letters.toUpperCase();
3653
+ }
3654
+ function Letters({ name, initials }) {
3655
+ const letters = initials?.trim() ? Array.from(initials.trim()).slice(0, 2).join("") : avatarInitials(name);
3656
+ return letters ? /* @__PURE__ */ jsx39("span", { className: "sc-avatar__initials", children: letters }) : /* @__PURE__ */ jsx39(UserIcon, { className: "sc-avatar__icon", size: "em" });
3657
+ }
3658
+ function Avatar({ name, initials, src, size = "md", label, className, ...rest }) {
3659
+ return /* @__PURE__ */ jsxs33(
3660
+ BaseAvatar.Root,
3661
+ {
3662
+ className: cx("sc-avatar", className),
3663
+ "data-size": size,
3664
+ role: label ? "img" : void 0,
3665
+ "aria-label": label,
3666
+ "aria-hidden": label ? void 0 : true,
3667
+ ...rest,
3668
+ children: [
3669
+ src ? /* @__PURE__ */ jsx39(BaseAvatar.Image, { className: "sc-avatar__image", src, alt: "" }) : null,
3670
+ /* @__PURE__ */ jsx39(BaseAvatar.Fallback, { className: "sc-avatar__fallback", children: /* @__PURE__ */ jsx39(Letters, { name, initials }) })
3671
+ ]
3672
+ }
3673
+ );
3674
+ }
3675
+ function AvatarButton({
3676
+ label,
3677
+ name,
3678
+ initials,
3679
+ src,
3680
+ size = "md",
3681
+ type,
3682
+ className,
3683
+ render,
3684
+ ref,
3685
+ ...rest
3686
+ }) {
3687
+ return useRender3({
3688
+ render,
3689
+ ref,
3690
+ defaultTagName: "button",
3691
+ props: {
3692
+ // `type` only means something on a real button; a rendered link keeps its own attributes.
3693
+ type: render ? type : type ?? "button",
3694
+ className: cx("sc-avatar-button", className),
3695
+ "data-size": size,
3696
+ "aria-label": label,
3697
+ ...rest,
3698
+ children: /* @__PURE__ */ jsx39(Avatar, { name, initials, src, size })
3699
+ }
3700
+ });
3701
+ }
3702
+
3643
3703
  // src/index.ts
3644
3704
  var version = "0.1.1";
3645
3705
  export {
@@ -3648,6 +3708,8 @@ export {
3648
3708
  ArrowLeftIcon,
3649
3709
  ArrowRightIcon,
3650
3710
  ArrowUpIcon,
3711
+ Avatar,
3712
+ AvatarButton,
3651
3713
  Badge,
3652
3714
  Banner,
3653
3715
  BellIcon,
@@ -3733,6 +3795,7 @@ export {
3733
3795
  WarningIcon,
3734
3796
  WordDiff,
3735
3797
  XIcon,
3798
+ avatarInitials,
3736
3799
  iconNames,
3737
3800
  useRowSelection,
3738
3801
  useToast,