@gravity-ui/aikit 2.20.1 → 2.20.2-beta.079381cf5bff4083d73b5fa37c58ece5ae3b69bc.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.
@@ -12,4 +12,5 @@
12
12
  }
13
13
  .g-aikit-submit-button__spinner {
14
14
  --g-color-line-brand: var(--g-color-text-brand-contrast);
15
+ --g-spin-color: var(--g-color-text-brand-contrast);
15
16
  }
@@ -1,3 +1,4 @@
1
+ import { type PopupProps } from '@gravity-ui/uikit';
1
2
  import { type HistoryListProps } from "./HistoryList.js";
2
3
  import "./History.css";
3
4
  /**
@@ -12,6 +13,16 @@ export interface HistoryProps extends Omit<HistoryListProps, 'onChatClick'> {
12
13
  anchorElement: HTMLElement | null;
13
14
  /** Show the mobile sheet title (default: `true`); it stays in `aria-label` either way */
14
15
  showSheetTitle?: boolean;
16
+ /**
17
+ * Keep the keyboard focus inside the desktop popup while it is open (default: `true`).
18
+ *
19
+ * The popup is rendered in a portal, so without focus management `Tab` from the trigger
20
+ * button walks through the rest of the page instead of entering the popup, and the chat
21
+ * list cannot be reached from the keyboard at all.
22
+ */
23
+ modal?: boolean;
24
+ /** The element to focus when the desktop popup opens (default: the popup itself) */
25
+ initialFocus?: PopupProps['initialFocus'];
15
26
  }
16
27
  /**
17
28
  * History component - wraps HistoryList in a Popup, and in a bottom Sheet in mobile mode
@@ -16,7 +16,7 @@ const b = (0, cn_1.block)('history');
16
16
  * @returns React component
17
17
  */
18
18
  function History(props) {
19
- const { open = false, onOpenChange, anchorElement, showSheetTitle = true } = props, listProps = tslib_1.__rest(props, ["open", "onOpenChange", "anchorElement", "showSheetTitle"]);
19
+ const { open = false, onOpenChange, anchorElement, showSheetTitle = true, modal = true, initialFocus } = props, listProps = tslib_1.__rest(props, ["open", "onOpenChange", "anchorElement", "showSheetTitle", "modal", "initialFocus"]);
20
20
  const isMobile = (0, uikit_1.useMobile)();
21
21
  const sheetId = (0, uikit_1.useUniqId)();
22
22
  const handleChatClick = () => {
@@ -26,6 +26,6 @@ function History(props) {
26
26
  if (isMobile) {
27
27
  return ((0, jsx_runtime_1.jsx)(uikit_1.Sheet, { id: sheetId, title: (0, i18n_1.i18n)('sheet-title'), visible: open, onClose: () => onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(false), contentClassName: b('sheet-content', { 'without-title': !showSheetTitle }), qa: "history-sheet", allowHideOnContentScroll: true, children: list }));
28
28
  }
29
- return ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { anchorElement: anchorElement, placement: "bottom-end", open: open, onOpenChange: onOpenChange, children: list }));
29
+ return ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { anchorElement: anchorElement, placement: "bottom-end", open: open, onOpenChange: onOpenChange, modal: modal, initialFocus: initialFocus, "aria-label": (0, i18n_1.i18n)('sheet-title'), children: list }));
30
30
  }
