@cloud-ru/ds-ai-suggestion 1.0.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 (98) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +201 -0
  3. package/README.md +226 -0
  4. package/dist/cjs/AiSuggestionParent/AiSuggestionParent.d.ts +7 -0
  5. package/dist/cjs/AiSuggestionParent/AiSuggestionParent.js +107 -0
  6. package/dist/cjs/AiSuggestionParent/AiSuggestionParentChip.d.ts +26 -0
  7. package/dist/cjs/AiSuggestionParent/AiSuggestionParentChip.js +24 -0
  8. package/dist/cjs/AiSuggestionParent/animation/AnimatedExpandableItem.d.ts +12 -0
  9. package/dist/cjs/AiSuggestionParent/animation/AnimatedExpandableItem.js +24 -0
  10. package/dist/cjs/AiSuggestionParent/animation/constants.d.ts +33 -0
  11. package/dist/cjs/AiSuggestionParent/animation/constants.js +69 -0
  12. package/dist/cjs/AiSuggestionParent/animation/styles.module.css +23 -0
  13. package/dist/cjs/AiSuggestionParent/constants.d.ts +9 -0
  14. package/dist/cjs/AiSuggestionParent/constants.js +12 -0
  15. package/dist/cjs/AiSuggestionParent/context/AiSuggestionParentGroupContext.d.ts +13 -0
  16. package/dist/cjs/AiSuggestionParent/context/AiSuggestionParentGroupContext.js +25 -0
  17. package/dist/cjs/AiSuggestionParent/index.d.ts +4 -0
  18. package/dist/cjs/AiSuggestionParent/index.js +24 -0
  19. package/dist/cjs/AiSuggestionParent/styles.module.css +156 -0
  20. package/dist/cjs/AiSuggestionParent/types.d.ts +44 -0
  21. package/dist/cjs/AiSuggestionParent/types.js +2 -0
  22. package/dist/cjs/AiSuggestionParent/utils/hasExclusiveParentGroup.d.ts +2 -0
  23. package/dist/cjs/AiSuggestionParent/utils/hasExclusiveParentGroup.js +7 -0
  24. package/dist/cjs/AiSuggestionParent/utils/itemGuards.d.ts +3 -0
  25. package/dist/cjs/AiSuggestionParent/utils/itemGuards.js +11 -0
  26. package/dist/cjs/AiSuggestionSimple/AiSuggestionSimple.d.ts +18 -0
  27. package/dist/cjs/AiSuggestionSimple/AiSuggestionSimple.js +17 -0
  28. package/dist/cjs/AiSuggestionSimple/constants.d.ts +18 -0
  29. package/dist/cjs/AiSuggestionSimple/constants.js +21 -0
  30. package/dist/cjs/AiSuggestionSimple/index.d.ts +3 -0
  31. package/dist/cjs/AiSuggestionSimple/index.js +24 -0
  32. package/dist/cjs/AiSuggestionSimple/styles.module.css +138 -0
  33. package/dist/cjs/AiSuggestionSimple/types.d.ts +5 -0
  34. package/dist/cjs/AiSuggestionSimple/types.js +2 -0
  35. package/dist/cjs/AiSuggestionSimple/utils.d.ts +2 -0
  36. package/dist/cjs/AiSuggestionSimple/utils.js +7 -0
  37. package/dist/cjs/index.d.ts +2 -0
  38. package/dist/cjs/index.js +18 -0
  39. package/dist/cjs/package.json +3 -0
  40. package/dist/cjs/style.css +317 -0
  41. package/dist/esm/AiSuggestionParent/AiSuggestionParent.d.ts +7 -0
  42. package/dist/esm/AiSuggestionParent/AiSuggestionParent.js +101 -0
  43. package/dist/esm/AiSuggestionParent/AiSuggestionParentChip.d.ts +26 -0
  44. package/dist/esm/AiSuggestionParent/AiSuggestionParentChip.js +18 -0
  45. package/dist/esm/AiSuggestionParent/animation/AnimatedExpandableItem.d.ts +12 -0
  46. package/dist/esm/AiSuggestionParent/animation/AnimatedExpandableItem.js +17 -0
  47. package/dist/esm/AiSuggestionParent/animation/constants.d.ts +33 -0
  48. package/dist/esm/AiSuggestionParent/animation/constants.js +63 -0
  49. package/dist/esm/AiSuggestionParent/animation/styles.module.css +23 -0
  50. package/dist/esm/AiSuggestionParent/constants.d.ts +9 -0
  51. package/dist/esm/AiSuggestionParent/constants.js +9 -0
  52. package/dist/esm/AiSuggestionParent/context/AiSuggestionParentGroupContext.d.ts +13 -0
  53. package/dist/esm/AiSuggestionParent/context/AiSuggestionParentGroupContext.js +21 -0
  54. package/dist/esm/AiSuggestionParent/index.d.ts +4 -0
  55. package/dist/esm/AiSuggestionParent/index.js +4 -0
  56. package/dist/esm/AiSuggestionParent/styles.module.css +156 -0
  57. package/dist/esm/AiSuggestionParent/types.d.ts +44 -0
  58. package/dist/esm/AiSuggestionParent/types.js +1 -0
  59. package/dist/esm/AiSuggestionParent/utils/hasExclusiveParentGroup.d.ts +2 -0
  60. package/dist/esm/AiSuggestionParent/utils/hasExclusiveParentGroup.js +4 -0
  61. package/dist/esm/AiSuggestionParent/utils/itemGuards.d.ts +3 -0
  62. package/dist/esm/AiSuggestionParent/utils/itemGuards.js +7 -0
  63. package/dist/esm/AiSuggestionSimple/AiSuggestionSimple.d.ts +18 -0
  64. package/dist/esm/AiSuggestionSimple/AiSuggestionSimple.js +11 -0
  65. package/dist/esm/AiSuggestionSimple/constants.d.ts +18 -0
  66. package/dist/esm/AiSuggestionSimple/constants.js +18 -0
  67. package/dist/esm/AiSuggestionSimple/index.d.ts +3 -0
  68. package/dist/esm/AiSuggestionSimple/index.js +3 -0
  69. package/dist/esm/AiSuggestionSimple/styles.module.css +138 -0
  70. package/dist/esm/AiSuggestionSimple/types.d.ts +5 -0
  71. package/dist/esm/AiSuggestionSimple/types.js +1 -0
  72. package/dist/esm/AiSuggestionSimple/utils.d.ts +2 -0
  73. package/dist/esm/AiSuggestionSimple/utils.js +4 -0
  74. package/dist/esm/index.d.ts +2 -0
  75. package/dist/esm/index.js +2 -0
  76. package/dist/esm/style.css +317 -0
  77. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  78. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  79. package/package.json +45 -0
  80. package/src/AiSuggestionParent/AiSuggestionParent.tsx +257 -0
  81. package/src/AiSuggestionParent/AiSuggestionParentChip.tsx +79 -0
  82. package/src/AiSuggestionParent/animation/AnimatedExpandableItem.tsx +53 -0
  83. package/src/AiSuggestionParent/animation/constants.ts +77 -0
  84. package/src/AiSuggestionParent/animation/styles.module.scss +25 -0
  85. package/src/AiSuggestionParent/constants.ts +10 -0
  86. package/src/AiSuggestionParent/context/AiSuggestionParentGroupContext.tsx +44 -0
  87. package/src/AiSuggestionParent/index.ts +4 -0
  88. package/src/AiSuggestionParent/styles.module.scss +197 -0
  89. package/src/AiSuggestionParent/types.ts +49 -0
  90. package/src/AiSuggestionParent/utils/hasExclusiveParentGroup.ts +6 -0
  91. package/src/AiSuggestionParent/utils/itemGuards.ts +10 -0
  92. package/src/AiSuggestionSimple/AiSuggestionSimple.tsx +72 -0
  93. package/src/AiSuggestionSimple/constants.ts +21 -0
  94. package/src/AiSuggestionSimple/index.ts +3 -0
  95. package/src/AiSuggestionSimple/styles.module.scss +166 -0
  96. package/src/AiSuggestionSimple/types.ts +7 -0
  97. package/src/AiSuggestionSimple/utils.ts +6 -0
  98. package/src/index.ts +2 -0
