diff --git a/.storybook/main.ts b/.storybook/main.ts
index 660899fd1c..8d181c8db4 100644
--- a/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -20,7 +20,7 @@ import type { StorybookConfig } from '@storybook/react-webpack5';
const config: StorybookConfig = {
stories: [
- '../examples/**/stories.@(ts|tsx|js|jsx)',
+ '../examples/**/{stories,*.stories}.@(ts|tsx|js|jsx)',
],
addons: [
'@storybook/addon-a11y',
diff --git a/examples/bpk-component-layout/box-examples.tsx b/examples/bpk-component-layout/box-examples.tsx
new file mode 100644
index 0000000000..091208374b
--- /dev/null
+++ b/examples/bpk-component-layout/box-examples.tsx
@@ -0,0 +1,203 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ BpkBox,
+ BpkSpacing,
+} from '../../packages/bpk-component-layout';
+
+import Wrapper from './layout-wrapper';
+
+import STYLES from './examples.module.scss';
+
+/**
+ * Core layout example – demonstrates basic spacing usage.
+ *
+ * @returns {JSX.Element} A box with padding and margin using Backpack spacing tokens.
+ */
+export const SpacingExample = () => (
+
+
+
+ Default box with padding and margin using Backpack spacing tokens.
+
+
+
+);
+
+/**
+ * RTL-friendly spacing example – demonstrates margin/padding logical props.
+ *
+ * @returns {JSX.Element} Box using marginInline & paddingInline in RTL context.
+ */
+export const RtlSpacingExample = () => (
+
+
+
+
+ Box using marginInline & paddingInline in RTL context.
+
+
+
+
+);
+
+/**
+ * Size example – demonstrates width/height using semantic values.
+ *
+ * @returns {JSX.Element} Box with 50% width and 6rem minHeight.
+ */
+export const SizeExample = () => (
+
+
+
+ Box with 50% width and 6rem minHeight.
+
+
+
+);
+
+/**
+ * Responsive example – demonstrates breakpoint-based responsive layout props.
+ *
+ * @returns {JSX.Element} A box whose spacing changes across breakpoints.
+ */
+export const ResponsiveExample = () => (
+
+
+
+
+ Responsive item 1
+
+
+
+
+ Responsive item 2
+
+
+
+
+);
+
+/**
+ * Position example – demonstrates top/left offsets using allowed values.
+ *
+ * @returns {JSX.Element} A relative box with an absolutely positioned child.
+ */
+export const PositionExample = () => (
+
+
+
+
+ Relative box (10rem x 6rem)
+
+
+
+ Positioned child (top/left from 12rem, 6rem)
+
+
+
+
+
+);
+
+/**
+ * Flexbox example – demonstrates using BpkBox as a flex container.
+ *
+ * @returns {JSX.Element} A flex row with evenly spaced items.
+ */
+export const FlexExample = () => (
+
+
+ {[1, 2, 3].map((i) => (
+
+
+ Flex item {i}
+
+
+ ))}
+
+
+);
+
+/**
+ * Grid example – demonstrates using BpkBox as a grid container.
+ *
+ * @returns {JSX.Element} A simple three-column grid.
+ */
+export const GridExample = () => (
+
+
+ {[1, 2, 3, 4, 5, 6].map((i) => (
+
+
+ Grid cell {i}
+
+
+ ))}
+
+
+);
+
+/**
+ * Mixed visual regression example – used for Percy/visual tests.
+ *
+ * @returns {JSX.Element} A wrapper containing all Box examples for visual regression.
+ */
+export const MixedExample = () => (
+
+
+
+
+
+
+
+
+
+);
+
+
diff --git a/examples/bpk-component-layout/box.stories.tsx b/examples/bpk-component-layout/box.stories.tsx
new file mode 100644
index 0000000000..881db0c82a
--- /dev/null
+++ b/examples/bpk-component-layout/box.stories.tsx
@@ -0,0 +1,67 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ArgTypes, Title, Markdown } from '@storybook/addon-docs/blocks';
+
+import { BpkProvider, BpkBox } from '../../packages/bpk-component-layout';
+
+import {
+ SpacingExample,
+ RtlSpacingExample,
+ SizeExample,
+ ResponsiveExample,
+ PositionExample,
+ FlexExample,
+ GridExample,
+} from './box-examples';
+
+export default {
+ title: 'bpk-component-layout/Box',
+ component: BpkBox,
+ decorators: [
+ (Story: any) => (
+
+
+
+ ),
+ ],
+ parameters: {
+ docs: {
+ page: () => (
+ <>
+
+
+
+ Notes: `BpkBox` is the base layout primitive. It exposes a curated,
+ structural prop surface and tokenised spacing.
+
+ >
+ ),
+ },
+ },
+};
+
+export const Spacing = () => ;
+export const RtlSpacing = () => ;
+export const Size = () => ;
+export const Responsive = () => ;
+export const Position = () => ;
+export const FlexViaBox = () => ;
+export const GridViaBox = () => ;
+
+
diff --git a/examples/bpk-component-layout/examples.module.scss b/examples/bpk-component-layout/examples.module.scss
new file mode 100644
index 0000000000..6a174327b0
--- /dev/null
+++ b/examples/bpk-component-layout/examples.module.scss
@@ -0,0 +1,66 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@use '../../packages/bpk-mixins/tokens';
+@use '../../packages/bpk-mixins/typography';
+
+.bpk-layout-examples {
+ &__frame {
+ padding: tokens.bpk-spacing-base();
+ background-color: tokens.$bpk-canvas-contrast-day;
+ border-radius: tokens.$bpk-border-radius-md;
+
+ // Subtle grid to make layout boundaries easier to see.
+ background-size: 8px 8px;
+
+ // Outline the root element of each example (not the inner content).
+ // This avoids needing border props on layout primitives.
+ > :where(*) {
+ outline: tokens.$bpk-border-size-sm solid tokens.$bpk-line-day;
+ outline-offset: tokens.bpk-spacing-sm();
+ background-color: tokens.$bpk-canvas-day;
+ }
+ }
+
+ // Generic “item boundary” styling for Storybook examples.
+ // Use this on regular DOM elements (not layout primitives) to avoid exposing
+ // border props on the layout surface.
+ &__item {
+ outline: tokens.$bpk-border-size-sm solid tokens.$bpk-line-day;
+ outline-offset: 0;
+ border-radius: tokens.$bpk-border-radius-sm;
+ background-color: tokens.$bpk-canvas-day;
+ box-sizing: border-box;
+ }
+
+ &__outline {
+ @include typography.bpk-body-default;
+
+ display: block;
+ width: 100%;
+ padding: tokens.bpk-spacing-sm();
+
+ color: tokens.$bpk-text-primary-day;
+ background-color: tokens.$bpk-surface-highlight-day;
+
+ outline: tokens.$bpk-border-size-sm dashed tokens.$bpk-line-day;
+ outline-offset: 0;
+ border-radius: tokens.$bpk-border-radius-sm;
+ box-sizing: border-box;
+ }
+}
diff --git a/examples/bpk-component-layout/flex-examples.tsx b/examples/bpk-component-layout/flex-examples.tsx
new file mode 100644
index 0000000000..c5facf5633
--- /dev/null
+++ b/examples/bpk-component-layout/flex-examples.tsx
@@ -0,0 +1,170 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ BpkBox,
+ BpkFlex,
+ BpkSpacing,
+} from '../../packages/bpk-component-layout';
+
+import Wrapper from './layout-wrapper';
+
+import STYLES from './examples.module.scss';
+
+export const BpkFlexExample = () => (
+
+
+ {[1, 2, 3].map((i) => (
+
+
+ Flex item {i}
+
+
+ ))}
+
+
+);
+
+export const BpkFlexDirectionExample = () => (
+
+
+
+
+ Column item 1
+
+
+
+
+ Column item 2
+
+
+
+
+);
+
+export const BpkFlexWrapExample = () => (
+
+
+ {[1, 2, 3, 4, 5, 6].map((i) => (
+
+
+ Wrap Item {i}
+
+
+ ))}
+
+
+);
+
+export const BpkFlexResponsiveExample = () => (
+
+
+ {[1, 2, 3].map((i) => (
+
+
+ Responsive Item {i}
+
+
+ ))}
+
+
+);
+
+export const BpkFlexItemExample = () => (
+
+
+
+
+
+ Grow: 1
+
+
+
+
+
+
+ Grow: 2
+
+
+
+
+
+
+ Basis: 200px, Shrink: 0
+
+
+
+
+
+);
+
+export const BpkFlexInlineExample = () => (
+
+
+
+
+
+ Inline Flex 1
+
+
+
+
+ Inline Flex 2
+
+
+
+ {' '}
+ Text adjacent to inline flex
+
+
+);
diff --git a/examples/bpk-component-layout/flex.stories.tsx b/examples/bpk-component-layout/flex.stories.tsx
new file mode 100644
index 0000000000..5bffee2f34
--- /dev/null
+++ b/examples/bpk-component-layout/flex.stories.tsx
@@ -0,0 +1,45 @@
+import { ArgTypes, Title, Markdown } from '@storybook/addon-docs/blocks';
+
+import { BpkFlex, BpkProvider } from '../../packages/bpk-component-layout';
+
+import {
+ BpkFlexExample,
+ BpkFlexDirectionExample,
+ BpkFlexWrapExample,
+ BpkFlexResponsiveExample,
+ BpkFlexItemExample,
+ BpkFlexInlineExample,
+} from './flex-examples';
+
+export default {
+ title: 'bpk-component-layout/Flex',
+ component: BpkFlex,
+ decorators: [
+ (Story: any) => (
+
+
+
+ ),
+ ],
+ parameters: {
+ docs: {
+ page: () => (
+ <>
+
+
+
+ Notes: `BpkFlex` is a layout primitive for flexbox layouts. It
+ supports responsive values keyed by Backpack breakpoints.
+
+ >
+ ),
+ },
+ },
+};
+
+export const Default = BpkFlexExample;
+export const Direction = BpkFlexDirectionExample;
+export const Wrap = BpkFlexWrapExample;
+export const Responsive = BpkFlexResponsiveExample;
+export const ItemProps = BpkFlexItemExample;
+export const Inline = BpkFlexInlineExample;
diff --git a/examples/bpk-component-layout/grid-examples.tsx b/examples/bpk-component-layout/grid-examples.tsx
new file mode 100644
index 0000000000..42a547fbef
--- /dev/null
+++ b/examples/bpk-component-layout/grid-examples.tsx
@@ -0,0 +1,175 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ BpkBox,
+ BpkGrid,
+ BpkGridItem,
+ BpkSpacing,
+} from '../../packages/bpk-component-layout';
+
+import Wrapper from './layout-wrapper';
+
+import STYLES from './examples.module.scss';
+
+export const BpkGridExample = () => (
+
+
+ {[1, 2, 3, 4, 5, 6].map((i) => (
+
+
+ Grid cell {i}
+
+
+ ))}
+
+
+);
+
+export const BpkGridSpanExample = () => (
+
+
+
+
+
+ Box: Span 2 Columns
+
+
+
+
+
+ Cell 2
+
+
+
+
+
+ Box: Span 2 Rows
+
+
+
+
+
+ Cell 4
+
+
+
+
+ Cell 5
+
+
+
+
+);
+
+export const BpkGridWithItemExample = () => (
+
+
+
+
+
+ rowSpan=2
+
+
+
+
+
+
+ colSpan=2
+
+
+
+
+
+
+ colSpan=2
+
+
+
+
+
+
+
+ colSpan=4
+
+
+
+
+
+);
+
+export const BpkGridResponsiveExample = () => (
+
+
+ {[1, 2, 3, 4].map((i) => (
+
+
+
+ Responsive Col {i}
+
+
+
+ ))}
+
+
+);
diff --git a/examples/bpk-component-layout/grid.stories.tsx b/examples/bpk-component-layout/grid.stories.tsx
new file mode 100644
index 0000000000..dda1825d30
--- /dev/null
+++ b/examples/bpk-component-layout/grid.stories.tsx
@@ -0,0 +1,59 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ArgTypes, Title, Markdown } from '@storybook/addon-docs/blocks';
+
+import { BpkGrid, BpkProvider } from '../../packages/bpk-component-layout';
+
+import {
+ BpkGridExample,
+ BpkGridSpanExample,
+ BpkGridWithItemExample,
+ BpkGridResponsiveExample,
+} from './grid-examples';
+
+export default {
+ title: 'bpk-component-layout/Grid',
+ component: BpkGrid,
+ decorators: [
+ (Story: any) => (
+
+
+
+ ),
+ ],
+ parameters: {
+ docs: {
+ page: () => (
+ <>
+
+
+
+ Notes: `BpkGrid` and `BpkGridItem` are layout primitives for CSS
+ grid layouts.
+
+ >
+ ),
+ },
+ },
+};
+
+export const Default = BpkGridExample;
+export const Span = BpkGridSpanExample;
+export const WithItem = BpkGridWithItemExample;
+export const Responsive = BpkGridResponsiveExample;
diff --git a/examples/bpk-component-layout/layout-wrapper.tsx b/examples/bpk-component-layout/layout-wrapper.tsx
new file mode 100644
index 0000000000..41d7f17e0d
--- /dev/null
+++ b/examples/bpk-component-layout/layout-wrapper.tsx
@@ -0,0 +1,32 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { ReactNode } from 'react';
+
+import { BpkProvider } from '../../packages/bpk-component-layout';
+
+import STYLES from './examples.module.scss';
+
+const Wrapper = ({ children }: { children: ReactNode }) => (
+
+ {children}
+
+);
+
+export default Wrapper;
+
diff --git a/examples/bpk-component-layout/stack-examples.tsx b/examples/bpk-component-layout/stack-examples.tsx
new file mode 100644
index 0000000000..8351ecb81e
--- /dev/null
+++ b/examples/bpk-component-layout/stack-examples.tsx
@@ -0,0 +1,193 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { BpkButtonV2, BUTTON_TYPES } from '../../packages/bpk-component-button';
+import {
+ BpkBox,
+ BpkSpacing,
+ BpkStack,
+ BpkVStack,
+ BpkHStack,
+} from '../../packages/bpk-component-layout';
+
+import Wrapper from './layout-wrapper';
+
+import STYLES from './examples.module.scss';
+
+const Item = ({ label }: { label: string }) => (
+
+
+ {label}
+
+
+);
+// Content block component using BpkBox
+const ContentBlock = ({
+ description,
+ title,
+}: {
+ title: string;
+ description: string;
+}) => (
+
+
+
+ {title}
+ {description}
+
+
+
+);
+
+// 1) Vertical stack of content blocks
+export const VerticalContentBlocksExample = () => (
+
+
+
+
+
+
+
+);
+
+// 2) Horizontal stack of buttons
+export const HorizontalButtonsExample = () => (
+
+
+ Primary
+ Secondary
+ Link
+ Delete
+
+
+);
+
+// 3) Nested Stack example
+export const NestedStackExample = () => (
+
+
+
+
+
+
+
+
+
+
+
+ Horizontal stack with small gap
+ Horizontal stack with small gap
+
+
+
+
+
+);
+
+// 4) Default vertical stack
+export const StackDefaultExample = () => (
+
+
+
+
+
+
+
+);
+
+// 5) Horizontal stack (row)
+export const StackHorizontalExample = () => (
+
+
+
+
+
+
+
+);
+
+// 6) HStack (row with center align)
+export const HStackExample = () => (
+
+
+
+
+
+
+
+);
+
+// 7) VStack (column)
+export const VStackExample = () => (
+
+
+
+
+
+
+
+);
+
+// 8) Responsive direction
+export const ResponsiveDirectionExample = () => (
+
+
+
+
+
+
+
+);
diff --git a/examples/bpk-component-layout/stack.stories.tsx b/examples/bpk-component-layout/stack.stories.tsx
new file mode 100644
index 0000000000..8b85e89a81
--- /dev/null
+++ b/examples/bpk-component-layout/stack.stories.tsx
@@ -0,0 +1,68 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ArgTypes, Title, Markdown } from '@storybook/addon-docs/blocks';
+
+import { BpkProvider, BpkStack } from '../../packages/bpk-component-layout';
+
+import {
+ StackDefaultExample,
+ StackHorizontalExample,
+ HStackExample,
+ VStackExample,
+ VerticalContentBlocksExample,
+ ResponsiveDirectionExample,
+ HorizontalButtonsExample,
+ NestedStackExample,
+} from './stack-examples';
+
+export default {
+ title: 'bpk-component-layout/Stack',
+ component: BpkStack,
+ decorators: [
+ (Story: any) => (
+
+
+
+ ),
+ ],
+ parameters: {
+ docs: {
+ page: () => (
+ <>
+
+
+
+ Notes: `BpkStack`, `BpkHStack` and `BpkVStack` are layout primitives
+ for stacking items with tokenised gaps.
+
+ >
+ ),
+ },
+ },
+};
+
+export const VerticalContentBlocks = () => ;
+export const HorizontalButtons = () => ;
+export const NestedStack = () => ;
+export const StackDefault = () => ;
+export const StackHorizontal = () => ;
+export const StackH = () => ;
+export const StackV = () => ;
+export const StackResponsive = () => ;
+
diff --git a/examples/bpk-component-layout/stories.tsx b/examples/bpk-component-layout/stories.tsx
new file mode 100644
index 0000000000..e797d5c9a0
--- /dev/null
+++ b/examples/bpk-component-layout/stories.tsx
@@ -0,0 +1,122 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ BpkBox,
+ BpkFlex,
+ BpkGrid,
+ BpkGridItem,
+ BpkProvider,
+ BpkStack,
+} from '../../packages/bpk-component-layout';
+
+import {
+ FlexExample,
+ GridExample,
+ PositionExample,
+ ResponsiveExample,
+ RtlSpacingExample,
+ SizeExample,
+ SpacingExample,
+} from './box-examples';
+import {
+ BpkFlexDirectionExample,
+ BpkFlexExample,
+ BpkFlexInlineExample,
+ BpkFlexItemExample,
+ BpkFlexResponsiveExample,
+ BpkFlexWrapExample,
+} from './flex-examples';
+import {
+ BpkGridExample,
+ BpkGridResponsiveExample,
+ BpkGridSpanExample,
+ BpkGridWithItemExample,
+} from './grid-examples';
+import {
+ HStackExample,
+ HorizontalButtonsExample,
+ NestedStackExample,
+ ResponsiveDirectionExample,
+ StackDefaultExample,
+ StackHorizontalExample,
+ VStackExample,
+ VerticalContentBlocksExample,
+} from './stack-examples';
+
+export default {
+ title: 'bpk-component-layout',
+ component: BpkProvider,
+ subcomponents: {
+ BpkBox,
+ BpkFlex,
+ BpkGrid,
+ BpkGridItem,
+ BpkStack,
+ },
+ parameters: {
+ docs: {
+ // Use Storybook's default docs rendering.
+ page: undefined,
+ },
+ },
+};
+
+export const VisualTest = () => (
+ <>
+ {/* Box examples */}
+
+
+
+
+
+
+
+
+ {/* Flex examples */}
+
+
+
+
+
+
+
+ {/* Grid examples */}
+
+
+
+
+
+ {/* Stack examples */}
+
+
+
+
+
+
+
+
+ >
+);
+
+export const VisualTestWithZoom = {
+ render: VisualTest,
+ args: {
+ zoomEnabled: true,
+ },
+};
diff --git a/packages/bpk-component-layout/README.md b/packages/bpk-component-layout/README.md
new file mode 100644
index 0000000000..2ad890319f
--- /dev/null
+++ b/packages/bpk-component-layout/README.md
@@ -0,0 +1,159 @@
+# bpk-component-layout
+
+> Backpack layout components and tokens.
+
+## Overview
+
+`bpk-component-layout` provides **layout-only** primitives and layout tokens for Backpack:
+
+- `BpkProvider` – wraps your app or stories to provide the Backpack layout system.
+- `BpkBox` – a low‑level layout container for spacing, sizing and structural composition.
+- `BpkFlex` – a flexbox layout primitive with an ergonomic, responsive API.
+- `BpkGrid` / `BpkGridItem` – grid layout primitives for container + item placement.
+- `BpkStack` / `BpkHStack` / `BpkVStack` – stack layout primitives with tokenised gaps.
+- Typed layout tokens – spacing and size.
+
+Under the hood, this package is implemented as a **facade over a layout system** and generates **CSS at runtime**, but the public API is Backpack‑flavoured and token‑driven. Consumers should only interact with the Backpack components and tokens described here, not with the underlying system.
+
+## Usage
+
+### BpkProvider
+
+`BpkProvider` must wrap any layout components so that they can resolve Backpack tokens correctly:
+
+```tsx
+import { BpkProvider } from '@skyscanner/backpack-web/bpk-component-layout';
+
+export default function App({ children }) {
+ return {children};
+}
+```
+
+### BpkBox
+
+`BpkBox` is a layout container that exposes a **restricted, tokenised** prop API. It is intended for spacing, sizing and structural layout only – not for typography, colors, borders or complex interaction.
+
+```tsx
+import {
+ BpkBox,
+ BpkProvider,
+ BpkSpacing,
+} from '@skyscanner/backpack-web/bpk-component-layout';
+
+export default function Example() {
+ return (
+
+
+ Layout content
+
+
+ );
+}
+```
+
+## Layout tokens and props
+
+The layout API is intentionally limited and strongly typed. The main groups are:
+
+- **Spacing** – `padding`, `margin`, logical props (`marginStart`, `marginEnd`, `paddingInline`), `gap`:
+ - Values: `BpkSpacing` tokens (`BpkSpacing.XS`, `BpkSpacing.SM`, `BpkSpacing.MD`, …) or percentages (e.g. `'50%'`).
+- **Size** – `width`, `height`, `minWidth`, `minHeight`, `maxWidth`, `maxHeight`:
+ - Values: rem strings (e.g. `'6rem'`), percentages (e.g. `'50%'`) or semantic values (`'auto' | 'full' | 'fit-content'`).
+- **Position** – `top`, `right`, `bottom`, `left`:
+ - Values: rem strings (e.g. `'1rem'`) or percentages (e.g. `'50%'`).
+- **Testing attributes** – `data-testid`, `data-cy` for automation and testing.
+
+In addition, `BpkBox` forwards through a set of **flexbox and grid layout props** from the underlying layout system, for example:
+
+- `display="flex"`, `flexDirection`, `justifyContent`, `alignItems`, `flexWrap`
+- `display="grid"`, `gridTemplateColumns`, `gridTemplateRows`, `gap`
+
+In addition, `BpkBox` re‑introduces a **minimal interaction surface**:
+
+- `onClick`, `onFocus`, `onBlur`
+
+No other event handlers are exposed on layout components.
+
+## Component roles
+
+- **`BpkProvider`**: Provides the runtime layout system (tokens + breakpoints) for all layout primitives. Wrap your app (or Storybook) with it.
+- **`BpkBox`**: The base structural primitive. Use it for spacing/sizing/positioning and for composing simple flex/grid layouts via `display` + related props.
+- **`BpkFlex`**: A dedicated flex container primitive. Prefer this when you want a clear, ergonomic flex API (`direction/align/justify/wrap/...`) with Backpack responsive values.
+- **`BpkGrid` / `BpkGridItem`**: Dedicated grid primitives. Prefer these for grid layout composition; use `BpkGridItem` when you want explicit spans/placement.
+- **`BpkStack` / `BpkHStack` / `BpkVStack`**: Dedicated stack primitives. Prefer these when you want consistent tokenised gaps and the simplest stacking API.
+
+### Responsive values
+
+Layout props support **responsive overrides keyed by Backpack breakpoints**.
+Instead of Chakra’s default `sm/md/lg` keys or array syntax, use Backpack breakpoint tokens:
+
+- `small-mobile`
+- `mobile`
+- `small-tablet`
+- `tablet`
+- `desktop`
+
+Example:
+
+```tsx
+
+```
+
+Under the hood these keys are mapped to Chakra’s breakpoint keys (`base`, `sm`, `md`, `lg`, `xl`, `2xl`) before generating CSS.
+
+> **Important:** Responsive values are **mobile-first (min-width)**. A key like `mobile` means “apply from the mobile breakpoint and above” (it is not an “only within mobile” range).
+
+> **Note:** Array-based responsive values (e.g. `padding={[...values]}`) are **not supported**.
+> Passing an array will be ignored and will log a warning in non‑production environments.
+
+### Responsive support (high-level)
+
+- **Supported broadly (recommended)**: container-level layout props and spacing tokens (e.g. `padding/margin/gap`, `width/height`, `direction/templateColumns`, etc.)
+- **Not automatically universal**: item placement props can be more complex; add responsive support based on real usage (PoC-driven).
+
+In particular:
+
+- **`BpkBox`** supports Backpack responsive values for:
+ - **Spacing/size/position** props (tokenised): `padding`, `margin`, `gap`, `width/height`, `top/right/bottom/left`, etc.
+ - **Key structural layout props**: `display`, flex container/item props, and grid container props (via Backpack breakpoint keys).
+- **`BpkGridItem`** placement props like `colSpan/rowSpan` are currently scalar (non-responsive) and should be extended only when needed.
+
+## Constraints and design principles
+
+To keep layout predictable, performant and consistent with Backpack:
+
+- **No arbitrary class names** – `className` is not supported on layout components; use layout props and tokens instead.
+- **No inline styles** – `style` is not supported on layout components to avoid ad‑hoc overrides of the design system.
+- **No shorthand props** – Chakra shorthands such as `p`, `m`, `w`, `h`, `bg`, `rounded`, `shadow` are not exposed on Backpack layout components.
+- **No colors, borders, radii or shadows** – visual props such as `color`, `backgroundColor`, `borderColor`, `borderWidth`, `borderRadius`, `boxShadow` are not part of the layout surface.
+- **No composite border shorthands** – props like `border`, `borderX`, `borderInline`, `borderBlock` are not supported.
+- **No typography props** – font family/size/line height/etc. should come from dedicated text components, not from layout primitives.
+- **No transition/transform props** – layout components are purely structural; animations and transforms should live in higher‑level components.
+- **Token‑driven spacing** – spacing props only accept Backpack spacing tokens (or percentages) to keep design consistent and avoid magic numbers.
+- **Breakpoint‑driven responsiveness** – responsive overrides must use Backpack breakpoint keys in object form; array syntax is intentionally disabled.
+
+## Storybook and examples
+
+This package includes Storybook examples under `examples/bpk-component-layout` showing:
+
+- Basic spacing
+- RTL‑friendly spacing (`marginInline`, `paddingInline`)
+- Size props
+- Position props
+- Flexbox layout
+- Grid layout
+- Responsive layout using Backpack breakpoints
+
+Use these examples as a reference for how to compose layout props and tokens. As new layout components (e.g. `BpkFlex`, `BpkGrid`, `BpkStack`) are added, they should follow the same prop and constraints model.
diff --git a/packages/bpk-component-layout/index.ts b/packages/bpk-component-layout/index.ts
new file mode 100644
index 0000000000..b92453a0fc
--- /dev/null
+++ b/packages/bpk-component-layout/index.ts
@@ -0,0 +1,54 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { BpkProvider } from './src/BpkProvider';
+export { BpkBox } from './src/BpkBox';
+export { BpkFlex } from './src/BpkFlex';
+export { BpkGrid } from './src/BpkGrid';
+export { BpkGridItem } from './src/BpkGridItem';
+
+export type { BpkProviderProps } from './src/BpkProvider';
+export type { BpkBoxProps } from './src/BpkBox';
+export type { BpkFlexProps } from './src/BpkFlex';
+export type { BpkGridProps } from './src/BpkGrid';
+export type { BpkGridItemProps } from './src/BpkGridItem';
+export { BpkStack, BpkHStack, BpkVStack } from './src/BpkStack';
+export type { BpkStackProps } from './src/BpkStack';
+
+export type {
+ BpkCommonLayoutProps,
+ BpkBoxSpecificProps,
+ BpkFlexSpecificProps,
+ BpkGridSpecificProps,
+ BpkGridItemSpecificProps,
+} from './src/types';
+export type { BpkStackSpecificProps } from './src/types';
+
+// Export token types and utilities
+export type {
+ BpkSpacingToken,
+ BpkBreakpointToken,
+ BpkSpacingValue,
+ BpkBreakpointValue,
+} from './src/tokens';
+export {
+ BpkSpacing,
+ BpkBreakpoint,
+ isValidSpacingValue,
+ isPercentage,
+} from './src/tokens';
diff --git a/packages/bpk-component-layout/src/BpkBox-test.tsx b/packages/bpk-component-layout/src/BpkBox-test.tsx
new file mode 100644
index 0000000000..39e88e202d
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkBox-test.tsx
@@ -0,0 +1,97 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { render, fireEvent } from '@testing-library/react';
+
+import '@testing-library/jest-dom';
+
+import { BpkBox } from './BpkBox';
+import { BpkProvider } from './BpkProvider';
+import { BpkSpacing } from './tokens';
+
+describe('BpkBox', () => {
+ it('renders children content', () => {
+ const { getByText } = render(
+
+ Content
+ ,
+ );
+
+ expect(getByText('Content')).toBeInTheDocument();
+ });
+
+ it('ignores className prop to prevent style overrides', () => {
+ const { container } = render(
+
+ {/* @ts-expect-error className is intentionally not part of the public API */}
+
+ Content
+
+ ,
+ );
+
+ // Chakra renders a div as the Box root element
+ const div = container.querySelector('div');
+ expect(div).not.toHaveClass('custom-class');
+ });
+
+ it('applies layout props via Backpack tokens', () => {
+ const { container } = render(
+
+
+ Token box
+
+ ,
+ );
+
+ const div = container.querySelector('div');
+ expect(div).toBeInTheDocument();
+ // We don't assert exact styles because Chakra generates classes & vars,
+ // but we at least assert that the element rendered successfully.
+ });
+
+ it('supports basic interaction props: onClick, onFocus, onBlur', () => {
+ const handleClick = jest.fn();
+ const handleFocus = jest.fn();
+ const handleBlur = jest.fn();
+
+ const { getByText } = render(
+
+
+ Clickable
+
+ ,
+ );
+
+ const element = getByText('Clickable');
+
+ fireEvent.focus(element);
+ expect(handleFocus).toHaveBeenCalledTimes(1);
+
+ fireEvent.click(element);
+ expect(handleClick).toHaveBeenCalledTimes(1);
+
+ fireEvent.blur(element);
+ expect(handleBlur).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/packages/bpk-component-layout/src/BpkBox.tsx b/packages/bpk-component-layout/src/BpkBox.tsx
new file mode 100644
index 0000000000..9024c99d2b
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkBox.tsx
@@ -0,0 +1,30 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Box } from '@chakra-ui/react';
+
+import { processBpkComponentProps } from './tokenUtils';
+
+import type { BpkBoxProps } from './types';
+
+export const BpkBox = ({ children, ...props }: BpkBoxProps) => {
+ const processedProps = processBpkComponentProps(props, { component: 'BpkBox' });
+ return {children};
+};
+
+export type { BpkBoxProps };
diff --git a/packages/bpk-component-layout/src/BpkFlex-test.tsx b/packages/bpk-component-layout/src/BpkFlex-test.tsx
new file mode 100644
index 0000000000..fd1875698a
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkFlex-test.tsx
@@ -0,0 +1,68 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom';
+
+import { BpkFlex } from './BpkFlex';
+import { BpkProvider } from './BpkProvider';
+import { BpkSpacing } from './tokens';
+
+describe('BpkFlex', () => {
+ it('renders children content', () => {
+ const { getByText } = render(
+
+ Content
+ ,
+ );
+ expect(getByText('Content')).toBeInTheDocument();
+ });
+
+ it('accepts flex props: direction, justify, align, wrap, gap', () => {
+ const { container } = render(
+
+
+ Content
+
+ ,
+ );
+ expect(container.firstChild).toBeInTheDocument();
+ expect(container.firstChild).toHaveStyle('flex-direction: column');
+ expect(container.firstChild).toHaveStyle('justify-content: center');
+ expect(container.firstChild).toHaveStyle('align-items: center');
+ expect(container.firstChild).toHaveStyle('flex-wrap: wrap');
+ expect(container.firstChild).toHaveStyle(`gap: .5rem`);
+ });
+
+ it('supports responsive direction', () => {
+ const { container } = render(
+
+
+ Content
+
+ ,
+ );
+ expect(container.firstChild).toBeInTheDocument();
+ });
+});
diff --git a/packages/bpk-component-layout/src/BpkFlex.tsx b/packages/bpk-component-layout/src/BpkFlex.tsx
new file mode 100644
index 0000000000..12b5b33873
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkFlex.tsx
@@ -0,0 +1,62 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Flex } from '@chakra-ui/react';
+
+import {
+ processBpkComponentProps,
+} from './tokenUtils';
+
+import type { BpkFlexProps } from './types';
+
+export const BpkFlex = ({
+ align,
+ basis,
+ children,
+ direction,
+ grow,
+ inline,
+ justify,
+ shrink,
+ wrap,
+ ...props
+}: BpkFlexProps) => {
+ const processedProps = processBpkComponentProps(props, {
+ component: 'BpkFlex',
+ responsiveProps: {
+ flexDirection: direction,
+ justifyContent: justify,
+ alignItems: align,
+ flexWrap: wrap,
+ flexGrow: grow,
+ flexShrink: shrink,
+ flexBasis: basis,
+ },
+ });
+
+ return (
+
+ {children}
+
+ );
+};
+
+export type { BpkFlexProps };
diff --git a/packages/bpk-component-layout/src/BpkGrid-test.tsx b/packages/bpk-component-layout/src/BpkGrid-test.tsx
new file mode 100644
index 0000000000..1638f6be0b
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkGrid-test.tsx
@@ -0,0 +1,49 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom';
+
+import { BpkGrid } from './BpkGrid';
+import { BpkProvider } from './BpkProvider';
+import { BpkSpacing } from './tokens';
+
+describe('BpkGrid', () => {
+ it('renders children content', () => {
+ const { getByText } = render(
+
+ Content
+ ,
+ );
+ expect(getByText('Content')).toBeInTheDocument();
+ });
+
+ it('accepts grid props: justify, align, gap', () => {
+ const { container } = render(
+
+
+ Content
+
+ ,
+ );
+ expect(container.firstChild).toBeInTheDocument();
+ expect(container.firstChild).toHaveStyle('justify-content: center');
+ expect(container.firstChild).toHaveStyle('align-items: center');
+ expect(container.firstChild).toHaveStyle('gap: .5rem');
+ });
+});
diff --git a/packages/bpk-component-layout/src/BpkGrid.tsx b/packages/bpk-component-layout/src/BpkGrid.tsx
new file mode 100644
index 0000000000..9e762719dd
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkGrid.tsx
@@ -0,0 +1,66 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Grid } from '@chakra-ui/react';
+
+import { processBpkComponentProps } from './tokenUtils';
+
+import type { BpkGridProps } from './types';
+
+export const BpkGrid = ({
+ align,
+ autoColumns,
+ autoFlow,
+ autoRows,
+ children,
+ column,
+ inline,
+ justify,
+ row,
+ templateAreas,
+ templateColumns,
+ templateRows,
+ ...props
+}: BpkGridProps) => {
+ const processedProps = processBpkComponentProps(props, {
+ component: 'BpkGrid',
+ responsiveProps: {
+ justifyContent: justify,
+ alignItems: align,
+ gridTemplateColumns: templateColumns,
+ gridTemplateRows: templateRows,
+ gridTemplateAreas: templateAreas,
+ gridAutoFlow: autoFlow,
+ gridAutoRows: autoRows,
+ gridAutoColumns: autoColumns,
+ gridColumn: column,
+ gridRow: row,
+ },
+ });
+
+ return (
+
+ {children}
+
+ );
+};
+
+export type { BpkGridProps };
diff --git a/packages/bpk-component-layout/src/BpkGridItem-test.tsx b/packages/bpk-component-layout/src/BpkGridItem-test.tsx
new file mode 100644
index 0000000000..cb7e2919a4
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkGridItem-test.tsx
@@ -0,0 +1,62 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom';
+
+import { BpkGridItem } from './BpkGridItem';
+import { BpkProvider } from './BpkProvider';
+import { BpkSpacing } from './tokens';
+
+describe('BpkGridItem', () => {
+ it('renders its children', () => {
+ const { getByText } = render(
+
+
+ Grid item
+
+ ,
+ );
+
+ expect(getByText('Grid item')).toBeInTheDocument();
+ });
+
+ it('accepts grid span props', () => {
+ const { container } = render(
+
+
+ Spanning item
+
+ ,
+ );
+
+ expect(container.firstChild).toBeInTheDocument();
+ expect(container.firstChild).toHaveStyle('grid-column: span 2/span 2');
+ expect(container.firstChild).toHaveStyle('grid-row: span 3/span 3');
+ });
+
+ it('supports Backpack spacing tokens', () => {
+ const { container } = render(
+
+ Spacing item
+ ,
+ );
+
+ expect(container.firstChild).toBeInTheDocument();
+ });
+});
diff --git a/packages/bpk-component-layout/src/BpkGridItem.tsx b/packages/bpk-component-layout/src/BpkGridItem.tsx
new file mode 100644
index 0000000000..9938cf09d8
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkGridItem.tsx
@@ -0,0 +1,55 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { GridItem } from '@chakra-ui/react';
+
+import { processBpkProps } from './tokenUtils';
+
+import type { BpkGridItemProps } from './types';
+
+export const BpkGridItem = ({
+ area,
+ children,
+ colEnd,
+ colSpan,
+ colStart,
+ rowEnd,
+ rowSpan,
+ rowStart,
+ ...props
+}: BpkGridItemProps) => {
+ const processedProps = processBpkProps(props);
+
+ return (
+
+ {children}
+
+ );
+};
+
+export type { BpkGridItemProps };
+
diff --git a/packages/bpk-component-layout/src/BpkProvider-test.tsx b/packages/bpk-component-layout/src/BpkProvider-test.tsx
new file mode 100644
index 0000000000..9b34dadfb4
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkProvider-test.tsx
@@ -0,0 +1,49 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { render } from '@testing-library/react';
+
+import '@testing-library/jest-dom';
+
+import { BpkBox } from './BpkBox';
+import { BpkProvider } from './BpkProvider';
+import { BpkSpacing } from './tokens';
+
+describe('BpkProvider', () => {
+ it('renders children inside Chakra system without crashing', () => {
+ const { getByText } = render(
+
+
+ Layout content
+
+ ,
+ );
+
+ expect(getByText('Layout content')).toBeInTheDocument();
+ });
+
+ it('can render plain DOM children', () => {
+ const { getByText } = render(
+
+ Plain child
+ ,
+ );
+
+ expect(getByText('Plain child')).toBeInTheDocument();
+ });
+});
diff --git a/packages/bpk-component-layout/src/BpkProvider.tsx b/packages/bpk-component-layout/src/BpkProvider.tsx
new file mode 100644
index 0000000000..20cd2a95fe
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkProvider.tsx
@@ -0,0 +1,46 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { ReactNode } from 'react';
+
+import { ChakraProvider, createSystem, defaultConfig } from '@chakra-ui/react';
+
+import { createBpkConfig } from './theme';
+
+export interface BpkProviderProps {
+ children: ReactNode;
+}
+
+/**
+ * Creates a Chakra UI system with Backpack token mappings
+ * Chakra UI 3.0 uses `createSystem` with `defaultConfig` and custom config
+ */
+const bpkSystem = createSystem(defaultConfig, createBpkConfig());
+
+/**
+ * BpkProvider - Provides Chakra UI context for Backpack layout components
+ *
+ * Chakra UI 3.0 requires the `value` prop to be set to a system object.
+ * We create a custom system with Backpack tokens using createSystem.
+ *
+ * @param {BpkProviderProps} props - The provider props.
+ * @returns {JSX.Element} The provider wrapping its children with Chakra context.
+ */
+export const BpkProvider = ({ children }: BpkProviderProps): JSX.Element => (
+ {children}
+);
diff --git a/packages/bpk-component-layout/src/BpkStack-test.tsx b/packages/bpk-component-layout/src/BpkStack-test.tsx
new file mode 100644
index 0000000000..98cb4e47b2
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkStack-test.tsx
@@ -0,0 +1,124 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { render } from '@testing-library/react';
+
+import '@testing-library/jest-dom';
+
+import { BpkProvider } from './BpkProvider';
+import { BpkStack, BpkHStack, BpkVStack } from './BpkStack';
+import { BpkSpacing } from './tokens';
+
+describe('BpkStack', () => {
+ it('renders children content', () => {
+ const { getByText } = render(
+
+
+ Child 1
+ Child 2
+
+ ,
+ );
+
+ expect(getByText('Child 1')).toBeInTheDocument();
+ expect(getByText('Child 2')).toBeInTheDocument();
+ });
+
+ describe('BpkHStack', () => {
+ it('defaults to row direction', () => {
+ const { container } = render(
+
+
+ Child 1
+ Child 2
+
+ ,
+ );
+
+ // Chakra's HStack uses direction="row" and aligns items "center" by default
+ const stack = container.firstChild;
+ expect(stack).toHaveStyle('flex-direction: row');
+ expect(stack).toHaveStyle('align-items: center');
+ });
+ });
+
+ describe('BpkVStack', () => {
+ it('defaults to column direction', () => {
+ const { container } = render(
+
+
+ Child 1
+ Child 2
+
+ ,
+ );
+
+ // Chakra's VStack uses direction="column" and aligns items "center" by default
+ const stack = container.firstChild;
+ expect(stack).toHaveStyle('flex-direction: column');
+ expect(stack).toHaveStyle('align-items: center');
+ });
+ });
+
+ describe('BpkStack Props', () => {
+ it('accepts valid gap tokens', () => {
+ const { container } = render(
+
+
+ Child 1
+
+ ,
+ );
+
+ // We can check if the style attribute or class reflects the gap.
+ // Chakra usually applies 'gap' for Stack gap.
+ // The exact value depends on the theme, but it should be present.
+ const stack = container.firstChild;
+ // bpk-gap-lg usually maps to 1.5rem (24px)
+ expect(stack).toHaveStyle('gap: 1.5rem');
+ });
+
+ it('supports align and justify props', () => {
+ const { container } = render(
+
+
+ Child 1
+
+ ,
+ );
+
+ const stack = container.firstChild;
+ expect(stack).toHaveStyle('align-items: center');
+ expect(stack).toHaveStyle('justify-content: space-between');
+ });
+
+ it('filters out invalid props (e.g. className)', () => {
+ const { container } = render(
+
+ {/* @ts-expect-error className is intentionally not part of the public API */}
+
+ Child
+
+ ,
+ );
+
+ const stack = container.firstChild;
+ expect(stack).not.toHaveClass('forbidden-class');
+ });
+ });
+});
diff --git a/packages/bpk-component-layout/src/BpkStack.constant.ts b/packages/bpk-component-layout/src/BpkStack.constant.ts
new file mode 100644
index 0000000000..148bf181a9
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkStack.constant.ts
@@ -0,0 +1,28 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// these options align with Chakra's StackOption excluding separator
+// TODO: add separator to Stack
+const StackOptionKeys = [
+ 'align',
+ 'justify',
+ 'wrap',
+ 'direction',
+] as const;
+
+export default StackOptionKeys;
diff --git a/packages/bpk-component-layout/src/BpkStack.tsx b/packages/bpk-component-layout/src/BpkStack.tsx
new file mode 100644
index 0000000000..34aaf16fec
--- /dev/null
+++ b/packages/bpk-component-layout/src/BpkStack.tsx
@@ -0,0 +1,41 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Stack, VStack, HStack } from '@chakra-ui/react';
+
+import { processBpkComponentProps } from './tokenUtils';
+
+import type { BpkStackProps } from './types';
+
+export const BpkStack = ({ children, ...props }: BpkStackProps) => {
+ const processedProps = processBpkComponentProps(props, { component: 'BpkStack' });
+ return {children};
+};
+
+export const BpkHStack = ({ children, ...props }: BpkStackProps) => {
+ const processedProps = processBpkComponentProps(props, { component: 'BpkStack' });
+ return {children};
+};
+
+export const BpkVStack = ({ children, ...props }: BpkStackProps) => {
+ const processedProps = processBpkComponentProps(props, { component: 'BpkStack' });
+ return {children};
+};
+
+export type { BpkStackProps };
+
diff --git a/packages/bpk-component-layout/src/accessibility-test.tsx b/packages/bpk-component-layout/src/accessibility-test.tsx
new file mode 100644
index 0000000000..3686a48635
--- /dev/null
+++ b/packages/bpk-component-layout/src/accessibility-test.tsx
@@ -0,0 +1,106 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { render } from '@testing-library/react';
+import { axe } from 'jest-axe';
+
+import '@testing-library/jest-dom';
+
+import { BpkBox } from './BpkBox';
+import { BpkFlex } from './BpkFlex';
+import { BpkGrid } from './BpkGrid';
+import { BpkProvider } from './BpkProvider';
+import { BpkStack } from './BpkStack';
+import { BpkSpacing } from './tokens';
+
+describe('bpk-component-layout accessibility tests', () => {
+ it('BpkBox basic usage should not have detectable accessibility issues', async () => {
+ const { container } = render(
+
+
+ Accessible layout content
+
+ ,
+ );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ });
+
+ it('BpkStack basic usage should not have detectable accessibility issues', async () => {
+ const { container } = render(
+
+
+ Item one
+ Item two
+
+ ,
+ );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ });
+
+ it('BpkFlex basic usage should not have detectable accessibility issues', async () => {
+ const { container } = render(
+
+
+ Item 1
+ Item 2
+
+ ,
+ );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ });
+
+ it('BpkGrid basic usage should not have detectable accessibility issues', async () => {
+ const { container } = render(
+
+
+ Cell 1
+ Cell 2
+ Cell 3
+ Cell 4
+
+ ,
+ );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ });
+});
diff --git a/packages/bpk-component-layout/src/commonProps.ts b/packages/bpk-component-layout/src/commonProps.ts
new file mode 100644
index 0000000000..cc23fcdf93
--- /dev/null
+++ b/packages/bpk-component-layout/src/commonProps.ts
@@ -0,0 +1,142 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type {
+ BpkSpacingValue,
+ BpkSizeValue,
+ BpkPositionValue,
+ BpkResponsiveValue,
+} from './tokens';
+
+/**
+ * Common spacing-related props shared by all Backpack layout components
+ * All spacing props must use Backpack spacing tokens or percentages
+ */
+export interface BpkSpacingProps {
+ // Padding props
+ padding?: BpkResponsiveValue;
+ paddingTop?: BpkResponsiveValue;
+ paddingRight?: BpkResponsiveValue;
+ paddingBottom?: BpkResponsiveValue;
+ paddingLeft?: BpkResponsiveValue;
+
+ // Margin props
+ margin?: BpkResponsiveValue;
+ marginTop?: BpkResponsiveValue;
+ marginRight?: BpkResponsiveValue;
+ marginBottom?: BpkResponsiveValue;
+ marginLeft?: BpkResponsiveValue;
+ marginStart?: BpkResponsiveValue;
+ marginEnd?: BpkResponsiveValue;
+ paddingStart?: BpkResponsiveValue;
+ paddingEnd?: BpkResponsiveValue;
+ marginInline?: BpkResponsiveValue;
+ paddingInline?: BpkResponsiveValue;
+
+ // Gap
+ gap?: BpkResponsiveValue;
+
+ // Size props
+ // width, height etc allow rem values, percentages and a small set of
+ // semantic strings. We intentionally do not use spacing tokens here to
+ // avoid coupling layout sizes to the spacing scale.
+ width?: BpkResponsiveValue;
+ height?: BpkResponsiveValue;
+ minWidth?: BpkResponsiveValue;
+ minHeight?: BpkResponsiveValue;
+ maxWidth?: BpkResponsiveValue;
+ maxHeight?: BpkResponsiveValue;
+
+ // Position props (use rem values or percentages)
+ top?: BpkResponsiveValue;
+ right?: BpkResponsiveValue;
+ bottom?: BpkResponsiveValue;
+ left?: BpkResponsiveValue;
+}
+
+/**
+ * Common props for all Backpack layout components
+ * Combines spacing and color props, and explicitly excludes className and
+ * certain props (e.g. typography, composite borders, transitions) to keep
+ * layout components purely structural.
+ *
+ * NOTE:
+ * - Layout components other than BpkBox do not expose event handlers.
+ * - BpkBox reintroduces a minimal set of events (onClick, onFocus, onBlur)
+ * on its own props type.
+ */
+export interface BpkCommonLayoutProps extends BpkSpacingProps {
+ // Explicitly exclude className
+ className?: never;
+
+ // Explicitly exclude style to avoid ad-hoc inline styling on layout primitives.
+ style?: never;
+
+ // Testing & automation attributes
+ 'data-testid'?: string;
+ 'data-cy'?: string;
+
+ // Explicitly exclude color-related props to keep layout purely structural.
+ // These props still exist on the underlying Chakra Box, so we mark them as
+ // never here to prevent them from leaking into public layout APIs.
+ color?: never;
+ background?: never;
+ backgroundColor?: never;
+ borderColor?: never;
+ borderTopColor?: never;
+ borderRightColor?: never;
+ borderBottomColor?: never;
+ borderLeftColor?: never;
+
+ // Explicitly exclude border width props from the public layout API for now.
+ borderWidth?: never;
+ borderTopWidth?: never;
+ borderRightWidth?: never;
+ borderBottomWidth?: never;
+ borderLeftWidth?: never;
+
+ // Explicitly exclude border radius props from the public layout API for now.
+ borderRadius?: never;
+ borderTopLeftRadius?: never;
+ borderTopRightRadius?: never;
+ borderBottomLeftRadius?: never;
+ borderBottomRightRadius?: never;
+
+ // Explicitly exclude shadow props from the public layout API for now.
+ boxShadow?: never;
+
+ // Explicitly exclude composite border shorthand props to enforce tokenised API
+ border?: never;
+ borderTop?: never;
+ borderRight?: never;
+ borderBottom?: never;
+ borderLeft?: never;
+ borderInline?: never;
+ borderBlock?: never;
+ borderX?: never;
+ borderY?: never;
+
+ // Explicitly exclude transition & transform related props for performance reasons
+ transition?: never;
+ transitionProperty?: never;
+ transitionDuration?: never;
+ transitionTimingFunction?: never;
+ transitionDelay?: never;
+ transform?: never;
+ transformOrigin?: never;
+}
diff --git a/packages/bpk-component-layout/src/theme.ts b/packages/bpk-component-layout/src/theme.ts
new file mode 100644
index 0000000000..4c67123ef9
--- /dev/null
+++ b/packages/bpk-component-layout/src/theme.ts
@@ -0,0 +1,214 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineConfig } from '@chakra-ui/react';
+
+import type { ChakraBreakpointKey } from './tokens';
+
+// Import tokens from Backpack foundations
+// Note: Some tokens may not be in TypeScript definitions but exist at runtime
+
+const bpkTokens = require('@skyscanner/bpk-foundations-web/tokens/base.es6');
+
+// NOTE:
+// We intentionally do not use the raw breakpoint *values* from foundations here.
+// Foundations exports breakpoint values such as `breakpointMobile = "32rem"` which
+// are used primarily for max-width queries (e.g. `(max-width: 32rem)`).
+//
+// Backpack layout responsive values in this package are mobile-first and behave
+// like Chakra breakpoints (min-width thresholds). To align with Backpack’s
+// intended breakpoint ranges we define lower-bound (min-width) thresholds:
+//
+// - small-mobile: 320px+
+// - mobile: 360px+
+// - small-tablet: 513px+
+// - tablet: 769px+
+// - desktop: 1025px+
+
+// Note: Spacing tokens are defined as SCSS functions in Backpack foundations,
+// not as direct values. We need to use the actual rem values from the SCSS functions.
+// Based on @skyscanner/bpk-foundations-web/tokens/base.default.scss:
+// - bpk-spacing-sm() returns .25rem
+// - bpk-spacing-md() returns .5rem
+// - bpk-spacing-lg() returns 1.5rem
+// - bpk-spacing-xl() returns 2rem (needs verification)
+// - bpk-spacing-xxl() returns 2.5rem
+// - bpk-spacing-base() returns 1rem (standard base spacing)
+// TODO: CLOV-1021 - will add spacing tokens to Backpack Foundations package and use them here after we ship the PoC
+const spacingXs = '.125rem'; // 2px
+const spacingSm = '.25rem';
+const spacingBase = '1rem'; // Standard base spacing
+const spacingMd = '.5rem';
+const spacingLg = '1.5rem';
+const spacingXl = '2rem';
+const spacingXxl = '2.5rem';
+
+/**
+ * Backpack Theme Configuration for Chakra UI
+ *
+ * This theme maps Backpack design tokens from @skyscanner/bpk-foundations-web
+ * to Chakra UI's theme structure.
+ */
+
+/**
+ * Maps Backpack spacing tokens to actual rem values.
+ * These come directly from @skyscanner/bpk-foundations-web.
+ */
+// Spacing tokens - directly imported from foundations
+const spacingMap: Record = {
+ 'bpk-spacing-none': { value: '0' },
+ // Temporary: Foundations does not yet export a 2px spacing token. This will be
+ // replaced with a foundations value once available.
+ 'bpk-spacing-xs': { value: spacingXs },
+ 'bpk-spacing-sm': { value: spacingSm },
+ 'bpk-spacing-base': { value: spacingBase },
+ 'bpk-spacing-md': { value: spacingMd },
+ 'bpk-spacing-lg': { value: spacingLg },
+ 'bpk-spacing-xl': { value: spacingXl },
+ 'bpk-spacing-xxl': { value: spacingXxl },
+};
+
+/**
+ * Maps Backpack border size tokens to actual border width values
+ * These come directly from @skyscanner/bpk-foundations-web
+ */
+const borderSizeMap: Record = {
+ 'bpk-border-size-sm': bpkTokens.borderSizeSm,
+ 'bpk-border-size-lg': bpkTokens.borderSizeLg,
+ 'bpk-border-size-xl': bpkTokens.borderSizeXl,
+};
+
+/**
+ * Maps Backpack border radius tokens to actual radius values.
+ * These come directly from @skyscanner/bpk-foundations-web.
+ */
+const borderRadiusMap: Record = {
+ 'bpk-border-radius-none': '0',
+ 'bpk-border-radius-xs': bpkTokens.borderRadiusXs,
+ 'bpk-border-radius-sm': bpkTokens.borderRadiusSm,
+ 'bpk-border-radius-md': bpkTokens.borderRadiusMd,
+ 'bpk-border-radius-lg': bpkTokens.borderRadiusLg,
+ 'bpk-border-radius-xl': bpkTokens.borderRadiusXl,
+ 'bpk-border-radius-full': bpkTokens.borderRadiusFull,
+};
+
+/**
+ * Maps Backpack shadow tokens to actual box-shadow values
+ * These come directly from @skyscanner/bpk-foundations-web
+ */
+const shadowMap: Record = {
+ 'bpk-shadow-sm': bpkTokens.boxShadowSm,
+ 'bpk-shadow-lg': bpkTokens.boxShadowLg,
+ 'bpk-shadow-xl': bpkTokens.boxShadowXl,
+};
+
+/**
+ * Chakra expects raw width values (e.g. "48rem"), not full media queries.
+ * The media query construction is handled internally by Chakra's system.
+ *
+ * We align Backpack breakpoint tokens to Chakra's keys like this:
+ * - base: 0 (implicit)
+ * - sm: small-mobile (>= 320px)
+ * - md: mobile (>= 360px)
+ * - lg: small-tablet (>= 513px)
+ * - xl: tablet (>= 769px)
+ * - 2xl: desktop (>= 1025px)
+ */
+// TODO: CLOV-1021 - will add breakpoint boundary tokens to Backpack Foundations package and use them here after we ship the PoC
+const breakpointMap: Record = {
+ base: '0rem',
+ sm: '20rem', // 320px
+ md: '22.5rem', // 360px
+ lg: '32.0625rem', // 513px
+ xl: '48.0625rem', // 769px
+ '2xl': '64.0625rem', // 1025px
+};
+
+/**
+ * Exports spacing map for use in tokenUtils
+ * This allows tokenUtils to look up actual spacing values
+ *
+ * @returns {Record} A map of spacing token names to values.
+ */
+export function getSpacingMap(): Record {
+ // Return simple string values for backward compatibility with utilities
+ const simpleMap: Record = {};
+ Object.entries(spacingMap).forEach(([key, obj]) => {
+ simpleMap[key] = obj.value;
+ });
+ return simpleMap;
+}
+
+/**
+ * Gets the actual spacing value for a Backpack spacing token
+ *
+ * @param {string} token - Backpack spacing token name.
+ * @returns {string | undefined} The actual spacing value.
+ */
+export function getSpacingValue(token: string): string | undefined {
+ return spacingMap[token]?.value;
+}
+
+/**
+ * Gets the actual border width value for a Backpack border size token
+ *
+ * @param {string} token - Backpack border size token name.
+ * @returns {string | undefined} The actual border width value.
+ */
+export function getBorderSizeValue(token: string): string | undefined {
+ return borderSizeMap[token];
+}
+
+/**
+ * Gets the actual border radius value for a Backpack border radius token
+ *
+ * @param {string} token - Backpack border radius token name.
+ * @returns {string | undefined} The actual border radius value.
+ */
+export function getBorderRadiusValue(token: string): string | undefined {
+ return borderRadiusMap[token];
+}
+
+/**
+ * Gets the actual box-shadow value for a Backpack shadow token
+ *
+ * @param {string} token - Backpack shadow token name.
+ * @returns {string | undefined} The actual box-shadow value.
+ */
+export function getShadowValue(token: string): string | undefined {
+ return shadowMap[token];
+}
+
+export function createBpkConfig() {
+ // Convert breakpoint map to Chakra UI format
+ // Breakpoints in Chakra v3 are typically simple strings in the breakpoints object
+ const chakraBreakpoints: Record = {};
+ Object.entries(breakpointMap).forEach(([token, value]) => {
+ chakraBreakpoints[token] = value;
+ });
+
+ return defineConfig({
+ cssVarsPrefix: 'bpk',
+ theme: {
+ tokens: {
+ spacing: spacingMap,
+ },
+ breakpoints: chakraBreakpoints,
+ },
+ });
+}
diff --git a/packages/bpk-component-layout/src/tokenUtils-test.ts b/packages/bpk-component-layout/src/tokenUtils-test.ts
new file mode 100644
index 0000000000..1f3f31a01d
--- /dev/null
+++ b/packages/bpk-component-layout/src/tokenUtils-test.ts
@@ -0,0 +1,200 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ convertBpkSpacingToChakra,
+ processBpkComponentProps,
+ processBpkProps,
+ processResponsiveProps,
+} from './tokenUtils';
+import { BpkSpacing } from './tokens';
+
+describe('processBpkProps', () => {
+ it('converts spacing tokens to rem values', () => {
+ const result = processBpkProps({ padding: BpkSpacing.MD });
+
+ // bpk-spacing-md is mapped to .5rem in theme.ts
+ expect(result.padding).toBe('.5rem');
+ });
+
+ it('supports the temporary 2px spacing token (bpk-spacing-xs)', () => {
+ const result = processBpkProps({ padding: BpkSpacing.XS });
+
+ // bpk-spacing-xs is mapped to .125rem (2px) in theme.ts
+ expect(result.padding).toBe('.125rem');
+ });
+
+ it('passes through percentage spacing values unchanged', () => {
+ const result = processBpkProps({ margin: '50%' });
+
+ expect(result.margin).toBe('50%');
+ });
+
+ it('converts RTL and inline spacing props', () => {
+ const result = processBpkProps({
+ marginInline: BpkSpacing.Base,
+ paddingStart: BpkSpacing.SM,
+ paddingEnd: BpkSpacing.LG,
+ });
+
+ expect(result.marginInline).toBe('1rem');
+ expect(result.paddingStart).toBe('.25rem');
+ expect(result.paddingEnd).toBe('1.5rem');
+ });
+
+ it('validates and passes through size props (rem and percentages)', () => {
+ const result = processBpkProps({
+ width: '10rem',
+ height: '50%',
+ minWidth: '1.5rem',
+ maxHeight: '100%',
+ });
+
+ expect(result.width).toBe('10rem');
+ expect(result.height).toBe('50%');
+ expect(result.minWidth).toBe('1.5rem');
+ expect(result.maxHeight).toBe('100%');
+ });
+
+ it('removes invalid size values', () => {
+ const result = processBpkProps({
+ width: 'not-a-valid-size',
+ });
+
+ expect(result.width).toBeUndefined();
+ });
+
+ it('removes className and logs a warning in non-production', () => {
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
+
+ const result = processBpkProps({
+ className: 'custom-class',
+ padding: BpkSpacing.Base,
+ });
+
+ expect('className' in result).toBe(false);
+ expect(result.padding).toBe('1rem');
+
+ // In Jest, NODE_ENV is "test" so the warning should be emitted.
+ expect(warnSpy).toHaveBeenCalled();
+ warnSpy.mockRestore();
+ });
+
+ it('removes style and logs a warning in non-production', () => {
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
+
+ const result = processBpkProps({
+ // style is not part of the public API but should still be stripped
+ // and warned about at runtime if passed through accidentally.
+ style: { dummy: 'value' },
+ padding: BpkSpacing.Base,
+ });
+
+ expect('style' in result).toBe(false);
+ expect(result.padding).toBe('1rem');
+
+ // In Jest, NODE_ENV is "test" so the warning should be emitted.
+ expect(warnSpy).toHaveBeenCalled();
+ warnSpy.mockRestore();
+ });
+
+ it('converts Backpack breakpoint keys to Chakra keys for responsive objects', () => {
+ const result = processBpkProps({
+ padding: {
+ mobile: BpkSpacing.SM,
+ tablet: BpkSpacing.MD,
+ },
+ });
+
+ expect(result.padding).toEqual({
+ md: '.25rem',
+ xl: '.5rem',
+ });
+ });
+
+ it('maps Backpack breakpoint keys for non-spacing layout props via processResponsiveProps', () => {
+ const result = processResponsiveProps({
+ display: { mobile: 'flex', desktop: 'grid' },
+ flexDirection: { mobile: 'column', tablet: 'row' },
+ gridTemplateColumns: { tablet: 'repeat(2, 1fr)', desktop: 'repeat(4, 1fr)' },
+ });
+
+ expect(result).toEqual({
+ display: { md: 'flex', '2xl': 'grid' },
+ flexDirection: { md: 'column', xl: 'row' },
+ gridTemplateColumns: { xl: 'repeat(2, 1fr)', '2xl': 'repeat(4, 1fr)' },
+ });
+ });
+
+ it('does not let allowlisted Box layout props fall through unprocessed (e.g. array responsive values)', () => {
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
+
+ const result = processBpkComponentProps(
+ {
+ // Chakra array syntax is intentionally not supported in the public API.
+ display: ['flex', 'grid'],
+ } as any,
+ { component: 'BpkBox' },
+ );
+
+ expect(result.display).toBeUndefined();
+ expect(warnSpy).toHaveBeenCalled();
+ warnSpy.mockRestore();
+ });
+
+ it('removes array-based responsive values and warns in non-production', () => {
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
+
+ const result = processBpkProps({
+ // array-based responsive values are intentionally not supported
+ padding: [BpkSpacing.SM, BpkSpacing.MD] as any,
+ });
+
+ expect(result.padding).toBeUndefined();
+ expect(warnSpy).toHaveBeenCalled();
+ warnSpy.mockRestore();
+ });
+
+ it('warns and drops unknown breakpoint keys from responsive objects', () => {
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
+
+ const result = processBpkProps({
+ padding: {
+ // unknown key should be ignored
+ phablet: BpkSpacing.SM,
+ mobile: BpkSpacing.MD,
+ } as any,
+ });
+
+ expect(result.padding).toEqual({
+ md: '.5rem',
+ });
+ expect(warnSpy).toHaveBeenCalled();
+ warnSpy.mockRestore();
+ });
+
+ it('warns and returns unknown spacing tokens as-is (dev fallback)', () => {
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
+
+ const result = convertBpkSpacingToChakra('bpk-spacing-unknown');
+
+ expect(result).toBe('bpk-spacing-unknown');
+ expect(warnSpy).toHaveBeenCalled();
+ warnSpy.mockRestore();
+ });
+});
diff --git a/packages/bpk-component-layout/src/tokenUtils.ts b/packages/bpk-component-layout/src/tokenUtils.ts
new file mode 100644
index 0000000000..69ff2a23c7
--- /dev/null
+++ b/packages/bpk-component-layout/src/tokenUtils.ts
@@ -0,0 +1,486 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import StackOptionKeys from './BpkStack.constant';
+import { getSpacingValue } from './theme';
+import {
+ BpkBreakpointToChakraKey,
+ isValidSpacingValue,
+ isValidSizeValue,
+ isValidPositionValue,
+ isPercentage,
+} from './tokens';
+
+import type { BpkBreakpointToken } from './tokens';
+
+export type BpkLayoutComponentName = 'BpkBox' | 'BpkFlex' | 'BpkGrid' | 'BpkStack';
+
+/**
+ * Allowlisted, component-scoped prop groups that are eligible for Backpack responsive value
+ * processing (Backpack breakpoint keys -> Chakra breakpoint keys).
+ *
+ * NOTE:
+ * - Spacing/size/position props are processed separately via `processBpkProps` and therefore
+ * are intentionally NOT included here.
+ * - These groups are meant to keep the responsive surface predictable per component, while
+ * avoiding duplicated per-component breakpoint mapping logic.
+ */
+type BpkResponsivePropGroups = {
+ /**
+ * Container-level layout props (how children are laid out).
+ */
+ container: readonly string[];
+ /**
+ * Item-level layout props (how this element participates in a parent layout).
+ */
+ item?: readonly string[];
+};
+
+export const BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT: Record<
+ BpkLayoutComponentName,
+ BpkResponsivePropGroups
+> = {
+ BpkBox: {
+ container: [
+ // Display
+ 'display',
+ // Flex container props
+ 'flexDirection',
+ 'flexWrap',
+ 'justifyContent',
+ 'alignItems',
+ 'alignContent',
+ // Grid container props
+ 'gridTemplateColumns',
+ 'gridTemplateRows',
+ 'gridTemplateAreas',
+ 'gridAutoFlow',
+ 'gridAutoRows',
+ 'gridAutoColumns',
+ ],
+ item: [
+ // Flex item props
+ 'flex',
+ 'flexGrow',
+ 'flexShrink',
+ 'flexBasis',
+ 'order',
+ 'alignSelf',
+ 'justifySelf',
+ // Grid item placement props (useful on Box when composing grids)
+ 'gridColumn',
+ 'gridRow',
+ ],
+ },
+ // Note: BpkFlex maps its public API props to these Chakra keys.
+ BpkFlex: {
+ container: [
+ 'flexDirection',
+ 'justifyContent',
+ 'alignItems',
+ 'flexWrap',
+ ],
+ item: [
+ 'flexGrow',
+ 'flexShrink',
+ 'flexBasis',
+ ],
+ },
+ // Note: BpkGrid maps its public API props to these Chakra keys.
+ BpkGrid: {
+ container: [
+ 'justifyContent',
+ 'alignItems',
+ 'gridTemplateColumns',
+ 'gridTemplateRows',
+ 'gridTemplateAreas',
+ 'gridAutoFlow',
+ 'gridAutoRows',
+ 'gridAutoColumns',
+ ],
+ item: [
+ // Used when placing the grid itself within a parent grid.
+ 'gridColumn',
+ 'gridRow',
+ ],
+ },
+ // Note: BpkStack uses Chakra Stack option prop names directly.
+ BpkStack: {
+ container: StackOptionKeys as unknown as readonly string[],
+ },
+};
+
+export const BPK_RESPONSIVE_PROP_KEYS_BY_COMPONENT: Record<
+ BpkLayoutComponentName,
+ readonly string[]
+> = {
+ BpkBox: [
+ ...BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkBox.container,
+ ...(BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkBox.item ?? []),
+ ],
+ BpkFlex: [
+ ...BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkFlex.container,
+ ...(BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkFlex.item ?? []),
+ ],
+ BpkGrid: [
+ ...BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkGrid.container,
+ ...(BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkGrid.item ?? []),
+ ],
+ BpkStack: [...BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkStack.container],
+};
+
+export type ProcessBpkComponentPropsOptions = {
+ component: BpkLayoutComponentName;
+ /**
+ * Optional map of responsive props. When provided, it will be filtered to the
+ * allowlist for the given component, then breakpoint-normalised.
+ *
+ * This is useful for components like `BpkFlex` and `BpkGrid` that expose a
+ * public API with different prop names.
+ */
+ responsiveProps?: Record;
+ /**
+ * Optional mapping of source prop name -> target prop name.
+ * Primarily kept for parity with `processResponsiveProps`.
+ */
+ propNameMap?: Record;
+};
+
+function filterToAllowlist(
+ props: Record,
+ allowlist: readonly string[],
+): Record {
+ const allowed = new Set(allowlist);
+ const result: Record = {};
+ Object.keys(props).forEach((key) => {
+ if (allowed.has(key) && props[key] !== undefined) {
+ result[key] = props[key];
+ }
+ });
+ return result;
+}
+
+/**
+ * Process a component's props in one place:
+ * - strip className/style
+ * - process spacing/size/position props (including breakpoint mapping + token conversion)
+ * - process allowlisted non-spacing responsive layout props (breakpoint mapping only)
+ *
+ * The allowlist is grouped by component via `BPK_RESPONSIVE_PROP_KEYS_BY_COMPONENT`.
+ *
+ * @param {T} props - The component props to process.
+ * @param {ProcessBpkComponentPropsOptions} options - Component processing options (allowlist group + mapping).
+ * @returns {Record} The processed props ready to pass to Chakra primitives.
+ */
+export function processBpkComponentProps>(
+ props: T,
+ options: ProcessBpkComponentPropsOptions,
+): Record {
+ const processed = processBpkProps(props);
+
+ const allowlist = BPK_RESPONSIVE_PROP_KEYS_BY_COMPONENT[options.component];
+ const responsiveSource = options.responsiveProps
+ ? filterToAllowlist(options.responsiveProps, allowlist)
+ : filterToAllowlist(processed, allowlist);
+
+ if (Object.keys(responsiveSource).length === 0) {
+ return processed;
+ }
+
+ // Ensure allowlisted layout props do NOT fall through unprocessed (e.g. array responsive values).
+ // These props must be provided via the responsive processing pipeline only.
+ const cleanedProcessed: Record = { ...processed };
+ allowlist.forEach((key) => {
+ if (key in cleanedProcessed) {
+ delete cleanedProcessed[key];
+ }
+ });
+
+ const responsiveProcessed = processResponsiveProps(
+ responsiveSource,
+ options.propNameMap,
+ );
+
+ // Remove keys that ended up as `undefined` (e.g. array responsive values are rejected).
+ Object.keys(responsiveProcessed).forEach((key) => {
+ if (responsiveProcessed[key] === undefined) {
+ delete responsiveProcessed[key];
+ }
+ });
+
+ return { ...cleanedProcessed, ...responsiveProcessed };
+}
+
+/**
+ * Converts Backpack spacing token to Chakra UI compatible value
+ * Returns the actual spacing value from the theme, not a token path
+ *
+ * @param {string} value - Backpack spacing token (e.g., 'bpk-spacing-base') or percentage
+ * @returns {string} The actual spacing value in rem or the percentage string
+ */
+export function convertBpkSpacingToChakra(value: string): string {
+ if (isPercentage(value)) {
+ return value; // Percentages pass through
+ }
+
+ // Look up the actual spacing value from the theme
+ const spacingValue = getSpacingValue(value);
+ if (spacingValue !== undefined) {
+ return spacingValue;
+ }
+
+ // Fallback: if token not found, return the value as-is (will cause a warning)
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.warn(
+ `Spacing token "${value}" not found in theme. Returning as-is.`
+ );
+ }
+ return value;
+}
+
+/**
+ * Recursively processes responsive values (arrays or objects) to validate and convert tokens
+ *
+ * @param {*} value - The value to process (could be string, array, or object)
+ * @param {Function} converter - Function to convert valid tokens to actual values
+ * @param {Function} validator - Function to validate if a token is allowed
+ * @param {string} propName - The name of the prop being processed (for warning messages)
+ * @returns {*} The processed value with tokens converted, or undefined for invalid tokens
+ */
+export function normalizeResponsiveObject(value: Record): Record {
+ const normalized: Record = {};
+ Object.entries(value).forEach(([key, val]) => {
+ if (key === 'base') {
+ normalized.base = val;
+ return;
+ }
+
+ const chakraKey = BpkBreakpointToChakraKey[key as BpkBreakpointToken];
+ if (chakraKey) {
+ normalized[chakraKey] = val;
+ } else if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.warn(
+ `Unknown breakpoint "${key}" used in responsive prop. ` +
+ 'Use Backpack breakpoint tokens such as mobile, tablet or desktop.'
+ );
+ }
+ });
+ return normalized;
+}
+
+export function processResponsiveValue(
+ value: any,
+ converter: (v: string) => string,
+ validator: (v: string) => boolean,
+ propName: string
+): any {
+ if (value === undefined || value === null) {
+ return value;
+ }
+
+ if (Array.isArray(value)) {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.warn(
+ `Array-based responsive values are not supported for prop "${propName}". ` +
+ `Please use Backpack breakpoint keys instead.`
+ );
+ }
+ return undefined;
+ }
+
+ if (typeof value === 'object') {
+ const normalized = normalizeResponsiveObject(value);
+ const result: Record = {};
+ Object.keys(normalized).forEach((key) => {
+ const processedValue = processResponsiveValue(
+ normalized[key],
+ converter,
+ validator,
+ propName
+ );
+ if (processedValue !== undefined) {
+ result[key] = processedValue;
+ }
+ });
+ return Object.keys(result).length > 0 ? result : undefined;
+ }
+
+ const strValue = String(value);
+ if (!validator(strValue)) {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.warn(
+ `Invalid value "${strValue}" for prop "${propName}". ` +
+ `Only Backpack tokens are allowed.`
+ );
+ }
+ return undefined; // Invalid values are removed
+ }
+
+ return converter(strValue);
+}
+
+/**
+ * Validates and converts spacing props for Chakra UI
+ * Handles all spacing-related properties including padding, margin, gap, size, border radius and position
+ *
+ * @param {T} props - Component props object
+ * @returns {Record} Processed props with spacing tokens converted to actual values
+ */
+export function processSpacingProps>(
+ props: T
+): Record {
+ const spacingKeys = [
+ // Padding props
+ 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',
+ 'paddingStart', 'paddingEnd', 'paddingInline',
+ // Margin props
+ 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',
+ 'marginStart', 'marginEnd', 'marginInline',
+ // Gap and spacing
+ 'gap', 'spacing',
+ 'rowGap', 'columnGap',
+ // Size props
+ 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
+ // Position props
+ 'top', 'right', 'bottom', 'left',
+ ];
+
+ const processed: Record = { ...props };
+
+ spacingKeys.forEach((key) => {
+ if (key in processed && processed[key] !== undefined) {
+ const sizeKeys = ['width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight'];
+ const positionKeys = ['top', 'right', 'bottom', 'left'];
+
+ const isSizeProp = sizeKeys.includes(key);
+ const isPositionProp = positionKeys.includes(key);
+
+ let converter: (v: string) => string;
+ if (isSizeProp || isPositionProp) {
+ converter = (v: string) => v;
+ } else {
+ converter = convertBpkSpacingToChakra;
+ }
+
+ let validator: (v: string) => boolean;
+ if (isSizeProp) {
+ validator = isValidSizeValue;
+ } else if (isPositionProp) {
+ validator = isValidPositionValue;
+ } else {
+ validator = isValidSpacingValue;
+ }
+
+ const processedValue = processResponsiveValue(
+ processed[key],
+ converter,
+ validator,
+ key
+ );
+
+ if (processedValue !== undefined) {
+ processed[key] = processedValue;
+ } else {
+ delete processed[key];
+ }
+ }
+ });
+
+ return processed;
+}
+
+/**
+ * Processes all props to convert Backpack tokens to Chakra UI format
+ * Also explicitly removes className and style to prevent ad-hoc overrides
+ *
+ * Processing order:
+ * 1. Remove className & style
+ * 2. Process spacing props (includes position)
+ *
+ * @param {T} props - Component props object
+ * @returns {Record} Processed props with tokens converted and disallowed props removed
+ */
+export function processBpkProps>(
+ props: T
+): Record {
+ // Explicitly remove className and style to prevent style overrides
+ const { className, style, ...cleanProps } = props;
+
+ if (className !== undefined && process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.warn(
+ 'className prop is not allowed on Backpack layout components. ' +
+ 'It has been removed to maintain design system consistency.'
+ );
+ }
+
+ if (style !== undefined && process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.warn(
+ 'style prop is not allowed on Backpack layout components. ' +
+ 'It has been removed to maintain design system consistency.'
+ );
+ }
+
+ // Process spacing props (includes position)
+ return processSpacingProps(cleanProps);
+}
+
+/**
+ * Processes responsive props that are simple string/enum values (non-spacing)
+ * using Backpack breakpoint keys. Array syntax is rejected as in spacing.
+ *
+ * @param {*} value - The value to process
+ * @param {string} propName - The name of the prop being processed
+ * @returns {*} The processed value with breakpoint keys mapped to Chakra keys
+ */
+export function processResponsiveStringProp(value: any, propName: string): any {
+ return processResponsiveValue(
+ value,
+ (v: string) => v,
+ () => true,
+ propName
+ );
+}
+
+/**
+ * Processes a collection of responsive props.
+ * @param {Record} props - Object containing prop values.
+ * @param {Record} propNameMap - Map of prop name to CSS/Chakra property name (for error messages and mapping).
+ * @returns {Record} Processed props object.
+ */
+export function processResponsiveProps(
+ props: Record,
+ propNameMap?: Record
+): Record {
+ const processed: Record = {};
+ Object.keys(props).forEach((key) => {
+ if (props[key] !== undefined) {
+ const targetPropName = propNameMap ? propNameMap[key] || key : key;
+ processed[targetPropName] = processResponsiveStringProp(
+ props[key],
+ targetPropName
+ );
+ }
+ });
+ return processed;
+}
diff --git a/packages/bpk-component-layout/src/tokens.ts b/packages/bpk-component-layout/src/tokens.ts
new file mode 100644
index 0000000000..26b8c10fa0
--- /dev/null
+++ b/packages/bpk-component-layout/src/tokens.ts
@@ -0,0 +1,172 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Backpack Design Tokens for Layout Components
+ *
+ * This file provides token mappings from Backpack design tokens to Chakra UI theme.
+ * All tokens are sourced from @skyscanner/bpk-foundations-web
+ */
+
+/**
+ * Backpack Spacing Tokens
+ * Use these constants to ensure type safety when passing spacing props
+ */
+export const BpkSpacing = {
+ None: 'bpk-spacing-none',
+ XS: 'bpk-spacing-xs',
+ SM: 'bpk-spacing-sm',
+ Base: 'bpk-spacing-base',
+ MD: 'bpk-spacing-md',
+ LG: 'bpk-spacing-lg',
+ XL: 'bpk-spacing-xl',
+ XXL: 'bpk-spacing-xxl',
+} as const;
+
+export type BpkSpacingToken = typeof BpkSpacing[keyof typeof BpkSpacing];
+
+/**
+ * Backpack Breakpoint Tokens
+ * Use these constants to ensure type safety when defining responsive overrides
+ * These map to the simplified keys defined in the Chakra theme
+ */
+export const BpkBreakpoint = {
+ SmallMobile: 'small-mobile',
+ Mobile: 'mobile',
+ SmallTablet: 'small-tablet',
+ Tablet: 'tablet',
+ Desktop: 'desktop',
+} as const;
+
+export type BpkBreakpointToken = typeof BpkBreakpoint[keyof typeof BpkBreakpoint];
+
+export type ChakraBreakpointKey = 'base' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
+
+export const BpkBreakpointToChakraKey: Record = {
+ // Keep this mapping in sync with the breakpoints configured in `theme.ts`.
+ // `base` is reserved for "default value" and is not a breakpoint token.
+ 'small-mobile': 'sm',
+ mobile: 'md',
+ 'small-tablet': 'lg',
+ tablet: 'xl',
+ desktop: '2xl',
+};
+
+/**
+ * Helper type for values that can be Backpack tokens or percentages
+ * but NOT px/rem values
+ */
+export type BpkSpacingValue = BpkSpacingToken | `${number}%`;
+export type BpkBreakpointValue = BpkBreakpointToken;
+
+/**
+ * Helper type for size props that can use rem, percentages or semantic values.
+ * This is intentionally separate from BpkSpacingValue to avoid encouraging
+ * spacing tokens for explicit sizes.
+ */
+export type BpkSizeValue =
+ | `${number}rem`
+ | `${number}%`
+ | 'auto'
+ | 'full'
+ | 'fit-content';
+
+/**
+ * Helper type for position props that can use rem or percentages.
+ * We intentionally do not allow semantic values like 'auto' here.
+ */
+export type BpkPositionValue =
+ | `${number}rem`
+ | `${number}%`;
+
+/**
+ * Helper type for flex-basis prop that can use rem, percentages or semantic values.
+ * Excludes 'px' values to enforce design system constraints.
+ */
+export type BpkBasisValue =
+ | `${number}rem`
+ | `${number}%`
+ | 'auto'
+ | 'content'
+ | 'fit-content'
+ | 'max-content'
+ | 'min-content'
+ | 'initial'
+ | 'inherit';
+
+/**
+ * Helper type for responsive values based on Backpack breakpoints.
+ *
+ * We intentionally only support:
+ * - a single scalar value (non-responsive)
+ * - an object keyed by Backpack breakpoint tokens (and optional base)
+ *
+ * We do NOT support array-based responsive values in the public API.
+ */
+export type BpkResponsiveValue =
+ | T
+ | Partial>;
+
+/**
+ * Validates if a value is a percentage string
+ *
+ * @param {string} value - The value to validate
+ * @returns {boolean} True if the value is a valid percentage string
+ */
+export function isPercentage(value: string): boolean {
+ return /^\d+(\.\d+)?%$/.test(value);
+}
+
+/**
+ * Validates if a spacing value is valid (token or percentage)
+ *
+ * @param {string} value - The spacing value to validate
+ * @returns {boolean} True if the value is a valid Backpack spacing token or percentage
+ */
+export function isValidSpacingValue(value: string): boolean {
+ return Object.values(BpkSpacing).includes(value as BpkSpacingToken) || isPercentage(value);
+}
+
+/**
+ * Validates if a size value is valid
+ *
+ * @param {string} value - The size value to validate
+ * @returns {boolean} True if the value is a valid rem/percentage/semantic size
+ */
+export function isValidSizeValue(value: string): boolean {
+ return (
+ /^-?\d+(\.\d+)?rem$/.test(value) || // rem values
+ isPercentage(value) || // percentage values
+ value === 'auto' ||
+ value === 'full' ||
+ value === 'fit-content'
+ );
+}
+
+/**
+ * Validates if a position value is valid
+ *
+ * @param {string} value - The position value to validate
+ * @returns {boolean} True if the value is a valid rem or percentage
+ */
+export function isValidPositionValue(value: string): boolean {
+ return (
+ /^-?\d+(\.\d+)?rem$/.test(value) || // rem values
+ isPercentage(value) // percentage values
+ );
+}
diff --git a/packages/bpk-component-layout/src/types.ts b/packages/bpk-component-layout/src/types.ts
new file mode 100644
index 0000000000..e9e53afd1c
--- /dev/null
+++ b/packages/bpk-component-layout/src/types.ts
@@ -0,0 +1,309 @@
+/*
+ * Backpack - Skyscanner's Design System
+ *
+ * Copyright 2016 Skyscanner Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { ReactNode } from 'react';
+
+import type StackOptionKeys from './BpkStack.constant';
+import type { BpkCommonLayoutProps } from './commonProps';
+import type { BpkSpacingValue, BpkResponsiveValue, BpkBasisValue } from './tokens';
+import type {
+ BoxProps,
+ FlexProps,
+ GridProps,
+ GridItemProps,
+ StackProps,
+} from '@chakra-ui/react';
+
+
+/**
+ * Layout-level event props that should not be exposed on layout components
+ * by default. BpkBox will reintroduce a minimal subset (onClick, onFocus,
+ * onBlur) explicitly on its own props type.
+ */
+type LayoutEventProps =
+ | 'onClick'
+ | 'onMouseEnter'
+ | 'onMouseLeave'
+ | 'onMouseOver'
+ | 'onMouseOut'
+ | 'onMouseDown'
+ | 'onMouseUp'
+ | 'onFocus'
+ | 'onBlur'
+ | 'onKeyDown'
+ | 'onKeyUp'
+ | 'onKeyPress';
+
+/**
+ * Shorthand props from the underlying layout system that we do NOT expose on
+ * Backpack layout components. These mostly mirror longer-form spacing,
+ * sizing and visual props that we already model explicitly via
+ * BpkCommonLayoutProps and BpkFlexGridProps.
+ */
+type DisallowedShorthandProps =
+ // Spacing shorthands
+ | 'p'
+ | 'pt'
+ | 'pr'
+ | 'pb'
+ | 'pl'
+ | 'px'
+ | 'py'
+ | 'm'
+ | 'mt'
+ | 'mr'
+ | 'mb'
+ | 'ml'
+ | 'mx'
+ | 'my'
+ // Size shorthands
+ | 'w'
+ | 'h'
+ | 'minW'
+ | 'maxW'
+ | 'minH'
+ | 'maxH'
+ // Visual shorthands that map to props we have intentionally excluded
+ | 'bg'
+ | 'rounded'
+ | 'shadow';
+
+/**
+ * Flexbox & grid layout props that we explicitly support on Backpack layout
+ * components. These are a curated subset of the underlying Box flex/grid API
+ * that are useful for structural layout.
+ */
+export interface BpkFlexGridProps {
+ // Flex layout props
+ display?: BoxProps['display'];
+ flexDirection?: BoxProps['flexDirection'];
+ flexWrap?: BoxProps['flexWrap'];
+ justifyContent?: BoxProps['justifyContent'];
+ alignItems?: BoxProps['alignItems'];
+ alignContent?: BoxProps['alignContent'];
+
+ flex?: BoxProps['flex'];
+ flexGrow?: BoxProps['flexGrow'];
+ flexShrink?: BoxProps['flexShrink'];
+ flexBasis?: BoxProps['flexBasis'];
+ order?: BoxProps['order'];
+ alignSelf?: BoxProps['alignSelf'];
+ justifySelf?: BoxProps['justifySelf'];
+
+ // Grid layout props
+ gridTemplateColumns?: BoxProps['gridTemplateColumns'];
+ gridTemplateRows?: BoxProps['gridTemplateRows'];
+ gridTemplateAreas?: BoxProps['gridTemplateAreas'];
+ gridAutoFlow?: BoxProps['gridAutoFlow'];
+ gridAutoRows?: BoxProps['gridAutoRows'];
+ gridAutoColumns?: BoxProps['gridAutoColumns'];
+ rowGap?: BoxProps['rowGap'];
+ columnGap?: BoxProps['columnGap'];
+}
+
+export type FlexGridPropKeys = keyof BpkFlexGridProps;
+
+/**
+ * Curated subset of Box layout props that support Backpack responsive values.
+ *
+ * NOTE:
+ * - These are structural layout props (flex/grid/display) that we want to allow
+ * on `BpkBox`, but using Backpack breakpoint keys rather than Chakra's
+ * array syntax or Chakra breakpoint keys.
+ * - Spacing/size/position props are handled separately via `BpkCommonLayoutProps`.
+ */
+type BpkBoxResponsiveLayoutProps = {
+ // Display
+ display?: BpkResponsiveValue;
+
+ // Flex container props
+ flexDirection?: BpkResponsiveValue;
+ flexWrap?: BpkResponsiveValue;
+ justifyContent?: BpkResponsiveValue;
+ alignItems?: BpkResponsiveValue;
+ alignContent?: BpkResponsiveValue;
+
+ // Flex item props
+ flex?: BpkResponsiveValue;
+ flexGrow?: BpkResponsiveValue;
+ flexShrink?: BpkResponsiveValue;
+ flexBasis?: BpkResponsiveValue;
+ order?: BpkResponsiveValue;
+ alignSelf?: BpkResponsiveValue;
+ justifySelf?: BpkResponsiveValue;
+
+ // Grid container props
+ gridTemplateColumns?: BpkResponsiveValue;
+ gridTemplateRows?: BpkResponsiveValue;
+ gridTemplateAreas?: BpkResponsiveValue;
+ gridAutoFlow?: BpkResponsiveValue;
+ gridAutoRows?: BpkResponsiveValue;
+ gridAutoColumns?: BpkResponsiveValue;
+
+ // Grid item placement props (useful on Box when composing grids)
+ gridColumn?: BpkResponsiveValue;
+ gridRow?: BpkResponsiveValue;
+};
+
+type BpkBoxResponsiveLayoutPropKeys = keyof BpkBoxResponsiveLayoutProps;
+
+/**
+ * Base type that removes common layout props, reserved props (className,
+ * children) and all layout-level event props from Chakra UI props.
+ *
+ * These will be replaced with Backpack-specific types.
+ */
+export type RemoveCommonProps = Omit<
+ T,
+ | keyof BpkCommonLayoutProps
+ | 'className'
+ | 'children'
+ | LayoutEventProps
+ | FlexGridPropKeys
+ | DisallowedShorthandProps
+>;
+
+/**
+ * Component-specific props for BpkBox
+ * Includes all Box props except those in BpkCommonLayoutProps
+ */
+export interface BpkBoxSpecificProps
+ extends Omit, BpkBoxResponsiveLayoutPropKeys>,
+ BpkBoxResponsiveLayoutProps,
+ Omit {}
+
+/**
+ * Props for BpkBox component
+ * Combines Box-specific props with Backpack common layout props
+ * and reintroduces a minimal set of interaction props.
+ */
+type BoxEventProps = Pick;
+
+export interface BpkBoxProps extends BpkCommonLayoutProps, BpkBoxSpecificProps {
+ children?: ReactNode;
+ onClick?: BoxEventProps['onClick'];
+ onFocus?: BoxEventProps['onFocus'];
+ onBlur?: BoxEventProps['onBlur'];
+}
+
+/**
+ * Component-specific props for BpkFlex
+ * Includes all Flex props except those in BpkCommonLayoutProps
+ */
+export interface BpkFlexSpecificProps extends RemoveCommonProps {
+ direction?: BpkResponsiveValue;
+ justify?: BpkResponsiveValue;
+ align?: BpkResponsiveValue;
+ wrap?: BpkResponsiveValue;
+ grow?: BpkResponsiveValue;
+ shrink?: BpkResponsiveValue;
+ basis?: BpkResponsiveValue;
+ inline?: boolean;
+}
+
+/**
+ * Props for BpkFlex component
+ * Combines Flex-specific props with Backpack common layout props
+ */
+export interface BpkFlexProps extends BpkCommonLayoutProps, BpkFlexSpecificProps {
+ children?: ReactNode;
+}
+
+/**
+ * Component-specific props for BpkGrid
+ * Includes all Grid props except those in BpkCommonLayoutProps
+ */
+export interface BpkGridSpecificProps extends RemoveCommonProps {
+ justify?: BpkResponsiveValue;
+ align?: BpkResponsiveValue;
+ templateColumns?: BpkResponsiveValue;
+ templateRows?: BpkResponsiveValue;
+ templateAreas?: BpkResponsiveValue;
+ autoFlow?: BpkResponsiveValue;
+ autoRows?: BpkResponsiveValue;
+ autoColumns?: BpkResponsiveValue;
+ rowGap?: BpkResponsiveValue;
+ columnGap?: BpkResponsiveValue;
+ column?: BpkResponsiveValue;
+ row?: BpkResponsiveValue;
+ inline?: boolean;
+}
+
+/**
+ * Props for BpkGrid component
+ * Combines Grid-specific props with Backpack common layout props
+ */
+export interface BpkGridProps extends BpkCommonLayoutProps, BpkGridSpecificProps {
+ children?: ReactNode;
+}
+
+/**
+ * Component-specific props for BpkGridItem
+ * Includes all GridItem props except those in BpkCommonLayoutProps
+ */
+export interface BpkGridItemSpecificProps extends RemoveCommonProps {
+ area?: GridItemProps['area'];
+ colEnd?: GridItemProps['colEnd'];
+ colStart?: GridItemProps['colStart'];
+ colSpan?: GridItemProps['colSpan'];
+ rowEnd?: GridItemProps['rowEnd'];
+ rowStart?: GridItemProps['rowStart'];
+ rowSpan?: GridItemProps['rowSpan'];
+}
+
+/**
+ * Props for BpkGridItem component
+ * Combines GridItem-specific props with Backpack common layout props
+ */
+export interface BpkGridItemProps extends BpkCommonLayoutProps, BpkGridItemSpecificProps {
+ children?: ReactNode;
+}
+
+// ---- Stack (moved from BpkStack.types.ts) ----
+type StackOptionKeysType = typeof StackOptionKeys[number];
+
+/**
+ * Overrides StackOptions to support BpkResponsiveValue
+ */
+type BpkStackOptions = {
+ [K in StackOptionKeysType]?: K extends keyof StackProps
+ ? BpkResponsiveValue | StackProps[K]
+ : never;
+};
+
+/**
+ * Component-specific props for BpkStack
+ * Includes all Stack props except those in BpkCommonLayoutProps
+ * Overrides StackOptions to support BpkResponsiveValue
+ */
+export interface BpkStackSpecificProps
+ extends Omit, StackOptionKeysType>,
+ BpkStackOptions,
+ BpkFlexGridProps {}
+
+/**
+ * Props for BpkStack component
+ * Combines Stack-specific props with Backpack common layout props
+ */
+export interface BpkStackProps extends BpkCommonLayoutProps, BpkStackSpecificProps {
+ children?: ReactNode;
+}
+
+export type { BpkCommonLayoutProps };
diff --git a/packages/package-lock.json b/packages/package-lock.json
index 5324e6b282..a226cf0915 100644
--- a/packages/package-lock.json
+++ b/packages/package-lock.json
@@ -9,6 +9,7 @@
"version": "21.0.1",
"license": "Apache-2.0",
"dependencies": {
+ "@chakra-ui/react": "^3.30.0",
"@floating-ui/react": "^0.26.12",
"@popperjs/core": "^2.11.8",
"@radix-ui/react-compose-refs": "^1.1.1",
@@ -50,6 +51,173 @@
}
}
},
+ "node_modules/@ark-ui/react": {
+ "version": "5.29.1",
+ "resolved": "https://registry.npmjs.org/@ark-ui/react/-/react-5.29.1.tgz",
+ "integrity": "sha512-HY6plob4CuDBMXqeYBSqjDzKziWoiTb5atDjBEw+jJIfwRdZcChdRHm1IPCFZ9LiQ5toa67748JFzo683UzqVg==",
+ "license": "MIT",
+ "dependencies": {
+ "@internationalized/date": "3.10.0",
+ "@zag-js/accordion": "1.29.1",
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/angle-slider": "1.29.1",
+ "@zag-js/async-list": "1.29.1",
+ "@zag-js/auto-resize": "1.29.1",
+ "@zag-js/avatar": "1.29.1",
+ "@zag-js/bottom-sheet": "1.29.1",
+ "@zag-js/carousel": "1.29.1",
+ "@zag-js/checkbox": "1.29.1",
+ "@zag-js/clipboard": "1.29.1",
+ "@zag-js/collapsible": "1.29.1",
+ "@zag-js/collection": "1.29.1",
+ "@zag-js/color-picker": "1.29.1",
+ "@zag-js/color-utils": "1.29.1",
+ "@zag-js/combobox": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/date-picker": "1.29.1",
+ "@zag-js/date-utils": "1.29.1",
+ "@zag-js/dialog": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/editable": "1.29.1",
+ "@zag-js/file-upload": "1.29.1",
+ "@zag-js/file-utils": "1.29.1",
+ "@zag-js/floating-panel": "1.29.1",
+ "@zag-js/focus-trap": "1.29.1",
+ "@zag-js/highlight-word": "1.29.1",
+ "@zag-js/hover-card": "1.29.1",
+ "@zag-js/i18n-utils": "1.29.1",
+ "@zag-js/image-cropper": "1.29.1",
+ "@zag-js/json-tree-utils": "1.29.1",
+ "@zag-js/listbox": "1.29.1",
+ "@zag-js/marquee": "1.29.1",
+ "@zag-js/menu": "1.29.1",
+ "@zag-js/number-input": "1.29.1",
+ "@zag-js/pagination": "1.29.1",
+ "@zag-js/password-input": "1.29.1",
+ "@zag-js/pin-input": "1.29.1",
+ "@zag-js/popover": "1.29.1",
+ "@zag-js/presence": "1.29.1",
+ "@zag-js/progress": "1.29.1",
+ "@zag-js/qr-code": "1.29.1",
+ "@zag-js/radio-group": "1.29.1",
+ "@zag-js/rating-group": "1.29.1",
+ "@zag-js/react": "1.29.1",
+ "@zag-js/scroll-area": "1.29.1",
+ "@zag-js/select": "1.29.1",
+ "@zag-js/signature-pad": "1.29.1",
+ "@zag-js/slider": "1.29.1",
+ "@zag-js/splitter": "1.29.1",
+ "@zag-js/steps": "1.29.1",
+ "@zag-js/switch": "1.29.1",
+ "@zag-js/tabs": "1.29.1",
+ "@zag-js/tags-input": "1.29.1",
+ "@zag-js/timer": "1.29.1",
+ "@zag-js/toast": "1.29.1",
+ "@zag-js/toggle": "1.29.1",
+ "@zag-js/toggle-group": "1.29.1",
+ "@zag-js/tooltip": "1.29.1",
+ "@zag-js/tour": "1.29.1",
+ "@zag-js/tree-view": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
+ "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/parser": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/types": "^7.28.5"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@babel/runtime": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
@@ -62,21 +230,219 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
+ "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.5",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@chakra-ui/react": {
+ "version": "3.30.0",
+ "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-3.30.0.tgz",
+ "integrity": "sha512-eIRRAilqY4f2zN8GWRnjcciBYsvy3GZDOmzGD9xk596LBxCTNCJaivdBiHCcgNlqA3y1wMyM1jepy2b2vQC4QA==",
+ "license": "MIT",
+ "dependencies": {
+ "@ark-ui/react": "^5.29.1",
+ "@emotion/is-prop-valid": "^1.4.0",
+ "@emotion/serialize": "^1.3.3",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
+ "@emotion/utils": "^1.4.2",
+ "@pandacss/is-valid-prop": "^1.4.2",
+ "csstype": "^3.2.3"
+ },
+ "peerDependencies": {
+ "@emotion/react": ">=11",
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/@emotion/babel-plugin": {
+ "version": "11.13.5",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
+ "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/runtime": "^7.18.3",
+ "@emotion/hash": "^0.9.2",
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/serialize": "^1.3.3",
+ "babel-plugin-macros": "^3.1.0",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/cache": {
+ "version": "11.14.0",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
+ "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/sheet": "^1.4.0",
+ "@emotion/utils": "^1.4.2",
+ "@emotion/weak-memoize": "^0.4.0",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
+ "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz",
+ "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==",
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/memoize": "^0.9.0"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
+ "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/react": {
+ "version": "11.14.0",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
+ "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.13.5",
+ "@emotion/cache": "^11.14.0",
+ "@emotion/serialize": "^1.3.3",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
+ "@emotion/utils": "^1.4.2",
+ "@emotion/weak-memoize": "^0.4.0",
+ "hoist-non-react-statics": "^3.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/serialize": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
+ "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==",
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/hash": "^0.9.2",
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/unitless": "^0.10.0",
+ "@emotion/utils": "^1.4.2",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@emotion/sheet": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
+ "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
+ "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz",
+ "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@emotion/utils": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz",
+ "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/weak-memoize": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
+ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@floating-ui/core": {
- "version": "1.6.5",
- "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.5.tgz",
- "integrity": "sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA==",
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
+ "license": "MIT",
"dependencies": {
- "@floating-ui/utils": "^0.2.5"
+ "@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/dom": {
- "version": "1.6.8",
- "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.8.tgz",
- "integrity": "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q==",
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
+ "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
+ "license": "MIT",
"dependencies": {
- "@floating-ui/core": "^1.6.0",
- "@floating-ui/utils": "^0.2.5"
+ "@floating-ui/core": "^1.7.3",
+ "@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/react": {
@@ -111,9 +477,10 @@
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
},
"node_modules/@floating-ui/utils": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.5.tgz",
- "integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ=="
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+ "license": "MIT"
},
"node_modules/@googlemaps/js-api-loader": {
"version": "1.16.2",
@@ -132,6 +499,69 @@
"supercluster": "^8.0.1"
}
},
+ "node_modules/@internationalized/date": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.10.0.tgz",
+ "integrity": "sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@internationalized/number": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.5.tgz",
+ "integrity": "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@pandacss/is-valid-prop": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/@pandacss/is-valid-prop/-/is-valid-prop-1.6.1.tgz",
+ "integrity": "sha512-adOSTq2JekBkvblToblRtrGjEJUxDTH40HTo5Lm5+l2jygKIb1fXHgwRG6JnO/z1QIA4DaCZftMRyVcOfQhagQ==",
+ "license": "MIT"
+ },
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
@@ -379,66 +809,977 @@
}
}
},
- "node_modules/@react-google-maps/api": {
- "version": "2.19.3",
- "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.19.3.tgz",
- "integrity": "sha512-jiLqvuOt5lOowkLeq7d077AByTyJp+s6hZVlLhlq7SBacBD37aUNpXBz2OsazfeR6Aw4a+9RRhAEjEFvrR1f5A==",
+ "node_modules/@react-google-maps/api": {
+ "version": "2.19.3",
+ "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.19.3.tgz",
+ "integrity": "sha512-jiLqvuOt5lOowkLeq7d077AByTyJp+s6hZVlLhlq7SBacBD37aUNpXBz2OsazfeR6Aw4a+9RRhAEjEFvrR1f5A==",
+ "dependencies": {
+ "@googlemaps/js-api-loader": "1.16.2",
+ "@googlemaps/markerclusterer": "2.5.3",
+ "@react-google-maps/infobox": "2.19.2",
+ "@react-google-maps/marker-clusterer": "2.19.2",
+ "@types/google.maps": "3.55.2",
+ "invariant": "2.2.4"
+ },
+ "peerDependencies": {
+ "react": "^16.8 || ^17 || ^18",
+ "react-dom": "^16.8 || ^17 || ^18"
+ }
+ },
+ "node_modules/@react-google-maps/infobox": {
+ "version": "2.19.2",
+ "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.19.2.tgz",
+ "integrity": "sha512-6wvBqeJsQ/eFSvoxg+9VoncQvNoVCdmxzxRpLvmjPD+nNC6mHM0vJH1xSqaKijkMrfLJT0nfkTGpovrF896jwg=="
+ },
+ "node_modules/@react-google-maps/marker-clusterer": {
+ "version": "2.19.2",
+ "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.19.2.tgz",
+ "integrity": "sha512-x9ibmsP0ZVqzyCo1Pitbw+4b6iEXRw/r1TCy3vOUR3eKrzWLnHYZMR325BkZW2r8fnuWE/V3Fp4QZOP9qYORCw=="
+ },
+ "node_modules/@skyscanner/bpk-foundations-common": {
+ "version": "24.0.0",
+ "resolved": "https://artifactory.skyscannertools.net/artifactory/api/npm/npm/@skyscanner/bpk-foundations-common/-/bpk-foundations-common-24.0.0.tgz",
+ "integrity": "sha512-Ye5sRBhi3vrpOZOjxRiziLDghttmGEwTZuPA5+FOwX5d75DDSfxIQ3YMUMZzZN8WEeTUJO3Y5oB/69y2GGmAUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "color": "^5.0.0"
+ }
+ },
+ "node_modules/@skyscanner/bpk-foundations-web": {
+ "version": "24.0.0",
+ "resolved": "https://artifactory.skyscannertools.net/artifactory/api/npm/npm/@skyscanner/bpk-foundations-web/-/bpk-foundations-web-24.0.0.tgz",
+ "integrity": "sha512-YRYtS6kJScToJH7UxJbZgFcKEA4qzlb7fY/jNES82/QyQApFRdTkbcHkRhh+bCnvMJdqacGVhzt5sHTPjY4l8Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@skyscanner/bpk-foundations-common": "^24.0.0",
+ "color": "^5.0.0"
+ }
+ },
+ "node_modules/@skyscanner/bpk-svgs": {
+ "version": "20.11.0",
+ "resolved": "https://artifactory.skyscannertools.net/artifactory/api/npm/npm/@skyscanner/bpk-svgs/-/bpk-svgs-20.11.0.tgz",
+ "integrity": "sha512-nSYoZyYCiMEGLZSu1mbPJKHqlnWcK9wnVOOB8ZfsExl7/sn3aFUJZRYjxThFyml//5g8zw0TeV8Q4UfRMctVXg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.16.0",
+ "npm": ">=9.5.1"
+ }
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.17",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
+ "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@types/google.maps": {
+ "version": "3.55.2",
+ "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.55.2.tgz",
+ "integrity": "sha512-JcTwzkxskR8DN/nnX96Pie3gGN3WHiPpuxzuQ9z3516o1bB243d8w8DHUJ8BohuzoT1o3HUFta2ns/mkZC8KRw=="
+ },
+ "node_modules/@types/parse-json": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
+ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@zag-js/accordion": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/accordion/-/accordion-1.29.1.tgz",
+ "integrity": "sha512-3laCyoAsInYPooQU5+tgwxiejU25M20etHbbZ6FIql8VRhKemYakpLaVdcXoFQXpwnnsVfyRv88fHYse+eR8vQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/anatomy": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.29.1.tgz",
+ "integrity": "sha512-Yq2E/32mwh4MxQ5jeP3NlweoqsO6Q2UFawyrCwyzbOUovbcoC74H4/2i/qjVlhpfEuVRRWDiqn31z/OWc4w3dw==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/angle-slider": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/angle-slider/-/angle-slider-1.29.1.tgz",
+ "integrity": "sha512-U+6ihVRiFSFodJSbJXTxsyH697bvmYoGLRjo7w14B2WBumbKxa/tXXPuUZdS5MBfJHKo1XUwX1HKQpBmSX8WWA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/rect-utils": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/aria-hidden": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-1.29.1.tgz",
+ "integrity": "sha512-Q8JRvyOjEplKv4xjrJvHvvaGCc/8wa29B7vxck1QBcLqtzSxI003WeFg7fYf4J9NxQmKuFx9iwoh/iD4JmLIbw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/async-list": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/async-list/-/async-list-1.29.1.tgz",
+ "integrity": "sha512-0PVllpwxt9ZT8wSwQiARq4eLj7SKJg2y5TwczgytV89TUezQLYYnLW5K7A8+3YxDDbsEsN5qArdAoZ8azkvkhA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/auto-resize": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/auto-resize/-/auto-resize-1.29.1.tgz",
+ "integrity": "sha512-ZAUqd3Mj9J9/SoeAJw9QtWAQgyf/66I2mXfVBIQK5VpgeDzOZ+J75zOaKr1h0abVlvi001+fFBMDj7N8MmqgTA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/avatar": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/avatar/-/avatar-1.29.1.tgz",
+ "integrity": "sha512-dkL6kk4Q4BvhJ6gDF+lb6rpmLkbFahFbXHyekDWQ003Ud+uW+MR3jIqIPuNnrKeGxts8Cl5q7ieI3sCneTWXyg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/bottom-sheet": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/bottom-sheet/-/bottom-sheet-1.29.1.tgz",
+ "integrity": "sha512-LaXGuu9jw1k5+/sWHk9XWcusykTVDT00fqRRmeVIL32BrgZF0o4286QvUWZrW3vyOLT4nJZVBIsuSz/4nSEqSw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/aria-hidden": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-trap": "1.29.1",
+ "@zag-js/remove-scroll": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/carousel": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/carousel/-/carousel-1.29.1.tgz",
+ "integrity": "sha512-Duyt9pTOWqoTX++XOfoZCsdb5MsPOybnQ0DQZz61jApsyKwd9C6I361az3nkTm7uMgq2T1/pk5Zd3YgBQLxjGg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/scroll-snap": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/checkbox": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/checkbox/-/checkbox-1.29.1.tgz",
+ "integrity": "sha512-+dWWLRzOVzuIdJ3BkO6zi525umeKx1/tlq3WnRR5ok5bGN/zSYWWUFl/bctWlTCuLO9sMpraHEnHZzYnjJoY/A==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-visible": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/clipboard": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/clipboard/-/clipboard-1.29.1.tgz",
+ "integrity": "sha512-oYIokwwgOr6a4v33l+AS2pao9yxDpwESu/p3oRbO2fNVPrbUVLj3b4pct+UJt2sR+CWAHl1d4QRI+DLmG2ybPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/collapsible": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/collapsible/-/collapsible-1.29.1.tgz",
+ "integrity": "sha512-g7iIMLHHYVnR729jZ7ZeQsldvpFcSUOeNAFyeFYhsWdAl+NoRhlNkeH5sAFxIT115s2FKJOOWEbPeu8xgVSgNg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/collection": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/collection/-/collection-1.29.1.tgz",
+ "integrity": "sha512-Yz1ElOm56as/IRRh9lW2eTndHeHBaxVNjS0cGTWFmrSOTdjY4+ilTcHTv3FtyUw5sZurChEgKmFs7oUbHm7RaA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/color-picker": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/color-picker/-/color-picker-1.29.1.tgz",
+ "integrity": "sha512-hxEt2fM0o8t2lw+Lt8qIGFEk0v5u/kc+MkF0RpBACtRjN7+xZ4pm6WOe6a1cW1NUa+VbHlKXfalst+hnEYML2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/color-utils": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/color-utils": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/color-utils/-/color-utils-1.29.1.tgz",
+ "integrity": "sha512-FZCvvjzyA2vkbX9ifv6xF+oL7M2vNmFEAgWpVDy9O671ofEvb/yryjxHBpK3wcTMcJwbFORC5hsDMbX2Tw5MTg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/combobox": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/combobox/-/combobox-1.29.1.tgz",
+ "integrity": "sha512-7w5XFjjk/kp/8kDbPe3rw4G/zTAKtH4H6e7xvl6Bo5kpEJw/aq7yt05o8tAa2WNqT+491aXiQePYqr5PkPpGgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/aria-hidden": "1.29.1",
+ "@zag-js/collection": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/core": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.29.1.tgz",
+ "integrity": "sha512-5Qw3VbLo+jqqyXrUon/LIqJT/+SGHwx5sI1/qseOZBqYj46oabM/WiEoRztFq+FDJuL9VeHnVD6WB683Si5qwg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/date-picker": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/date-picker/-/date-picker-1.29.1.tgz",
+ "integrity": "sha512-uus+kuZ+dEHfGYr3QukIkVzYB/skh2EWnlDk/3hOAEw8KSzi3GQzpRIJFfGWaVoFBGvXvLRf8Vj/4ufrfLSsoQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/date-utils": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/live-region": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ },
+ "peerDependencies": {
+ "@internationalized/date": ">=3.0.0"
+ }
+ },
+ "node_modules/@zag-js/date-utils": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/date-utils/-/date-utils-1.29.1.tgz",
+ "integrity": "sha512-NLEMNs2tRxRoJsobqajwAb+zuhx69MuA1UA1SxJAoauM6p8MulX8bJ4aqd3ZDPKlkGQbXu6e62fuTRkbjJDRXw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@internationalized/date": ">=3.0.0"
+ }
+ },
+ "node_modules/@zag-js/dialog": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-1.29.1.tgz",
+ "integrity": "sha512-fDNgeXqpY576L/PtRQn08XscY1nrL4jBvpw9JGq/w/PWeicM7K+kM9gnoEBz5MB7W+bMR+11AJXz/iKGE1GBzA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/aria-hidden": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-trap": "1.29.1",
+ "@zag-js/remove-scroll": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/dismissable": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-1.29.1.tgz",
+ "integrity": "sha512-4EsVsPudQ17KaInrLQdeZyU8apjzXinfPjgSNBR7CPMU60O0J/zV9mXbn4lwXEE5Hy35lXq8s4V+W6wD0CwbLg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/interact-outside": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/dom-query": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.29.1.tgz",
+ "integrity": "sha512-GGN+Kt/+J9eiPeEqU+PsRYoNoRdFTNYP2ENCCaBSeypCsaxaG4wo99nbsoBwJwhr/c8zeUmULErgrGGoSh0F1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/editable": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/editable/-/editable-1.29.1.tgz",
+ "integrity": "sha512-NpZNRF0cF1AA9OHQpIpU4Jlo4hSPomZ5FpMWmVX4kXbo49YywkPfSDgFCdcsGUIyTLXCmfirI9PWRP4B2IxlVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/interact-outside": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/file-upload": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/file-upload/-/file-upload-1.29.1.tgz",
+ "integrity": "sha512-n321mbdiE6yeUvfDr6sTKxQMJz/BHDvYJvyCaO+MirXdrD80iSop7u4/caekqBFcerxtXg4FcjpPl1fvCGHr+w==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/file-utils": "1.29.1",
+ "@zag-js/i18n-utils": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/file-utils": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/file-utils/-/file-utils-1.29.1.tgz",
+ "integrity": "sha512-nS6549/SkqFldlheXWSMiT+4NMVyB9PMg1DII36JANjgfoceVN/jBM21a6u7CssdpNnSYwqnD4Ozjeqkb3ZO5Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/i18n-utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/floating-panel": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/floating-panel/-/floating-panel-1.29.1.tgz",
+ "integrity": "sha512-fcUKp0NfbTijU8FyA9BI3qNM/YlwFuuS8ixghiaweT/GlbJF9YUlyWzLXKE24I3rE+o0ykq53NEHdQGTco/2hg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/rect-utils": "1.29.1",
+ "@zag-js/store": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/focus-trap": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-trap/-/focus-trap-1.29.1.tgz",
+ "integrity": "sha512-dDp/nuptTp1OJbEjSkLPNy6DxOSfYHKX292uvBV80xyLZUQ4s38wi8VCOuywpgF607WYIRozHI5PB8kaoz0sWA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/focus-visible": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.29.1.tgz",
+ "integrity": "sha512-3zkxNQ0Gx8Xp45y7tfwqZZfJWLYwZhf9rEeMJT49InR9egWqtHCw/RjOQGR/2vydrPv7mfa14ikY/Gql2AX4TQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/highlight-word": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/highlight-word/-/highlight-word-1.29.1.tgz",
+ "integrity": "sha512-54FVVE4NlixIzUTpaJvR7O+fNg9jJomWr3F3LoOkgaKJYuRxitHp1hLmSsdjxRkusMs+1qNHsYN4E9lWNv7kow==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/hover-card": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/hover-card/-/hover-card-1.29.1.tgz",
+ "integrity": "sha512-neKWMHaxL5yIno2BrbhUPm1zQD1o0+ydoYNoUucFDxexZQwcrjORwsgeBfYP6cle6Ne0Aw6OsSE4xowR9LEZVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/i18n-utils": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/i18n-utils/-/i18n-utils-1.29.1.tgz",
+ "integrity": "sha512-c1N5evLLkQpGizPZ8HSek14gaOJgRr7/vlXwWlaC1aSaGrRjZmi/YMmuTThCP4nja/6zKPNg9NJMbuwi/o3UTw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/image-cropper": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/image-cropper/-/image-cropper-1.29.1.tgz",
+ "integrity": "sha512-Xgwt/GwGZ8dT4fM/CRrSZhBhDIWdJiBlsCxp2vz1d9v/6Wju2uVtcM8iaeKUjKZ2NXsnEXTi6/gexlqyeuRjTQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/interact-outside": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-1.29.1.tgz",
+ "integrity": "sha512-hqZYr+OcnW+egU8W297pVK+6YMa+HOyFA0GHF45+29cB+mmTnMPTRcrdqNDFKA+f+ABQl3RH32E1WZjkluJc6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/json-tree-utils": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/json-tree-utils/-/json-tree-utils-1.29.1.tgz",
+ "integrity": "sha512-SKHXFDh92iFUaU/pIgL3j03L/OJMvF+ZiUVY9bitHdBxHE9aJX4ZjdjArYnQIUX3KIFhb4hkyfuW3mxLtvTfGA==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/listbox": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/listbox/-/listbox-1.29.1.tgz",
+ "integrity": "sha512-UShb0caYtLshSHIwnVWz9QOvzm6WDb5+uogNHObt+6ALk77TZfKDxl29jmQ6/14H9ErYHLVsA6akschIaBswUg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/collection": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-visible": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/live-region": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/live-region/-/live-region-1.29.1.tgz",
+ "integrity": "sha512-6+e5BQdzj/nuIK4Uxr3Tv5tKR9X3wP8DbLZPhAVF78XYPamuO19NhRjV4ph6Sp3Jme9gjP8BbaPGyXN4D6lDhA==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/marquee": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/marquee/-/marquee-1.29.1.tgz",
+ "integrity": "sha512-dGyQCPHvwhzVxGKyugqMzvhA5/1d8PS+OoNPxDo1ozKrvNvcsEtDG6lsNMy+jolllthw+m87pcqhA1AHZvpe9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/menu": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/menu/-/menu-1.29.1.tgz",
+ "integrity": "sha512-+L/J+nHlw0N3vwDqGFm7KAu3sbC0l4OVPziTjInlvrliwFbmMX86g17sVKvD/Ke/yc3YvTtJt48AAhidK1EWtA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/rect-utils": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/number-input": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/number-input/-/number-input-1.29.1.tgz",
+ "integrity": "sha512-tme/FOl+jdPy0lYiKo60XdIYheAmfNXPvGb2W4SQtPO2YT3mESdPC/TpCCOVvgIY93k5+5aa8MLEX6GJsTjL+A==",
+ "license": "MIT",
+ "dependencies": {
+ "@internationalized/number": "3.6.5",
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/pagination": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/pagination/-/pagination-1.29.1.tgz",
+ "integrity": "sha512-7KKCdUKPQNK6VuroRfxmxpNcWpuAUy6ZFvMUnaYFFBmCB7FGkOUAO1yEsYuJ9diAZvfprqw+8xnL5g93Xx/RtQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/password-input": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/password-input/-/password-input-1.29.1.tgz",
+ "integrity": "sha512-fbHzf2r3nW32ANj+/3SFKXLh6RYNe1udPPje8VlTmAgBPFKQ7f57S/G26EaFZHU7651B1VFzpJl1ERfnIty9UA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/pin-input": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/pin-input/-/pin-input-1.29.1.tgz",
+ "integrity": "sha512-i9umQG1QEH4RmX9U+YGj0YiBjb7q8jRRC1OtKUJj5vesHAN553eg0WLbHcmfgyF6NwfM73/S+0JRJ9v92neWWw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/popover": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/popover/-/popover-1.29.1.tgz",
+ "integrity": "sha512-MQ83k6JmvnvbvExZUvytNDUFZN7e4HHMdpq9meT5z1K+D9HaQ+gatHNk76cvv0H+yO+q90DDs5OUQ4ulzK/u2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/aria-hidden": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-trap": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/remove-scroll": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/popper": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/popper/-/popper-1.29.1.tgz",
+ "integrity": "sha512-elVi8eWMMrmOvtv627cc3+1bAeKM1VIrB4enpd6ccponXcPosaSTXHMR+lSxy9uOWaHZ/GkqYs+fWzguUJznSA==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "1.7.4",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/presence": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/presence/-/presence-1.29.1.tgz",
+ "integrity": "sha512-xJj9BT5YX2Pb7VnrABYXrU35BOoiM5yT9Y1baGqfQLkginZ+Cp2CwszL6856f2ZUw3xnxBfDsSTPznoH+p9Z7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/progress": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/progress/-/progress-1.29.1.tgz",
+ "integrity": "sha512-UxyfFl+7dKKIqVxbyDjlXnAQSQt5gx0tWP7pt3KWuz6PSdU23fpq1dgv4YYBl8rX5EjX81B9uykE3WP8TRsz2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/qr-code": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/qr-code/-/qr-code-1.29.1.tgz",
+ "integrity": "sha512-n8EpfB0QVN2AhhSQZEN3jfqnsuXmeW5jH7e7TA8as2RMYZXx1dSQLF1fiaKtx8VlS6/mKfMjokZqnhOGtIOXzw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1",
+ "proxy-memoize": "3.0.1",
+ "uqr": "0.1.2"
+ }
+ },
+ "node_modules/@zag-js/radio-group": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/radio-group/-/radio-group-1.29.1.tgz",
+ "integrity": "sha512-KFgF+8T+0nT6igPdCGmpsU5KxVsJVIsseVuABl3/IY679FZog0wAitbCHu9j/QoZxuS/kXj1eD2SbG/+92eDLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-visible": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/rating-group": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/rating-group/-/rating-group-1.29.1.tgz",
+ "integrity": "sha512-Vcqv9FvsxCGaIVlA9LucDiLbttLapyil8Jc8KpKLAODsj1FSVVwgK50AkJnLw7n7SRoD+zx8HTIB1txfT9AQiw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/react": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-1.29.1.tgz",
+ "integrity": "sha512-nvy7BruQojqQ0GLpHbP1BewJXVdqBLOkSzA2JA1BNRCCN19hZ8qCvpjAhZPYXoq1t9eecOju7K33lBFjpck9KA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.29.1",
+ "@zag-js/store": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/@zag-js/rect-utils": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/rect-utils/-/rect-utils-1.29.1.tgz",
+ "integrity": "sha512-3gxfOQb6JlxSbhoX7ULax79gRA3mz9U7A9MduG0GAABgbIXp8SIawNMQBd+ZjfXjVOGeEoA8bEVvDsWnpQ5SIw==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/remove-scroll": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-1.29.1.tgz",
+ "integrity": "sha512-qv/Ipa0apWE20BMTGfvigSOgPn930fXRsdKvMMuJVzaamoGkubfcs1h3HkNG1g/IB1Bx4N7GwD6oWiCMaeHdlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/scroll-area": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/scroll-area/-/scroll-area-1.29.1.tgz",
+ "integrity": "sha512-IVrX6GidcHSmxlTMCBRnQLyOwt6JFrwSlrXB3NptSO72OXk/Lm8GSXAQwek8ijmCHDQtbjHWDLufG5ACEvMNaQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/scroll-snap": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/scroll-snap/-/scroll-snap-1.29.1.tgz",
+ "integrity": "sha512-M/fZDx1IGB6D1IWhouR06q7XAYxpv85ag8Gvz+JVXG4mpo6UBg6t4Ur+DJ4CEfS6KyNmR8pnImZ4aoqmkhiMag==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/select": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/select/-/select-1.29.1.tgz",
+ "integrity": "sha512-LtQqZ2Psu6x8LmJhJh5RI0H8imgzmXCvupaGXIm3SDbKhnmT561RHVeupi5KUaz4OUN/qz3FSMVZzpex5ndfAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/collection": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/signature-pad": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/signature-pad/-/signature-pad-1.29.1.tgz",
+ "integrity": "sha512-N+ej4a99voyR+Xm5w4ma0DsDoSEP/nYrwL9mYSik02/rZs/qPz5ve+qbuUJkLeuzNa3gvzoZhaaVjZb9IuyQbw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1",
+ "perfect-freehand": "^1.2.2"
+ }
+ },
+ "node_modules/@zag-js/slider": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/slider/-/slider-1.29.1.tgz",
+ "integrity": "sha512-BHT3GqM54TjnzuqJfVjcreDFfkXLQNKXBKdTRKQtOkSNsQ7M9Lci8UBHn4WcvQJN5RZ37zsc+Z7zHfHEe/1KSg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/splitter": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/splitter/-/splitter-1.29.1.tgz",
+ "integrity": "sha512-Ky5xddGoSxhinNl4XuJRCWfBYsV4JVPZ7k/o49KZb1+dtD2gGyKW7aJmFV7oGAtB3TBm96CTNsC/vraGVJrr/A==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/steps": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/steps/-/steps-1.29.1.tgz",
+ "integrity": "sha512-Bd6Fx1jii9SWjweKISjRh2Wi8OdZJgreH71gNOAjY7BlANhBD+V/euaGX2CwrQXNh1UnBYXYpy664p5aQbkbjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/store": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.29.1.tgz",
+ "integrity": "sha512-SDyYek8BRtsRPz/CbxmwlXt6B0j6rCezeZN6uAswE4kkmO4bfAjIErrgnImx3TqfjMXlTm4oFUFqeqRJpdnJRg==",
+ "license": "MIT",
+ "dependencies": {
+ "proxy-compare": "3.0.1"
+ }
+ },
+ "node_modules/@zag-js/switch": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/switch/-/switch-1.29.1.tgz",
+ "integrity": "sha512-/Ztm/QDAQBFDcERadobfDuJufXHCBqPh/Mmuau1OTeZ+6EfwRCsPOzHsPmKUpQHOqerMXkYvDbFkNHjS7pfAYg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-visible": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/tabs": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tabs/-/tabs-1.29.1.tgz",
+ "integrity": "sha512-aicopH3c9Nf+HiybboNPtpdL7iNue48BJn4buBm/6cJ+6Xw/rqHaPpodayS2JNWro7tVdT2erf5+My/sD96MUg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/tags-input": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tags-input/-/tags-input-1.29.1.tgz",
+ "integrity": "sha512-izj0IVpBIRKGvd/RlO5zhupmZIHhlH96hBSWNQ1jwETmJRFnsV8RihyQ4P5XzQ9pfFlQozff58YoffunHk2KsA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/auto-resize": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/interact-outside": "1.29.1",
+ "@zag-js/live-region": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/timer": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/timer/-/timer-1.29.1.tgz",
+ "integrity": "sha512-v2pFcO7VHlVFdRXkW6zRNWt7VWArxbpD3id2MkaRWQ2FOi1kFfvOD/Vyy0pG5ymreclULgP9Mm1P22Fg8r++JA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
+ },
+ "node_modules/@zag-js/toast": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toast/-/toast-1.29.1.tgz",
+ "integrity": "sha512-x3gTqe9bRcqEnfwCFlugFmde5n0sYqHw01zNrp38s9zi4OZ8zeUJLK1tF0JSmEWClXECjV25E3V4Fm1ECRgRsA==",
+ "license": "MIT",
"dependencies": {
- "@googlemaps/js-api-loader": "1.16.2",
- "@googlemaps/markerclusterer": "2.5.3",
- "@react-google-maps/infobox": "2.19.2",
- "@react-google-maps/marker-clusterer": "2.19.2",
- "@types/google.maps": "3.55.2",
- "invariant": "2.2.4"
- },
- "peerDependencies": {
- "react": "^16.8 || ^17 || ^18",
- "react-dom": "^16.8 || ^17 || ^18"
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
}
},
- "node_modules/@react-google-maps/infobox": {
- "version": "2.19.2",
- "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.19.2.tgz",
- "integrity": "sha512-6wvBqeJsQ/eFSvoxg+9VoncQvNoVCdmxzxRpLvmjPD+nNC6mHM0vJH1xSqaKijkMrfLJT0nfkTGpovrF896jwg=="
+ "node_modules/@zag-js/toggle": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toggle/-/toggle-1.29.1.tgz",
+ "integrity": "sha512-pWjHq19RASVOmVi+S34pftBwCVZX676BZEgn/JmVq93Zn8VtOZRzqtRfgeios15Q+1acJkW0EmEZZW38CAQ7cQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
},
- "node_modules/@react-google-maps/marker-clusterer": {
- "version": "2.19.2",
- "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.19.2.tgz",
- "integrity": "sha512-x9ibmsP0ZVqzyCo1Pitbw+4b6iEXRw/r1TCy3vOUR3eKrzWLnHYZMR325BkZW2r8fnuWE/V3Fp4QZOP9qYORCw=="
+ "node_modules/@zag-js/toggle-group": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toggle-group/-/toggle-group-1.29.1.tgz",
+ "integrity": "sha512-Yava/DsXl7zRN0zPjVw4NO9HBh3cFEIyW0GXcm6BCmBpoD3eLUktUHskeCAIxnErLhAcL5NxZwAmt4+FB60Nsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
+ }
},
- "node_modules/@skyscanner/bpk-foundations-common": {
- "version": "24.0.0",
- "resolved": "https://artifactory.skyscannertools.net/artifactory/api/npm/npm/@skyscanner/bpk-foundations-common/-/bpk-foundations-common-24.0.0.tgz",
- "integrity": "sha512-Ye5sRBhi3vrpOZOjxRiziLDghttmGEwTZuPA5+FOwX5d75DDSfxIQ3YMUMZzZN8WEeTUJO3Y5oB/69y2GGmAUw==",
- "license": "Apache-2.0",
+ "node_modules/@zag-js/tooltip": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tooltip/-/tooltip-1.29.1.tgz",
+ "integrity": "sha512-oKtfLEPwoX1PERVknfQjBh6H6IQRMeQjF+cmyf7ix0vSbPjCMx7ZniyRzeujk/4McG9HISnhRvkQCReiBiDMiA==",
+ "license": "MIT",
"dependencies": {
- "color": "^5.0.0"
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-visible": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
}
},
- "node_modules/@skyscanner/bpk-foundations-web": {
- "version": "24.0.0",
- "resolved": "https://artifactory.skyscannertools.net/artifactory/api/npm/npm/@skyscanner/bpk-foundations-web/-/bpk-foundations-web-24.0.0.tgz",
- "integrity": "sha512-YRYtS6kJScToJH7UxJbZgFcKEA4qzlb7fY/jNES82/QyQApFRdTkbcHkRhh+bCnvMJdqacGVhzt5sHTPjY4l8Q==",
- "license": "Apache-2.0",
+ "node_modules/@zag-js/tour": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tour/-/tour-1.29.1.tgz",
+ "integrity": "sha512-wjqSN+iMD5GomNVOc/bKOleCGbxGxErxtbKPXqQpqheADHXm1wl55O4gl2QpOsJuLRUiXhS8YJn2efULRPEA9g==",
+ "license": "MIT",
"dependencies": {
- "@skyscanner/bpk-foundations-common": "^24.0.0",
- "color": "^5.0.0"
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dismissable": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/focus-trap": "1.29.1",
+ "@zag-js/interact-outside": "1.29.1",
+ "@zag-js/popper": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
}
},
- "node_modules/@skyscanner/bpk-svgs": {
- "version": "20.11.0",
- "resolved": "https://artifactory.skyscannertools.net/artifactory/api/npm/npm/@skyscanner/bpk-svgs/-/bpk-svgs-20.11.0.tgz",
- "integrity": "sha512-nSYoZyYCiMEGLZSu1mbPJKHqlnWcK9wnVOOB8ZfsExl7/sn3aFUJZRYjxThFyml//5g8zw0TeV8Q4UfRMctVXg==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.16.0",
- "npm": ">=9.5.1"
+ "node_modules/@zag-js/tree-view": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tree-view/-/tree-view-1.29.1.tgz",
+ "integrity": "sha512-0QMKpVY5xXq6sLf4aYgIHUMbtnmuhOgkQLYkEqN3rVnEfZRIr7YeIlLtPPad+oY8VetHRTBe4EfM80yrFHviLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.29.1",
+ "@zag-js/collection": "1.29.1",
+ "@zag-js/core": "1.29.1",
+ "@zag-js/dom-query": "1.29.1",
+ "@zag-js/types": "1.29.1",
+ "@zag-js/utils": "1.29.1"
}
},
- "node_modules/@types/google.maps": {
- "version": "3.55.2",
- "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.55.2.tgz",
- "integrity": "sha512-JcTwzkxskR8DN/nnX96Pie3gGN3WHiPpuxzuQ9z3516o1bB243d8w8DHUJ8BohuzoT1o3HUFta2ns/mkZC8KRw=="
+ "node_modules/@zag-js/types": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.29.1.tgz",
+ "integrity": "sha512-/TVhGOxfakEF0IGA9s9Z+5hhzB5PJhLiGsr+g+nj8B2cpZM4HMQGi1h5N2EDXzTTRVEADqCB9vHwL4nw9gsBIw==",
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "3.1.3"
+ }
+ },
+ "node_modules/@zag-js/types/node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/utils": {
+ "version": "1.29.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.29.1.tgz",
+ "integrity": "sha512-qxGlQPcNn9QeP/F/KynnP2aPPUhjfVM0FrEiTzRTnt62kF+aLJBoYmLzoSnU8WqUq7dW5El71POW6lYyI7WQkg==",
+ "license": "MIT"
},
"node_modules/a11y-focus-scope": {
"version": "1.1.3",
@@ -454,6 +1795,32 @@
"resolved": "https://registry.npmjs.org/a11y-focus-store/-/a11y-focus-store-1.0.0.tgz",
"integrity": "sha512-N07kBzfvJuQrYFck3C+N7QFrzqaIZB+gVcm9apVGAjDHfaMkPjgex6EpRRz12mGps898Og5AYycH2xDdbbuaLg=="
},
+ "node_modules/babel-plugin-macros": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+ "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "cosmiconfig": "^7.0.0",
+ "resolve": "^1.19.0"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/color": {
"version": "5.0.3",
"resolved": "https://artifactory.skyscannertools.net/artifactory/api/npm/npm/color/-/color-5.0.3.tgz",
@@ -506,12 +1873,36 @@
"integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==",
"license": "MIT"
},
- "node_modules/csstype": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+ "license": "MIT",
"peer": true
},
+ "node_modules/cosmiconfig": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT"
+ },
"node_modules/d3-array": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
@@ -602,6 +1993,24 @@
"integrity": "sha512-y8e109LYGgoQDveiEBD3DYXKba1jWf5BA8YU1FL5Tvm0BTdEfy54WLCwnuYWZNnzzvALy/QQ4Hov+Q9RVRv+Zw==",
"peer": true
},
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
@@ -634,16 +2043,96 @@
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
"license": "MIT"
},
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/focusin": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/focusin/-/focusin-2.0.0.tgz",
"integrity": "sha512-yChGflLcqxiImpR1ibm59DjM7YCsyKIFszlmftLy+RNzYrXqiiPCMNtnEaj4DbD0oFj4fp8Jj7GLHYf1JWDvOg=="
},
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/internmap": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
@@ -666,16 +2155,66 @@
"loose-envify": "^1.0.0"
}
},
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/kdbush": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz",
"integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="
},
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
@@ -707,6 +2246,13 @@
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
},
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/normalize.css": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-4.2.0.tgz",
@@ -720,6 +2266,68 @@
"node": ">=0.10.0"
}
},
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/perfect-freehand": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/perfect-freehand/-/perfect-freehand-1.2.2.tgz",
+ "integrity": "sha512-eh31l019WICQ03pkF3FSzHxB8n07ItqIQ++G5UV8JX0zVOXzgTGCqnRR0jJ2h9U8/2uW4W4mtGJELt9kEV0CFQ==",
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC",
+ "peer": true
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -730,6 +2338,21 @@
"react-is": "^16.13.1"
}
},
+ "node_modules/proxy-compare": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz",
+ "integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==",
+ "license": "MIT"
+ },
+ "node_modules/proxy-memoize": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/proxy-memoize/-/proxy-memoize-3.0.1.tgz",
+ "integrity": "sha512-VDdG/VYtOgdGkWJx7y0o7p+zArSf2383Isci8C+BP3YXgMYDoPd3cCBjw0JdWb6YBb9sFiOPbAADDVTPJnh+9g==",
+ "license": "MIT",
+ "dependencies": {
+ "proxy-compare": "^3.0.0"
+ }
+ },
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
@@ -856,6 +2479,37 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
+ "node_modules/resolve": {
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/scheduler": {
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
@@ -875,6 +2529,23 @@
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
},
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/supercluster": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz",
@@ -883,6 +2554,19 @@
"kdbush": "^4.0.2"
}
},
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/tabbable": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-1.1.3.tgz",
@@ -893,6 +2577,22 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
+ },
+ "node_modules/uqr": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/uqr/-/uqr-0.1.2.tgz",
+ "integrity": "sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==",
+ "license": "MIT"
+ },
+ "node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">= 6"
+ }
}
}
}
diff --git a/packages/package.json b/packages/package.json
index 0d7cdba48c..2536d321f8 100644
--- a/packages/package.json
+++ b/packages/package.json
@@ -22,6 +22,7 @@
"access": "public"
},
"dependencies": {
+ "@chakra-ui/react": "^3.30.0",
"@floating-ui/react": "^0.26.12",
"@popperjs/core": "^2.11.8",
"@radix-ui/react-compose-refs": "^1.1.1",