cozy-search 2.6.2 → 2.7.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 (58) hide show
  1. package/dist/components/Assistant/AssistantAvatar.js +3 -1
  2. package/dist/components/Assistant/AssistantContainer.js +3 -1
  3. package/dist/components/Assistant/AssistantMenu.d.ts +16 -0
  4. package/dist/components/Assistant/AssistantMenu.js +160 -0
  5. package/dist/components/Assistant/AssistantSelection.d.ts +12 -1
  6. package/dist/components/Assistant/AssistantSelection.js +55 -115
  7. package/dist/components/Assistant/AssistantSelectionItem.js +3 -1
  8. package/dist/components/Assistant/AssistantSidebarItem.d.ts +9 -0
  9. package/dist/components/Assistant/AssistantSidebarItem.js +108 -0
  10. package/dist/components/Assistant/styles.styl +13 -0
  11. package/dist/components/Conversations/Conversation.js +74 -14
  12. package/dist/components/Conversations/ConversationBar.js +13 -5
  13. package/dist/components/Conversations/ConversationComposer.js +53 -23
  14. package/dist/components/Conversations/ConversationListItem.js +20 -40
  15. package/dist/components/Conversations/ConversationListItemWider.js +14 -11
  16. package/dist/components/Conversations/styles.styl +110 -23
  17. package/dist/components/CozyAssistantRuntimeProvider.js +15 -8
  18. package/dist/components/CreateAssistantSteps/BasicInfoStep.js +37 -1
  19. package/dist/components/CreateAssistantSteps/Provider.js +1 -0
  20. package/dist/components/CreateAssistantSteps/ProviderSelectionStep.js +1 -0
  21. package/dist/components/CreateAssistantSteps/styles.styl +14 -0
  22. package/dist/components/KnowledgeBase/FolderPickerDialog.js +3 -1
  23. package/dist/components/KnowledgeBase/KnowledgeBaseChip.d.ts +7 -5
  24. package/dist/components/KnowledgeBase/KnowledgeBaseChip.js +65 -31
  25. package/dist/components/KnowledgeBase/conversationAssistant.d.ts +2 -1
  26. package/dist/components/KnowledgeBase/conversationAssistant.js +6 -1
  27. package/dist/components/KnowledgeBase/conversationAssistant.spec.js +24 -0
  28. package/dist/components/KnowledgeBase/styles.styl +18 -0
  29. package/dist/components/Messages/AssistantMessage.js +25 -21
  30. package/dist/components/Messages/UserMessage.js +4 -1
  31. package/dist/components/Messages/styles.styl +41 -0
  32. package/dist/components/Search/SearchBarMobile.js +13 -5
  33. package/dist/components/Sidebar/index.js +55 -30
  34. package/dist/components/Sidebar/styles.styl +12 -11
  35. package/dist/components/TwakeKnowledges/SourceButton.d.ts +14 -0
  36. package/dist/components/TwakeKnowledges/SourceButton.js +98 -0
  37. package/dist/components/TwakeKnowledges/TwakeKnowledgeSelector.d.ts +9 -0
  38. package/dist/components/TwakeKnowledges/TwakeKnowledgeSelector.js +75 -50
  39. package/dist/components/TwakeKnowledges/styles.styl +29 -2
  40. package/dist/components/Views/AssistantView.js +9 -1
  41. package/dist/components/Views/CreateAssistantDialog.js +5 -1
  42. package/dist/components/Views/DeleteAssistantDialog.js +1 -0
  43. package/dist/components/Views/EditAssistantDialog.js +5 -1
  44. package/dist/hooks/useConversation.d.ts +2 -2
  45. package/dist/hooks/useConversation.js +25 -4
  46. package/dist/hooks/useConversation.spec.js +14 -2
  47. package/dist/hooks/useConversation.spec.jsx +21 -3
  48. package/dist/locales/en.json +5 -1
  49. package/dist/locales/fr.json +6 -2
  50. package/dist/locales/index.js +21 -5
  51. package/dist/locales/ru.json +5 -1
  52. package/dist/locales/vi.json +5 -1
  53. package/dist/stylesheet.css +253 -30
  54. package/package.json +2 -2
  55. package/dist/components/TwakeKnowledges/TwakeKnowledgeChip.d.ts +0 -13
  56. package/dist/components/TwakeKnowledges/TwakeKnowledgeChip.js +0 -80
  57. package/dist/components/TwakeKnowledges/WebSearchChip.d.ts +0 -5
  58. package/dist/components/TwakeKnowledges/WebSearchChip.js +0 -75
