@ssa-ui-kit/core 3.25.0 → 3.26.0

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.
Files changed (47) hide show
  1. package/dist/ai/source-map.md +76 -23
  2. package/dist/components/Breadcrumbs/styles.d.ts +1 -1
  3. package/dist/components/Chip/helpers.d.ts +2 -2
  4. package/dist/components/Chip/types.d.ts +10 -3
  5. package/dist/components/ContextMenu/ContextMenu.d.ts +74 -0
  6. package/dist/components/ContextMenu/ContextMenuOption.d.ts +18 -0
  7. package/dist/components/ContextMenu/index.d.ts +3 -0
  8. package/dist/components/ContextMenu/styles.d.ts +17 -0
  9. package/dist/components/ContextMenu/types.d.ts +153 -0
  10. package/dist/components/ContextMenu/utils.d.ts +79 -0
  11. package/dist/components/Dropdown/Dropdown.d.ts +1 -1
  12. package/dist/components/Dropdown/types.d.ts +14 -0
  13. package/dist/components/DropdownOptions/DropdownOptions.d.ts +5 -5
  14. package/dist/components/DropdownOptions/useToggleListKeys.d.ts +33 -0
  15. package/dist/components/DropdownOptions/utils.d.ts +9 -0
  16. package/dist/components/FiltersMultiSelect/FiltersMultiSelectProvider.d.ts +9 -0
  17. package/dist/components/FiltersMultiSelect/components/FiltersMultiSelectOption.d.ts +31 -1
  18. package/dist/components/FiltersMultiSelect/components/FiltersMultiSelectOptions.d.ts +29 -2
  19. package/dist/components/FiltersMultiSelect/utils.d.ts +15 -0
  20. package/dist/components/Footer/Footer.d.ts +42 -0
  21. package/dist/components/Footer/index.d.ts +1 -0
  22. package/dist/components/Footer/styles.d.ts +53 -0
  23. package/dist/components/Footer/types.d.ts +110 -0
  24. package/dist/components/Header/Header.d.ts +4 -4
  25. package/dist/components/Header/HeaderMobileMenu.d.ts +4 -3
  26. package/dist/components/Header/styles.d.ts +15 -4
  27. package/dist/components/Label/Label.d.ts +11 -1
  28. package/dist/components/Label/index.d.ts +1 -0
  29. package/dist/components/Label/types.d.ts +36 -1
  30. package/dist/components/MultipleDropdown/MultipleDropdown.d.ts +4 -1
  31. package/dist/components/MultipleDropdown/types.d.ts +8 -0
  32. package/dist/components/MultipleDropdownOptions/MultipleDropdownOptions.d.ts +27 -0
  33. package/dist/components/Table/ColumnFreezeMenu.d.ts +2 -0
  34. package/dist/components/TextField/TextField.d.ts +1 -1
  35. package/dist/components/TextField/types.d.ts +7 -0
  36. package/dist/components/Textarea/types.d.ts +4 -0
  37. package/dist/components/Typeahead/Typeahead.context.d.ts +10 -1
  38. package/dist/components/Typeahead/Typeahead.d.ts +1 -1
  39. package/dist/components/Typeahead/components/TypeaheadOptions.d.ts +13 -1
  40. package/dist/components/Typeahead/styles.d.ts +5 -0
  41. package/dist/components/Typeahead/types.d.ts +14 -1
  42. package/dist/components/Typeahead/useTypeahead.d.ts +12 -2
  43. package/dist/components/index.d.ts +5 -0
  44. package/dist/index.js +3593 -2167
  45. package/dist/index.mjs +3588 -2168
  46. package/dist/tsbuildcache +1 -1
  47. package/package.json +3 -3
@@ -4,6 +4,7 @@ import { Interpolation, Theme } from '@emotion/react';
4
4
  import { DropdownOptionProps } from '../DropdownOptions';
5
5
  import { CommonProps } from '../../types/emotion';
6
6
  import { IconProps } from '../Icon/types';
