@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.
Files changed (56) hide show
  1. package/bpk-component-ai-blurb/src/BpkAiBlurb.module.css +1 -1
  2. package/bpk-component-ai-blurb/src/BpkAiBlurbFeedback.js +13 -21
  3. package/bpk-component-bubble/src/BpkBubble.module.css +1 -1
  4. package/bpk-component-calendar/src/BpkCalendarNav.d.ts +1 -1
  5. package/bpk-component-calendar/src/BpkCalendarNav.js +0 -1
  6. package/bpk-component-chatbot-input/index.d.ts +1 -2
  7. package/bpk-component-chatbot-input/src/BpkChatbotInput.d.ts +13 -3
  8. package/bpk-component-chatbot-input/src/BpkChatbotInput.js +18 -98
  9. package/bpk-component-chatbot-input/src/BpkChatbotInput.module.css +1 -1
  10. package/bpk-component-chatbot-input/src/BpkChatbotInputContext.d.ts +9 -0
  11. package/bpk-component-chatbot-input/src/BpkChatbotInputContext.js +26 -0
  12. package/bpk-component-chatbot-input/src/BpkChatbotInputInput.d.ts +3 -0
  13. package/bpk-component-chatbot-input/src/BpkChatbotInputInput.js +125 -0
  14. package/bpk-component-chatbot-input/src/BpkChatbotInputRoot.d.ts +3 -0
  15. package/bpk-component-chatbot-input/src/BpkChatbotInputRoot.js +77 -0
  16. package/bpk-component-chatbot-input/src/BpkChatbotInputToolbar.d.ts +3 -0
  17. package/bpk-component-chatbot-input/src/BpkChatbotInputToolbar.js +33 -0
  18. package/bpk-component-chatbot-input/src/TextAreaField/TextAreaField.d.ts +1 -0
  19. package/bpk-component-chatbot-input/src/TextAreaField/TextAreaField.js +5 -1
  20. package/bpk-component-chatbot-input/src/common-types.d.ts +23 -3
  21. package/bpk-component-chatbot-input/src/hooks/useChatbotInput.d.ts +2 -1
  22. package/bpk-component-chatbot-input/src/hooks/useChatbotInput.js +3 -1
  23. package/bpk-component-chatbot-input/src/hooks/useTextAreaAutoResize.d.ts +2 -1
  24. package/bpk-component-chatbot-input/src/hooks/useTextAreaAutoResize.js +19 -6
  25. package/bpk-component-layout/index.d.ts +4 -0
  26. package/bpk-component-layout/index.js +2 -0
  27. package/bpk-component-layout/src/BpkArkProvider.d.ts +20 -0
  28. package/bpk-component-layout/src/BpkArkProvider.js +112 -0
  29. package/bpk-component-layout/src/BpkLayoutProvider.d.ts +19 -0
  30. package/bpk-component-layout/src/BpkLayoutProvider.js +50 -0
  31. package/bpk-component-layout/src/BpkProvider.d.ts +6 -7
  32. package/bpk-component-layout/src/BpkProvider.js +13 -96
  33. package/bpk-component-layout/src/resolveTextStyle.d.ts +13 -0
  34. package/bpk-component-layout/src/resolveTextStyle.js +265 -0
  35. package/bpk-component-layout/src/theme.js +29 -252
  36. package/bpk-component-layout/src/tokenUtils.js +31 -9
  37. package/bpk-component-select/index.d.ts +5 -0
  38. package/bpk-component-select/index.js +3 -1
  39. package/bpk-component-select/src/BpkSelect.d.ts +18 -0
  40. package/bpk-component-select/src/BpkSelect.js +3 -28
  41. package/bpk-component-select/src/themeAttributes.d.ts +2 -0
  42. package/bpk-component-text/src/BpkText.module.css +1 -1
  43. package/bpk-component-theme-toggle/src/BpkThemeToggle.js +0 -1
  44. package/bpk-scrim-utils/src/focusScope.d.ts +5 -0
  45. package/bpk-scrim-utils/src/focusScope.js +88 -0
  46. package/bpk-scrim-utils/src/focusStore.d.ts +6 -0
  47. package/bpk-scrim-utils/src/focusStore.js +74 -0
  48. package/bpk-scrim-utils/src/withScrim.js +2 -5
  49. package/bpk-stylesheets/base.css +1 -1
  50. package/bpk-stylesheets/font.css +1 -1
  51. package/bpk-stylesheets/font.scss +80 -1
  52. package/bpk-stylesheets/larken.css +1 -1
  53. package/bpk-stylesheets/larken.scss +63 -1
  54. package/package.json +3 -5
  55. package/bpk-component-chatbot-input/src/SendButton/SendButton.d.ts +0 -9
  56. 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 isCapped = lines >= 5;
103
- const maxInputHeight = isCapped ? MAX_INPUT_HEIGHT_PHASE_2 : MAX_INPUT_HEIGHT_PHASE_1;
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 extraSpace = isCapped ? PARENT_PADDING_TOP : 0;
106
- const targetContainerHeight = Math.max(MIN_CONTAINER_HEIGHT, Math.min(targetInputHeight - extraSpace, MAX_CONTAINER_HEIGHT));
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
- const prevMaxHeight = prev.isCapped ? MAX_INPUT_HEIGHT_PHASE_2 : MAX_INPUT_HEIGHT_PHASE_1;
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
- * Wraps children with:
9
- * - Chakra UI system context (for layout components: BpkFlex, BpkGrid, etc.)
10
- * - Ark UI LocaleProvider (for Ark-based components: BpkCheckboxV2, BpkSegmentedControlV2, etc.)
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
- * RTL support: reads document direction reactively via MutationObserver and passes
13
- * the appropriate locale to Ark's LocaleProvider. All Ark-based components in the
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 { useEffect, useState } from 'react';
20
- import { LocaleProvider } from '@ark-ui/react';
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
- * Creates a Chakra UI system with Backpack token mappings.
23
+ * BpkProvider - Provides context for both Backpack layout and Ark-based components.
26
24
  *
27
- * Uses `defaultBaseConfig` (conditions + utilities only) instead of
28
- * `defaultConfig` to avoid bundling ~141KB of unused component recipes.
29
- * See: https://chakra-ui.com/guides/component-bundle-optimization
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
- * RTL support: reads document direction reactively via MutationObserver and passes
107
- * the appropriate locale to Ark's LocaleProvider. All Ark-based components in the
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
- const locale = useArkLocale();
117
- return /*#__PURE__*/_jsx(ChakraProvider, {
118
- value: bpkSystem,
119
- children: /*#__PURE__*/_jsx(LocaleProvider, {
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>;