31
31
  //# sourceMappingURL=History.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"History.js","sourceRoot":"../../../../../src","sources":["components/templates/History/History.tsx"],"names":[],"mappings":";;AA+BA,0BAqCC;;;AApED,6CAAqE;AAErE,6CAAwC;AAExC,kDAAiE;AACjE,0CAA4B;AAE5B,yBAAwB;AAExB,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,SAAS,CAAC,CAAC;AAgB3B;;;;;GAKG;AACH,SAAgB,OAAO,CAAC,KAAmB;IACvC,MAAM,EAAC,IAAI,GAAG,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,GAAG,IAAI,KAAkB,KAAK,EAAlB,SAAS,kBAAI,KAAK,EAAxF,2DAAgF,CAAQ,CAAC;IAC/F,MAAM,QAAQ,GAAG,IAAA,iBAAS,GAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;IAE5B,MAAM,eAAe,GAAG,GAAG,EAAE;QACzB,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,uBAAC,yBAAW,oBAAK,SAAS,IAAE,WAAW,EAAE,eAAe,IAAI,CAAC;IAE1E,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,CACH,uBAAC,aAAK,IACF,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,IAAA,WAAI,EAAC,aAAa,CAAC,EAC1B,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,KAAK,CAAC,EACpC,gBAAgB,EAAE,CAAC,CAAC,eAAe,EAAE,EAAC,eAAe,EAAE,CAAC,cAAc,EAAC,CAAC,EACxE,EAAE,EAAC,eAAe,EAClB,wBAAwB,kBAEvB,IAAI,GACD,CACX,CAAC;IACN,CAAC;IAED,OAAO,CACH,uBAAC,aAAK,IACF,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAC,YAAY,EACtB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,YAAY,YAEzB,IAAI,GACD,CACX,CAAC;AACN,CAAC","sourcesContent":["import {Popup, Sheet, useMobile, useUniqId} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\n\nimport {HistoryList, type HistoryListProps} from './HistoryList';\nimport {i18n} from './i18n';\n\nimport './History.scss';\n\nconst b = block('history');\n\n/**\n * Props for the History component\n */\nexport interface HistoryProps extends Omit<HistoryListProps, 'onChatClick'> {\n /** Control popup open state */\n open?: boolean;\n /** Callback when popup open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Anchor element for the popup */\n anchorElement: HTMLElement | null;\n /** Show the mobile sheet title (default: `true`); it stays in `aria-label` either way */\n showSheetTitle?: boolean;\n}\n\n/**\n * History component - wraps HistoryList in a Popup, and in a bottom Sheet in mobile mode\n *\n * @param props - Component props\n * @returns React component\n */\nexport function History(props: HistoryProps) {\n const {open = false, onOpenChange, anchorElement, showSheetTitle = true, ...listProps} = props;\n const isMobile = useMobile();\n const sheetId = useUniqId();\n\n const handleChatClick = () => {\n onOpenChange?.(false);\n };\n\n const list = <HistoryList {...listProps} onChatClick={handleChatClick} />;\n\n if (isMobile) {\n return (\n <Sheet\n id={sheetId}\n title={i18n('sheet-title')}\n visible={open}\n onClose={() => onOpenChange?.(false)}\n contentClassName={b('sheet-content', {'without-title': !showSheetTitle})}\n qa=\"history-sheet\"\n allowHideOnContentScroll\n >\n {list}\n </Sheet>\n );\n }\n\n return (\n <Popup\n anchorElement={anchorElement}\n placement=\"bottom-end\"\n open={open}\n onOpenChange={onOpenChange}\n >\n {list}\n </Popup>\n );\n}\n"]}
