@skyscanner/backpack-web 42.10.0 → 42.11.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.
- package/bpk-component-ai-blurb/src/BpkAiBlurb.module.css +1 -1
- package/bpk-component-ai-blurb/src/BpkAiBlurbFeedback.js +13 -21
- package/bpk-component-bottom-sheet/src/BpkBottomSheet.js +1 -0
- package/bpk-component-chatbot-input/index.d.ts +1 -2
- package/bpk-component-chatbot-input/src/BpkChatbotInput.d.ts +13 -3
- package/bpk-component-chatbot-input/src/BpkChatbotInput.js +18 -98
- package/bpk-component-chatbot-input/src/BpkChatbotInput.module.css +1 -1
- package/bpk-component-chatbot-input/src/BpkChatbotInputContext.d.ts +9 -0
- package/bpk-component-chatbot-input/src/BpkChatbotInputContext.js +26 -0
- package/bpk-component-chatbot-input/src/BpkChatbotInputInput.d.ts +3 -0
- package/bpk-component-chatbot-input/src/BpkChatbotInputInput.js +125 -0
- package/bpk-component-chatbot-input/src/BpkChatbotInputRoot.d.ts +3 -0
- package/bpk-component-chatbot-input/src/BpkChatbotInputRoot.js +77 -0
- package/bpk-component-chatbot-input/src/BpkChatbotInputToolbar.d.ts +3 -0
- package/bpk-component-chatbot-input/src/BpkChatbotInputToolbar.js +33 -0
- package/bpk-component-chatbot-input/src/TextAreaField/TextAreaField.d.ts +1 -0
- package/bpk-component-chatbot-input/src/TextAreaField/TextAreaField.js +5 -1
- package/bpk-component-chatbot-input/src/common-types.d.ts +23 -3
- package/bpk-component-chatbot-input/src/hooks/useChatbotInput.d.ts +2 -1
- package/bpk-component-chatbot-input/src/hooks/useChatbotInput.js +3 -1
- package/bpk-component-chatbot-input/src/hooks/useTextAreaAutoResize.d.ts +2 -1
- package/bpk-component-chatbot-input/src/hooks/useTextAreaAutoResize.js +19 -6
- package/bpk-component-navigation-bar/src/BpkNavigationBar.d.ts +3 -0
- package/bpk-component-navigation-bar/src/BpkNavigationBar.js +2 -1
- package/bpk-component-navigation-bar/src/BpkNavigationBar.module.css +1 -1
- package/bpk-component-page-indicator/src/NavButton.js +3 -3
- package/package.json +2 -2
- package/bpk-component-chatbot-input/src/SendButton/SendButton.d.ts +0 -9
- package/bpk-component-chatbot-input/src/SendButton/SendButton.js +0 -47
|
@@ -15,4 +15,4 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
-
.bpk-ai-blurb{display:flex;flex-direction:column;gap:.5rem}.bpk-ai-blurb__header{color:#626971}.bpk-ai-blurb__header svg{fill:currentcolor}.bpk-ai-blurb__summary{display:block}.bpk-ai-blurb__error{display:flex;margin:0;flex-wrap:wrap;align-items:baseline;gap:0 .25rem;font-size:.75rem;line-height:1rem;font-weight:400}.bpk-ai-
|
|
18
|
+
.bpk-ai-blurb{display:flex;flex-direction:column;gap:.5rem}.bpk-ai-blurb__header{color:#626971}.bpk-ai-blurb__header svg{fill:currentcolor}.bpk-ai-blurb__summary{display:block}.bpk-ai-blurb__error{display:flex;margin:0;flex-wrap:wrap;align-items:baseline;gap:0 .25rem;font-size:.75rem;line-height:1rem;font-weight:400}.bpk-ai-blurb__ellipsis{display:inline;vertical-align:baseline;margin-inline-start:.25rem}.bpk-ai-blurb__ellipsis-dot{display:inline;opacity:0;vertical-align:baseline;animation:bpk-ai-blurb-ellipsis-dot-1 1.2s infinite step-end}@media(prefers-reduced-motion: reduce){.bpk-ai-blurb__ellipsis-dot{opacity:1;animation:none}}.bpk-ai-blurb__ellipsis-dot--2{animation-name:bpk-ai-blurb-ellipsis-dot-2}.bpk-ai-blurb__ellipsis-dot--3{animation-name:bpk-ai-blurb-ellipsis-dot-3}@keyframes bpk-ai-blurb-ellipsis-dot-1{0%{opacity:1}75%{opacity:0}100%{opacity:0}}@keyframes bpk-ai-blurb-ellipsis-dot-2{0%{opacity:0}25%{opacity:1}75%{opacity:0}100%{opacity:0}}@keyframes bpk-ai-blurb-ellipsis-dot-3{0%{opacity:0}50%{opacity:1}75%{opacity:0}100%{opacity:0}}
|
|
@@ -18,14 +18,10 @@
|
|
|
18
18
|
|
|
19
19
|
import { useState } from 'react';
|
|
20
20
|
import BpkAriaLive from "../../bpk-component-aria-live";
|
|
21
|
-
import BpkSmallThumbsDownIcon from "../../bpk-component-icon/sm/thumbs-down";
|
|
22
|
-
import BpkSmallThumbsUpIcon from "../../bpk-component-icon/sm/thumbs-up";
|
|
23
21
|
import { BpkFlex, BpkSpacing } from "../../bpk-component-layout";
|
|
24
22
|
import BpkText, { TEXT_STYLES } from "../../bpk-component-text";
|
|
25
|
-
import
|
|
26
|
-
import STYLES from "./BpkAiBlurb.module.css";
|
|
23
|
+
import BpkThumbButton from "../../bpk-component-thumb-button";
|
|
27
24
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
28
|
-
const getClassName = cssModules(STYLES);
|
|
29
25
|
const BpkAiBlurbFeedback = ({
|
|
30
26
|
feedbackText,
|
|
31
27
|
onFeedback,
|
|
@@ -45,22 +41,18 @@ const BpkAiBlurbFeedback = ({
|
|
|
45
41
|
children: [/*#__PURE__*/_jsx(BpkText, {
|
|
46
42
|
textStyle: TEXT_STYLES.caption,
|
|
47
43
|
children: feedbackText
|
|
48
|
-
}), /*#__PURE__*/_jsx(
|
|
49
|
-
type: "
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
onClick: () => handleVote(false)
|
|
60
|
-
"aria-label": thumbsDownLabel,
|
|
61
|
-
children: /*#__PURE__*/_jsx(BpkSmallThumbsDownIcon, {
|
|
62
|
-
"aria-hidden": true
|
|
63
|
-
})
|
|
44
|
+
}), /*#__PURE__*/_jsx(BpkThumbButton, {
|
|
45
|
+
type: "up",
|
|
46
|
+
size: "small",
|
|
47
|
+
iconColor: "primary",
|
|
48
|
+
accessibilityLabel: thumbsUpLabel,
|
|
49
|
+
onClick: () => handleVote(true)
|
|
50
|
+
}), /*#__PURE__*/_jsx(BpkThumbButton, {
|
|
51
|
+
type: "down",
|
|
52
|
+
size: "small",
|
|
53
|
+
iconColor: "primary",
|
|
54
|
+
accessibilityLabel: thumbsDownLabel,
|
|
55
|
+
onClick: () => handleVote(false)
|
|
64
56
|
})]
|
|
65
57
|
}), /*#__PURE__*/_jsx(BpkAriaLive, {
|
|
66
58
|
visible: hasVoted,
|
|
@@ -132,6 +132,7 @@ const BpkBottomSheet = ({
|
|
|
132
132
|
title: titleWithId,
|
|
133
133
|
titleTextStyle: TEXT_STYLES.label1,
|
|
134
134
|
titleTagName: hasTitle ? 'h2' : 'span',
|
|
135
|
+
wrapTitle: true,
|
|
135
136
|
className: getClassName('bpk-bottom-sheet--header'),
|
|
136
137
|
leadingButton: /*#__PURE__*/_jsx(BpkCloseButton, {
|
|
137
138
|
label: closeLabel,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import BpkChatbotInput from './src/BpkChatbotInput';
|
|
2
|
-
export type {
|
|
2
|
+
export type { BpkChatbotInputInputProps, BpkChatbotInputNamespace, BpkChatbotInputRootProps, BpkChatbotInputToolbarProps, ChatbotInputType, SendButtonRenderProps, } from './src/common-types';
|
|
3
3
|
export { CHATBOT_INPUT_TYPES } from './src/common-types';
|
|
4
|
-
export type { ChatbotInputType } from './src/common-types';
|
|
5
4
|
export { useChatbotInputManager } from './src/hooks';
|
|
6
5
|
export { default as themeAttributes } from './src/themeAttributes';
|
|
7
6
|
export default BpkChatbotInput;
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { BpkChatbotInputNamespace } from './common-types';
|
|
2
|
+
/**
|
|
3
|
+
* BpkChatbotInput is a composable chatbot input namespace for Backpack.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* <BpkChatbotInput.Root>
|
|
7
|
+
* <BpkChatbotInput.Input {...inputProps} />
|
|
8
|
+
* <BpkChatbotInput.Toolbar>
|
|
9
|
+
* <BpkButton type={BUTTON_TYPES.link}>Attach</BpkButton>
|
|
10
|
+
* </BpkChatbotInput.Toolbar>
|
|
11
|
+
* </BpkChatbotInput.Root>
|
|
12
|
+
*/
|
|
13
|
+
declare const BpkChatbotInput: BpkChatbotInputNamespace;
|
|
4
14
|
export default BpkChatbotInput;
|
|
@@ -16,103 +16,23 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
onInputBlur,
|
|
38
|
-
onInputChange,
|
|
39
|
-
onInputClick = () => {},
|
|
40
|
-
onInputFocus,
|
|
41
|
-
onKeyDown = () => {},
|
|
42
|
-
onSubmit,
|
|
43
|
-
placeholder,
|
|
44
|
-
sendAriaLabel
|
|
45
|
-
}) => {
|
|
46
|
-
const {
|
|
47
|
-
containerHeight,
|
|
48
|
-
handleSubmit,
|
|
49
|
-
inputProps,
|
|
50
|
-
inputRef,
|
|
51
|
-
isCapped,
|
|
52
|
-
isCars,
|
|
53
|
-
isExpanding,
|
|
54
|
-
isOverLimit,
|
|
55
|
-
sendButtonDisabled,
|
|
56
|
-
textareaHeight
|
|
57
|
-
} = useChatbotInput({
|
|
58
|
-
placeholder,
|
|
59
|
-
inputType,
|
|
60
|
-
inputValue,
|
|
61
|
-
isPolling,
|
|
62
|
-
isSending,
|
|
63
|
-
maxCharacters,
|
|
64
|
-
onInputBlur,
|
|
65
|
-
onInputChange,
|
|
66
|
-
onInputClick,
|
|
67
|
-
onInputFocus,
|
|
68
|
-
onKeyDown,
|
|
69
|
-
onSubmit
|
|
70
|
-
});
|
|
71
|
-
const isComposer = inputType === CHATBOT_INPUT_TYPES.COMPOSER;
|
|
72
|
-
const containerClassName = getClassName(isCars ? 'bpk-chatbot-input--cars' : 'bpk-chatbot-input--composer', isComposer && 'bpk-chatbot-input--composer--with-shadow', isOverLimit && !isCars && 'bpk-chatbot-input--composer--overLimit');
|
|
73
|
-
const flexProps = isCars ? {
|
|
74
|
-
align: 'center',
|
|
75
|
-
gap: BpkSpacing.MD,
|
|
76
|
-
paddingTop: BpkSpacing.MD,
|
|
77
|
-
paddingBottom: BpkSpacing.MD,
|
|
78
|
-
paddingEnd: BpkSpacing.MD,
|
|
79
|
-
paddingStart: BpkSpacing.Base
|
|
80
|
-
} : {
|
|
81
|
-
align: isExpanding ? 'flex-end' : 'center',
|
|
82
|
-
gap: BpkSpacing.Base,
|
|
83
|
-
padding: BpkSpacing.Base
|
|
84
|
-
};
|
|
85
|
-
const handleContainerEvent = e => {
|
|
86
|
-
e.stopPropagation();
|
|
87
|
-
};
|
|
88
|
-
return /*#__PURE__*/_jsx("div", {
|
|
89
|
-
className: containerClassName,
|
|
90
|
-
onClick: handleContainerEvent,
|
|
91
|
-
onTouchStart: handleContainerEvent,
|
|
92
|
-
role: "presentation",
|
|
93
|
-
"data-testid": "bpk-chatbot-input-container",
|
|
94
|
-
...getDataComponentAttribute('ChatbotInput'),
|
|
95
|
-
children: /*#__PURE__*/_jsxs(BpkFlex, {
|
|
96
|
-
...flexProps,
|
|
97
|
-
children: [isCars ? /*#__PURE__*/_jsx(InputField, {
|
|
98
|
-
ref: inputRef,
|
|
99
|
-
...inputProps
|
|
100
|
-
}) : /*#__PURE__*/_jsx(TextAreaField, {
|
|
101
|
-
ref: inputRef,
|
|
102
|
-
containerHeight: containerHeight,
|
|
103
|
-
textareaHeight: textareaHeight,
|
|
104
|
-
isCapped: isCapped,
|
|
105
|
-
isExpanding: isExpanding,
|
|
106
|
-
isComposer: isComposer,
|
|
107
|
-
...inputProps
|
|
108
|
-
}), /*#__PURE__*/_jsx(SendButton, {
|
|
109
|
-
isCars: isCars,
|
|
110
|
-
disabled: sendButtonDisabled,
|
|
111
|
-
onClick: handleSubmit,
|
|
112
|
-
ariaLabel: isCars && isPolling ? loadingAriaLabel : sendAriaLabel,
|
|
113
|
-
isLoading: !!(isCars && isPolling)
|
|
114
|
-
})]
|
|
115
|
-
})
|
|
116
|
-
});
|
|
19
|
+
import BpkChatbotInputInput from "./BpkChatbotInputInput";
|
|
20
|
+
import BpkChatbotInputRoot from "./BpkChatbotInputRoot";
|
|
21
|
+
import BpkChatbotInputToolbar from "./BpkChatbotInputToolbar";
|
|
22
|
+
/**
|
|
23
|
+
* BpkChatbotInput is a composable chatbot input namespace for Backpack.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* <BpkChatbotInput.Root>
|
|
27
|
+
* <BpkChatbotInput.Input {...inputProps} />
|
|
28
|
+
* <BpkChatbotInput.Toolbar>
|
|
29
|
+
* <BpkButton type={BUTTON_TYPES.link}>Attach</BpkButton>
|
|
30
|
+
* </BpkChatbotInput.Toolbar>
|
|
31
|
+
* </BpkChatbotInput.Root>
|
|
32
|
+
*/
|
|
33
|
+
const BpkChatbotInput = {
|
|
34
|
+
Root: BpkChatbotInputRoot,
|
|
35
|
+
Input: BpkChatbotInputInput,
|
|
36
|
+
Toolbar: BpkChatbotInputToolbar
|
|
117
37
|
};
|
|
118
38
|
export default BpkChatbotInput;
|
|
@@ -15,4 +15,4 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
-
.bpk-chatbot-input--cars{transition:border-color 200ms ease,box-shadow 200ms ease;border:.09375rem solid #c1c7cf;background:#fff;box-shadow:none;box-sizing:border-box;touch-action:manipulation;border-radius:.75rem;border-radius:var(--bpk-chatbot-input-border-radius, 0.75rem)}.bpk-no-touch-support .bpk-chatbot-input--cars:hover:not(:active):not(:disabled){border-color:#0062e3;border-color:var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227))}:global(.bpk-no-touch-support) .bpk-chatbot-input--cars:hover:not(:active):not(:disabled){border-color:#0062e3;border-color:var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227))}.bpk-chatbot-input--cars:active{border-color:#0062e3;border-color:var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227))}.bpk-chatbot-input--cars:focus-within{box-shadow:0 0 0 .03125rem #0062e3;box-shadow:0 0 0 .03125rem var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227));border-color:#0062e3;border-color:var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227))}.bpk-chatbot-input--composer{position:relative;transition:transform .3s cubic-bezier(0.4, 0, 0.2, 1),box-shadow .3s cubic-bezier(0.4, 0, 0.2, 1);border:none;background:#fff;box-sizing:border-box;will-change:transform,box-shadow;border-radius:.75rem;border-radius:var(--bpk-chatbot-input-border-radius, 0.75rem)}.bpk-chatbot-input--composer--with-shadow:focus-within{box-shadow:0px
|
|
18
|
+
.bpk-chatbot-input--cars{transition:border-color 200ms ease,box-shadow 200ms ease;border:.09375rem solid #c1c7cf;background:#fff;box-shadow:none;box-sizing:border-box;touch-action:manipulation;border-radius:.75rem;border-radius:var(--bpk-chatbot-input-border-radius, 0.75rem)}.bpk-no-touch-support .bpk-chatbot-input--cars:hover:not(:active):not(:disabled){border-color:#0062e3;border-color:var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227))}:global(.bpk-no-touch-support) .bpk-chatbot-input--cars:hover:not(:active):not(:disabled){border-color:#0062e3;border-color:var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227))}.bpk-chatbot-input--cars:active{border-color:#0062e3;border-color:var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227))}.bpk-chatbot-input--cars:focus-within{box-shadow:0 0 0 .03125rem #0062e3;box-shadow:0 0 0 .03125rem var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227));border-color:#0062e3;border-color:var(--bpk-chatbot-input-focus-border-color, rgb(0, 98, 227))}.bpk-chatbot-input--composer{position:relative;transition:transform .3s cubic-bezier(0.4, 0, 0.2, 1),box-shadow .3s cubic-bezier(0.4, 0, 0.2, 1);border:none;background:#fff;box-sizing:border-box;will-change:transform,box-shadow;border-radius:.75rem;border-radius:var(--bpk-chatbot-input-border-radius, 0.75rem)}.bpk-chatbot-input--composer--with-shadow:focus-within{box-shadow:0px 4px 14px 0px rgba(37,32,31,.25)}.bpk-chatbot-input--composer--overLimit{transform:translateY(-0.25rem)}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ChatbotInputType } from './common-types';
|
|
2
|
+
type BpkChatbotInputContextValue = {
|
|
3
|
+
inputType: ChatbotInputType;
|
|
4
|
+
isOverLimit: boolean;
|
|
5
|
+
setIsOverLimit: (value: boolean) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const BpkChatbotInputContext: import("react").Context<BpkChatbotInputContextValue>;
|
|
8
|
+
export declare const useChatbotInputContext: () => BpkChatbotInputContextValue;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Backpack - Skyscanner's Design System
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2016 Skyscanner Ltd
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { createContext, useContext } from 'react';
|
|
20
|
+
import { CHATBOT_INPUT_TYPES } from "./common-types";
|
|
21
|
+
export const BpkChatbotInputContext = /*#__PURE__*/createContext({
|
|
22
|
+
inputType: CHATBOT_INPUT_TYPES.COMPOSER,
|
|
23
|
+
isOverLimit: false,
|
|
24
|
+
setIsOverLimit: () => {}
|
|
25
|
+
});
|
|
26
|
+
export const useChatbotInputContext = () => useContext(BpkChatbotInputContext);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BpkChatbotInputInputProps } from './common-types';
|
|
2
|
+
declare const BpkChatbotInputInput: ({ inputValue, isPolling, isSending, loadingAriaLabel, maxCharacters, maxLines, onInputBlur, onInputChange, onInputClick, onInputFocus, onKeyDown, onSubmit, placeholder, renderSendButton, sendAriaLabel, }: BpkChatbotInputInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export default BpkChatbotInputInput;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Backpack - Skyscanner's Design System
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2016 Skyscanner Ltd
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { useEffect } from 'react';
|
|
20
|
+
import BpkButton, { BUTTON_TYPES, SIZE_TYPES } from "../../bpk-component-button";
|
|
21
|
+
import { withButtonAlignment } from "../../bpk-component-icon";
|
|
22
|
+
import ArrowUpIcon from "../../bpk-component-icon/sm/long-arrow-up";
|
|
23
|
+
import { BpkFlex, BpkSpacing } from "../../bpk-component-layout";
|
|
24
|
+
import { getDataComponentAttribute } from "../../bpk-react-utils";
|
|
25
|
+
import { useChatbotInputContext } from "./BpkChatbotInputContext";
|
|
26
|
+
import InputField from "./InputField/InputField";
|
|
27
|
+
import TextAreaField from "./TextAreaField/TextAreaField";
|
|
28
|
+
import { CHATBOT_INPUT_TYPES } from "./common-types";
|
|
29
|
+
import { MAX_CHARACTERS } from "./constants";
|
|
30
|
+
import { useChatbotInput } from "./hooks";
|
|
31
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
32
|
+
const AlignedArrowUpIcon = withButtonAlignment(ArrowUpIcon);
|
|
33
|
+
const BpkChatbotInputInput = ({
|
|
34
|
+
inputValue,
|
|
35
|
+
isPolling = false,
|
|
36
|
+
isSending = false,
|
|
37
|
+
loadingAriaLabel,
|
|
38
|
+
maxCharacters = MAX_CHARACTERS,
|
|
39
|
+
maxLines,
|
|
40
|
+
onInputBlur,
|
|
41
|
+
onInputChange,
|
|
42
|
+
onInputClick = () => {},
|
|
43
|
+
onInputFocus,
|
|
44
|
+
onKeyDown = () => {},
|
|
45
|
+
onSubmit,
|
|
46
|
+
placeholder,
|
|
47
|
+
renderSendButton,
|
|
48
|
+
sendAriaLabel
|
|
49
|
+
}) => {
|
|
50
|
+
const {
|
|
51
|
+
inputType,
|
|
52
|
+
setIsOverLimit
|
|
53
|
+
} = useChatbotInputContext();
|
|
54
|
+
const {
|
|
55
|
+
containerHeight,
|
|
56
|
+
handleSubmit,
|
|
57
|
+
inputProps,
|
|
58
|
+
inputRef,
|
|
59
|
+
isCapped,
|
|
60
|
+
isCars,
|
|
61
|
+
isExpanding,
|
|
62
|
+
isOverLimit,
|
|
63
|
+
sendButtonDisabled,
|
|
64
|
+
textareaHeight
|
|
65
|
+
} = useChatbotInput({
|
|
66
|
+
placeholder,
|
|
67
|
+
inputType,
|
|
68
|
+
inputValue,
|
|
69
|
+
isPolling,
|
|
70
|
+
isSending,
|
|
71
|
+
maxCharacters,
|
|
72
|
+
maxLines,
|
|
73
|
+
onInputBlur,
|
|
74
|
+
onInputChange,
|
|
75
|
+
onInputClick,
|
|
76
|
+
onInputFocus,
|
|
77
|
+
onKeyDown,
|
|
78
|
+
onSubmit
|
|
79
|
+
});
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
setIsOverLimit(isOverLimit);
|
|
82
|
+
}, [isOverLimit, setIsOverLimit]);
|
|
83
|
+
const isComposer = inputType === CHATBOT_INPUT_TYPES.COMPOSER;
|
|
84
|
+
const flexProps = isCars ? {
|
|
85
|
+
align: 'center',
|
|
86
|
+
gap: BpkSpacing.MD
|
|
87
|
+
} : {
|
|
88
|
+
align: isExpanding ? 'flex-end' : 'center',
|
|
89
|
+
gap: BpkSpacing.Base
|
|
90
|
+
};
|
|
91
|
+
return /*#__PURE__*/_jsxs(BpkFlex, {
|
|
92
|
+
width: "100%",
|
|
93
|
+
...flexProps,
|
|
94
|
+
...getDataComponentAttribute('ChatbotInput.Input'),
|
|
95
|
+
children: [isCars ? /*#__PURE__*/_jsx(InputField, {
|
|
96
|
+
ref: inputRef,
|
|
97
|
+
...inputProps
|
|
98
|
+
}) : /*#__PURE__*/_jsx(TextAreaField, {
|
|
99
|
+
ref: inputRef,
|
|
100
|
+
containerHeight: containerHeight,
|
|
101
|
+
textareaHeight: textareaHeight,
|
|
102
|
+
isCapped: isCapped,
|
|
103
|
+
isExpanding: isExpanding,
|
|
104
|
+
isComposer: isComposer,
|
|
105
|
+
maxLines: maxLines,
|
|
106
|
+
...inputProps
|
|
107
|
+
}), renderSendButton ? renderSendButton({
|
|
108
|
+
disabled: sendButtonDisabled,
|
|
109
|
+
onClick: handleSubmit,
|
|
110
|
+
loading: isPolling,
|
|
111
|
+
ariaLabel: isPolling ? loadingAriaLabel : sendAriaLabel
|
|
112
|
+
}) : /*#__PURE__*/_jsx(BpkButton, {
|
|
113
|
+
type: BUTTON_TYPES.primary,
|
|
114
|
+
size: SIZE_TYPES.small,
|
|
115
|
+
iconOnly: true,
|
|
116
|
+
onClick: handleSubmit,
|
|
117
|
+
disabled: sendButtonDisabled,
|
|
118
|
+
loading: isPolling,
|
|
119
|
+
"aria-label": isPolling ? loadingAriaLabel : sendAriaLabel,
|
|
120
|
+
"data-testid": "bpk-chatbot-input-send",
|
|
121
|
+
children: /*#__PURE__*/_jsx(AlignedArrowUpIcon, {})
|
|
122
|
+
})]
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
export default BpkChatbotInputInput;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Backpack - Skyscanner's Design System
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2016 Skyscanner Ltd
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
20
|
+
import { BpkVStack, BpkSpacing } from "../../bpk-component-layout";
|
|
21
|
+
import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
|
|
22
|
+
import { BpkChatbotInputContext } from "./BpkChatbotInputContext";
|
|
23
|
+
import { CHATBOT_INPUT_TYPES } from "./common-types";
|
|
24
|
+
import STYLES from "./BpkChatbotInput.module.css";
|
|
25
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
26
|
+
const getClassName = cssModules(STYLES);
|
|
27
|
+
const BpkChatbotInputRoot = ({
|
|
28
|
+
align = 'flex-start',
|
|
29
|
+
children,
|
|
30
|
+
gap = BpkSpacing.Base,
|
|
31
|
+
inputType = CHATBOT_INPUT_TYPES.COMPOSER,
|
|
32
|
+
...rest
|
|
33
|
+
}) => {
|
|
34
|
+
const isCars = inputType === CHATBOT_INPUT_TYPES.CARS;
|
|
35
|
+
const isComposer = inputType === CHATBOT_INPUT_TYPES.COMPOSER;
|
|
36
|
+
const [isOverLimit, setIsOverLimit] = useState(false);
|
|
37
|
+
const stableSetIsOverLimit = useCallback(value => {
|
|
38
|
+
setIsOverLimit(value);
|
|
39
|
+
}, []);
|
|
40
|
+
const contextValue = useMemo(() => ({
|
|
41
|
+
inputType,
|
|
42
|
+
isOverLimit,
|
|
43
|
+
setIsOverLimit: stableSetIsOverLimit
|
|
44
|
+
}), [inputType, isOverLimit, stableSetIsOverLimit]);
|
|
45
|
+
const containerClassName = getClassName(isCars ? 'bpk-chatbot-input--cars' : 'bpk-chatbot-input--composer', isComposer && 'bpk-chatbot-input--composer--with-shadow', isOverLimit && !isCars && 'bpk-chatbot-input--composer--overLimit');
|
|
46
|
+
const paddingProps = isCars ? {
|
|
47
|
+
paddingTop: BpkSpacing.MD,
|
|
48
|
+
paddingBottom: BpkSpacing.MD,
|
|
49
|
+
paddingEnd: BpkSpacing.MD,
|
|
50
|
+
paddingStart: BpkSpacing.Base
|
|
51
|
+
} : {
|
|
52
|
+
padding: BpkSpacing.Base
|
|
53
|
+
};
|
|
54
|
+
const handleContainerEvent = e => {
|
|
55
|
+
e.stopPropagation();
|
|
56
|
+
};
|
|
57
|
+
return /*#__PURE__*/_jsx(BpkChatbotInputContext.Provider, {
|
|
58
|
+
value: contextValue,
|
|
59
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
60
|
+
className: containerClassName,
|
|
61
|
+
onClick: handleContainerEvent,
|
|
62
|
+
onTouchStart: handleContainerEvent,
|
|
63
|
+
role: "presentation",
|
|
64
|
+
"data-testid": "bpk-chatbot-input-container",
|
|
65
|
+
...getDataComponentAttribute('ChatbotInput'),
|
|
66
|
+
children: /*#__PURE__*/_jsx(BpkVStack, {
|
|
67
|
+
align: align,
|
|
68
|
+
gap: gap,
|
|
69
|
+
width: "100%",
|
|
70
|
+
...paddingProps,
|
|
71
|
+
...rest,
|
|
72
|
+
children: children
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
export default BpkChatbotInputRoot;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Backpack - Skyscanner's Design System
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2016 Skyscanner Ltd
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { BpkHStack, BpkSpacing } from "../../bpk-component-layout";
|
|
20
|
+
import { getDataComponentAttribute } from "../../bpk-react-utils";
|
|
21
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
|
+
const BpkChatbotInputToolbar = ({
|
|
23
|
+
children,
|
|
24
|
+
gap = BpkSpacing.Base,
|
|
25
|
+
...rest
|
|
26
|
+
}) => /*#__PURE__*/_jsx(BpkHStack, {
|
|
27
|
+
gap: gap,
|
|
28
|
+
width: "100%",
|
|
29
|
+
...getDataComponentAttribute('ChatbotInput.Toolbar'),
|
|
30
|
+
...rest,
|
|
31
|
+
children: children
|
|
32
|
+
});
|
|
33
|
+
export default BpkChatbotInputToolbar;
|
|
@@ -5,6 +5,7 @@ interface TextAreaFieldProps extends BaseInputFieldProps {
|
|
|
5
5
|
isCapped: boolean;
|
|
6
6
|
isExpanding: boolean;
|
|
7
7
|
isComposer: boolean;
|
|
8
|
+
maxLines?: number;
|
|
8
9
|
}
|
|
9
10
|
declare const TextAreaField: import("react").ForwardRefExoticComponent<TextAreaFieldProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
10
11
|
export default TextAreaField;
|
|
@@ -30,6 +30,7 @@ const TextAreaField = /*#__PURE__*/forwardRef(({
|
|
|
30
30
|
isComposer,
|
|
31
31
|
isExpanding,
|
|
32
32
|
isOverLimit = false,
|
|
33
|
+
maxLines,
|
|
33
34
|
onInputBlur,
|
|
34
35
|
onInputChange,
|
|
35
36
|
onInputClick,
|
|
@@ -84,7 +85,10 @@ const TextAreaField = /*#__PURE__*/forwardRef(({
|
|
|
84
85
|
rows: 1,
|
|
85
86
|
style: {
|
|
86
87
|
height: `${textareaHeight}px`,
|
|
87
|
-
resize: 'none'
|
|
88
|
+
resize: 'none',
|
|
89
|
+
...(maxLines !== undefined && {
|
|
90
|
+
maxHeight: `${textareaHeight}px`
|
|
91
|
+
})
|
|
88
92
|
}
|
|
89
93
|
})]
|
|
90
94
|
})
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import type { KeyboardEvent } from 'react';
|
|
1
|
+
import type { KeyboardEvent, ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { Props as BpkButtonProps } from '../../bpk-component-button';
|
|
3
|
+
import type { BpkStackProps } from '../../bpk-component-layout';
|
|
2
4
|
export declare const CHATBOT_INPUT_TYPES: {
|
|
3
5
|
readonly CARS: "cars";
|
|
4
6
|
readonly CARS_COMPOSER: "cars-composer";
|
|
5
7
|
readonly COMPOSER: "composer";
|
|
6
8
|
};
|
|
7
9
|
export type ChatbotInputType = (typeof CHATBOT_INPUT_TYPES)[keyof typeof CHATBOT_INPUT_TYPES];
|
|
8
|
-
export type
|
|
10
|
+
export type SendButtonRenderProps = {
|
|
11
|
+
disabled: boolean;
|
|
12
|
+
onClick: () => void;
|
|
13
|
+
loading: boolean;
|
|
14
|
+
ariaLabel: string;
|
|
15
|
+
};
|
|
16
|
+
export type BpkChatbotInputInputProps = {
|
|
9
17
|
inputValue: string;
|
|
10
18
|
/** Accessible label for the loading state button (required for screen readers). */
|
|
11
19
|
loadingAriaLabel: string;
|
|
@@ -18,10 +26,22 @@ export type BpkChatbotInputProps = {
|
|
|
18
26
|
placeholder: string;
|
|
19
27
|
isSending?: boolean;
|
|
20
28
|
isPolling?: boolean;
|
|
21
|
-
inputType?: ChatbotInputType;
|
|
22
29
|
maxCharacters?: number;
|
|
30
|
+
/** Maximum number of visible lines before the textarea scrolls. Defaults to 4 (expanding to 5 when content exceeds 4 lines). Only applies to multiline input types. */
|
|
31
|
+
maxLines?: number;
|
|
23
32
|
onInputClick?: () => void;
|
|
24
33
|
onKeyDown?: (e: KeyboardEvent) => void;
|
|
34
|
+
/** Optional render prop for customising the send button. The consumer should return a BpkButton with the supplied props. When omitted, the default send button is used. */
|
|
35
|
+
renderSendButton?: (props: SendButtonRenderProps) => ReactElement<BpkButtonProps>;
|
|
36
|
+
};
|
|
37
|
+
export type BpkChatbotInputRootProps = BpkStackProps & {
|
|
38
|
+
inputType?: ChatbotInputType;
|
|
39
|
+
};
|
|
40
|
+
export type BpkChatbotInputToolbarProps = BpkStackProps;
|
|
41
|
+
export type BpkChatbotInputNamespace = {
|
|
42
|
+
Root: (props: BpkChatbotInputRootProps) => ReactNode;
|
|
43
|
+
Input: (props: BpkChatbotInputInputProps) => ReactNode;
|
|
44
|
+
Toolbar: (props: BpkChatbotInputToolbarProps) => ReactNode;
|
|
25
45
|
};
|
|
26
46
|
export interface BaseInputFieldProps {
|
|
27
47
|
value: string;
|
|
@@ -11,6 +11,7 @@ interface UseChatbotInputOptions {
|
|
|
11
11
|
isPolling?: boolean;
|
|
12
12
|
inputType?: ChatbotInputType;
|
|
13
13
|
maxCharacters?: number;
|
|
14
|
+
maxLines?: number;
|
|
14
15
|
onInputClick?: () => void;
|
|
15
16
|
onKeyDown?: (e: KeyboardEvent) => void;
|
|
16
17
|
}
|
|
@@ -28,5 +29,5 @@ interface UseChatbotInputReturn {
|
|
|
28
29
|
textareaHeight: number;
|
|
29
30
|
isCapped: boolean;
|
|
30
31
|
}
|
|
31
|
-
declare const useChatbotInput: ({ inputType, inputValue, isPolling, isSending, maxCharacters, onInputBlur, onInputChange, onInputClick, onInputFocus, onKeyDown, onSubmit, placeholder, }: UseChatbotInputOptions) => UseChatbotInputReturn;
|
|
32
|
+
declare const useChatbotInput: ({ inputType, inputValue, isPolling, isSending, maxCharacters, maxLines, onInputBlur, onInputChange, onInputClick, onInputFocus, onKeyDown, onSubmit, placeholder, }: UseChatbotInputOptions) => UseChatbotInputReturn;
|
|
32
33
|
export default useChatbotInput;
|
|
@@ -26,6 +26,7 @@ const useChatbotInput = ({
|
|
|
26
26
|
isPolling = false,
|
|
27
27
|
isSending = false,
|
|
28
28
|
maxCharacters = MAX_CHARACTERS,
|
|
29
|
+
maxLines,
|
|
29
30
|
onInputBlur,
|
|
30
31
|
onInputChange,
|
|
31
32
|
onInputClick = () => {},
|
|
@@ -48,7 +49,8 @@ const useChatbotInput = ({
|
|
|
48
49
|
} = useTextAreaAutoResize({
|
|
49
50
|
ref: inputRef,
|
|
50
51
|
value: inputValue,
|
|
51
|
-
enabled: isMultiLine
|
|
52
|
+
enabled: isMultiLine,
|
|
53
|
+
maxLines
|
|
52
54
|
});
|
|
53
55
|
const handleSubmit = useCallback(() => {
|
|
54
56
|
if (inputValue.trim() && !isDisabled && !isOverLimit) {
|
|
@@ -3,6 +3,7 @@ interface UseTextAreaAutoResizeProps {
|
|
|
3
3
|
ref: RefObject<HTMLTextAreaElement>;
|
|
4
4
|
value: string;
|
|
5
5
|
enabled?: boolean;
|
|
6
|
+
maxLines?: number;
|
|
6
7
|
}
|
|
7
8
|
interface UseTextAreaAutoResizeReturn {
|
|
8
9
|
isExpanding: boolean;
|
|
@@ -18,5 +19,5 @@ export declare const MAX_INPUT_HEIGHT_PHASE_2: number;
|
|
|
18
19
|
export declare const MIN_CONTAINER_HEIGHT = 24;
|
|
19
20
|
export declare const MAX_CONTAINER_HEIGHT = 96;
|
|
20
21
|
export declare const PARENT_PADDING_TOP = 16;
|
|
21
|
-
declare const useTextAreaAutoResize: ({ enabled, ref, value, }: UseTextAreaAutoResizeProps) => UseTextAreaAutoResizeReturn;
|
|
22
|
+
declare const useTextAreaAutoResize: ({ enabled, maxLines, ref, value, }: UseTextAreaAutoResizeProps) => UseTextAreaAutoResizeReturn;
|
|
22
23
|
export default useTextAreaAutoResize;
|
|
@@ -26,6 +26,7 @@ export const MAX_CONTAINER_HEIGHT = 96;
|
|
|
26
26
|
export const PARENT_PADDING_TOP = 16;
|
|
27
27
|
const useTextAreaAutoResize = ({
|
|
28
28
|
enabled = true,
|
|
29
|
+
maxLines,
|
|
29
30
|
ref,
|
|
30
31
|
value
|
|
31
32
|
}) => {
|
|
@@ -99,15 +100,27 @@ const useTextAreaAutoResize = ({
|
|
|
99
100
|
scrollHeight
|
|
100
101
|
} = measureEl;
|
|
101
102
|
const lines = Math.max(1, Math.ceil(scrollHeight / lineHeightRef.current));
|
|
102
|
-
const
|
|
103
|
-
const
|
|
103
|
+
const hasCustomMaxLines = maxLines !== undefined;
|
|
104
|
+
const isCapped = hasCustomMaxLines ? lines >= maxLines : lines >= 5;
|
|
105
|
+
let maxInputHeight;
|
|
106
|
+
if (hasCustomMaxLines) {
|
|
107
|
+
maxInputHeight = lineHeightRef.current * maxLines;
|
|
108
|
+
} else {
|
|
109
|
+
maxInputHeight = isCapped ? MAX_INPUT_HEIGHT_PHASE_2 : MAX_INPUT_HEIGHT_PHASE_1;
|
|
110
|
+
}
|
|
104
111
|
const targetInputHeight = Math.max(MIN_INPUT_HEIGHT, Math.min(scrollHeight, maxInputHeight));
|
|
105
|
-
const
|
|
106
|
-
const
|
|
112
|
+
const customMaxContainerHeight = hasCustomMaxLines ? lineHeightRef.current * maxLines : MAX_CONTAINER_HEIGHT;
|
|
113
|
+
const extraSpace = isCapped && !hasCustomMaxLines ? PARENT_PADDING_TOP : 0;
|
|
114
|
+
const targetContainerHeight = Math.max(MIN_CONTAINER_HEIGHT, Math.min(targetInputHeight - extraSpace, customMaxContainerHeight));
|
|
107
115
|
setDimensions(prev => {
|
|
108
116
|
const isContentAdded = value.length > previousValueRef.current.length;
|
|
109
117
|
const isAppending = value.startsWith(previousValueRef.current);
|
|
110
|
-
|
|
118
|
+
let prevMaxHeight;
|
|
119
|
+
if (hasCustomMaxLines) {
|
|
120
|
+
prevMaxHeight = lineHeightRef.current * maxLines;
|
|
121
|
+
} else {
|
|
122
|
+
prevMaxHeight = prev.isCapped ? MAX_INPUT_HEIGHT_PHASE_2 : MAX_INPUT_HEIGHT_PHASE_1;
|
|
123
|
+
}
|
|
111
124
|
const isInitialRender = isInitialRenderRef.current;
|
|
112
125
|
const shouldScroll = isContentAdded && isAppending && textarea.scrollHeight > prevMaxHeight || isInitialRender && scrollHeight > maxInputHeight;
|
|
113
126
|
shouldScrollRef.current = shouldScroll;
|
|
@@ -122,7 +135,7 @@ const useTextAreaAutoResize = ({
|
|
|
122
135
|
};
|
|
123
136
|
});
|
|
124
137
|
previousValueRef.current = value;
|
|
125
|
-
}, [value, ref, enabled, containerWidth]);
|
|
138
|
+
}, [value, ref, enabled, containerWidth, maxLines]);
|
|
126
139
|
useLayoutEffect(() => {
|
|
127
140
|
if (shouldScrollRef.current) {
|
|
128
141
|
scrollToBottom();
|
|
@@ -10,6 +10,9 @@ export type Props = {
|
|
|
10
10
|
title: ReactNode;
|
|
11
11
|
titleTextStyle?: TextStyle;
|
|
12
12
|
titleTagName?: Tag;
|
|
13
|
+
/** When true, prevents the title from being truncated with an ellipsis and allows it to wrap onto multiple lines.
|
|
14
|
+
* Note: this prop only applies when `title` is a string; ReactNode titles are not truncated and wrap naturally. */
|
|
15
|
+
wrapTitle?: boolean;
|
|
13
16
|
className?: string;
|
|
14
17
|
leadingButton?: ReactElement | null;
|
|
15
18
|
trailingButton?: ReactElement | null;
|
|
@@ -36,6 +36,7 @@ const BpkNavigationBar = props => {
|
|
|
36
36
|
titleTagName = "span",
|
|
37
37
|
titleTextStyle = TEXT_STYLES.heading5,
|
|
38
38
|
trailingButton,
|
|
39
|
+
wrapTitle = false,
|
|
39
40
|
...rest
|
|
40
41
|
} = props;
|
|
41
42
|
|
|
@@ -51,7 +52,7 @@ const BpkNavigationBar = props => {
|
|
|
51
52
|
className: getClassNames('bpk-navigation-bar__leading-item', `bpk-navigation-bar__leading-item--${barStyle}`),
|
|
52
53
|
children: leadingButton
|
|
53
54
|
}), typeof title === 'string' ? /*#__PURE__*/_jsx("span", {
|
|
54
|
-
className: getClassNames('bpk-navigation-bar__title', `bpk-navigation-bar__title--${barStyle}
|
|
55
|
+
className: getClassNames('bpk-navigation-bar__title', `bpk-navigation-bar__title--${barStyle}`, wrapTitle && 'bpk-navigation-bar__title--wrap'),
|
|
55
56
|
children: /*#__PURE__*/_jsx(BpkText, {
|
|
56
57
|
id: titleId,
|
|
57
58
|
textStyle: titleTextStyle,
|
|
@@ -15,4 +15,4 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
-
.bpk-navigation-bar{position:relative;display:grid;min-height:3.5rem;padding:1rem;grid-template-rows:auto;grid-template-columns:minmax(1.5rem, auto) minmax(1rem, 1fr) minmax(1.5rem, auto);justify-content:space-between;align-items:center;gap:1rem;background-color:#fff;background-color:var(--bpk-navigation-bar-background-color, rgb(255, 255, 255))}.bpk-navigation-bar--on-dark{background-color:#05203c}.bpk-navigation-bar__title{grid-column:2;text-align:center;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;color:#161616;color:var(--bpk-navigation-bar-title-color, rgb(22, 22, 22))}.bpk-navigation-bar__title :first-child{display:inline}.bpk-navigation-bar__title--on-dark{color:#fff}.bpk-navigation-bar__title-container{justify-self:center}.bpk-navigation-bar__leading-item,.bpk-navigation-bar__trailing-item{font-size:.875rem;line-height:1.25rem;font-weight:700}.bpk-navigation-bar__leading-item{grid-column:1;justify-self:start}.bpk-navigation-bar__trailing-item{grid-column:3;justify-self:end}.bpk-navigation-bar__sticky{position:sticky;top:0;z-index:899;box-shadow:0px 1px 3px 0px rgba(37,32,31,.3)}
|
|
18
|
+
.bpk-navigation-bar{position:relative;display:grid;min-height:3.5rem;padding:1rem;grid-template-rows:auto;grid-template-columns:minmax(1.5rem, auto) minmax(1rem, 1fr) minmax(1.5rem, auto);justify-content:space-between;align-items:center;gap:1rem;background-color:#fff;background-color:var(--bpk-navigation-bar-background-color, rgb(255, 255, 255))}.bpk-navigation-bar--on-dark{background-color:#05203c}.bpk-navigation-bar__title{grid-column:2;text-align:center;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;color:#161616;color:var(--bpk-navigation-bar-title-color, rgb(22, 22, 22))}.bpk-navigation-bar__title :first-child{display:inline}.bpk-navigation-bar__title--on-dark{color:#fff}.bpk-navigation-bar__title--wrap{text-overflow:unset;white-space:normal;overflow:visible}.bpk-navigation-bar__title-container{justify-self:center}.bpk-navigation-bar__leading-item,.bpk-navigation-bar__trailing-item{font-size:.875rem;line-height:1.25rem;font-weight:700}.bpk-navigation-bar__leading-item{grid-column:1;justify-self:start}.bpk-navigation-bar__trailing-item{grid-column:3;justify-self:end}.bpk-navigation-bar__sticky{position:sticky;top:0;z-index:899;box-shadow:0px 1px 3px 0px rgba(37,32,31,.3)}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import BpkButton, { BUTTON_TYPES } from "../../bpk-component-button";
|
|
20
|
-
import {
|
|
20
|
+
import { withLargeButtonAlignment, withRtlSupport } from "../../bpk-component-icon";
|
|
21
21
|
import LeftArrowIcon from "../../bpk-component-icon/lg/chevron-left";
|
|
22
22
|
import RightArrowIcon from "../../bpk-component-icon/lg/chevron-right";
|
|
23
23
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -26,8 +26,8 @@ export const DIRECTIONS = {
|
|
|
26
26
|
INDICATORS: 'INDICATORS',
|
|
27
27
|
NEXT: 'NEXT'
|
|
28
28
|
};
|
|
29
|
-
const AlignedLeftArrowIcon =
|
|
30
|
-
const AlignedRightArrowIcon =
|
|
29
|
+
const AlignedLeftArrowIcon = withLargeButtonAlignment(withRtlSupport(LeftArrowIcon));
|
|
30
|
+
const AlignedRightArrowIcon = withLargeButtonAlignment(withRtlSupport(RightArrowIcon));
|
|
31
31
|
const NavButton = ({
|
|
32
32
|
ariaLabel,
|
|
33
33
|
currentIndex,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyscanner/backpack-web",
|
|
3
|
-
"version": "42.
|
|
3
|
+
"version": "42.11.0",
|
|
4
4
|
"description": "Backpack Design System web library",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"d3-scale": "^4.0.2",
|
|
36
36
|
"downshift": "^9.0.10",
|
|
37
37
|
"intersection-observer": "^0.12.2",
|
|
38
|
-
"lodash": "^4.
|
|
38
|
+
"lodash": "^4.18.1",
|
|
39
39
|
"lodash.clamp": "^4.0.3",
|
|
40
40
|
"lodash.debounce": "^4.0.8",
|
|
41
41
|
"normalize.css": "4.2.0",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export interface SendButtonProps {
|
|
2
|
-
ariaLabel: string;
|
|
3
|
-
isCars?: boolean;
|
|
4
|
-
disabled?: boolean;
|
|
5
|
-
isLoading?: boolean;
|
|
6
|
-
onClick: () => void;
|
|
7
|
-
}
|
|
8
|
-
declare const SendButton: ({ ariaLabel, disabled, isCars, isLoading, onClick, }: SendButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
-
export default SendButton;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Backpack - Skyscanner's Design System
|
|
3
|
-
*
|
|
4
|
-
* Copyright 2016 Skyscanner Ltd
|
|
5
|
-
*
|
|
6
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
-
* you may not use this file except in compliance with the License.
|
|
8
|
-
* You may obtain a copy of the License at
|
|
9
|
-
*
|
|
10
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
*
|
|
12
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
-
* See the License for the specific language governing permissions and
|
|
16
|
-
* limitations under the License.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import BpkButton, { BUTTON_TYPES, SIZE_TYPES } from "../../../bpk-component-button";
|
|
20
|
-
import { withRtlSupport, withButtonAlignment } from "../../../bpk-component-icon";
|
|
21
|
-
import ArrowRightIcon from "../../../bpk-component-icon/sm/long-arrow-right";
|
|
22
|
-
import ArrowUpIcon from "../../../bpk-component-icon/sm/long-arrow-up";
|
|
23
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
|
-
const AlignedArrowRightIcon = withButtonAlignment(withRtlSupport(ArrowRightIcon));
|
|
25
|
-
const AlignedArrowUpIcon = withButtonAlignment(ArrowUpIcon);
|
|
26
|
-
const SendButton = ({
|
|
27
|
-
ariaLabel,
|
|
28
|
-
disabled = false,
|
|
29
|
-
isCars = true,
|
|
30
|
-
isLoading = false,
|
|
31
|
-
onClick
|
|
32
|
-
}) => {
|
|
33
|
-
const buttonType = isCars ? BUTTON_TYPES.featured : BUTTON_TYPES.primary;
|
|
34
|
-
const Icon = isCars ? AlignedArrowRightIcon : AlignedArrowUpIcon;
|
|
35
|
-
return /*#__PURE__*/_jsx(BpkButton, {
|
|
36
|
-
type: buttonType,
|
|
37
|
-
size: SIZE_TYPES.small,
|
|
38
|
-
iconOnly: true,
|
|
39
|
-
loading: isLoading,
|
|
40
|
-
onClick: onClick,
|
|
41
|
-
disabled: disabled,
|
|
42
|
-
"aria-label": ariaLabel,
|
|
43
|
-
"data-testid": isLoading ? 'bpk-chatbot-input-loading' : 'bpk-chatbot-input-send',
|
|
44
|
-
children: /*#__PURE__*/_jsx(Icon, {})
|
|
45
|
-
});
|
|
46
|
-
};
|
|
47
|
-
export default SendButton;
|