7
+ import { LabelBadge } from '../Label/types';
7
8
  export declare enum DropdownPositions {
8
9
  top = "top",
9
10
  bottom = "bottom",
@@ -108,6 +109,12 @@ export interface DropdownProps<P extends DropdownOptionProps> extends CommonProp
108
109
  * Label text displayed above the dropdown
109
110
  */
110
111
  label?: string;
112
+ /**
113
+ * Status badge to the right of the label, e.g.
114
+ * `{ text: 'default', color: 'grey' }`. Announced as the toggle's
115
+ * description. Needs a `label`.
116
+ */
117
+ labelBadge?: LabelBadge;
111
118
  /**
112
119
  * Helper text displayed below the dropdown
113
120
  * Shown when no errors are present
@@ -232,4 +239,11 @@ export interface DropdownContextType {
232
239
  * Computed by Dropdown based on dropdownPosition prop and available viewport space
233
240
  */
234
241
  placement?: 'top' | 'bottom';
242
+ /**
243
+ * Option highlighted by the keyboard or the pointer. Focus stays on the
244
+ * toggle, so the list is driven from there.
245
+ */
246
+ activeValue?: string | number | null;
247
+ /** Moves the highlight; called by the list on pointer moves. */
248
+ setActiveValue?: (value: string | number | null) => void;
235
249
  }
@@ -2,8 +2,9 @@ import { DropdownItemsListProps } from './types';
2
2
  /**
3
3
  * DropdownOptions - Options menu container for Dropdown component
4
4
  *
5
- * Renders the scrollable list of options that appears when the dropdown is open.
6
- * Provides proper ARIA attributes for accessibility and keyboard navigation.
5
+ * Renders the `DropdownOption` children as a `ContextMenu` placed under (or
6
+ * above) the Dropdown toggle. Focus stays on the toggle; the highlighted
7
+ * option is driven from there and announced through `aria-activedescendant`.
7
8
  *
8
9
  * Placement (opening upward or downward) is driven entirely by the parent
9
10
  * Dropdown via context — this component does not calculate position itself.
@@ -31,9 +32,8 @@ import { DropdownItemsListProps } from './types';
31
32
  * @see {@link DropdownOption} - Individual option components
32
33
  *
33
34
  * @accessibility
34
- * - Uses role="listbox" for proper ARIA semantics
35
- * - Supports keyboard navigation (Arrow keys, Enter, Escape)
36
- * - Screen reader friendly
35
+ * - Uses role="listbox" with role="option" rows
36
+ * - Arrow keys, Home, End, Enter, Space and Escape on the toggle
37
37
  */
38
38
  declare const DropdownOptions: ({ "aria-labelledby": ariaLabelledbyNative, ariaLabelledby, id, children, }: DropdownItemsListProps) => import("@emotion/react/jsx-runtime").JSX.Element;
39
39
  export default DropdownOptions;
@@ -0,0 +1,33 @@
1
+ import { KeyboardEvent } from 'react';
2
+ import { ContextMenuItem } from '../ContextMenu';
3
+ import { OptionValue } from './utils';
4
+ /** Options of {@link useToggleListKeys}. */
5
+ export interface UseToggleListKeysOptions {
6
+ /** Id of the ContextMenu the toggle controls. */
7
+ listId: string;
8
+ isOpen: boolean;
9
+ disabled?: boolean;
10
+ menuItems: ContextMenuItem<OptionValue>[];
11
+ /** Highlighted option. */
12
+ activeValue: OptionValue | null;
13
+ setActiveValue: (value: OptionValue | null) => void;
14
+ /** Opens the list; `key` is the arrow that opened it. */
15
+ open: (key: string) => void;
16
+ close: () => void;
17
+ /** Enter or Space on the highlighted option. */
18
+ onPick: (value: OptionValue) => void;
19
+ /** Consumer handlers, run first; `preventDefault()` skips the built-in keys. */
20
+ onKeyDown?: (event: KeyboardEvent<HTMLButtonElement>) => void;
21
+ onKeyUp?: (event: KeyboardEvent<HTMLButtonElement>) => void;
22
+ }
23
+ /**
24
+ * Keyboard for a dropdown toggle that keeps focus while it drives its list:
25
+ * arrows open it, then Arrow/Home/End move the highlight, Enter/Space pick,
26
+ * Escape/Tab close. Returns the toggle's handlers and its
27
+ * `aria-activedescendant`.
28
+ */
29
+ export declare const useToggleListKeys: ({ listId, isOpen, disabled, menuItems, activeValue, setActiveValue, open, close, onPick, onKeyDown, onKeyUp, }: UseToggleListKeysOptions) => {
30
+ onKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void;
31
+ onKeyUp: (event: KeyboardEvent<HTMLButtonElement>) => void;
32
+ 'aria-activedescendant': string | undefined;
33
+ };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { ContextMenuItem } from '../ContextMenu';
3
+ /** Value of a Dropdown option as the list sees it. */
4
+ export type OptionValue = string | number;
5
+ /**
6
+ * Reads `DropdownOption` children into ContextMenu items. The label resolves
7
+ * as `children` → `label` → `value`, as it always has.
8
+ */
9
+ export declare const toDropdownMenuItems: (children: React.ReactNode) => ContextMenuItem<OptionValue>[];
@@ -1,7 +1,16 @@
1
+ import { MutableRefObject } from 'react';
1
2
  import { UseFiltersMultiSelectStore } from './useFiltersMultiSelect';