1
+ {"version":3,"file":"History.js","sourceRoot":"../../../../../src","sources":["components/templates/History/History.tsx"],"names":[],"mappings":";;AAyCA,0BAgDC;;;AAzFD,6CAAsF;AAEtF,6CAAwC;AAExC,kDAAiE;AACjE,0CAA4B;AAE5B,yBAAwB;AAExB,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,SAAS,CAAC,CAAC;AA0B3B;;;;;GAKG;AACH,SAAgB,OAAO,CAAC,KAAmB;IACvC,MAAM,EACF,IAAI,GAAG,KAAK,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,GAAG,IAAI,EACrB,KAAK,GAAG,IAAI,EACZ,YAAY,KAEZ,KAAK,EADF,SAAS,kBACZ,KAAK,EARH,oFAQL,CAAQ,CAAC;IACV,MAAM,QAAQ,GAAG,IAAA,iBAAS,GAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;IAE5B,MAAM,eAAe,GAAG,GAAG,EAAE;QACzB,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,uBAAC,yBAAW,oBAAK,SAAS,IAAE,WAAW,EAAE,eAAe,IAAI,CAAC;IAE1E,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,CACH,uBAAC,aAAK,IACF,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,IAAA,WAAI,EAAC,aAAa,CAAC,EAC1B,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,KAAK,CAAC,EACpC,gBAAgB,EAAE,CAAC,CAAC,eAAe,EAAE,EAAC,eAAe,EAAE,CAAC,cAAc,EAAC,CAAC,EACxE,EAAE,EAAC,eAAe,EAClB,wBAAwB,kBAEvB,IAAI,GACD,CACX,CAAC;IACN,CAAC;IAED,OAAO,CACH,uBAAC,aAAK,IACF,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAC,YAAY,EACtB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,gBACd,IAAA,WAAI,EAAC,aAAa,CAAC,YAE9B,IAAI,GACD,CACX,CAAC;AACN,CAAC","sourcesContent":["import {Popup, type PopupProps, Sheet, useMobile, useUniqId} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\n\nimport {HistoryList, type HistoryListProps} from './HistoryList';\nimport {i18n} from './i18n';\n\nimport './History.scss';\n\nconst b = block('history');\n\n/**\n * Props for the History component\n */\nexport interface HistoryProps extends Omit<HistoryListProps, 'onChatClick'> {\n /** Control popup open state */\n open?: boolean;\n /** Callback when popup open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Anchor element for the popup */\n anchorElement: HTMLElement | null;\n /** Show the mobile sheet title (default: `true`); it stays in `aria-label` either way */\n showSheetTitle?: boolean;\n /**\n * Keep the keyboard focus inside the desktop popup while it is open (default: `true`).\n *\n * The popup is rendered in a portal, so without focus management `Tab` from the trigger\n * button walks through the rest of the page instead of entering the popup, and the chat\n * list cannot be reached from the keyboard at all.\n */\n modal?: boolean;\n /** The element to focus when the desktop popup opens (default: the popup itself) */\n initialFocus?: PopupProps['initialFocus'];\n}\n\n/**\n * History component - wraps HistoryList in a Popup, and in a bottom Sheet in mobile mode\n *\n * @param props - Component props\n * @returns React component\n */\nexport function History(props: HistoryProps) {\n const {\n open = false,\n onOpenChange,\n anchorElement,\n showSheetTitle = true,\n modal = true,\n initialFocus,\n ...listProps\n } = props;\n const isMobile = useMobile();\n const sheetId = useUniqId();\n\n const handleChatClick = () => {\n onOpenChange?.(false);\n };\n\n const list = <HistoryList {...listProps} onChatClick={handleChatClick} />;\n\n if (isMobile) {\n return (\n <Sheet\n id={sheetId}\n title={i18n('sheet-title')}\n visible={open}\n onClose={() => onOpenChange?.(false)}\n contentClassName={b('sheet-content', {'without-title': !showSheetTitle})}\n qa=\"history-sheet\"\n allowHideOnContentScroll\n >\n {list}\n </Sheet>\n );\n }\n\n return (\n <Popup\n anchorElement={anchorElement}\n placement=\"bottom-end\"\n open={open}\n onOpenChange={onOpenChange}\n modal={modal}\n initialFocus={initialFocus}\n aria-label={i18n('sheet-title')}\n >\n {list}\n </Popup>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- export type ControlSize = 'xs' | 's' | 'm' | 'l' | 'xl';
1
+ export type ControlSize = 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl';
2
2
  /**
3
3
  * Resolves a control size: an explicit size always wins, otherwise the mobile
4
4
  * default is used in mobile mode and the desktop default elsewhere.
@@ -1 +1 @@
1
- {"version":3,"file":"useMobileControlSize.js","sourceRoot":"../../../src","sources":["hooks/useMobileControlSize.ts"],"names":[],"mappings":";;AAQA,4DASC;AAKD,oDAQC;AAKD,gDAEC;AArCD,6CAA4C;AAI5C;;;GAGG;AACH,SAAgB,wBAAwB,CAAwB,MAK/D;IACG,MAAM,EAAC,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAC,GAAG,MAAM,CAAC;IAE/D,OAAO,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAChC,IAAmB,EACnB,cAAiB,EACjB,aAAgB;IAEhB,MAAM,QAAQ,GAAG,IAAA,iBAAS,GAAE,CAAC;IAE7B,OAAO,wBAAwB,CAAC,EAAC,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAC,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,IAA6B;IAC5D,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import {useMobile} from '@gravity-ui/uikit';\n\nexport type ControlSize = 'xs' | 's' | 'm' | 'l' | 'xl';\n\n/**\n * Resolves a control size: an explicit size always wins, otherwise the mobile\n * default is used in mobile mode and the desktop default elsewhere.\n */\nexport function resolveMobileControlSize<T extends ControlSize>(params: {\n size: T | undefined;\n desktopDefault: T;\n mobileDefault: T;\n isMobile: boolean;\n}): T {\n const {size, desktopDefault, mobileDefault, isMobile} = params;\n\n return size ?? (isMobile ? mobileDefault : desktopDefault);\n}\n\n/**\n * Mobile-aware control size, driven by the uikit `MobileProvider` context.\n */\nexport function useMobileControlSize<T extends ControlSize>(\n size: T | undefined,\n desktopDefault: T,\n mobileDefault: T,\n): T {\n const isMobile = useMobile();\n\n return resolveMobileControlSize({size, desktopDefault, mobileDefault, isMobile});\n}\n\n/**\n * Icon size matching the resolved control size.\n */\nexport function getControlIconSize(size: ControlSize | undefined): number {\n return size === 'xl' ? 20 : 16;\n}\n"]}
1
+ {"version":3,"file":"useMobileControlSize.js","sourceRoot":"../../../src","sources":["hooks/useMobileControlSize.ts"],"names":[],"mappings":";;AAUA,4DASC;AAKD,oDAQC;AAKD,gDAEC;AAvCD,6CAA4C;AAM5C;;;GAGG;AACH,SAAgB,wBAAwB,CAAwB,MAK/D;IACG,MAAM,EAAC,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAC,GAAG,MAAM,CAAC;IAE/D,OAAO,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAChC,IAAmB,EACnB,cAAiB,EACjB,aAAgB;IAEhB,MAAM,QAAQ,GAAG,IAAA,iBAAS,GAAE,CAAC;IAE7B,OAAO,wBAAwB,CAAC,EAAC,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAC,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,IAA6B;IAC5D,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import {useMobile} from '@gravity-ui/uikit';\n\n// `xxs` only exists on `Label`, which uikit 7.48 gained. It is listed here so that the helpers\n// stay usable with the whole `LabelProps['size']` union across the supported uikit range.\nexport type ControlSize = 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl';\n\n/**\n * Resolves a control size: an explicit size always wins, otherwise the mobile\n * default is used in mobile mode and the desktop default elsewhere.\n */\nexport function resolveMobileControlSize<T extends ControlSize>(params: {\n size: T | undefined;\n desktopDefault: T;\n mobileDefault: T;\n isMobile: boolean;\n}): T {\n const {size, desktopDefault, mobileDefault, isMobile} = params;\n\n return size ?? (isMobile ? mobileDefault : desktopDefault);\n}\n\n/**\n * Mobile-aware control size, driven by the uikit `MobileProvider` context.\n */\nexport function useMobileControlSize<T extends ControlSize>(\n size: T | undefined,\n desktopDefault: T,\n mobileDefault: T,\n): T {\n const isMobile = useMobile();\n\n return resolveMobileControlSize({size, desktopDefault, mobileDefault, isMobile});\n}\n\n/**\n * Icon size matching the resolved control size.\n */\nexport function getControlIconSize(size: ControlSize | undefined): number {\n return size === 'xl' ? 20 : 16;\n}\n"]}
@@ -1 +1 @@
1
- {"version":"2.20.1","type":"commonjs","sideEffects":["*.css","*.scss"]}
1
+ {"version":"2.20.2-beta.079381cf5bff4083d73b5fa37c58ece5ae3b69bc.0","type":"commonjs","sideEffects":["*.css","*.scss"]}
@@ -113,6 +113,8 @@ import ruLocale from 'dayjs/locale/ru.js';
113
113
  | `filterFunction` | `ChatFilterFunction` | - | `defaultChatFilter` | Custom filter function for search |
114
114
  | `size` | `'s' \| 'm' \| 'l' \| 'xl'` | - | `m`, `xl` on mobile | Size of the list and of the row delete button |
115
115
  | `showSheetTitle` | `boolean` | - | `true` | Show the mobile sheet title (stays in `aria-label`) |
116
+ | `modal` | `boolean` | - | `true` | Keep the keyboard focus inside the desktop popup |
117
+ | `initialFocus` | `PopupProps['initialFocus']` | - | - | Element to focus when the desktop popup opens |
116
118
 
117
119
  Without an explicit `size` the list is `m` on desktop and `xl` in mobile mode, and the row delete
118
120
  button follows it: `s` on desktop, `xl` with a `20px` icon on mobile, so a row keeps a comfortable
@@ -414,7 +416,12 @@ To bring the desktop metrics back into the sheet:
414
416
  - Uses semantic HTML with proper button elements
415
417
  - Keyboard navigation support through Popup and List components
416
418
  - Click areas are properly sized for touch devices
417
- - Focus management handled by underlying UI kit components
419
+ - On desktop the popup is a modal dialog: opening it moves the focus inside, `Tab` and
420
+ `Shift + Tab` cycle through the search field and the chat list, and `Escape` closes the popup and
421
+ returns the focus to the trigger button. Pass `modal={false}` to opt out — the focus then stays on
422
+ the trigger and the popup is only reachable after tabbing through the rest of the page, because it
423
+ is rendered in a portal
424
+ - The popup is labelled with the same "Chat history" string as the mobile sheet
418
425
 
419
426
  ## Internationalization
420
427
 
@@ -12,4 +12,5 @@
12
12
  }