@@ -2,16 +2,67 @@
2
2
 
3
3
  .composerContainer
4
4
  position relative
5
- border 1px solid var(--borderMainColor)
6
- border-radius 20px
7
- padding 8px 8px 8px 16px
5
+ border 1px solid var(--borderGhostDisabledColor)
6
+ border-radius 16px
7
+ padding 12px 12px 12px 16px
8
8
  background-color var(--paperBackgroundColor)
9
+ box-shadow 0 1px 2px 0 rgba(0, 0, 0, 0.05)
9
10
  z-index calc(var(--zIndex-modal) + 15)
10
11
 
12
+ &--mobile
13
+ // The design's "Overlay+Shadow": a 1px ring and two soft shadows
14
+ // instead of a border
15
+ border-color transparent
16
+ border-radius 28px
17
+ padding-bottom 8px
18
+ box-shadow 0 0 0 1px rgba(0, 0, 0, 0.04), 0 2px 8px 0 rgba(0, 0, 0, 0.04), 0 4px 40px 8px rgba(0, 0, 0, 0.02)
19
+
20
+ &--mobile-dark
21
+ // The shadows vanish on a dark background: keep a border there
22
+ border-color var(--borderMainColor)
23
+
24
+ .composer-dock
25
+ // The composer and the disclaimer sit on a fade: the conversation runs
26
+ // under them and dissolves into the background over the 32px above the
27
+ // composer (the design's gradient background)
28
+ position relative
29
+ z-index calc(var(--zIndex-modal) + 15)
30
+ margin-top -32px
31
+ padding-top 32px
32
+ background linear-gradient(to top, var(--paperBackgroundColor) calc(100% - 32px), transparent)
33
+
11
34
  .composerActions
12
- margin-top 16px
35
+ margin-top 12px
13
36
  gap 8px
14
37
 