3
+ import type { FilterMenuItem } from './utils';
2
4
  export interface FiltersMultiSelectContextValue {
3
5
  store: UseFiltersMultiSelectStore;
4
6
  emptyNode?: React.ReactNode;
7
+ /** Id of the options list, referenced by the search input. */
8
+ listId?: string;
9
+ /** Highlighted option, driven from the search input and the pointer. */
10
+ activeValue?: string | null;
11
+ setActiveValue?: (value: string | null) => void;
12
+ /** The rendered options, kept here for the search input's keyboard. */
13
+ itemsRef?: MutableRefObject<FilterMenuItem[]>;
5
14
  }
6
15
  export declare const FiltersMultiSelectProvider: ({ children, value, }: {
7
16
  value: FiltersMultiSelectContextValue;
@@ -1,7 +1,37 @@
1
1
  import { Filter } from '../useFiltersMultiSelect';
2
2
  export interface FiltersMultiSelectOptionProps {
3
+ /** The filter this row adds. `group: true` makes it a select-only row. */
3
4
  filter: Filter;
5
+ /** Row content. */
4
6
  children: React.ReactNode;
7
+ /**
8
+ * @deprecated Ignored — the row's state comes from the store's selected
9
+ * filters. Removed in the next major release.
10
+ */
5
11
  selected?: boolean;
6
12
  }
7
- export declare const FiltersMultiSelectOption: ({ filter, children, selected, }: FiltersMultiSelectOptionProps) => import("@emotion/react/jsx-runtime").JSX.Element;
13
+ /**
14
+ * FiltersMultiSelectOption - One filter row of a `FiltersMultiSelect`.
15
+ *
16
+ * Declarative: `FiltersMultiSelectOptions` reads its props and renders the
17
+ * row, so it renders nothing on its own. Regular filters get + (include) and
18
+ * − (exclude) controls; `group` filters get a single check-circle.
19
+ *
20
+ * @category Form Controls
21
+ * @subcategory Selection
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * <FiltersMultiSelectOptions>
26
+ * <FiltersMultiSelectOption filter={{ id: '1', label: 'Active' }}>
27
+ * Active
28
+ * </FiltersMultiSelectOption>
29
+ * <FiltersMultiSelectOption filter={{ id: 'g', label: 'Saved', group: true }}>
30
+ * Saved
31
+ * </FiltersMultiSelectOption>
32
+ * </FiltersMultiSelectOptions>
33
+ * ```
34
+ *
35
+ * @see {@link FiltersMultiSelectOptions} - The list that renders it
36
+ */
37
+ export declare const FiltersMultiSelectOption: (_props: FiltersMultiSelectOptionProps) => null;
@@ -1,4 +1,31 @@
1
1
  import React, { type HTMLAttributes } from 'react';
2
- export declare const FiltersMultiSelectOptions: ({ children, ...props }: {
2
+ /**
3
+ * FiltersMultiSelectOptions - The options list of a `FiltersMultiSelect`.
4
+ *
5
+ * Renders its `FiltersMultiSelectOption` children as an include / exclude
6
+ * `ContextMenu`: + and − on each row (one check-circle on group rows), Enter
7
+ * in the search input cycles the highlighted row. Shows the
8
+ * `FiltersMultiSelect` `emptyNode` when it has no options.
9
+ *
10
+ * @category Form Controls
11
+ * @subcategory Selection
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * <FiltersMultiSelect store={store}>
16
+ * <FiltersMultiSelectOptions>
17
+ * {filters.map((filter) => (
18
+ * <FiltersMultiSelectOption key={filter.id} filter={filter}>
19
+ * {filter.label}
20
+ * </FiltersMultiSelectOption>
21
+ * ))}
22
+ * </FiltersMultiSelectOptions>
23
+ * </FiltersMultiSelect>
24
+ * ```
25
+ *
26
+ * @see {@link FiltersMultiSelect} - Parent component
27
+ * @see {@link FiltersMultiSelectOption} - One filter row
28
+ */
29
+ export declare const FiltersMultiSelectOptions: ({ children, onMouseDown, ...props }: {
3
30
  children: React.ReactNode;
4
- } & HTMLAttributes<HTMLDivElement>) => import("@emotion/react/jsx-runtime").JSX.Element;
31
+ } & Omit<HTMLAttributes<HTMLUListElement>, "onChange" | "defaultValue" | "children">) => import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { ContextMenuIncludeExcludeEntry, ContextMenuIncludeExcludeType, ContextMenuItem } from '../ContextMenu';
3
+ import { Filter, SelectedFilter, UseFiltersMultiSelectStore } from './useFiltersMultiSelect';
4
+ /** A ContextMenu row together with the filter it stands for. */
5
+ export type FilterMenuItem = ContextMenuItem<string> & {
6
+ filter: Filter;
7
+ };
8
+ /** Reads `FiltersMultiSelectOption` children into ContextMenu items. */
9
+ export declare const toFilterMenuItems: (children: React.ReactNode) => FilterMenuItem[];
10
+ /** The store's selection in ContextMenu's `includeExclude` shape. */
11
+ export declare const toMenuSelection: (selectedFilters: SelectedFilter[]) => ContextMenuIncludeExcludeEntry<string>[];
12
+ /** The store's current type for a filter, in ContextMenu's terms. */
13
+ export declare const getMenuType: (store: UseFiltersMultiSelectStore, id: string) => ContextMenuIncludeExcludeType | undefined;
14
+ /** Selects `filter` as `type`, or unselects it when `type` is undefined. */
15
+ export declare const setFilterType: (store: UseFiltersMultiSelectStore, { id, label }: Filter, type: ContextMenuIncludeExcludeType | undefined) => void;
@@ -0,0 +1,42 @@
1
+ import { FooterProps } from './types';
2
+ /**
3
+ * Footer - The page's bottom bar: a copyright line and legal links, and
4
+ * optionally a logo, a short description and navigation columns above them.
5
+ *
6
+ * ### Default and extended
7
+ * With only `copyright` and `links` the Footer is a single bar in one of
8
+ * three sizes. Passing `logo`, `description` or `columns` makes it extended:
9
+ * the brand block and columns sit above the same bar. The design has the
10
+ * extended footer in medium only, so it ignores `size`.
11
+ *
12
+ * ### Links
13
+ * A link with a `path` renders as a react-router link, so the Footer must
14
+ * then sit inside a router; a link with an `href` renders as a plain anchor.
15
+ * Each column is its own navigation landmark, named by its title.
16
+ *
17
+ * ### Layout
18
+ * The layout follows the Footer's own width, not the window's. Below 900px
19
+ * the bottom bar stacks the copyright over the links, and the extended
20
+ * footer puts the brand block above its columns, two per row.
21
+ *
22
+ * @category Navigation
23
+ * @example
24
+ * ```tsx
25
+ * <Footer
26
+ * copyright="Acme © 2007-2026. All rights reserved."
27
+ * links={[
28
+ * { id: 'privacy', label: 'Privacy Policy', path: '/privacy' },
29
+ * { id: 'terms', label: 'Terms & Conditions', path: '/terms' },
30
+ * ]}
31
+ * logo={<img src="/logo.svg" alt="Acme" height={64} />}
32
+ * columns={[
33
+ * {
34
+ * id: 'company',
35
+ * title: 'Company',
36
+ * links: [{ id: 'about', label: 'About us', path: '/about' }],
37
+ * },
38
+ * ]}
39
+ * />
40
+ * ```
41
+ */
42
+ export declare const Footer: import("react").ForwardRefExoticComponent<FooterProps & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1 @@
1
+ export * from './Footer';
@@ -0,0 +1,53 @@
1
+ import { Theme } from '@emotion/react';
2
+ import { FooterSize, FooterTheme } from './types';
3
+ export declare const TYPOGRAPHY: Record<FooterSize, {
4
+ fontSize: number;
5
+ lineHeight: number;
6
+ fontWeight: number;
7
+ }>;
8
+ /** From this footer width up the design layout; below it, everything stacks. */
9
+ export declare const DESKTOP_MIN_WIDTH = 900;
10
+ export declare const resolvePalette: (theme: Theme, footerTheme: FooterTheme) => {
11
+ background: string;
12
+ text: `rgb${string}` | undefined;
13
+ accent: `rgb${string}` | undefined;
14
+ } | {
15
+ background: `rgb${string}` | "transparent";
16
+ text: `rgb${string}` | undefined;
17
+ accent: `rgb${string}` | "transparent";
18
+ };
19
+ export type FooterPalette = ReturnType<typeof resolvePalette>;
20
+ /**
21
+ * The query container. It is the footer itself, so consumer styles land on
22
+ * the outermost element; the padding the query switches lives on the inner
23
+ * wrapper, as a container cannot query its own width. The kit's global reset
24
+ * gives every element its own color, hence the explicit inherit inside.
25
+ */
26
+ export declare const container: (palette: FooterPalette) => import("@emotion/react").SerializedStyles;
27
+ export declare const inner: import("@emotion/react").SerializedStyles;
28
+ /**
29
+ * Design: 24px above the content, 40px between it and the bottom bar. The
30
+ * container already pads 12px, so this adds the other 12px on top.
31
+ */
32
+ export declare const extended: import("@emotion/react").SerializedStyles;
33
+ export declare const content: import("@emotion/react").SerializedStyles;
34
+ export declare const brand: import("@emotion/react").SerializedStyles;
35
+ /**
36
+ * Fixed height, as in the design's placeholder; width follows the logo so
37
+ * wordmarks fit.
38
+ */
39
+ export declare const logo: import("@emotion/react").SerializedStyles;
40
+ export declare const description: import("@emotion/react").SerializedStyles;
41
+ /**
42
+ * Two columns side by side on phones. On desktop the design's 160px gaps,
43
+ * shrinking with the footer so a fourth column still fits.
44
+ */
45
+ export declare const columns: import("@emotion/react").SerializedStyles;
46
+ export declare const column: import("@emotion/react").SerializedStyles;
47
+ export declare const columnTitle: import("@emotion/react").SerializedStyles;
48
+ export declare const linkList: import("@emotion/react").SerializedStyles;
49
+ /** Stacked on phones; copyright left and links right from 900px. */
50
+ export declare const bottomBar: (size: FooterSize) => import("@emotion/react").SerializedStyles;
51
+ export declare const copyright: import("@emotion/react").SerializedStyles;
52
+ export declare const legalList: import("@emotion/react").SerializedStyles;
53
+ export declare const link: (theme: Theme, palette: FooterPalette) => import("@emotion/react").SerializedStyles;
@@ -0,0 +1,110 @@
1
+ import { HTMLAttributes, ReactNode } from 'react';
2
+ /**
3
+ * Footer size: the text size of the bottom bar — 14px, 16px or 20px — and so
4
+ * its height, 42px, 48px or 52px. The extended footer is always medium.
5
+ */
6
+ export type FooterSize = 'small' | 'medium' | 'large';
7
+ /**
8
+ * Footer color scheme: the light grey bar, or the dark graphite gradient the
9
+ * Header uses.
10
+ */
11
+ export type FooterTheme = 'light' | 'dark';
12
+ /**
13
+ * One link of the Footer — a legal link in the bottom bar, or a line of a
14
+ * navigation column.
15
+ *
16
+ * Give it a `path` to render a react-router link (the Footer must then sit
17
+ * inside a router), or an `href` for a plain anchor — a page on another site,
18
+ * a `mailto:`. With neither it renders as plain text.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * const links: FooterLink[] = [
23
+ * { id: 'privacy', label: 'Privacy Policy', path: '/privacy' },
24
+ * { id: 'terms', label: 'Terms & Conditions', href: 'https://example.com/terms' },
25
+ * ];
26
+ * ```
27
+ */
28
+ export interface FooterLink {
29
+ /** Unique key of the link within its list */
30
+ id: string;
31
+ /** Visible label */
32
+ label: ReactNode;
33
+ /** In-app route, rendered as a react-router link. Wins over `href`. */
34
+ path?: string;
35
+ /** Address of a plain anchor, for links outside the app */
36
+ href?: string;
37
+ }
38
+ /**
39
+ * A navigation column of the extended Footer: a bold title over a list of
40
+ * links.
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * const column: FooterColumn = {
45
+ * id: 'company',
46
+ * title: 'Company',
47
+ * links: [
48
+ * { id: 'about', label: 'About us', path: '/about' },
49
+ * { id: 'careers', label: 'Careers', path: '/careers' },
50
+ * ],
51
+ * };
52
+ * ```
53
+ */
54
+ export interface FooterColumn {
55
+ /** Unique key of the column */
56
+ id: string;
57
+ /** Column title; also names the column's navigation landmark */
58
+ title: ReactNode;
59
+ /** Links listed under the title */
60
+ links: FooterLink[];
61
+ }
62
+ /**
63
+ * Props for the Footer component.
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * <Footer
68
+ * copyright="Acme © 2007-2026. All rights reserved."
69
+ * links={[{ id: 'privacy', label: 'Privacy Policy', path: '/privacy' }]}
70
+ * />
71
+ * ```
72
+ */
73
+ export interface FooterProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
74
+ /** Copyright line, on the left of the bottom bar */
75
+ copyright?: ReactNode;
76
+ /** Legal links — privacy policy, terms — on the right of the bottom bar */
77
+ links?: FooterLink[];
78
+ /**
79
+ * Project logo, at the top left of the extended footer, in a 64px high box.
80
+ * Passing it makes the footer extended.
81
+ */
82
+ logo?: ReactNode;
83
+ /**
84
+ * Short text under the logo — a tagline, the company name. Passing it makes
85
+ * the footer extended.
86
+ */
87
+ description?: ReactNode;
88
+ /**
89
+ * Navigation columns on the right of the extended footer. Passing any makes
90
+ * the footer extended.
91
+ */
92
+ columns?: FooterColumn[];
93
+ /**
94
+ * Color scheme. Named after the kit's other light/dark components (Header,
95
+ * TreeView) — not the Emotion theme.
96
+ * @default 'light'
97
+ */
98
+ theme?: FooterTheme;
99
+ /**
100
+ * Text size and height of the bottom bar. Ignored by the extended footer,
101
+ * which the design only has in medium.
102
+ * @default 'small'
103
+ */
104
+ size?: FooterSize;
105
+ /**
106
+ * Accessible name of the legal links' navigation landmark
107
+ * @default 'Legal'
108
+ */
109
+ linksLabel?: string;
110
+ }
@@ -11,10 +11,10 @@ import { HeaderProps } from './types';
11
11
  * further. Following a link closes them.
12
12
  *
13
13
  * ### Layout
14
- * From 900px the navigation is centred between the logo and the right side,
15
- * and scrolls sideways when it does not fit. Below 900px it moves into a
16
- * drawer opened by a burger button, the logo is centred and `rightSide`
17
- * stays as it is.
14
+ * The layout follows the Header's own width, not the window's. From 900px
15
+ * the navigation is centred between the logo and the right side, and scrolls
16
+ * sideways when it does not fit. Below 900px it moves into a drawer opened
17
+ * by a burger button, the logo is centred and `rightSide` stays as it is.
18
18
  *
19
19
  * ### Selected state
20
20
  * The design sets the selected item in bold. The kit marks it by color
@@ -10,9 +10,10 @@ interface HeaderMobileMenuProps {
10
10
  navLabel: string;
11
11
  }
12
12
  /**
13
- * The navigation below 900px: a full-width drawer holding a `TreeView`, the
14
- * same engine as CollapsibleNavBar's menu. The tree owns expansion and opens
15
- * the group holding the current page; this module owns the routing.
13
+ * The navigation below 900px: a 400px drawer (full width on phones) holding
14
+ * a `TreeView`, the same engine as CollapsibleNavBar's menu. The tree owns
15
+ * expansion and opens the group holding the current page; this module owns
16
+ * the routing.
16
17
  */
17
18
  export declare const HeaderMobileMenu: ({ store, items, headerTheme, palette, pathname, navLabel, }: HeaderMobileMenuProps) => import("@emotion/react/jsx-runtime").JSX.Element;
18
19
  export {};
@@ -5,6 +5,8 @@ export declare const SIZES: Record<HeaderSize, {
5
5
  logo: number;
6
6
  }>;
7
7
  export declare const MENU_WIDTH = 164;
8
+ /** From this header width up the bar shows the nav; below it, the burger. */
9
+ export declare const DESKTOP_MIN_WIDTH = 900;
8
10
  /** Design: dropdowns sit 6px below their trigger and flyouts 6px aside. */
9
11
  export declare const MENU_OFFSET = 6;
10
12
  export declare const resolvePalette: (theme: Theme, headerTheme: HeaderTheme) => {
@@ -33,10 +35,16 @@ export declare const resolvePalette: (theme: Theme, headerTheme: HeaderTheme) =>
33
35
  drawerBackground: `rgb${string}` | "transparent";
34
36
  };
35
37
  export type HeaderPalette = ReturnType<typeof resolvePalette>;
36
- export declare const root: (theme: Theme, palette: HeaderPalette, size: HeaderSize) => import("@emotion/react").SerializedStyles;
38
+ /**
39
+ * The query container. It is the `header` itself, so consumer styles such
40
+ * as `position: sticky` land on the outermost element; the layout that
41
+ * the query switches lives on the bar inside.
42
+ */
43
+ export declare const container: (palette: HeaderPalette) => import("@emotion/react").SerializedStyles;
44
+ export declare const bar: (size: HeaderSize) => import("@emotion/react").SerializedStyles;
37
45
  export declare const burger: (theme: Theme, palette: HeaderPalette) => import("@emotion/react").SerializedStyles;
38
46
  /** Holds the burger's column when there is no menu, so the logo stays centred. */
39
- export declare const burgerPlaceholder: (theme: Theme) => import("@emotion/react").SerializedStyles;
47
+ export declare const burgerPlaceholder: import("@emotion/react").SerializedStyles;
40
48
  /**
41
49
  * Fixed height from the size; width follows the logo so wordmarks fit, but
42
50
  * never drops below a square, so an empty box still holds its place.
@@ -46,7 +54,7 @@ export declare const logo: (size: HeaderSize) => import("@emotion/react").Serial
46
54
  * The scroll container. Dropdowns are portalled, so the overflow here does
47
55
  * not clip them.
48
56
  */
49
- export declare const nav: (theme: Theme) => import("@emotion/react").SerializedStyles;
57
+ export declare const nav: import("@emotion/react").SerializedStyles;
50
58
  /** `margin: auto` centres the list while it fits and lets it scroll after. */
51
59
  export declare const navList: import("@emotion/react").SerializedStyles;
52
60
  export declare const rightSide: import("@emotion/react").SerializedStyles;
@@ -59,5 +67,8 @@ export declare const navItem: (theme: Theme, palette: HeaderPalette, active: boo
59
67
  export declare const menu: (theme: Theme, palette: HeaderPalette) => import("@emotion/react").SerializedStyles;
60
68
  export declare const menuItem: (theme: Theme, palette: HeaderPalette, active: boolean) => import("@emotion/react").SerializedStyles;
61
69
  export declare const drawerContent: (palette: HeaderPalette) => import("@emotion/react").SerializedStyles;
62
- /** Chevron of a mobile group row; flips while the group is open. */
70
+ /**
71
+ * Chevron of a mobile group row; flips while the group is open. Pushed to the
72
+ * row's end so every chevron shares one vertical line.
73
+ */
63
74
  export declare const mobileToggle: (expanded: boolean) => import("@emotion/react").SerializedStyles;
@@ -1,3 +1,13 @@
1
1
  import { LabelProps } from './types';
2
- declare const Label: ({ children, htmlFor, className, disabled, isDisabled, onMouseEnter, onMouseLeave, }: LabelProps) => import("@emotion/react/jsx-runtime").JSX.Element;
2
+ /**
3
+ * Builds the default badge id for a label's `htmlFor`, so a field can point
4
+ * its control's `aria-describedby` at the badge.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * <input id="email" aria-describedby={getLabelBadgeId('email')} />
9
+ * ```
10
+ */
11
+ export declare const getLabelBadgeId: (htmlFor: string) => string;
12
+ declare const Label: ({ children, htmlFor, id, badge, className, disabled, isDisabled, onMouseEnter, onMouseLeave, }: LabelProps) => import("@emotion/react/jsx-runtime").JSX.Element;
3
13
  export default Label;
@@ -1 +1,2 @@
1
1
  export { default } from './Label';
2
+ export { getLabelBadgeId } from './Label';
@@ -1,8 +1,43 @@
1
- import { MouseEventHandler } from 'react';
1
+ import { MouseEventHandler, ReactNode } from 'react';
2
2
  import { CommonProps } from '../../types/emotion';
3
+ import { ChipProps } from '../Chip/types';
4
+ /**
5
+ * A small status pill shown to the right of a field label — "mapped",
6
+ * "default", "not present in the CV". Rendered as an outlined Chip.
7
+ *
8
+ * The badge sits next to the `<label>` element, not inside it, so it does
9
+ * not become part of the field's accessible name. Point the control's
10
+ * `aria-describedby` at its `id` to have it announced as a description —
11
+ * the kit's fields with a `labelBadge` prop do this for you.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const badge: LabelBadge = { text: 'mapped', color: 'primary' };
16
+ * const custom: LabelBadge = { text: 'not present in the CV', color: '#ff8a00' };
17
+ * ```
18
+ */
19
+ export interface LabelBadge {
20
+ /** Badge text */
21
+ text: ReactNode;
22
+ /**
23
+ * A Chip color: `primary`, `success`, `warning`… , any theme color key
24
+ * (e.g. `'purple'`) or a CSS color (e.g. `'#ff8a00'`).
25
+ * @default 'default'
26
+ */
27
+ color?: ChipProps['color'];
28
+ /**
29
+ * `id` of the badge element, for the control's `aria-describedby`
30
+ * @default `${htmlFor}-badge`, or a generated id without `htmlFor`
31
+ */
32
+ id?: string;
33
+ }
3
34
  export interface LabelProps extends CommonProps {
4
35
  htmlFor?: string;
36
+ /** `id` of the `<label>` element, e.g. for a control's `aria-labelledby` */
37
+ id?: string;
5
38
  children: React.ReactNode;
39
+ /** Status badge shown to the right of the label text */
40
+ badge?: LabelBadge;
6
41
  /** Renders the label in its muted, disabled state. */
7
42
  disabled?: boolean;
8
43
  /**
@@ -68,7 +68,10 @@ import { DropdownProps } from './types';
68
68
  *
69
69
  * @accessibility
70
70
  * - ARIA attributes set according to WAI-ARIA combobox pattern
71
- * - Keyboard navigation (Arrow keys, Enter, Escape)
71
+ * - Focus stays on the toggle, which points at the highlighted option with
72
+ * `aria-activedescendant`
73
+ * - Arrow keys, Home and End move the highlight; Enter or Space toggles it
74
+ * (picks and closes in single-select mode); Escape and Tab close
72
75
  * - Click outside to close
73
76
  * - Screen reader friendly with aria-expanded and aria-controls
74
77
  *
@@ -119,4 +119,12 @@ export interface DropdownContextType<T extends DropdownOptionProps> {
119
119
  * Max height (px) of the options list
120
120
  */
121
121
  maxHeight?: number;
122
+ /**
123
+ * Highlighted option, driven by the toggle's keyboard and the pointer
124
+ */
125
+ activeValue?: string | number | null;
126
+ /**
127
+ * Updates the highlighted option
128
+ */
129
+ setActiveValue?: (value: string | number | null) => void;
122
130
  }
@@ -1,3 +1,30 @@
1
1
  import { DropdownItemsListProps } from './types';
2
+ /**
3
+ * MultipleDropdownOptions - Options menu container for MultipleDropdown
4
+ *
5
+ * Renders the `DropdownOption` children as a `ContextMenu` under the
6
+ * MultipleDropdown toggle: a checkbox per row in multi-select mode, a check
7
+ * mark on the selected row otherwise. Focus stays on the toggle; the
8
+ * highlighted option is driven from there and announced through
9
+ * `aria-activedescendant`.
10
+ *
11
+ * @category Form Controls
12
+ * @subcategory Selection
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * // Rendered by MultipleDropdown from its DropdownOption children
17
+ * <MultipleDropdown label="Fruits" onChange={handleChange}>
18
+ * <DropdownOption value="apple">Apple</DropdownOption>
19
+ * <DropdownOption value="banana">Banana</DropdownOption>
20
+ * </MultipleDropdown>
21
+ * ```
22
+ *
23
+ * @see {@link MultipleDropdown} - Parent component
24
+ *
25
+ * @accessibility
26
+ * - Uses role="listbox" (multi-selectable in multi-select mode) with role="option" rows
27
+ * - Arrow keys, Home, End, Enter, Space and Escape on the toggle
28
+ */
2
29
  declare const MultipleDropdownOptions: ({ "aria-labelledby": ariaLabelledbyNative, ariaLabelledby, id, children, }: DropdownItemsListProps) => import("@emotion/react/jsx-runtime").JSX.Element;
3
30
  export default MultipleDropdownOptions;
@@ -27,6 +27,8 @@ import { ColumnFreezeMenuProps } from './types';
27
27
  *
28
28
  * @accessibility
29
29
  * - The trigger is a labelled button, reachable by keyboard even while hidden
30
+ * - Opening moves focus into the menu (`role="menu"`): arrows, Home, End and
31
+ * type-to-find move the highlight, Enter or Space picks, Escape closes
30
32
  * - Clicks inside the menu do not reach the header cell, so they never sort
31
33
  */
32
34
  export declare const ColumnFreezeMenu: ({ columnId }: ColumnFreezeMenuProps) => import("@emotion/react/jsx-runtime").JSX.Element;
@@ -75,5 +75,5 @@ import { TextFieldProps } from './types';
75
75
  * - ARIA attributes via React Hook Form (when register is provided)
76
76
  * - Error messages announced to screen readers
77
77
  */
78
- declare const TextField: ({ multirow, name, label, errors, helperText, success, disabled, maxLength, ...props }: TextFieldProps) => import("@emotion/react/jsx-runtime").JSX.Element;
78
+ declare const TextField: ({ multirow, name, label, labelBadge, errors, helperText, success, disabled, maxLength, ...props }: TextFieldProps) => import("@emotion/react/jsx-runtime").JSX.Element;
79
79
  export default TextField;