13
13
  .g-aikit-submit-button__spinner {
14
14
  --g-color-line-brand: var(--g-color-text-brand-contrast);
15
+ --g-spin-color: var(--g-color-text-brand-contrast);
15
16
  }
@@ -1,3 +1,4 @@
1
+ import { type PopupProps } from '@gravity-ui/uikit';
1
2
  import { type HistoryListProps } from "./HistoryList.js";
2
3
  import "./History.css";
3
4
  /**
@@ -12,6 +13,16 @@ export interface HistoryProps extends Omit<HistoryListProps, 'onChatClick'> {
12
13
  anchorElement: HTMLElement | null;
13
14
  /** Show the mobile sheet title (default: `true`); it stays in `aria-label` either way */
14
15
  showSheetTitle?: boolean;
16
+ /**
17
+ * Keep the keyboard focus inside the desktop popup while it is open (default: `true`).
18
+ *
19
+ * The popup is rendered in a portal, so without focus management `Tab` from the trigger
20
+ * button walks through the rest of the page instead of entering the popup, and the chat
21
+ * list cannot be reached from the keyboard at all.
22
+ */
23
+ modal?: boolean;
24
+ /** The element to focus when the desktop popup opens (default: the popup itself) */
25
+ initialFocus?: PopupProps['initialFocus'];
15
26
  }