38
+ .welcome
39
+ // Room for the halo, which is larger than the title
40
+ min-height 166px
41
+
42
+ .welcome-halo
43
+ // The blurred pastel gradient behind the welcome title. Purely
44
+ // decorative, so its colors are the design's, not theme tokens; in the
45
+ // dark theme it is dimmed to a soft glow.
46
+ position absolute
47
+ top 50%
48
+ left 50%
49
+ width 100%
50
+ max-width 629px
51
+ height 166px
52
+ transform translate(-50%, -50%)
53
+ border-radius 9999px
54
+ opacity 0.5
55
+ filter blur(62.5px)
56
+ background linear-gradient(270deg, #c5ccfd 0%, #f0c7fc 21%, #f7bbe1 39%, #f5c7d2 62%, #fbe3b9 82%, #fcd8a4 100%)
57
+ pointer-events none
58
+
59
+ &--dark
60
+ opacity 0.2
61
+
62
+ .welcome-title
63
+ font-size 32px
64
+ line-height 40px
65
+
15
66
  .conversationBar
16
67
  flex 1
17
68
  min-width 0
@@ -27,14 +78,43 @@
27
78
  background-color transparent !important
28
79
  border-color transparent !important
29
80
 
81
+ .viewport-fade-top
82
+ // Under the 48px sidebar bar of mobile: the text scrolled under the bar
83
+ // dissolves over 24px instead of being cut at its edge. Hidden while
84
+ // the conversation is at the top of its scroll.
85
+ position absolute
86
+ top 48px
87
+ left 0
88
+ right 0
89
+ height 24px
90
+ background linear-gradient(to bottom, var(--paperBackgroundColor), transparent)
91
+ opacity 0
92
+ transition opacity 150ms
93
+ pointer-events none
94
+ z-index calc(var(--zIndex-modal) + 15)
95
+
96
+ &--visible
97
+ opacity 1
98
+
30
99
  .conversationViewport
31
100
  +mobile()
32
101
  // Small symmetric gutter so the LLM response uses nearly the full
33
- // mobile width. The floating sidebar-toggle button sits on an opaque
34
- // tile, so text scrolling beneath it stays visually covered.
102
+ // mobile width
35
103
  padding-left 8px
36
104
  padding-right 8px
37
105
 
106
+ // With messages only, so the welcome screen keeps its spacing
107
+ &--filled
108
+ // The bottom padding is the fade under the composer: the last lines
109
+ // can scroll clear of it
110
+ padding-bottom 32px
111
+
112
+ +mobile()
113
+ // The first message sits 8px below the 48px sidebar bar over the
114
+ // conversation (the message brings its own 16px margin); the text
115
+ // then scrolls under the bar
116
+ padding-top 40px
117
+
38
118
 
39
119
  .conversationBar-input
40
120
  max-height 80px
@@ -105,8 +185,13 @@
105
185
  hyphens auto
106
186
 
107
187
  .conversation-list-item
188
+ // A sidebar item of the design: 8px gutter, 5px vertical padding,
189
+ // 36px min height, 8px radius, selected on the action-selected color
108
190
  border-radius 8px !important
109
- align-items stretch !important
191
+ align-items center !important
192
+ min-height 36px !important
193
+ padding-top 5px !important
194
+ padding-bottom 5px !important
110
195
  // force 0 gap to override cozy-ui gap 16px on .MuiListItem-root
111
196
  gap: 0 !important
112
197
 
@@ -116,43 +201,45 @@
116
201
  pointer-events auto
117
202
 
118
203
  &--selected
119
- &--light
120
- background var(--primaryColorLightest) !important
121
- &--dark
122
- background var(--grey900) !important
204
+ background var(--actionColorSelected) !important
205
+
206
+ .conversation-list-item-action
207
+ opacity 1
208
+ pointer-events auto
123
209
 
124
210
  &--wider
125
211
  align-items center !important
126
212
 
127
- .conversation-list-item-divider
128
- // Counteract the item's 16px horizontal padding so the divider spans the
129
- // full width and sits flush with the bottom edge of the selected highlight
130
- margin 8px -16px -8px -16px !important
131
-
132
213
  .conversation-list-item-action
133
214
  position absolute !important
134
- top 8px
135
- right 8px
215
+ top 50%
216
+ right 4px
217
+ transform translateY(-50%)
136
218
  opacity 0
137
219
  pointer-events none
138
220
 
139
221
  .conversation-list-item-text
140
- line-height 16px
141
222
  overflow hidden
142
- margin-right 28px !important
223
+ margin-right 24px !important
143
224
 
144
225
  .conversation-list-item-title
145
226
  color var(--primaryTextColor)
146
227
  font-size 14px
147
228
  font-weight 500
229
+ line-height 18px
230
+ letter-spacing 0.25px
231
+
232
+ .conversation-list-item-subtitle
233
+ color var(--secondaryTextColor)
234
+ font-size 12px
235
+ font-weight 500
148
236
  line-height 16px
149
237
  letter-spacing 0.5px
150
238
 
151
239
  .conversation-list-item-meta
152
240
  gap 4px
153
-
154
- .conversation-list-item-subtitle
155
- color var(--secondaryTextColor)
241
+ color var(--primaryTextColor)
156
242
  font-size 11px
157
243
  font-weight 400
158
244
  line-height 16px
245
+ letter-spacing 0
@@ -98,7 +98,13 @@ var ConversationLoader = function ConversationLoader(_ref) {
98
98
  var conversation = queryResult.data;
99
99
  var isLoading = (0, _cozyClient.isQueryLoading)(queryResult);
100
100
  var boundId = conversation === null || conversation === void 0 ? void 0 : (_conversation$relatio = conversation.relationships) === null || _conversation$relatio === void 0 ? void 0 : (_conversation$relatio2 = _conversation$relatio.assistant) === null || _conversation$relatio2 === void 0 ? void 0 : (_conversation$relatio3 = _conversation$relatio2.data) === null || _conversation$relatio3 === void 0 ? void 0 : _conversation$relatio3._id;
101
- var defaultId = (0, _useDefaultAssistantId.useDefaultAssistantId)();
101
+ var defaultId = (0, _useDefaultAssistantId.useDefaultAssistantId)(); // The assistant picked to start this conversation on, set by
102
+ // useConversation when navigating here
103
+
104
+ var _ref2 = (0, _reactRouterDom.useLocation)(),
105
+ locationState = _ref2.state;
106
+
107
+ var requestedId = locationState === null || locationState === void 0 ? void 0 : locationState.assistantId;
102
108
  var initialMessages = (0, _react2.useMemo)(function () {
103
109
  return convertMessagesToThreadMessages(conversation === null || conversation === void 0 ? void 0 : conversation.messages, t);
104
110
  }, [conversation === null || conversation === void 0 ? void 0 : conversation.messages, t]); // Undefined until the conversation, and the default a new one starts
@@ -109,7 +115,8 @@ var ConversationLoader = function ConversationLoader(_ref) {
109
115
  boundId: boundId,
110
116
  conversation: conversation,
111
117
  isLoading: isLoading,
112
- defaultId: defaultId
118
+ defaultId: defaultId,
119
+ requestedId: requestedId
113
120
  });
114
121
  (0, _react2.useEffect)(function () {
115
122
  if (resolvedAssistantId) setSelectedAssistantId(resolvedAssistantId);
@@ -130,10 +137,10 @@ var ConversationLoader = function ConversationLoader(_ref) {
130
137
  }, children);
131
138
  };
132
139
 
133
- var CozyAssistantRuntimeProviderInner = function CozyAssistantRuntimeProviderInner(_ref2) {
134
- var children = _ref2.children,
135
- conversationId = _ref2.conversationId,
136
- initialMessages = _ref2.initialMessages;
140
+ var CozyAssistantRuntimeProviderInner = function CozyAssistantRuntimeProviderInner(_ref3) {
141
+ var children = _ref3.children,
142
+ conversationId = _ref3.conversationId,
143
+ initialMessages = _ref3.initialMessages;
137
144
 
138
145
  var _useI18n2 = (0, _twakeI18n.useI18n)(),
139
146
  t = _useI18n2.t;
@@ -271,8 +278,8 @@ var CozyAssistantRuntimeProviderInner = function CozyAssistantRuntimeProviderInn
271
278
  */
272
279
 
273
280
 
274
- var CozyAssistantRuntimeProvider = function CozyAssistantRuntimeProvider(_ref3) {
275
- var children = _ref3.children;
281
+ var CozyAssistantRuntimeProvider = function CozyAssistantRuntimeProvider(_ref4) {
282
+ var children = _ref4.children;
276
283
 
277
284
  var _useParams = (0, _reactRouterDom.useParams)(),
278
285
  conversationId = _useParams.conversationId;
@@ -13,8 +13,12 @@ var _react = _interopRequireWildcard(require("react"));
13
13
 
14
14
  var _TextField = _interopRequireDefault(require("cozy-ui/transpiled/react/TextField"));
15
15
 
16
+ var _Tooltip = _interopRequireDefault(require("cozy-ui/transpiled/react/Tooltip"));
17
+
16
18
  var _Typography = _interopRequireDefault(require("cozy-ui/transpiled/react/Typography"));
17
19
 
20
+ var _CozyTheme = require("cozy-ui/transpiled/react/providers/CozyTheme");
21
+
18
22
  var _twakeI18n = require("twake-i18n");
19
23
 
20
24
  var _KnowledgeBaseSection = _interopRequireDefault(require("../KnowledgeBase/KnowledgeBaseSection"));
@@ -28,6 +32,7 @@ var styles = {
28
32
  "avatar-container": "styles__avatar-container___kJ_64",
29
33
  "avatar-image": "styles__avatar-image___2Mkxj",
30
34
  "file-input": "styles__file-input___2fB5n",
35
+ "avatar-tooltip": "styles__avatar-tooltip___1o6_5",
31
36
  "ModelSelectionStep": "styles__ModelSelectionStep___1auXB",
32
37
  "grid-container": "styles__grid-container___3wOus",
33
38
  "grid-container--mobile": "styles__grid-container--mobile___uCAg1",
@@ -56,6 +61,9 @@ var BasicInfoStep = function BasicInfoStep(_ref) {
56
61
  var _useI18n = (0, _twakeI18n.useI18n)(),
57
62
  t = _useI18n.t;
58
63
 
64
+ var _useCozyTheme = (0, _CozyTheme.useCozyTheme)(),
65
+ type = _useCozyTheme.type;
66
+
59
67
  var fileInputRef = (0, _react.useRef)(null);
60
68
 
61
69
  var handleAvatarClick = function handleAvatarClick() {
@@ -90,6 +98,34 @@ var BasicInfoStep = function BasicInfoStep(_ref) {
90
98
  className: "u-mb-half"
91
99
  }, t('assistant_create.steps.basic_info.avatar')), /*#__PURE__*/_react.default.createElement("div", {
92
100
  className: "u-flex u-flex-items-center u-flex-justify-center"
101
+ }, /*#__PURE__*/_react.default.createElement(_Tooltip.default, {
102
+ title: t('assistant_create.steps.basic_info.upload_photo'),
103
+ placement: "bottom-start",
104
+ arrow: false,
105
+ classes: {
106
+ tooltip: styles['avatar-tooltip'],
107
+ // Rendered outside the themed tree: the theme class brings
108
+ // the dark colors when needed
109
+ popper: "TwakeTheme--".concat(type)
110
+ } // Sits at the lower right of the avatar, next to the pointer,
111
+ // as a native tooltip would (the design): shifted from the
112
+ // bottom-left corner by half the 64px avatar plus (9px, 7px),
113
+ // and never flipped away from it
114
+ ,
115
+ PopperProps: {
116
+ modifiers: {
117
+ offset: {
118
+ enabled: true,
119
+ offset: '41, -25'
120
+ },
121
+ flip: {
122
+ enabled: false
123
+ },
124
+ preventOverflow: {
125
+ enabled: false
126
+ }
127
+ }
128
+ }
93
129
  }, /*#__PURE__*/_react.default.createElement("div", {
94
130
  role: "button",
95
131
  tabIndex: 0,
@@ -102,7 +138,7 @@ var BasicInfoStep = function BasicInfoStep(_ref) {
102
138
  className: "u-w-100 u-h-100 u-obj-cover ".concat(styles['avatar-image'])
103
139
  }) : /*#__PURE__*/_react.default.createElement(_twakeIcons.Icon, {
104
140
  icon: _twakeIcons.Plus
105
- })), /*#__PURE__*/_react.default.createElement("input", {
141
+ }))), /*#__PURE__*/_react.default.createElement("input", {
106
142
  type: "file",
107
143
  ref: fileInputRef,
108
144
  onChange: handleFileChange,
@@ -28,6 +28,7 @@ var styles = {
28
28
  "avatar-container": "styles__avatar-container___kJ_64",
29
29
  "avatar-image": "styles__avatar-image___2Mkxj",
30
30
  "file-input": "styles__file-input___2fB5n",
31
+ "avatar-tooltip": "styles__avatar-tooltip___1o6_5",
31
32
  "ModelSelectionStep": "styles__ModelSelectionStep___1auXB",
32
33
  "grid-container": "styles__grid-container___3wOus",
33
34
  "grid-container--mobile": "styles__grid-container--mobile___uCAg1",
@@ -67,6 +67,7 @@ var styles = {
67
67
  "avatar-container": "styles__avatar-container___kJ_64",
68
68
  "avatar-image": "styles__avatar-image___2Mkxj",
69
69
  "file-input": "styles__file-input___2fB5n",
70
+ "avatar-tooltip": "styles__avatar-tooltip___1o6_5",
70
71
  "ModelSelectionStep": "styles__ModelSelectionStep___1auXB",
71
72
  "grid-container": "styles__grid-container___3wOus",
72
73
  "grid-container--mobile": "styles__grid-container--mobile___uCAg1",
@@ -11,6 +11,20 @@
11
11
  & .file-input
12
12
  display none
13
13
 
14
+ // The "Upload a photo" hint of the avatar: a small light tooltip with the
15
+ // design's elevation, not the dark default one. Doubled to outweigh the
16
+ // theme's tooltip rule, injected after this stylesheet.
17
+ .avatar-tooltip.avatar-tooltip
18
+ padding 8px
19
+ border-radius 8px
20
+ background-color var(--paperBackgroundColor)
21
+ color var(--primaryTextColor)
22
+ font-size 12px
23
+ font-weight 500
24
+ line-height 20px
25
+ letter-spacing 0.1px
26
+ box-shadow 0 2px 3px rgba(0, 0, 0, 0.15), 0 1px 1px rgba(0, 0, 0, 0.3)
27
+
14
28
  .ModelSelectionStep
15
29
  & .grid-container
16
30
  display grid
@@ -26,7 +26,9 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
26
26
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
27
27
 
28
28
  var styles = {
29
- "intentHost": "styles__intentHost___1ixnl"
29
+ "intentHost": "styles__intentHost___1ixnl",
30
+ "folder-tooltip": "styles__folder-tooltip___2lWW_",
31
+ "folder-tooltip-arrow": "styles__folder-tooltip-arrow___3MALJ"
30
32
  };
31
33
  /**
32
34
  * Hosts the Drive `PICK io.cozy.files` intent (folder `reference` mode)
@@ -1,17 +1,19 @@
1
1
  export default KnowledgeBaseChip;
2
2
  /**
3
- * Composer chip showing the selected assistant's knowledge-base folder,
4
- * rendered in the "selected source" style (like the email source chip).
3
+ * The Drive source of the composer when the selected assistant has a
4
+ * knowledge-base folder: a chip named after the folder (`variant="chip"`,
5
+ * desktop) or an icon button (`variant="icon"`, mobile).
5
6
  *
6
7
  * Clicking stays in-app: it opens a small menu with explicit actions —
7
8
  * open the folder in Drive (new tab) or change the knowledge base through
8
- * the Drive folder picker (persisted on the assistant immediately).
9
+ * the Drive folder picker (persisted on the assistant immediately). The
10
+ * menu starts with the folder name, which the icon button does not show.
9
11
  */
10
- declare function KnowledgeBaseChip({ dirId, folder, isRoot, isUnavailable, isLast, onChangeFolder }: {
12
+ declare function KnowledgeBaseChip({ dirId, folder, isRoot, isUnavailable, onChangeFolder, variant }: {
11
13
  dirId: any;
12
14
  folder: any;
13
15
  isRoot: any;
14
16
  isUnavailable: any;
15
- isLast: any;
16
17
  onChangeFolder: any;
18
+ variant?: string | undefined;
17
19
  }): JSX.Element;
@@ -9,12 +9,10 @@ exports.default = void 0;
9
9
 
10
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
11
 
12
- var _twakeIcons = require("@linagora/twake-icons");
13
-
14
- var _classnames = _interopRequireDefault(require("classnames"));
15
-
16
12
  var _react = _interopRequireWildcard(require("react"));
17
13
 
14
+ var _twakeIcons = require("@linagora/twake-icons");
15
+
18
16
  var _cozyClient = require("cozy-client");
19
17
 
20
18
  var _ActionsMenu = _interopRequireDefault(require("cozy-ui/transpiled/react/ActionsMenu"));
@@ -23,26 +21,44 @@ var _ActionsMenuItem = _interopRequireDefault(require("cozy-ui/transpiled/react/
23
21
 
24
22
  var _Chips = _interopRequireDefault(require("cozy-ui/transpiled/react/Chips"));
25
23
 
24
+ var _Tooltip = _interopRequireDefault(require("cozy-ui/transpiled/react/Tooltip"));
25
+
26
26
  var _Typography = _interopRequireDefault(require("cozy-ui/transpiled/react/Typography"));
27
27
 
28
28
  var _twakeI18n = require("twake-i18n");
29
29
 
30
30
  var _FolderPickerDialog = _interopRequireDefault(require("./FolderPickerDialog"));
31
31
 
32
- var _tdrive = _interopRequireDefault(require("../../assets/tdrive.png"));
32
+ var _SourceButton = _interopRequireWildcard(require("../TwakeKnowledges/SourceButton"));
33
33
 
34
34
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
35
35
 
36
36
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
37
37
 
38
+ var styles = {
39
+ "intentHost": "styles__intentHost___1ixnl",
40
+ "folder-tooltip": "styles__folder-tooltip___2lWW_",
41
+ "folder-tooltip-arrow": "styles__folder-tooltip-arrow___3MALJ"
42
+ };
43
+ var sourceStyles = {
44
+ "source-button": "styles__source-button___9t9wI",
45
+ "source-button-image": "styles__source-button-image___2batD",
46
+ "source-button-image--inactive": "styles__source-button-image--inactive___3hs2C",
47
+ "source-chip": "styles__source-chip___1h51w",
48
+ "source-chip-icon": "styles__source-chip-icon___3-N0x",
49
+ "source-chip-label": "styles__source-chip-label___2mLIx"
50
+ };
38
51
  /**
39
- * Composer chip showing the selected assistant's knowledge-base folder,
40
- * rendered in the "selected source" style (like the email source chip).
52
+ * The Drive source of the composer when the selected assistant has a
53
+ * knowledge-base folder: a chip named after the folder (`variant="chip"`,
54
+ * desktop) or an icon button (`variant="icon"`, mobile).
41
55
  *
42
56
  * Clicking stays in-app: it opens a small menu with explicit actions —
43
57
  * open the folder in Drive (new tab) or change the knowledge base through
44
- * the Drive folder picker (persisted on the assistant immediately).
58
+ * the Drive folder picker (persisted on the assistant immediately). The
59
+ * menu starts with the folder name, which the icon button does not show.
45
60
  */
61
+
46
62
  var KnowledgeBaseChip = function KnowledgeBaseChip(_ref) {
47
63
  var _folder$name;
48
64
 
@@ -50,8 +66,9 @@ var KnowledgeBaseChip = function KnowledgeBaseChip(_ref) {
50
66
  folder = _ref.folder,
51
67
  isRoot = _ref.isRoot,
52
68
  isUnavailable = _ref.isUnavailable,
53
- isLast = _ref.isLast,
54
- onChangeFolder = _ref.onChangeFolder;
69
+ onChangeFolder = _ref.onChangeFolder,
70
+ _ref$variant = _ref.variant,
71
+ variant = _ref$variant === void 0 ? 'chip' : _ref$variant;
55
72
 
56
73
  var _useI18n = (0, _twakeI18n.useI18n)(),
57
74
  t = _useI18n.t;
@@ -85,33 +102,46 @@ var KnowledgeBaseChip = function KnowledgeBaseChip(_ref) {
85
102
  hash: "/folder/".concat(dirId)
86
103
  });
87
104
  var label = isUnavailable ? t('assistant.knowledge_base.unavailable') : isRoot ? t('assistant.twake_knowledges.drive') : (_folder$name = folder === null || folder === void 0 ? void 0 : folder.name) !== null && _folder$name !== void 0 ? _folder$name : '…';
88
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
105
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, variant === 'icon' ? /*#__PURE__*/_react.default.createElement(_SourceButton.default, {
89
106
  ref: chipRef,
90
- className: (0, _classnames.default)({
91
- 'u-mr-half': !isLast
92
- })
107
+ icon: _twakeIcons.Drive,
108
+ preserveColor: true,
109
+ label: label,
110
+ isActive: !isUnavailable,
111
+ "aria-haspopup": "menu",
112
+ "aria-expanded": isMenuOpen,
113
+ onClick: function onClick() {
114
+ return setIsMenuOpen(true);
115
+ }
116
+ }) :
117
+ /*#__PURE__*/
118
+ // Hovering the chip tells what the folder is for (the design's
119
+ // tooltip); nothing to tell when the folder is gone
120
+ _react.default.createElement(_Tooltip.default, {
121
+ title: isUnavailable ? '' : t('assistant.knowledge_base.folder_hint'),
122
+ placement: "top",
123
+ classes: {
124
+ tooltip: styles['folder-tooltip'],
125
+ arrow: styles['folder-tooltip-arrow']
126
+ }
127
+ }, /*#__PURE__*/_react.default.createElement("div", {
128
+ ref: chipRef
93
129
  }, /*#__PURE__*/_react.default.createElement(_Chips.default, {
94
- icon: /*#__PURE__*/_react.default.createElement("img", {
95
- alt: "",
96
- "aria-hidden": "true",
97
- src: _tdrive.default,
98
- width: 16,
99
- className: "u-m-0"
100
- }),
101
- label: /*#__PURE__*/_react.default.createElement("span", {
102
- className: "u-flex u-flex-items-center"
103
- }, label, /*#__PURE__*/_react.default.createElement(_twakeIcons.Icon, {
104
- icon: _twakeIcons.Dropdown,
130
+ icon: /*#__PURE__*/_react.default.createElement(_twakeIcons.Icon, {
131
+ icon: _twakeIcons.Drive,
105
132
  size: 16,
106
- className: "u-ml-half"
107
- })),
108
- variant: "ghost",
133
+ preserveColor: true
134
+ }),
135
+ label: label,
109
136
  clickable: true,
137
+ "aria-haspopup": "menu",
138
+ "aria-expanded": isMenuOpen,
110
139
  onClick: function onClick() {
111
140
  return setIsMenuOpen(true);
112
141
  },
113
- className: "u-w-auto u-ph-half u-mr-0"
114
- })), isMenuOpen && /*#__PURE__*/_react.default.createElement(_ActionsMenu.default, {
142
+ className: sourceStyles['source-chip'],
143
+ classes: _SourceButton.CHIP_CLASSES
144
+ }))), isMenuOpen && /*#__PURE__*/_react.default.createElement(_ActionsMenu.default, {
115
145
  open: true,
116
146
  ref: chipRef,
117
147
  onClose: closeMenu,
@@ -120,7 +150,11 @@ var KnowledgeBaseChip = function KnowledgeBaseChip(_ref) {
120
150
  vertical: 'bottom',
121
151
  horizontal: 'left'
122
152
  }
123
- }, !isUnavailable && /*#__PURE__*/_react.default.createElement(_ActionsMenuItem.default, {
153
+ }, variant === 'icon' && /*#__PURE__*/_react.default.createElement(_Typography.default, {
154
+ variant: "body2",
155
+ className: "u-ph-1 u-pb-half u-ellipsis",
156
+ component: "div"
157
+ }, label), !isUnavailable && /*#__PURE__*/_react.default.createElement(_ActionsMenuItem.default, {
124
158
  component: "a",
125
159
  href: folderUrl,
126
160
  target: "_blank",
@@ -1,6 +1,7 @@
1
- export function resolveConversationAssistantId({ boundId, conversation, isLoading, defaultId }: {
1
+ export function resolveConversationAssistantId({ boundId, conversation, isLoading, defaultId, requestedId }: {
2
2
  boundId: string | undefined;
3
3
  conversation: object | undefined;
4
4
  isLoading: boolean;
5
5
  defaultId: string | null | undefined;
6
+ requestedId?: string | undefined;
6
7
  }): string | undefined;
@@ -21,17 +21,22 @@ var _constants = require("../constants");
21
21
  * @param {string|null|undefined} params.defaultId - The configured default
22
22
  * assistant id, only when its document is known to exist; undefined while
23
23
  * that is being checked.
24
+ * @param {string|undefined} [params.requestedId] - The assistant the user
25
+ * picked to start this new conversation on (the history state of the
26
+ * navigation), which wins over the default.
24
27
  * @returns {string|undefined}
25
28
  */
26
29
  var resolveConversationAssistantId = function resolveConversationAssistantId(_ref) {
27
30
  var boundId = _ref.boundId,
28
31
  conversation = _ref.conversation,
29
32
  isLoading = _ref.isLoading,
30
- defaultId = _ref.defaultId;
33
+ defaultId = _ref.defaultId,
34
+ requestedId = _ref.requestedId;
31
35
  if (boundId) return boundId;
32
36
  if (isLoading) return undefined;
33
37
 
34
38
  if (!conversation) {
39
+ if (requestedId) return requestedId;
35
40
  if (defaultId === undefined) return undefined;
36
41
  return defaultId || _constants.DEFAULT_ASSISTANT._id;
37
42
  }
@@ -56,6 +56,30 @@ describe('resolveConversationAssistantId', () => {
56
56
  ).toBe('docs')
57
57
  })
58
58
 
59
+ it('selects the requested assistant for a new conversation, over the default', () => {
60
+ expect(
61
+ resolveConversationAssistantId({
62
+ boundId: undefined,
63
+ conversation: undefined,
64
+ isLoading: false,
65
+ defaultId: 'docs',
66
+ requestedId: 'meeting'
67
+ })
68
+ ).toBe('meeting')
69
+ })
70
+
71
+ it('selects the requested assistant for a new conversation without waiting for the default', () => {
72
+ expect(
73
+ resolveConversationAssistantId({
74
+ boundId: undefined,
75
+ conversation: undefined,
76
+ isLoading: false,
77
+ defaultId: undefined,
78
+ requestedId: 'meeting'
79
+ })
80
+ ).toBe('meeting')
81
+ })
82
+
59
83
  it('selects the sentinel for a new conversation without a configured default', () => {
60
84
  expect(
61
85
  resolveConversationAssistantId({
@@ -10,3 +10,21 @@
10
10
  width 100%
11
11
  height 100%
12
12
  border none
13
+
14
+ // The hint of the folder chip: the design's tooltip (12px medium, centered,
15
+ // on grey A400). Doubled to outweigh the theme's tooltip rule, injected
16
+ // after this stylesheet.
17
+ .folder-tooltip.folder-tooltip
18
+ max-width 258px
19
+ padding 8px 12px
20
+ border-radius 4px
21
+ background-color var(--greyA400)
22
+ color var(--white)
23
+ font-size 12px
24
+ font-weight 500
25
+ line-height 15.8px
26
+ letter-spacing 0.5px
27
+ text-align center
28
+
29
+ .folder-tooltip-arrow.folder-tooltip-arrow
30
+ color var(--greyA400)