@skyscanner/backpack-web 42.9.0 → 42.10.0-dev-v24445021679.1
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-bubble/src/BpkBubble.module.css +1 -1
- package/bpk-component-calendar/src/BpkCalendarNav.d.ts +1 -1
- package/bpk-component-calendar/src/BpkCalendarNav.js +0 -1
- 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-layout/index.d.ts +4 -0
- package/bpk-component-layout/index.js +2 -0
- package/bpk-component-layout/src/BpkArkProvider.d.ts +20 -0
- package/bpk-component-layout/src/BpkArkProvider.js +112 -0
- package/bpk-component-layout/src/BpkLayoutProvider.d.ts +19 -0
- package/bpk-component-layout/src/BpkLayoutProvider.js +50 -0
- package/bpk-component-layout/src/BpkProvider.d.ts +6 -7
- package/bpk-component-layout/src/BpkProvider.js +13 -96
- package/bpk-component-layout/src/resolveTextStyle.d.ts +13 -0
- package/bpk-component-layout/src/resolveTextStyle.js +265 -0
- package/bpk-component-layout/src/theme.js +29 -252
- package/bpk-component-layout/src/tokenUtils.js +31 -9
- package/bpk-component-select/index.d.ts +5 -0
- package/bpk-component-select/index.js +3 -1
- package/bpk-component-select/src/BpkSelect.d.ts +18 -0
- package/bpk-component-select/src/BpkSelect.js +3 -28
- package/bpk-component-select/src/themeAttributes.d.ts +2 -0
- package/bpk-component-text/src/BpkText.module.css +1 -1
- package/bpk-component-theme-toggle/src/BpkThemeToggle.js +0 -1
- package/bpk-scrim-utils/src/focusScope.d.ts +5 -0
- package/bpk-scrim-utils/src/focusScope.js +88 -0
- package/bpk-scrim-utils/src/focusStore.d.ts +6 -0
- package/bpk-scrim-utils/src/focusStore.js +74 -0
- package/bpk-scrim-utils/src/withScrim.js +2 -5
- package/bpk-stylesheets/base.css +1 -1
- package/bpk-stylesheets/font.css +1 -1
- package/bpk-stylesheets/font.scss +80 -1
- package/bpk-stylesheets/larken.css +1 -1
- package/bpk-stylesheets/larken.scss +63 -1
- package/package.json +3 -5
- package/bpk-component-chatbot-input/src/SendButton/SendButton.d.ts +0 -9
- package/bpk-component-chatbot-input/src/SendButton/SendButton.js +0 -47
|
@@ -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();
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
export { BpkProvider } from './src/BpkProvider';
|
|
2
|
+
export { BpkLayoutProvider } from './src/BpkLayoutProvider';
|
|
3
|
+
export { BpkArkProvider } from './src/BpkArkProvider';
|
|
2
4
|
export { BpkBox } from './src/BpkBox';
|
|
3
5
|
export { BpkVessel } from './src/BpkVessel';
|
|
4
6
|
export { BpkFlex } from './src/BpkFlex';
|
|
5
7
|
export { BpkGrid } from './src/BpkGrid';
|
|
6
8
|
export { BpkGridItem } from './src/BpkGridItem';
|
|
7
9
|
export type { BpkProviderProps } from './src/BpkProvider';
|
|
10
|
+
export type { BpkLayoutProviderProps } from './src/BpkLayoutProvider';
|
|
11
|
+
export type { BpkArkProviderProps } from './src/BpkArkProvider';
|
|
8
12
|
export type { BpkBoxProps } from './src/BpkBox';
|
|
9
13
|
export type { BpkVesselProps } from './src/BpkVessel';
|
|
10
14
|
export type { BpkFlexProps } from './src/BpkFlex';
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
export { BpkProvider } from "./src/BpkProvider";
|
|
20
|
+
export { BpkLayoutProvider } from "./src/BpkLayoutProvider";
|
|
21
|
+
export { BpkArkProvider } from "./src/BpkArkProvider";
|
|
20
22
|
export { BpkBox } from "./src/BpkBox";
|
|
21
23
|
export { BpkVessel } from "./src/BpkVessel";
|
|
22
24
|
export { BpkFlex } from "./src/BpkFlex";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface BpkArkProviderProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* BpkArkProvider - Provides locale context for Ark-based Backpack components.
|
|
7
|
+
*
|
|
8
|
+
* Wraps children with Ark UI's LocaleProvider, reactively tracking
|
|
9
|
+
* document direction (html[dir]) and language (html[lang]) via MutationObserver.
|
|
10
|
+
* This enables correct RTL rendering for Ark-based components such as
|
|
11
|
+
* BpkCheckboxV2, BpkSegmentedControlV2, etc.
|
|
12
|
+
*
|
|
13
|
+
* Use BpkProvider (which composes BpkLayoutProvider + BpkArkProvider) if you
|
|
14
|
+
* need both layout primitives and Ark-based components. Use BpkArkProvider
|
|
15
|
+
* directly only if you need Ark locale context without the Chakra layout system.
|
|
16
|
+
*
|
|
17
|
+
* @param {BpkArkProviderProps} props - The provider props.
|
|
18
|
+
* @returns {JSX.Element} The provider wrapping its children with Ark locale context.
|
|
19
|
+
*/
|
|
20
|
+
export declare const BpkArkProvider: ({ children, }: BpkArkProviderProps) => JSX.Element;
|
|
@@ -0,0 +1,112 @@
|
|
|
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, useState } from 'react';
|
|
20
|
+
import { LocaleProvider } from '@ark-ui/react';
|
|
21
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
|
+
// Fallback locale mapping used when no explicit locale is available on the document.
|
|
23
|
+
// Maps DOM direction to minimal BCP 47 locales understood by Ark's isRTL() utility.
|
|
24
|
+
// 'ar-SA' is the minimal RTL locale — Ark only uses it to derive dir='rtl'.
|
|
25
|
+
const FALLBACK_LOCALE_BY_DIRECTION = {
|
|
26
|
+
ltr: 'en-US',
|
|
27
|
+
rtl: 'ar-SA'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Known RTL language subtags (ISO 639 codes). Used as fallback when
|
|
31
|
+
// Intl.Locale.textInfo is unavailable (Node < 22, older browsers).
|
|
32
|
+
const RTL_LANGUAGE_SUBTAGS = new Set(['ar', 'he', 'fa', 'ur', 'yi', 'iw', 'ps', 'sd', 'ug', 'ku']);
|
|
33
|
+
|
|
34
|
+
// Returns the text direction implied by a BCP 47 locale string.
|
|
35
|
+
// Uses Intl.Locale.textInfo when available (Chrome 99+, Safari 15.4+, Firefox 126+, Node 22+);
|
|
36
|
+
// falls back to a known-RTL-subtag lookup.
|
|
37
|
+
const getLangDir = locale => {
|
|
38
|
+
try {
|
|
39
|
+
const dir = new Intl.Locale(locale).textInfo?.direction;
|
|
40
|
+
if (dir) return dir === 'rtl' ? 'rtl' : 'ltr';
|
|
41
|
+
} catch {
|
|
42
|
+
// Ignore invalid locale strings
|
|
43
|
+
}
|
|
44
|
+
return RTL_LANGUAGE_SUBTAGS.has(locale.split('-')[0].toLowerCase()) ? 'rtl' : 'ltr';
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Resolves the locale to pass to Ark's LocaleProvider.
|
|
48
|
+
//
|
|
49
|
+
// Priority rules:
|
|
50
|
+
// 1. If html[dir] is explicitly set:
|
|
51
|
+
// - Use html[lang] only when its direction is consistent with html[dir].
|
|
52
|
+
// - Otherwise fall back to FALLBACK_LOCALE_BY_DIRECTION[dir].
|
|
53
|
+
// This prevents an LTR html[lang] (e.g. 'en' from a page template) from
|
|
54
|
+
// overriding an explicit html[dir]="rtl" signal (e.g. from a dev RTL toggle).
|
|
55
|
+
// 2. If html[dir] is not set: use html[lang] if present, else 'en-US'.
|
|
56
|
+
//
|
|
57
|
+
// SSR-safe: returns 'en-US' when document is unavailable.
|
|
58
|
+
const getArkLocale = () => {
|
|
59
|
+
if (typeof document === 'undefined') return 'en-US';
|
|
60
|
+
const explicitDir = document.documentElement.getAttribute('dir');
|
|
61
|
+
const lang = document.documentElement.getAttribute('lang');
|
|
62
|
+
if (explicitDir === 'rtl' || explicitDir === 'ltr') {
|
|
63
|
+
if (lang && getLangDir(lang) === explicitDir) return lang;
|
|
64
|
+
return FALLBACK_LOCALE_BY_DIRECTION[explicitDir];
|
|
65
|
+
}
|
|
66
|
+
return lang || 'en-US';
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Reactive hook: subscribes to document.documentElement[dir] and [lang] changes
|
|
70
|
+
// via MutationObserver. Re-renders when direction or locale is toggled
|
|
71
|
+
// (e.g. Storybook RTL toolbar, runtime locale switcher).
|
|
72
|
+
// SSR-safe: always initialises to 'en-US' so server and client agree on the first render,
|
|
73
|
+
// avoiding hydration mismatches. The real locale is read inside useEffect,
|
|
74
|
+
// which does not run on the server.
|
|
75
|
+
const useArkLocale = () => {
|
|
76
|
+
const [locale, setLocale] = useState('en-US');
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
setLocale(getArkLocale());
|
|
79
|
+
const observer = new MutationObserver(() => setLocale(getArkLocale()));
|
|
80
|
+
observer.observe(document.documentElement, {
|
|
81
|
+
attributes: true,
|
|
82
|
+
attributeFilter: ['dir', 'lang']
|
|
83
|
+
});
|
|
84
|
+
return () => observer.disconnect();
|
|
85
|
+
}, []);
|
|
86
|
+
return locale;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* BpkArkProvider - Provides locale context for Ark-based Backpack components.
|
|
91
|
+
*
|
|
92
|
+
* Wraps children with Ark UI's LocaleProvider, reactively tracking
|
|
93
|
+
* document direction (html[dir]) and language (html[lang]) via MutationObserver.
|
|
94
|
+
* This enables correct RTL rendering for Ark-based components such as
|
|
95
|
+
* BpkCheckboxV2, BpkSegmentedControlV2, etc.
|
|
96
|
+
*
|
|
97
|
+
* Use BpkProvider (which composes BpkLayoutProvider + BpkArkProvider) if you
|
|
98
|
+
* need both layout primitives and Ark-based components. Use BpkArkProvider
|
|
99
|
+
* directly only if you need Ark locale context without the Chakra layout system.
|
|
100
|
+
*
|
|
101
|
+
* @param {BpkArkProviderProps} props - The provider props.
|
|
102
|
+
* @returns {JSX.Element} The provider wrapping its children with Ark locale context.
|
|
103
|
+
*/
|
|
104
|
+
export const BpkArkProvider = ({
|
|
105
|
+
children
|
|
106
|
+
}) => {
|
|
107
|
+
const locale = useArkLocale();
|
|
108
|
+
return /*#__PURE__*/_jsx(LocaleProvider, {
|
|
109
|
+
locale: locale,
|
|
110
|
+
children: children
|
|
111
|
+
});
|
|
112
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface BpkLayoutProviderProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* BpkLayoutProvider - Provides context for Backpack layout components only.
|
|
7
|
+
*
|
|
8
|
+
* Wraps children with the Chakra UI system context configured with Backpack
|
|
9
|
+
* tokens (spacing, breakpoints). This is the minimal provider needed by
|
|
10
|
+
* layout primitives (BpkBox, BpkFlex, BpkGrid, BpkStack, etc.).
|
|
11
|
+
*
|
|
12
|
+
* Use this instead of BpkProvider when you only need layout components and
|
|
13
|
+
* want to avoid bundling Ark UI (used by BpkCheckboxV2, BpkSegmentedControlV2,
|
|
14
|
+
* and other Ark-based components).
|
|
15
|
+
*
|
|
16
|
+
* @param {BpkLayoutProviderProps} props - The provider props.
|
|
17
|
+
* @returns {JSX.Element} The provider wrapping its children with Chakra context.
|
|
18
|
+
*/
|
|
19
|
+
export declare const BpkLayoutProvider: ({ children, }: BpkLayoutProviderProps) => JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
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 { ChakraProvider, createSystem, defaultBaseConfig } from '@chakra-ui/react';
|
|
20
|
+
import { createBpkConfig } from "./theme";
|
|
21
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
|
+
/**
|
|
23
|
+
* Creates a Chakra UI system with Backpack token mappings.
|
|
24
|
+
*
|
|
25
|
+
* Uses `defaultBaseConfig` (conditions + utilities only) instead of
|
|
26
|
+
* `defaultConfig` to avoid bundling ~141KB of unused component recipes.
|
|
27
|
+
* See: https://chakra-ui.com/guides/component-bundle-optimization
|
|
28
|
+
*/
|
|
29
|
+
const bpkSystem = createSystem(defaultBaseConfig, createBpkConfig());
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* BpkLayoutProvider - Provides context for Backpack layout components only.
|
|
33
|
+
*
|
|
34
|
+
* Wraps children with the Chakra UI system context configured with Backpack
|
|
35
|
+
* tokens (spacing, breakpoints). This is the minimal provider needed by
|
|
36
|
+
* layout primitives (BpkBox, BpkFlex, BpkGrid, BpkStack, etc.).
|
|
37
|
+
*
|
|
38
|
+
* Use this instead of BpkProvider when you only need layout components and
|
|
39
|
+
* want to avoid bundling Ark UI (used by BpkCheckboxV2, BpkSegmentedControlV2,
|
|
40
|
+
* and other Ark-based components).
|
|
41
|
+
*
|
|
42
|
+
* @param {BpkLayoutProviderProps} props - The provider props.
|
|
43
|
+
* @returns {JSX.Element} The provider wrapping its children with Chakra context.
|
|
44
|
+
*/
|
|
45
|
+
export const BpkLayoutProvider = ({
|
|
46
|
+
children
|
|
47
|
+
}) => /*#__PURE__*/_jsx(ChakraProvider, {
|
|
48
|
+
value: bpkSystem,
|
|
49
|
+
children: children
|
|
50
|
+
});
|
|
@@ -3,15 +3,14 @@ export interface BpkProviderProps {
|
|
|
3
3
|
children: ReactNode;
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
|
-
* BpkProvider - Provides context for Backpack layout and Ark-based components.
|
|
6
|
+
* BpkProvider - Provides context for both Backpack layout and Ark-based components.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* - Chakra UI system
|
|
10
|
-
* - Ark UI
|
|
8
|
+
* This is a convenience wrapper that composes:
|
|
9
|
+
* - BpkLayoutProvider (Chakra UI system for layout components: BpkFlex, BpkGrid, etc.)
|
|
10
|
+
* - BpkArkProvider (Ark UI locale for Ark-based components: BpkCheckboxV2, BpkSegmentedControlV2, etc.)
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* tree render correctly in RTL without requiring additional wrapping or prop changes.
|
|
12
|
+
* If you only use layout components and want a smaller bundle, use BpkLayoutProvider
|
|
13
|
+
* directly instead — it does not pull in @ark-ui/react.
|
|
15
14
|
*
|
|
16
15
|
* @param {BpkProviderProps} props - The provider props.
|
|
17
16
|
* @returns {JSX.Element} The provider wrapping its children with Chakra and Ark context.
|
|
@@ -16,109 +16,26 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { ChakraProvider, createSystem, defaultBaseConfig } from '@chakra-ui/react';
|
|
22
|
-
import { createBpkConfig } from "./theme";
|
|
19
|
+
import { BpkArkProvider } from "./BpkArkProvider";
|
|
20
|
+
import { BpkLayoutProvider } from "./BpkLayoutProvider";
|
|
23
21
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
22
|
/**
|
|
25
|
-
*
|
|
23
|
+
* BpkProvider - Provides context for both Backpack layout and Ark-based components.
|
|
26
24
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*/
|
|
31
|
-
const bpkSystem = createSystem(defaultBaseConfig, createBpkConfig());
|
|
32
|
-
// Fallback locale mapping used when no explicit locale is available on the document.
|
|
33
|
-
// Maps DOM direction to minimal BCP 47 locales understood by Ark's isRTL() utility.
|
|
34
|
-
// 'ar-SA' is the minimal RTL locale — Ark only uses it to derive dir='rtl'.
|
|
35
|
-
const FALLBACK_LOCALE_BY_DIRECTION = {
|
|
36
|
-
ltr: 'en-US',
|
|
37
|
-
rtl: 'ar-SA'
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// Known RTL language subtags (ISO 639 codes). Used as fallback when
|
|
41
|
-
// Intl.Locale.textInfo is unavailable (Node < 22, older browsers).
|
|
42
|
-
const RTL_LANGUAGE_SUBTAGS = new Set(['ar', 'he', 'fa', 'ur', 'yi', 'iw', 'ps', 'sd', 'ug', 'ku']);
|
|
43
|
-
|
|
44
|
-
// Returns the text direction implied by a BCP 47 locale string.
|
|
45
|
-
// Uses Intl.Locale.textInfo when available (Chrome 99+, Safari 15.4+, Firefox 126+, Node 22+);
|
|
46
|
-
// falls back to a known-RTL-subtag lookup.
|
|
47
|
-
const getLangDir = locale => {
|
|
48
|
-
try {
|
|
49
|
-
const dir = new Intl.Locale(locale).textInfo?.direction;
|
|
50
|
-
if (dir) return dir === 'rtl' ? 'rtl' : 'ltr';
|
|
51
|
-
} catch {
|
|
52
|
-
// Ignore invalid locale strings
|
|
53
|
-
}
|
|
54
|
-
return RTL_LANGUAGE_SUBTAGS.has(locale.split('-')[0].toLowerCase()) ? 'rtl' : 'ltr';
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Resolves the locale to pass to Ark's LocaleProvider.
|
|
58
|
-
//
|
|
59
|
-
// Priority rules:
|
|
60
|
-
// 1. If html[dir] is explicitly set:
|
|
61
|
-
// - Use html[lang] only when its direction is consistent with html[dir].
|
|
62
|
-
// - Otherwise fall back to FALLBACK_LOCALE_BY_DIRECTION[dir].
|
|
63
|
-
// This prevents an LTR html[lang] (e.g. 'en' from a page template) from
|
|
64
|
-
// overriding an explicit html[dir]="rtl" signal (e.g. from a dev RTL toggle).
|
|
65
|
-
// 2. If html[dir] is not set: use html[lang] if present, else 'en-US'.
|
|
66
|
-
//
|
|
67
|
-
// SSR-safe: returns 'en-US' when document is unavailable.
|
|
68
|
-
const getArkLocale = () => {
|
|
69
|
-
if (typeof document === 'undefined') return 'en-US';
|
|
70
|
-
const explicitDir = document.documentElement.getAttribute('dir');
|
|
71
|
-
const lang = document.documentElement.getAttribute('lang');
|
|
72
|
-
if (explicitDir === 'rtl' || explicitDir === 'ltr') {
|
|
73
|
-
if (lang && getLangDir(lang) === explicitDir) return lang;
|
|
74
|
-
return FALLBACK_LOCALE_BY_DIRECTION[explicitDir];
|
|
75
|
-
}
|
|
76
|
-
return lang || 'en-US';
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// Reactive hook: subscribes to document.documentElement[dir] and [lang] changes
|
|
80
|
-
// via MutationObserver. Re-renders BpkProvider when direction or locale is toggled
|
|
81
|
-
// (e.g. Storybook RTL toolbar, runtime locale switcher).
|
|
82
|
-
// SSR-safe: always initialises to 'en-US' so server and client agree on the first render,
|
|
83
|
-
// avoiding hydration mismatches. The real locale is read inside useEffect,
|
|
84
|
-
// which does not run on the server.
|
|
85
|
-
const useArkLocale = () => {
|
|
86
|
-
const [locale, setLocale] = useState('en-US');
|
|
87
|
-
useEffect(() => {
|
|
88
|
-
setLocale(getArkLocale());
|
|
89
|
-
const observer = new MutationObserver(() => setLocale(getArkLocale()));
|
|
90
|
-
observer.observe(document.documentElement, {
|
|
91
|
-
attributes: true,
|
|
92
|
-
attributeFilter: ['dir', 'lang']
|
|
93
|
-
});
|
|
94
|
-
return () => observer.disconnect();
|
|
95
|
-
}, []);
|
|
96
|
-
return locale;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* BpkProvider - Provides context for Backpack layout and Ark-based components.
|
|
101
|
-
*
|
|
102
|
-
* Wraps children with:
|
|
103
|
-
* - Chakra UI system context (for layout components: BpkFlex, BpkGrid, etc.)
|
|
104
|
-
* - Ark UI LocaleProvider (for Ark-based components: BpkCheckboxV2, BpkSegmentedControlV2, etc.)
|
|
25
|
+
* This is a convenience wrapper that composes:
|
|
26
|
+
* - BpkLayoutProvider (Chakra UI system for layout components: BpkFlex, BpkGrid, etc.)
|
|
27
|
+
* - BpkArkProvider (Ark UI locale for Ark-based components: BpkCheckboxV2, BpkSegmentedControlV2, etc.)
|
|
105
28
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* tree render correctly in RTL without requiring additional wrapping or prop changes.
|
|
29
|
+
* If you only use layout components and want a smaller bundle, use BpkLayoutProvider
|
|
30
|
+
* directly instead — it does not pull in @ark-ui/react.
|
|
109
31
|
*
|
|
110
32
|
* @param {BpkProviderProps} props - The provider props.
|
|
111
33
|
* @returns {JSX.Element} The provider wrapping its children with Chakra and Ark context.
|
|
112
34
|
*/
|
|
113
35
|
export const BpkProvider = ({
|
|
114
36
|
children
|
|
115
|
-
}) => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
locale: locale,
|
|
121
|
-
children: children
|
|
122
|
-
})
|
|
123
|
-
});
|
|
124
|
-
};
|
|
37
|
+
}) => /*#__PURE__*/_jsx(BpkLayoutProvider, {
|
|
38
|
+
children: /*#__PURE__*/_jsx(BpkArkProvider, {
|
|
39
|
+
children: children
|
|
40
|
+
})
|
|
41
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expands a textStyle token (or responsive object of tokens) into concrete
|
|
3
|
+
* CSS property values that can be spread directly onto a Chakra component.
|
|
4
|
+
*
|
|
5
|
+
* Supports:
|
|
6
|
+
* - Static values: `textStyle="heading-3"` → `{ fontSize, lineHeight, fontWeight }`
|
|
7
|
+
* - Responsive objects: `textStyle={{ mobile: 'heading-5', desktop: 'heading-3' }}`
|
|
8
|
+
* → `{ fontSize: { md: '...', '2xl': '...' }, lineHeight: { ... }, ... }`
|
|
9
|
+
*
|
|
10
|
+
* @param {any} value - A textStyle token string, responsive object, or undefined/null.
|
|
11
|
+
* @returns {Record<string, any>} An object of CSS props to spread, or an empty object if no match.
|
|
12
|
+
*/
|
|
13
|
+
export declare function expandTextStyleProps(value: any): Record<string, any>;
|