16
27
  /**
17
28
  * History component - wraps HistoryList in a Popup, and in a bottom Sheet in mobile mode
@@ -13,7 +13,7 @@ const b = block('history');
13
13
  * @returns React component
14
14
  */
15
15
  export function History(props) {
16
- const { open = false, onOpenChange, anchorElement, showSheetTitle = true } = props, listProps = __rest(props, ["open", "onOpenChange", "anchorElement", "showSheetTitle"]);
16
+ const { open = false, onOpenChange, anchorElement, showSheetTitle = true, modal = true, initialFocus } = props, listProps = __rest(props, ["open", "onOpenChange", "anchorElement", "showSheetTitle", "modal", "initialFocus"]);
17
17
  const isMobile = useMobile();
18
18
  const sheetId = useUniqId();
19
19
  const handleChatClick = () => {
@@ -23,6 +23,6 @@ export function History(props) {
23
23
  if (isMobile) {
24
24
  return (_jsx(Sheet, { id: sheetId, title: i18n('sheet-title'), visible: open, onClose: () => onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(false), contentClassName: b('sheet-content', { 'without-title': !showSheetTitle }), qa: "history-sheet", allowHideOnContentScroll: true, children: list }));
25
25
  }
26
- return (_jsx(Popup, { anchorElement: anchorElement, placement: "bottom-end", open: open, onOpenChange: onOpenChange, children: list }));
26
+ return (_jsx(Popup, { anchorElement: anchorElement, placement: "bottom-end", open: open, onOpenChange: onOpenChange, modal: modal, initialFocus: initialFocus, "aria-label": i18n('sheet-title'), children: list }));
27
27
  }
28
28
  //# sourceMappingURL=History.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"History.js","sourceRoot":"../../../../../src","sources":["components/templates/History/History.tsx"],"names":[],"mappings":";;AAAA,OAAO,EAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAErE,OAAO,EAAC,KAAK,EAAC,6BAA0B;AAExC,OAAO,EAAC,WAAW,EAAwB,yBAAsB;AACjE,OAAO,EAAC,IAAI,EAAC,wBAAe;AAE5B,uBAAwB;AAExB,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;AAgB3B;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,KAAmB;IACvC,MAAM,EAAC,IAAI,GAAG,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,GAAG,IAAI,KAAkB,KAAK,EAAlB,SAAS,UAAI,KAAK,EAAxF,2DAAgF,CAAQ,CAAC;IAC/F,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,MAAM,eAAe,GAAG,GAAG,EAAE;QACzB,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,KAAC,WAAW,oBAAK,SAAS,IAAE,WAAW,EAAE,eAAe,IAAI,CAAC;IAE1E,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,CACH,KAAC,KAAK,IACF,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,EAC1B,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,KAAK,CAAC,EACpC,gBAAgB,EAAE,CAAC,CAAC,eAAe,EAAE,EAAC,eAAe,EAAE,CAAC,cAAc,EAAC,CAAC,EACxE,EAAE,EAAC,eAAe,EAClB,wBAAwB,kBAEvB,IAAI,GACD,CACX,CAAC;IACN,CAAC;IAED,OAAO,CACH,KAAC,KAAK,IACF,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAC,YAAY,EACtB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,YAAY,YAEzB,IAAI,GACD,CACX,CAAC;AACN,CAAC","sourcesContent":["import {Popup, Sheet, useMobile, useUniqId} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\n\nimport {HistoryList, type HistoryListProps} from './HistoryList';\nimport {i18n} from './i18n';\n\nimport './History.scss';\n\nconst b = block('history');\n\n/**\n * Props for the History component\n */\nexport interface HistoryProps extends Omit<HistoryListProps, 'onChatClick'> {\n /** Control popup open state */\n open?: boolean;\n /** Callback when popup open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Anchor element for the popup */\n anchorElement: HTMLElement | null;\n /** Show the mobile sheet title (default: `true`); it stays in `aria-label` either way */\n showSheetTitle?: boolean;\n}\n\n/**\n * History component - wraps HistoryList in a Popup, and in a bottom Sheet in mobile mode\n *\n * @param props - Component props\n * @returns React component\n */\nexport function History(props: HistoryProps) {\n const {open = false, onOpenChange, anchorElement, showSheetTitle = true, ...listProps} = props;\n const isMobile = useMobile();\n const sheetId = useUniqId();\n\n const handleChatClick = () => {\n onOpenChange?.(false);\n };\n\n const list = <HistoryList {...listProps} onChatClick={handleChatClick} />;\n\n if (isMobile) {\n return (\n <Sheet\n id={sheetId}\n title={i18n('sheet-title')}\n visible={open}\n onClose={() => onOpenChange?.(false)}\n contentClassName={b('sheet-content', {'without-title': !showSheetTitle})}\n qa=\"history-sheet\"\n allowHideOnContentScroll\n >\n {list}\n </Sheet>\n );\n }\n\n return (\n <Popup\n anchorElement={anchorElement}\n placement=\"bottom-end\"\n open={open}\n onOpenChange={onOpenChange}\n >\n {list}\n </Popup>\n );\n}\n"]}
1
+ {"version":3,"file":"History.js","sourceRoot":"../../../../../src","sources":["components/templates/History/History.tsx"],"names":[],"mappings":";;AAAA,OAAO,EAAC,KAAK,EAAmB,KAAK,EAAE,SAAS,EAAE,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAEtF,OAAO,EAAC,KAAK,EAAC,6BAA0B;AAExC,OAAO,EAAC,WAAW,EAAwB,yBAAsB;AACjE,OAAO,EAAC,IAAI,EAAC,wBAAe;AAE5B,uBAAwB;AAExB,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;AA0B3B;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,KAAmB;IACvC,MAAM,EACF,IAAI,GAAG,KAAK,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,GAAG,IAAI,EACrB,KAAK,GAAG,IAAI,EACZ,YAAY,KAEZ,KAAK,EADF,SAAS,UACZ,KAAK,EARH,oFAQL,CAAQ,CAAC;IACV,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,MAAM,eAAe,GAAG,GAAG,EAAE;QACzB,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,KAAC,WAAW,oBAAK,SAAS,IAAE,WAAW,EAAE,eAAe,IAAI,CAAC;IAE1E,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,CACH,KAAC,KAAK,IACF,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,EAC1B,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,KAAK,CAAC,EACpC,gBAAgB,EAAE,CAAC,CAAC,eAAe,EAAE,EAAC,eAAe,EAAE,CAAC,cAAc,EAAC,CAAC,EACxE,EAAE,EAAC,eAAe,EAClB,wBAAwB,kBAEvB,IAAI,GACD,CACX,CAAC;IACN,CAAC;IAED,OAAO,CACH,KAAC,KAAK,IACF,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAC,YAAY,EACtB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,gBACd,IAAI,CAAC,aAAa,CAAC,YAE9B,IAAI,GACD,CACX,CAAC;AACN,CAAC","sourcesContent":["import {Popup, type PopupProps, Sheet, useMobile, useUniqId} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\n\nimport {HistoryList, type HistoryListProps} from './HistoryList';\nimport {i18n} from './i18n';\n\nimport './History.scss';\n\nconst b = block('history');\n\n/**\n * Props for the History component\n */\nexport interface HistoryProps extends Omit<HistoryListProps, 'onChatClick'> {\n /** Control popup open state */\n open?: boolean;\n /** Callback when popup open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Anchor element for the popup */\n anchorElement: HTMLElement | null;\n /** Show the mobile sheet title (default: `true`); it stays in `aria-label` either way */\n showSheetTitle?: boolean;\n /**\n * Keep the keyboard focus inside the desktop popup while it is open (default: `true`).\n *\n * The popup is rendered in a portal, so without focus management `Tab` from the trigger\n * button walks through the rest of the page instead of entering the popup, and the chat\n * list cannot be reached from the keyboard at all.\n */\n modal?: boolean;\n /** The element to focus when the desktop popup opens (default: the popup itself) */\n initialFocus?: PopupProps['initialFocus'];\n}\n\n/**\n * History component - wraps HistoryList in a Popup, and in a bottom Sheet in mobile mode\n *\n * @param props - Component props\n * @returns React component\n */\nexport function History(props: HistoryProps) {\n const {\n open = false,\n onOpenChange,\n anchorElement,\n showSheetTitle = true,\n modal = true,\n initialFocus,\n ...listProps\n } = props;\n const isMobile = useMobile();\n const sheetId = useUniqId();\n\n const handleChatClick = () => {\n onOpenChange?.(false);\n };\n\n const list = <HistoryList {...listProps} onChatClick={handleChatClick} />;\n\n if (isMobile) {\n return (\n <Sheet\n id={sheetId}\n title={i18n('sheet-title')}\n visible={open}\n onClose={() => onOpenChange?.(false)}\n contentClassName={b('sheet-content', {'without-title': !showSheetTitle})}\n qa=\"history-sheet\"\n allowHideOnContentScroll\n >\n {list}\n </Sheet>\n );\n }\n\n return (\n <Popup\n anchorElement={anchorElement}\n placement=\"bottom-end\"\n open={open}\n onOpenChange={onOpenChange}\n modal={modal}\n initialFocus={initialFocus}\n aria-label={i18n('sheet-title')}\n >\n {list}\n </Popup>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- export type ControlSize = 'xs' | 's' | 'm' | 'l' | 'xl';
1
+ export type ControlSize = 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl';
2
2
  /**
3
3
  * Resolves a control size: an explicit size always wins, otherwise the mobile
4
4
  * default is used in mobile mode and the desktop default elsewhere.
@@ -1 +1 @@
1
- {"version":3,"file":"useMobileControlSize.js","sourceRoot":"../../../src","sources":["hooks/useMobileControlSize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAI5C;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAwB,MAK/D;IACG,MAAM,EAAC,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAC,GAAG,MAAM,CAAC;IAE/D,OAAO,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAChC,IAAmB,EACnB,cAAiB,EACjB,aAAgB;IAEhB,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;IAE7B,OAAO,wBAAwB,CAAC,EAAC,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAC,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAA6B;IAC5D,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import {useMobile} from '@gravity-ui/uikit';\n\nexport type ControlSize = 'xs' | 's' | 'm' | 'l' | 'xl';\n\n/**\n * Resolves a control size: an explicit size always wins, otherwise the mobile\n * default is used in mobile mode and the desktop default elsewhere.\n */\nexport function resolveMobileControlSize<T extends ControlSize>(params: {\n size: T | undefined;\n desktopDefault: T;\n mobileDefault: T;\n isMobile: boolean;\n}): T {\n const {size, desktopDefault, mobileDefault, isMobile} = params;\n\n return size ?? (isMobile ? mobileDefault : desktopDefault);\n}\n\n/**\n * Mobile-aware control size, driven by the uikit `MobileProvider` context.\n */\nexport function useMobileControlSize<T extends ControlSize>(\n size: T | undefined,\n desktopDefault: T,\n mobileDefault: T,\n): T {\n const isMobile = useMobile();\n\n return resolveMobileControlSize({size, desktopDefault, mobileDefault, isMobile});\n}\n\n/**\n * Icon size matching the resolved control size.\n */\nexport function getControlIconSize(size: ControlSize | undefined): number {\n return size === 'xl' ? 20 : 16;\n}\n"]}
1
+ {"version":3,"file":"useMobileControlSize.js","sourceRoot":"../../../src","sources":["hooks/useMobileControlSize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAM5C;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAwB,MAK/D;IACG,MAAM,EAAC,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAC,GAAG,MAAM,CAAC;IAE/D,OAAO,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAChC,IAAmB,EACnB,cAAiB,EACjB,aAAgB;IAEhB,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;IAE7B,OAAO,wBAAwB,CAAC,EAAC,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAC,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAA6B;IAC5D,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import {useMobile} from '@gravity-ui/uikit';\n\n// `xxs` only exists on `Label`, which uikit 7.48 gained. It is listed here so that the helpers\n// stay usable with the whole `LabelProps['size']` union across the supported uikit range.\nexport type ControlSize = 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl';\n\n/**\n * Resolves a control size: an explicit size always wins, otherwise the mobile\n * default is used in mobile mode and the desktop default elsewhere.\n */\nexport function resolveMobileControlSize<T extends ControlSize>(params: {\n size: T | undefined;\n desktopDefault: T;\n mobileDefault: T;\n isMobile: boolean;\n}): T {\n const {size, desktopDefault, mobileDefault, isMobile} = params;\n\n return size ?? (isMobile ? mobileDefault : desktopDefault);\n}\n\n/**\n * Mobile-aware control size, driven by the uikit `MobileProvider` context.\n */\nexport function useMobileControlSize<T extends ControlSize>(\n size: T | undefined,\n desktopDefault: T,\n mobileDefault: T,\n): T {\n const isMobile = useMobile();\n\n return resolveMobileControlSize({size, desktopDefault, mobileDefault, isMobile});\n}\n\n/**\n * Icon size matching the resolved control size.\n */\nexport function getControlIconSize(size: ControlSize | undefined): number {\n return size === 'xl' ? 20 : 16;\n}\n"]}
@@ -1 +1 @@
1
- {"version":"2.20.1","type":"module","sideEffects":["*.css","*.scss"]}
1
+ {"version":"2.20.2-beta.079381cf5bff4083d73b5fa37c58ece5ae3b69bc.0","type":"module","sideEffects":["*.css","*.scss"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/aikit",
3
- "version": "2.20.1",
3
+ "version": "2.20.2-beta.079381cf5bff4083d73b5fa37c58ece5ae3b69bc.0",
4
4
  "description": "Gravity UI base kit for building ai assistant chats",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -745,7 +745,7 @@
745
745
  "@gravity-ui/readme-validator": "^1.3.0",
746
746
  "@gravity-ui/stylelint-config": "^4.0.1",
747
747
  "@gravity-ui/tsconfig": "^1.0.0",
748
- "@gravity-ui/uikit": "^7.25.0",
748
+ "@gravity-ui/uikit": "^7.48.3",
749
749
  "@playwright/experimental-ct-react": "^1.56.1",
750
750
  "@playwright/test": "^1.56.1",
751
751
  "@storybook/addon-docs": "^9.0.5",