@@ -0,0 +1,33 @@
1
+ import type { Transition } from 'framer-motion';
2
+ /**
3
+ * Animation contract — двухслойный chip + FLIP-spring layout (1:1 из ai-components).
4
+ *
5
+ * Per-property timing:
6
+ * width / marginRight / scale → sync, одна duration, один easing.
7
+ * opacity → со stagger (visual ripple).
8
+ * layout (FLIP) → spring (110, 22, 1).
9
+ *
10
+ * Длительности:
11
+ * enter width/scale → 650ms opacity → 450ms, stagger 60ms
12
+ * exit width/scale → 550ms opacity → 280ms, stagger 80ms
13
+ */
14
+ /** easings:
15
+ * enter — easeOutQuart
16
+ * exit — easeInQuart
17
+ * bubble — easeOutBack overshoot ~5% для inner scale
18
+ */
19
+ export declare const ENTER_EASE: Transition['ease'];
20
+ export declare const EXIT_EASE: Transition['ease'];
21
+ export declare const BUBBLE_ENTER_EASE: Transition['ease'];
22
+ export declare const ENTER_WIDTH_S = 0.65;
23
+ export declare const ENTER_OPACITY_S = 0.45;
24
+ export declare const EXIT_OPACITY_S = 0.28;
25
+ export declare const EXIT_WIDTH_S = 0.55;
26
+ export declare const STAGGER_FORWARD_OPACITY_S = 0.06;
27
+ export declare const STAGGER_BACKWARD_OPACITY_S = 0.08;
28
+ export declare const MAX_STAGGER_WINDOW_S = 0.5;
29
+ export declare const GAP_PX = 4;
30
+ export declare const layoutSpring: Transition;
31
+ export declare const cappedStagger: (idealPerChip: number, total: number, index: number) => number;
32
+ export declare const outerChipTransition: (activated: boolean) => Transition;
33
+ export declare const innerChipTransition: (index: number, total: number, activated: boolean) => Transition;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.innerChipTransition = exports.outerChipTransition = exports.cappedStagger = exports.layoutSpring = exports.GAP_PX = exports.MAX_STAGGER_WINDOW_S = exports.STAGGER_BACKWARD_OPACITY_S = exports.STAGGER_FORWARD_OPACITY_S = exports.EXIT_WIDTH_S = exports.EXIT_OPACITY_S = exports.ENTER_OPACITY_S = exports.ENTER_WIDTH_S = exports.BUBBLE_ENTER_EASE = exports.EXIT_EASE = exports.ENTER_EASE = void 0;
4
+ /**
5
+ * Animation contract — двухслойный chip + FLIP-spring layout (1:1 из ai-components).
6
+ *
7
+ * Per-property timing:
8
+ * width / marginRight / scale → sync, одна duration, один easing.
9
+ * opacity → со stagger (visual ripple).
10
+ * layout (FLIP) → spring (110, 22, 1).
11
+ *
12
+ * Длительности:
13
+ * enter width/scale → 650ms opacity → 450ms, stagger 60ms
14
+ * exit width/scale → 550ms opacity → 280ms, stagger 80ms
15
+ */
16
+ /** easings:
17
+ * enter — easeOutQuart
18
+ * exit — easeInQuart
19
+ * bubble — easeOutBack overshoot ~5% для inner scale
20
+ */
21
+ exports.ENTER_EASE = [0.22, 1, 0.36, 1];
22
+ exports.EXIT_EASE = [0.64, 0, 0.78, 0];
23
+ exports.BUBBLE_ENTER_EASE = [0.34, 1.5, 0.64, 1];
24
+ exports.ENTER_WIDTH_S = 0.65;
25
+ exports.ENTER_OPACITY_S = 0.45;
26
+ exports.EXIT_OPACITY_S = 0.28;
27
+ exports.EXIT_WIDTH_S = 0.55;
28
+ exports.STAGGER_FORWARD_OPACITY_S = 0.06;
29
+ exports.STAGGER_BACKWARD_OPACITY_S = 0.08;
30
+ exports.MAX_STAGGER_WINDOW_S = 0.5;
31
+ exports.GAP_PX = 4;
32
+ exports.layoutSpring = {
33
+ type: 'spring',
34
+ stiffness: 110,
35
+ damping: 22,
36
+ mass: 1,
37
+ };
38
+ const cappedStagger = (idealPerChip, total, index) => {
39
+ if (total <= 1) {
40
+ return 0;
41
+ }
42
+ const perChip = Math.min(idealPerChip, exports.MAX_STAGGER_WINDOW_S / (total - 1));
43
+ return index * perChip;
44
+ };
45
+ exports.cappedStagger = cappedStagger;
46
+ const sizeTransition = (activated) => ({
47
+ duration: activated ? exports.ENTER_WIDTH_S : exports.EXIT_WIDTH_S,
48
+ ease: activated ? exports.ENTER_EASE : exports.EXIT_EASE,
49
+ });
50
+ const outerChipTransition = (activated) => ({
51
+ width: sizeTransition(activated),
52
+ marginRight: sizeTransition(activated),
53
+ layout: exports.layoutSpring,
54
+ });
55
+ exports.outerChipTransition = outerChipTransition;
56
+ const innerChipTransition = (index, total, activated) => ({
57
+ scale: {
58
+ duration: activated ? exports.ENTER_WIDTH_S : exports.EXIT_WIDTH_S,
59
+ ease: activated ? exports.BUBBLE_ENTER_EASE : exports.EXIT_EASE,
60
+ },
61
+ opacity: {
62
+ duration: activated ? exports.ENTER_OPACITY_S : exports.EXIT_OPACITY_S,
63
+ ease: activated ? exports.ENTER_EASE : exports.EXIT_EASE,
64
+ delay: activated
65
+ ? (0, exports.cappedStagger)(exports.STAGGER_FORWARD_OPACITY_S, total, index)
66
+ : (0, exports.cappedStagger)(exports.STAGGER_BACKWARD_OPACITY_S, total, total - 1 - index),
67
+ },
68
+ });
69
+ exports.innerChipTransition = innerChipTransition;
@@ -0,0 +1,23 @@
1
+ .outerChip{
2
+ contain:layout;
3
+ display:inline-flex;
4
+ flex-shrink:0;
5
+ align-items:center;
6
+ justify-content:center;
7
+ }
8
+
9
+ .innerChip{
10
+ will-change:transform, opacity;
11
+ transform-origin:center;
12
+ display:inline-flex;
13
+ }
14
+
15
+ .innerChipHidden{
16
+ pointer-events:none;
17
+ }
18
+
19
+ .triggerWrap{
20
+ display:inline-flex;
21
+ flex-shrink:0;
22
+ margin-right:var(--sn-primitive-dimension-4, 4px);
23
+ }
@@ -0,0 +1,9 @@
1
+ export declare const CHILD_TYPE: {
2
+ readonly Suggestion: "suggestion";
3
+ readonly Parent: "parent";
4
+ };
5
+ export declare const TEST_IDS: {
6
+ readonly root: "ai-suggestion-parent";
7
+ readonly trigger: "ai-suggestion-parent__trigger";
8
+ readonly chevron: "ai-suggestion-parent__chevron";
9
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TEST_IDS = exports.CHILD_TYPE = void 0;
4
+ exports.CHILD_TYPE = {
5
+ Suggestion: 'suggestion',
6
+ Parent: 'parent',
7
+ };
8
+ exports.TEST_IDS = {
9
+ root: 'ai-suggestion-parent',
10
+ trigger: 'ai-suggestion-parent__trigger',
11
+ chevron: 'ai-suggestion-parent__chevron',
12
+ };
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ type AiSuggestionParentGroupContextValue = {
3
+ expandedKey: string | null;
4
+ requestExpand(key: string): void;
5
+ collapseKey(key: string): void;
6
+ };
7
+ export type AiSuggestionParentGroupProviderProps = {
8
+ children: ReactNode;
9
+ initialExpandedKey?: string | null;
10
+ };
11
+ export declare function AiSuggestionParentGroupProvider({ children, initialExpandedKey, }: AiSuggestionParentGroupProviderProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare function useAiSuggestionParentGroup(): AiSuggestionParentGroupContextValue | null;
13
+ export {};
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AiSuggestionParentGroupProvider = AiSuggestionParentGroupProvider;
4
+ exports.useAiSuggestionParentGroup = useAiSuggestionParentGroup;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const AiSuggestionParentGroupContext = (0, react_1.createContext)(null);
8
+ function AiSuggestionParentGroupProvider({ children, initialExpandedKey = null, }) {
9
+ const [expandedKey, setExpandedKey] = (0, react_1.useState)(initialExpandedKey);
10
+ const requestExpand = (0, react_1.useCallback)((key) => {
11
+ setExpandedKey(prev => (prev === key ? null : key));
12
+ }, []);
13
+ const collapseKey = (0, react_1.useCallback)((key) => {
14
+ setExpandedKey(prev => (prev === key ? null : prev));
15
+ }, []);
16
+ const value = (0, react_1.useMemo)(() => ({
17
+ expandedKey,
18
+ requestExpand,
19
+ collapseKey,
20
+ }), [collapseKey, expandedKey, requestExpand]);
21
+ return (0, jsx_runtime_1.jsx)(AiSuggestionParentGroupContext.Provider, { value: value, children: children });
22
+ }
23
+ function useAiSuggestionParentGroup() {
24
+ return (0, react_1.useContext)(AiSuggestionParentGroupContext);
25
+ }
@@ -0,0 +1,4 @@
1
+ export * from './AiSuggestionParent';
2
+ export { AiSuggestionParentChip } from './AiSuggestionParentChip';
3
+ export { CHILD_TYPE, TEST_IDS as AI_SUGGESTION_PARENT_TEST_IDS } from './constants';
4
+ export * from './types';
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.AI_SUGGESTION_PARENT_TEST_IDS = exports.CHILD_TYPE = exports.AiSuggestionParentChip = void 0;
18
+ __exportStar(require("./AiSuggestionParent"), exports);
19
+ var AiSuggestionParentChip_1 = require("./AiSuggestionParentChip");
20
+ Object.defineProperty(exports, "AiSuggestionParentChip", { enumerable: true, get: function () { return AiSuggestionParentChip_1.AiSuggestionParentChip; } });
21
+ var constants_1 = require("./constants");
22
+ Object.defineProperty(exports, "CHILD_TYPE", { enumerable: true, get: function () { return constants_1.CHILD_TYPE; } });
23
+ Object.defineProperty(exports, "AI_SUGGESTION_PARENT_TEST_IDS", { enumerable: true, get: function () { return constants_1.TEST_IDS; } });
24
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,156 @@
1
+ .root{
2
+ display:flex;
3
+ flex-wrap:wrap;
4
+ row-gap:var(--sn-primitive-dimension-4, 4px);
5
+ align-items:center;
6
+ min-width:0;
7
+ max-width:100%;
8
+ }
9
+
10
+ .root[data-flatten]{
11
+ display:contents;
12
+ }
13
+
14
+ .label{
15
+ overflow:hidden;
16
+ text-overflow:ellipsis;
17
+ white-space:nowrap;
18
+ }
19
+
20
+ .icon{
21
+ color:currentcolor;
22
+ }
23
+
24
+ .chevron{
25
+ display:flex;
26
+ flex-shrink:0;
27
+ align-items:center;
28
+ justify-content:center;
29
+ width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
30
+ height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
31
+ color:currentcolor;
32
+ }
33
+
34
+ .chip{
35
+ cursor:pointer;
36
+ position:relative;
37
+ display:inline-flex;
38
+ flex-shrink:0;
39
+ align-items:center;
40
+ justify-content:center;
41
+ box-sizing:border-box;
42
+ margin:0;
43
+ padding:0;
44
+ border:var(--sn-primitive-strokeWeight-strokeRegular, 1px) solid var(--sn-theme-color-material-stateLayer-neutral-border-default-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843)));
45
+ border-radius:var(--sn-primitive-dimension-full, 10000px);
46
+ font-family:inherit;
47
+ text-decoration:none;
48
+ background-color:var(--sn-theme-color-neutral-background1Level, var(--sn-brand-color-neutral-95, var(--sn-primitive-color-gray-95, #fdfdfd)));
49
+ outline:0;
50
+ outline-offset:0;
51
+ transition:background-color 450ms cubic-bezier(1, 0, 0.26, 0.7), border-color 450ms cubic-bezier(1, 0, 0.26, 0.7), color 450ms cubic-bezier(1, 0, 0.26, 0.7), outline-color 120ms ease;
52
+ }
53
+ .chip .icon,
54
+ .chip .label,
55
+ .chip .chevron{
56
+ color:var(--sn-theme-color-neutral-text, var(--sn-brand-color-neutral-45, var(--sn-primitive-color-gray-45, #81869c)));
57
+ }
58
+ .chip:disabled{
59
+ cursor:not-allowed;
60
+ opacity:var(--sn-theme-effect-opacity-disabled, 0.4);
61
+ }
62
+ .chip:not(:disabled):focus-visible{
63
+ outline:var(--sn-primitive-strokeWeight-strokeSemiBold, 2px) solid var(--sn-theme-color-primary-accent, var(--sn-brand-color-primary-55, var(--sn-brandRole-color-brandA-55, var(--sn-primitive-color-brandA-55, #389f74))));
64
+ outline-offset:0;
65
+ }
66
+ .chip[data-activated]{
67
+ border-color:var(--sn-theme-color-primary-accent, var(--sn-brand-color-primary-55, var(--sn-brandRole-color-brandA-55, var(--sn-primitive-color-brandA-55, #389f74))));
68
+ background-color:var(--sn-theme-color-primary-background1Level, var(--sn-brand-color-primary-95, var(--sn-brandRole-color-brandA-95, var(--sn-primitive-color-brandA-95, #f5fdf8))));
69
+ transition:background-color 450ms cubic-bezier(0.7, 0.26, 0, 1.58), border-color 450ms cubic-bezier(0.7, 0.26, 0, 1.58), color 450ms cubic-bezier(0.7, 0.26, 0, 1.58), outline-color 120ms ease;
70
+ }
71
+ .chip[data-activated] .icon,
72
+ .chip[data-activated] .label,
73
+ .chip[data-activated] .chevron{
74
+ color:var(--sn-theme-color-primary-text, var(--sn-brand-color-primary-45, var(--sn-brandRole-color-brandA-45, var(--sn-primitive-color-brandA-45, #22775b))));
75
+ }
76
+ @media (hover: hover){
77
+ .chip[data-activated]:hover:not(:disabled){
78
+ border-color:color-mix(in srgb, var(--sn-theme-color-primary-accent, var(--sn-brand-color-primary-55, var(--sn-brandRole-color-brandA-55, var(--sn-primitive-color-brandA-55, #389f74)))) 80%, transparent);
79
+ background-color:var(--sn-theme-color-primary-background2Level, var(--sn-brand-color-primary-99, var(--sn-brandRole-color-brandA-99, var(--sn-primitive-color-brandA-99, #fbfffc))));
80
+ }
81
+ }
82
+ @media (hover: hover){
83
+ .chip:not([data-activated], :disabled):hover{
84
+ border-color:var(--sn-theme-color-material-stateLayer-neutral-border-hovered-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-hovered-borderColor, rgba(159, 166, 198, 0.6509803922)));
85
+ }
86
+ }
87
+ .chip[data-size=s]{
88
+ font-family:var(--sn-regular-label-m-fontFamily, var(--sn-brand-font-fontFamily-regular-label, var(--sn-primitive-fontFamily-brandA-sans, SB Sans Interface)));
89
+ font-weight:var(--sn-regular-label-m-fontWeight, var(--sn-theme-typography-fontWeight-regular-label-m, var(--sn-brand-font-fontWeight-light-regular-label-m, var(--sn-primitive-font-fontWeightValue-550, 550))));
90
+ line-height:var(--sn-regular-label-m-lineHeight, var(--sn-density-typography-roleLabel-lineHeightM, var(--sn-primitive-font-lineHeight-by16, 24px)));
91
+ font-size:var(--sn-regular-label-m-fontSize, var(--sn-density-typography-roleLabel-fontSizeM, var(--sn-primitive-font-fontSize-16, 16px)));
92
+ letter-spacing:var(--sn-regular-label-m-letterSpacing, var(--sn-primitive-font-letterSpacing-s, 0px));
93
+ paragraph-spacing:var(--sn-regular-label-m-paragraphSpacing, var(--sn-primitive-font-paragraphSpacing-byFontSize12, 6px));
94
+ height:var(--sn-primitive-dimension-32, 32px);
95
+ padding-inline:var(--sn-primitive-dimension-4, 4px);
96
+ }
97
+ .chip[data-size=s] .icon{
98
+ display:flex;
99
+ flex-shrink:0;
100
+ align-items:center;
101
+ justify-content:center;
102
+ width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
103
+ height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
104
+ }
105
+ .chip[data-size=s] .icon > svg{
106
+ display:block;
107
+ width:100%;
108
+ height:100%;
109
+ }
110
+ .chip[data-size=s] .labelContainer{
111
+ padding-inline:var(--sn-primitive-dimension-4, 4px) var(--sn-primitive-dimension-0, 0);
112
+ }
113
+ .chip[data-size=m]{
114
+ font-family:var(--sn-regular-label-l-fontFamily, var(--sn-brand-font-fontFamily-regular-label, var(--sn-primitive-fontFamily-brandA-sans, SB Sans Interface)));
115
+ font-weight:var(--sn-regular-label-l-fontWeight, var(--sn-theme-typography-fontWeight-regular-label-l, var(--sn-brand-font-fontWeight-light-regular-label-l, var(--sn-primitive-font-fontWeightValue-550, 550))));
116
+ line-height:var(--sn-regular-label-l-lineHeight, var(--sn-density-typography-roleLabel-lineHeightL, var(--sn-primitive-font-lineHeight-by20, 28px)));
117
+ font-size:var(--sn-regular-label-l-fontSize, var(--sn-density-typography-roleLabel-fontSizeL, var(--sn-primitive-font-fontSize-20, 20px)));
118
+ letter-spacing:var(--sn-regular-label-l-letterSpacing, var(--sn-primitive-font-letterSpacing-s, 0px));
119
+ paragraph-spacing:var(--sn-regular-label-l-paragraphSpacing, var(--sn-primitive-font-paragraphSpacing-byFontSize14, 7px));
120
+ height:var(--sn-primitive-dimension-40, 40px);
121
+ padding-inline:var(--sn-primitive-dimension-8, 8px);
122
+ }
123
+ .chip[data-size=m] .icon{
124
+ display:flex;
125
+ flex-shrink:0;
126
+ align-items:center;
127
+ justify-content:center;
128
+ width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
129
+ height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
130
+ }
131
+ .chip[data-size=m] .icon > svg{
132
+ display:block;
133
+ width:100%;
134
+ height:100%;
135
+ }
136
+ .chip[data-size=m] .labelContainer{
137
+ padding-inline:var(--sn-primitive-dimension-8, 8px) var(--sn-primitive-dimension-2, 2px);
138
+ }
139
+
140
+ .labelContainer{
141
+ display:inline-flex;
142
+ align-items:center;
143
+ justify-content:center;
144
+ }
145
+
146
+ .chevronIcon{
147
+ display:block;
148
+ max-width:100%;
149
+ max-height:100%;
150
+ transition:transform 450ms cubic-bezier(1, 0, 0.26, 0.7);
151
+ }
152
+
153
+ .chip[data-activated] .chevronIcon{
154
+ transform:rotate(90deg);
155
+ transition:transform 450ms cubic-bezier(0.7, 0.26, 0, 1.58);
156
+ }
@@ -0,0 +1,44 @@
1
+ import { WithSupportProps } from '@cloud-ru/ds-utils';
2
+ import { MouseEvent, ReactNode } from 'react';
3
+ import { Size } from '../AiSuggestionSimple/types';
4
+ import { CHILD_TYPE } from './constants';
5
+ export type AiSuggestionParentProps = WithSupportProps<{
6
+ /** Текст на триггере */
7
+ label?: string;
8
+ /** Иконка слева от текста */
9
+ icon?: ReactNode;
10
+ /** Размер (Figma: Mobile Off → `s`, Mobile On → `m`) */
11
+ size?: Size;
12
+ /** Блокирует взаимодействие */
13
+ disabled?: boolean;
14
+ /** Controlled — раскрыт (Figma: Activated=On) */
15
+ expanded?: boolean;
16
+ /** Uncontrolled — initial expanded */
17
+ defaultExpanded?: boolean;
18
+ /** Колбэк toggle (controlled и uncontrolled) */
19
+ onExpandedChange?(expanded: boolean): void;
20
+ /** Вложенные подсказки и группы */
21
+ items?: AiSuggestionParentItem[];
22
+ /** Колбэк клика по вложенной подсказке */
23
+ onItemClick?(index: number, event: MouseEvent<HTMLButtonElement>): void;
24
+ /** Дополнительный CSS-класс */
25
+ className?: string;
26
+ }>;
27
+ export type AiSuggestionParentSuggestionItem = {
28
+ type?: typeof CHILD_TYPE.Suggestion;
29
+ key?: string;
30
+ items?: never;
31
+ label?: string;
32
+ icon?: ReactNode;
33
+ disabled?: boolean;
34
+ onClick?(event: MouseEvent<HTMLButtonElement>): void;
35
+ };
36
+ export type AiSuggestionParentNestedItem = {
37
+ type?: typeof CHILD_TYPE.Parent;
38
+ key?: string;
39
+ label?: string;
40
+ icon?: ReactNode;
41
+ disabled?: boolean;
42
+ items?: AiSuggestionParentItem[];
43
+ };
44
+ export type AiSuggestionParentItem = AiSuggestionParentSuggestionItem | AiSuggestionParentNestedItem;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import { AiSuggestionParentItem } from '../types';
2
+ export declare function hasExclusiveParentGroup(items: AiSuggestionParentItem[]): boolean;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasExclusiveParentGroup = hasExclusiveParentGroup;
4
+ const itemGuards_1 = require("./itemGuards");
5
+ function hasExclusiveParentGroup(items) {
6
+ return items.filter(itemGuards_1.isNestedItem).length >= 2;
7
+ }
@@ -0,0 +1,3 @@
1
+ import { AiSuggestionParentItem, AiSuggestionParentNestedItem, AiSuggestionParentSuggestionItem } from '../types';
2
+ export declare function isNestedItem(item: AiSuggestionParentItem): item is AiSuggestionParentNestedItem;
3
+ export declare function isSuggestionItem(item: AiSuggestionParentItem): item is AiSuggestionParentSuggestionItem;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isNestedItem = isNestedItem;
4
+ exports.isSuggestionItem = isSuggestionItem;
5
+ const constants_1 = require("../constants");
6
+ function isNestedItem(item) {
7
+ return item.type === constants_1.CHILD_TYPE.Parent || item.items !== undefined;
8
+ }
9
+ function isSuggestionItem(item) {
10
+ return !isNestedItem(item);
11
+ }
@@ -0,0 +1,18 @@
1
+ import { WithSupportProps } from '@cloud-ru/ds-utils';
2
+ import { ButtonHTMLAttributes, ReactNode } from 'react';
3
+ import { Appearance, Size } from './types';
4
+ export type AiSuggestionSimpleProps = WithSupportProps<{
5
+ /** Текст подсказки */
6
+ label?: string;
7
+ /** Иконка слева от текста */
8
+ icon?: ReactNode;
9
+ /** Внешний вид (Figma: Primary On/Off) */
10
+ appearance?: Appearance;
11
+ /** Размер (Figma: Mobile Off → `s`, Mobile On → `m`) */
12
+ size?: Size;
13
+ /** Блокирует взаимодействие */
14
+ disabled?: boolean;
15
+ /** Дополнительный CSS-класс */
16
+ className?: string;
17
+ }> & Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'tabIndex' | 'onClick'>;
18
+ export declare function AiSuggestionSimple({ label, icon, appearance, size, disabled, tabIndex, onClick, className, ...rest }: AiSuggestionSimpleProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AiSuggestionSimple = AiSuggestionSimple;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const utils_1 = require("@cloud-ru/ds-utils");
9
+ const classnames_1 = __importDefault(require("classnames"));
10
+ const constants_1 = require("./constants");
11
+ const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
12
+ const utils_2 = require("./utils");
13
+ function AiSuggestionSimple({ label = 'Label text', icon, appearance = constants_1.APPEARANCE.Neutral, size = constants_1.SIZE.S, disabled = false, tabIndex, onClick, className, ...rest }) {
14
+ const layerState = (0, utils_2.getLayerState)(appearance);
15
+ const rootTestId = rest['data-test-id'] ?? constants_1.TEST_IDS.root;
16
+ return ((0, jsx_runtime_1.jsxs)("button", { type: 'button', className: (0, classnames_1.default)(styles_module_scss_1.default.chip, className), ...(0, utils_1.extractSupportProps)(rest), "data-size": size, "data-appearance": appearance, "data-disabled": disabled || undefined, "data-test-id": rootTestId, disabled: disabled, tabIndex: tabIndex, onClick: disabled ? undefined : onClick, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.stateLayer, "aria-hidden": true, "data-state": layerState }), (0, jsx_runtime_1.jsxs)("span", { className: styles_module_scss_1.default.content, children: [icon && ((0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.icon, "data-test-id": constants_1.TEST_IDS.icon, children: icon })), label && ((0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.labelContainer, children: (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.label, "data-test-id": constants_1.TEST_IDS.label, children: label }) }))] })] }));
17
+ }
@@ -0,0 +1,18 @@
1
+ export declare const SIZE: {
2
+ readonly S: "s";
3
+ readonly M: "m";
4
+ };
5
+ export declare const APPEARANCE: {
6
+ readonly Primary: "primary";
7
+ readonly Neutral: "neutral";
8
+ };
9
+ export declare const TEST_IDS: {
10
+ readonly root: "ai-suggestion-simple";
11
+ readonly chip: "ai-suggestion-simple__chip";
12
+ readonly icon: "ai-suggestion-simple__icon";
13
+ readonly label: "ai-suggestion-simple__label";
14
+ };
15
+ export declare const LAYER_STATE: {
16
+ readonly ActivatedOnBackground: "activatedOnBackground";
17
+ readonly EmptyNeutralOnBackground: "emptyNeutralOnBackground";
18
+ };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LAYER_STATE = exports.TEST_IDS = exports.APPEARANCE = exports.SIZE = void 0;
4
+ exports.SIZE = {
5
+ S: 's',
6
+ M: 'm',
7
+ };
8
+ exports.APPEARANCE = {
9
+ Primary: 'primary',
10
+ Neutral: 'neutral',
11
+ };
12
+ exports.TEST_IDS = {
13
+ root: 'ai-suggestion-simple',
14
+ chip: 'ai-suggestion-simple__chip',
15
+ icon: 'ai-suggestion-simple__icon',
16
+ label: 'ai-suggestion-simple__label',
17
+ };
18
+ exports.LAYER_STATE = {
19
+ ActivatedOnBackground: 'activatedOnBackground',
20
+ EmptyNeutralOnBackground: 'emptyNeutralOnBackground',
21
+ };
@@ -0,0 +1,3 @@
1
+ export * from './AiSuggestionSimple';
2
+ export { APPEARANCE, LAYER_STATE, SIZE, TEST_IDS as AI_SUGGESTION_SIMPLE_TEST_IDS } from './constants';
3
+ export * from './types';
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.AI_SUGGESTION_SIMPLE_TEST_IDS = exports.SIZE = exports.LAYER_STATE = exports.APPEARANCE = void 0;
18
+ __exportStar(require("./AiSuggestionSimple"), exports);
19
+ var constants_1 = require("./constants");
20
+ Object.defineProperty(exports, "APPEARANCE", { enumerable: true, get: function () { return constants_1.APPEARANCE; } });
21
+ Object.defineProperty(exports, "LAYER_STATE", { enumerable: true, get: function () { return constants_1.LAYER_STATE; } });
22
+ Object.defineProperty(exports, "SIZE", { enumerable: true, get: function () { return constants_1.SIZE; } });
23
+ Object.defineProperty(exports, "AI_SUGGESTION_SIMPLE_TEST_IDS", { enumerable: true, get: function () { return constants_1.TEST_IDS; } });
24
+ __exportStar(require("./types"), exports);