@obosbbl/grunnmuren-react 3.3.3 → 3.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__stories__/layout.stories.cjs +25 -12
- package/dist/__stories__/layout.stories.js +25 -12
- package/dist/index.d.mts +57 -22
- package/dist/index.mjs +336 -291
- package/package.json +5 -2
|
@@ -298,7 +298,6 @@ const cardLinkVariants = cva.cva({
|
|
|
298
298
|
});
|
|
299
299
|
};
|
|
300
300
|
|
|
301
|
-
const roundedMediaCorners = '*:data-[slot="media"]:*:rounded-3xl';
|
|
302
301
|
// Common variant for "standard" and "full-bleed" Hero variants
|
|
303
302
|
const oneColumnLayout = [
|
|
304
303
|
// Vertical spacing in the <Content>
|
|
@@ -311,7 +310,7 @@ const oneColumnLayout = [
|
|
|
311
310
|
'lg:*:not-data-[slot="content"]:not-data-[slot="media"]:not-data-[slot="carousel"]:col-span-3 lg:*:not-data-[slot="content"]:not-data-[slot="media"]:justify-self-end',
|
|
312
311
|
// <Media> and <Carousel> content takes up the full width on medium screens and above
|
|
313
312
|
'lg:*:data-[slot="media"]:col-span-full *:data-[slot="media"]:*:w-full',
|
|
314
|
-
'lg:*:data-[slot="carousel"]:col-span-full
|
|
313
|
+
'lg:*:data-[slot="carousel"]:col-span-full',
|
|
315
314
|
// Aligns <Content> and any element beside it (e.g. <Media>, <Badge>, <CTA> etc.) to the bottom of the <Content> container
|
|
316
315
|
'lg:items-end'
|
|
317
316
|
];
|
|
@@ -327,7 +326,10 @@ const variants = cva.cva({
|
|
|
327
326
|
// Vertical spacing in the <Content>
|
|
328
327
|
'*:data-[slot="content"]:gap-y-3',
|
|
329
328
|
// Make sure <Media> content fills any available vertical and horizontal space
|
|
330
|
-
'*:data-[slot="media"]:*:object-cover'
|
|
329
|
+
'*:data-[slot="media"]:*:object-cover',
|
|
330
|
+
'*:data-[slot="carousel"]:overflow-hidden *:data-[slot="carousel"]:rounded-3xl',
|
|
331
|
+
// Make the carousel items full width, so we scroll one at a time
|
|
332
|
+
'**:data-[slot="carousel-item"]:basis-full'
|
|
331
333
|
],
|
|
332
334
|
variants: {
|
|
333
335
|
/**
|
|
@@ -335,7 +337,6 @@ const variants = cva.cva({
|
|
|
335
337
|
* @default standard
|
|
336
338
|
* */ variant: {
|
|
337
339
|
standard: [
|
|
338
|
-
roundedMediaCorners,
|
|
339
340
|
oneColumnLayout,
|
|
340
341
|
nonFullBleedAspectRatiosForSmallScreens,
|
|
341
342
|
'lg:*:data-[slot="media"]:*:aspect-2/1'
|
|
@@ -345,32 +346,44 @@ const variants = cva.cva({
|
|
|
345
346
|
// Position the media and carousel content to fill the entire viewport width
|
|
346
347
|
'*:data-[slot="media"]:*:absolute *:data-[slot="media"]:*:left-0',
|
|
347
348
|
// Special case for Carousel, where the Media is nested inside a CarouselItem
|
|
348
|
-
'*:data-[slot="carousel"]:**:data-[slot="media"]:w-full
|
|
349
|
+
'*:data-[slot="carousel"]:**:data-[slot="media"]:w-full',
|
|
349
350
|
// Match the heights of the <Media> or <Carousel> wrapper for the Media content (e.g. image, VideoLoop, video etc.)
|
|
350
351
|
// This is necessary due to the absolute positioning of the media and carousel containers in this variant
|
|
351
352
|
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
352
353
|
'**:data-[slot="media"]:h-80 sm:**:data-[slot="media"]:h-[25rem] md:**:data-[slot="media"]:h-[30rem] lg:**:data-[slot="media"]:h-[35rem] xl:**:data-[slot="media"]:h-[40rem] 2xl:**:data-[slot="media"]:h-[42rem] 3xl:**:data-[slot="media"]:h-[48rem] 4xl:**:data-[slot="media"]:h-[53rem]',
|
|
353
|
-
|
|
354
|
-
'**:data-[slot="media"]:*:h-80 sm:**:data-[slot="media"]:*:h-[25rem] md:**:data-[slot="media"]:*:h-[30rem] lg:**:data-[slot="media"]:*:h-[35rem] xl:**:data-[slot="media"]:*:h-[40rem] 2xl:**:data-[slot="media"]:*:h-[42rem] 3xl:**:data-[slot="media"]:*:h-[48rem] 4xl:**:data-[slot="media"]:*:h-[53rem]',
|
|
354
|
+
'**:data-[slot="media"]:*:h-[inherit]',
|
|
355
355
|
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
356
356
|
'*:data-[slot="carousel"]:h-80 sm:*:data-[slot="carousel"]:h-[25rem] md:*:data-[slot="carousel"]:h-[30rem] lg:*:data-[slot="carousel"]:h-[35rem] xl:*:data-[slot="carousel"]:h-[40rem] 2xl:*:data-[slot="carousel"]:h-[42rem] 3xl:*:data-[slot="carousel"]:h-[48rem] 4xl:*:data-[slot="carousel"]:h-[53rem]',
|
|
357
|
+
'*:data-[slot="carousel"]:w-full!',
|
|
357
358
|
// Override aspect ratio of the media and carousel-item slots (since we can not use aspect for full-bleed layout)
|
|
358
359
|
'**:data-[slot="carousel-item"]:data-[slot="media"]:*:aspect-none',
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
360
|
+
// break out the carousel out of the container
|
|
361
|
+
'**:data-[slot="carousel-items-container"]:absolute **:data-[slot="carousel-items-container"]:right-0 **:data-[slot="carousel-items-container"]:left-0 **:data-[slot="carousel-items-container"]:h-[inherit]',
|
|
362
|
+
// Positions the carousel controls inside the carousel
|
|
363
|
+
'**:data-[slot="carousel-controls"]:z-10 **:data-[slot="carousel-controls"]:mb-4 *:data-[slot="carousel"]:flex *:data-[slot="carousel"]:items-end *:data-[slot="carousel"]:justify-end'
|
|
362
364
|
],
|
|
363
365
|
'two-column': [
|
|
364
366
|
'lg:items-center lg:*:col-span-6',
|
|
365
367
|
// Vertical spacing in the <Content>
|
|
366
368
|
'lg:*:data-[slot="content"]:gap-y-7',
|
|
367
|
-
roundedMediaCorners,
|
|
368
369
|
nonFullBleedAspectRatiosForSmallScreens,
|
|
369
370
|
// Set media aspect ratio to 1:1 (square)
|
|
370
|
-
'lg:*:data-[slot="media"]:*:aspect-
|
|
371
|
+
'lg:*:data-[slot="media"]:*:aspect-square'
|
|
371
372
|
]
|
|
372
373
|
}
|
|
373
374
|
},
|
|
375
|
+
compoundVariants: [
|
|
376
|
+
{
|
|
377
|
+
variant: [
|
|
378
|
+
'standard',
|
|
379
|
+
'two-column'
|
|
380
|
+
],
|
|
381
|
+
className: [
|
|
382
|
+
'*:data-[slot="media"]:*:rounded-3xl',
|
|
383
|
+
'**:data-[slot="carousel-controls"]:absolute *:data-[slot="carousel"]:relative **:data-[slot="carousel-controls"]:right-4 **:data-[slot="carousel-controls"]:bottom-4 **:data-[slot="carousel-container"]:rounded-3xl'
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
],
|
|
374
387
|
defaultVariants: {
|
|
375
388
|
variant: 'standard'
|
|
376
389
|
}
|
|
@@ -296,7 +296,6 @@ const cardLinkVariants = cva({
|
|
|
296
296
|
});
|
|
297
297
|
};
|
|
298
298
|
|
|
299
|
-
const roundedMediaCorners = '*:data-[slot="media"]:*:rounded-3xl';
|
|
300
299
|
// Common variant for "standard" and "full-bleed" Hero variants
|
|
301
300
|
const oneColumnLayout = [
|
|
302
301
|
// Vertical spacing in the <Content>
|
|
@@ -309,7 +308,7 @@ const oneColumnLayout = [
|
|
|
309
308
|
'lg:*:not-data-[slot="content"]:not-data-[slot="media"]:not-data-[slot="carousel"]:col-span-3 lg:*:not-data-[slot="content"]:not-data-[slot="media"]:justify-self-end',
|
|
310
309
|
// <Media> and <Carousel> content takes up the full width on medium screens and above
|
|
311
310
|
'lg:*:data-[slot="media"]:col-span-full *:data-[slot="media"]:*:w-full',
|
|
312
|
-
'lg:*:data-[slot="carousel"]:col-span-full
|
|
311
|
+
'lg:*:data-[slot="carousel"]:col-span-full',
|
|
313
312
|
// Aligns <Content> and any element beside it (e.g. <Media>, <Badge>, <CTA> etc.) to the bottom of the <Content> container
|
|
314
313
|
'lg:items-end'
|
|
315
314
|
];
|
|
@@ -325,7 +324,10 @@ const variants = cva({
|
|
|
325
324
|
// Vertical spacing in the <Content>
|
|
326
325
|
'*:data-[slot="content"]:gap-y-3',
|
|
327
326
|
// Make sure <Media> content fills any available vertical and horizontal space
|
|
328
|
-
'*:data-[slot="media"]:*:object-cover'
|
|
327
|
+
'*:data-[slot="media"]:*:object-cover',
|
|
328
|
+
'*:data-[slot="carousel"]:overflow-hidden *:data-[slot="carousel"]:rounded-3xl',
|
|
329
|
+
// Make the carousel items full width, so we scroll one at a time
|
|
330
|
+
'**:data-[slot="carousel-item"]:basis-full'
|
|
329
331
|
],
|
|
330
332
|
variants: {
|
|
331
333
|
/**
|
|
@@ -333,7 +335,6 @@ const variants = cva({
|
|
|
333
335
|
* @default standard
|
|
334
336
|
* */ variant: {
|
|
335
337
|
standard: [
|
|
336
|
-
roundedMediaCorners,
|
|
337
338
|
oneColumnLayout,
|
|
338
339
|
nonFullBleedAspectRatiosForSmallScreens,
|
|
339
340
|
'lg:*:data-[slot="media"]:*:aspect-2/1'
|
|
@@ -343,32 +344,44 @@ const variants = cva({
|
|
|
343
344
|
// Position the media and carousel content to fill the entire viewport width
|
|
344
345
|
'*:data-[slot="media"]:*:absolute *:data-[slot="media"]:*:left-0',
|
|
345
346
|
// Special case for Carousel, where the Media is nested inside a CarouselItem
|
|
346
|
-
'*:data-[slot="carousel"]:**:data-[slot="media"]:w-full
|
|
347
|
+
'*:data-[slot="carousel"]:**:data-[slot="media"]:w-full',
|
|
347
348
|
// Match the heights of the <Media> or <Carousel> wrapper for the Media content (e.g. image, VideoLoop, video etc.)
|
|
348
349
|
// This is necessary due to the absolute positioning of the media and carousel containers in this variant
|
|
349
350
|
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
350
351
|
'**:data-[slot="media"]:h-80 sm:**:data-[slot="media"]:h-[25rem] md:**:data-[slot="media"]:h-[30rem] lg:**:data-[slot="media"]:h-[35rem] xl:**:data-[slot="media"]:h-[40rem] 2xl:**:data-[slot="media"]:h-[42rem] 3xl:**:data-[slot="media"]:h-[48rem] 4xl:**:data-[slot="media"]:h-[53rem]',
|
|
351
|
-
|
|
352
|
-
'**:data-[slot="media"]:*:h-80 sm:**:data-[slot="media"]:*:h-[25rem] md:**:data-[slot="media"]:*:h-[30rem] lg:**:data-[slot="media"]:*:h-[35rem] xl:**:data-[slot="media"]:*:h-[40rem] 2xl:**:data-[slot="media"]:*:h-[42rem] 3xl:**:data-[slot="media"]:*:h-[48rem] 4xl:**:data-[slot="media"]:*:h-[53rem]',
|
|
352
|
+
'**:data-[slot="media"]:*:h-[inherit]',
|
|
353
353
|
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
354
354
|
'*:data-[slot="carousel"]:h-80 sm:*:data-[slot="carousel"]:h-[25rem] md:*:data-[slot="carousel"]:h-[30rem] lg:*:data-[slot="carousel"]:h-[35rem] xl:*:data-[slot="carousel"]:h-[40rem] 2xl:*:data-[slot="carousel"]:h-[42rem] 3xl:*:data-[slot="carousel"]:h-[48rem] 4xl:*:data-[slot="carousel"]:h-[53rem]',
|
|
355
|
+
'*:data-[slot="carousel"]:w-full!',
|
|
355
356
|
// Override aspect ratio of the media and carousel-item slots (since we can not use aspect for full-bleed layout)
|
|
356
357
|
'**:data-[slot="carousel-item"]:data-[slot="media"]:*:aspect-none',
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
358
|
+
// break out the carousel out of the container
|
|
359
|
+
'**:data-[slot="carousel-items-container"]:absolute **:data-[slot="carousel-items-container"]:right-0 **:data-[slot="carousel-items-container"]:left-0 **:data-[slot="carousel-items-container"]:h-[inherit]',
|
|
360
|
+
// Positions the carousel controls inside the carousel
|
|
361
|
+
'**:data-[slot="carousel-controls"]:z-10 **:data-[slot="carousel-controls"]:mb-4 *:data-[slot="carousel"]:flex *:data-[slot="carousel"]:items-end *:data-[slot="carousel"]:justify-end'
|
|
360
362
|
],
|
|
361
363
|
'two-column': [
|
|
362
364
|
'lg:items-center lg:*:col-span-6',
|
|
363
365
|
// Vertical spacing in the <Content>
|
|
364
366
|
'lg:*:data-[slot="content"]:gap-y-7',
|
|
365
|
-
roundedMediaCorners,
|
|
366
367
|
nonFullBleedAspectRatiosForSmallScreens,
|
|
367
368
|
// Set media aspect ratio to 1:1 (square)
|
|
368
|
-
'lg:*:data-[slot="media"]:*:aspect-
|
|
369
|
+
'lg:*:data-[slot="media"]:*:aspect-square'
|
|
369
370
|
]
|
|
370
371
|
}
|
|
371
372
|
},
|
|
373
|
+
compoundVariants: [
|
|
374
|
+
{
|
|
375
|
+
variant: [
|
|
376
|
+
'standard',
|
|
377
|
+
'two-column'
|
|
378
|
+
],
|
|
379
|
+
className: [
|
|
380
|
+
'*:data-[slot="media"]:*:rounded-3xl',
|
|
381
|
+
'**:data-[slot="carousel-controls"]:absolute *:data-[slot="carousel"]:relative **:data-[slot="carousel-controls"]:right-4 **:data-[slot="carousel-controls"]:bottom-4 **:data-[slot="carousel-container"]:rounded-3xl'
|
|
382
|
+
]
|
|
383
|
+
}
|
|
384
|
+
],
|
|
372
385
|
defaultVariants: {
|
|
373
386
|
variant: 'standard'
|
|
374
387
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -2,7 +2,7 @@ import { DisclosureProps as DisclosureProps$1, ButtonProps as ButtonProps$1, Lin
|
|
|
2
2
|
export { ListBoxItemProps as ComboboxItemProps, DisclosureGroup, DisclosureGroupProps, Form, Group, LabelProps, ListBoxItemProps as SelectItemProps } from 'react-aria-components';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as react from 'react';
|
|
5
|
-
import { RefAttributes, HTMLAttributes, HTMLProps, ComponentProps, Ref,
|
|
5
|
+
import { RefAttributes, HTMLAttributes, HTMLProps, ComponentProps, Ref, ReactNode, RefObject, Dispatch, SetStateAction, JSX } from 'react';
|
|
6
6
|
import * as cva from 'cva';
|
|
7
7
|
import { VariantProps } from 'cva';
|
|
8
8
|
import { DisclosureState } from 'react-stately';
|
|
@@ -214,35 +214,70 @@ type CardLinkProps = (Omit<LinkProps$1, 'href'> & Required<Pick<LinkProps$1, 'hr
|
|
|
214
214
|
*/
|
|
215
215
|
declare const CardLink: ({ className: _className, href, ...restProps }: CardLinkProps) => react_jsx_runtime.JSX.Element;
|
|
216
216
|
|
|
217
|
-
type CarouselProps = Omit<HTMLProps<HTMLDivElement>, 'onChange'> & {
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
type CarouselProps = Omit<HTMLProps<HTMLDivElement>, 'onChange' | 'onSelect'> & {
|
|
218
|
+
children?: React.ReactNode;
|
|
219
|
+
/**
|
|
220
|
+
* Alignment of the items relative to the carousel viewport.
|
|
221
|
+
* @default 'center'
|
|
222
|
+
*/
|
|
223
|
+
align?: 'start' | 'center' | 'end';
|
|
224
|
+
/** Delay in milliseconds between each automatic transition of the carousel. Any interaction with the carousel will immediately stop the autoplay. */
|
|
225
|
+
autoPlayDelay?: number;
|
|
226
|
+
/**
|
|
227
|
+
* The initial snapped index of the carousel.
|
|
228
|
+
* @default 0
|
|
229
|
+
*/
|
|
230
|
+
initialIndex?: number;
|
|
231
|
+
/**
|
|
232
|
+
* Whether the carousel infinitely loops.
|
|
233
|
+
* @default false
|
|
234
|
+
*/
|
|
235
|
+
loop?: boolean;
|
|
236
|
+
/**
|
|
237
|
+
* Orientation of the carousel.
|
|
238
|
+
* @default 'horizontal'
|
|
239
|
+
*/
|
|
240
|
+
orientation?: 'horizontal' | 'vertical';
|
|
241
|
+
/**
|
|
242
|
+
* Callback invoked when the snapped index changes.
|
|
243
|
+
*/
|
|
244
|
+
onSelect?: (index: number) => void;
|
|
220
245
|
/**
|
|
221
|
-
* Callback
|
|
222
|
-
* The argument to the callback is an object containing `index` of the new item scrolled into view and the `id` of that item (if set on the `<CarouselItem>`)
|
|
223
|
-
* It also provides `prevIndex` which is the index of the previous item that was in view
|
|
224
|
-
* And `prevId`, which is the id of the previous item that was in view (if set on the `<CarouselItem>`)
|
|
225
|
-
* @param item { index: number; id?: string; prevIndex: number; prevId?: string }
|
|
246
|
+
* Callback invoked after the carousel scrolling "settles". Think of this as the debounced version of `onSelect`.
|
|
226
247
|
*/
|
|
227
|
-
|
|
248
|
+
onSettled?: (index: number) => void;
|
|
249
|
+
/**
|
|
250
|
+
* Whether the carousel should scroll with regular mouse/trackpad scroll gestures, in addition to swipe gestures.
|
|
251
|
+
* @default false
|
|
252
|
+
*/
|
|
253
|
+
scrollGestures?: boolean;
|
|
228
254
|
};
|
|
229
|
-
declare const Carousel: ({
|
|
255
|
+
declare const Carousel: ({ autoPlayDelay, align, children, initialIndex, orientation, onSelect, onSettled, loop, scrollGestures, ref, ...rest }: CarouselProps) => react_jsx_runtime.JSX.Element;
|
|
256
|
+
type CarouselItemsContainer = HTMLProps<HTMLDivElement> & {
|
|
257
|
+
children: React.ReactNode;
|
|
258
|
+
};
|
|
259
|
+
declare const CarouselItemsContainer: ({ children, className, ...rest }: CarouselItemsContainer) => react_jsx_runtime.JSX.Element;
|
|
230
260
|
type CarouselItemsProps = HTMLProps<HTMLDivElement> & {
|
|
231
261
|
/** The <CarouselItem/> components to be displayed within the carousel. */
|
|
232
262
|
children: React.ReactNode;
|
|
233
263
|
};
|
|
234
264
|
declare const CarouselItems: ({ className, children }: CarouselItemsProps) => react_jsx_runtime.JSX.Element;
|
|
265
|
+
type CarouselControlsProps = HTMLProps<HTMLDivElement> & {
|
|
266
|
+
/** The <CarouselItem/> components to be displayed within the carousel. */
|
|
267
|
+
children: React.ReactNode;
|
|
268
|
+
};
|
|
269
|
+
/**
|
|
270
|
+
* This is internal for now, but we will expose it in the future when we support more flexible positioning of prev/next and other actions.
|
|
271
|
+
* It is used to render the prev/next buttons in the carousel for now.
|
|
272
|
+
*/
|
|
273
|
+
declare const CarouselControls: ({ children, className, ...rest }: CarouselControlsProps) => react_jsx_runtime.JSX.Element;
|
|
274
|
+
type CarouselButtonProps = ButtonProps & {
|
|
275
|
+
slot: 'next' | 'prev';
|
|
276
|
+
};
|
|
277
|
+
declare const CarouselButton: ({ className, isIconOnly, color, variant, slot, ...rest }: CarouselButtonProps) => react_jsx_runtime.JSX.Element;
|
|
235
278
|
type CarouselItemProps = HTMLProps<HTMLDivElement> & {
|
|
236
279
|
/** The component/components to display as the <CarouselItem/>. */
|
|
237
|
-
children:
|
|
238
|
-
};
|
|
239
|
-
type CarouselItem = Pick<CarouselItemProps, 'id'> & {
|
|
240
|
-
/** The index of the item that is currently in view */
|
|
241
|
-
index: number;
|
|
242
|
-
/** The index of the previous item that was in view */
|
|
243
|
-
prevIndex: number;
|
|
244
|
-
/** The id of the previous item that was in view */
|
|
245
|
-
prevId?: CarouselItemProps['id'];
|
|
280
|
+
children: React.ReactNode;
|
|
246
281
|
};
|
|
247
282
|
declare const CarouselItem: ({ className, children, ...rest }: CarouselItemProps) => react_jsx_runtime.JSX.Element;
|
|
248
283
|
|
|
@@ -758,5 +793,5 @@ type VideoLoopProps = {
|
|
|
758
793
|
};
|
|
759
794
|
declare const VideoLoop: ({ src, format, alt, className }: VideoLoopProps) => react_jsx_runtime.JSX.Element;
|
|
760
795
|
|
|
761
|
-
export { Accordion, AccordionItem, Alertbox, Avatar, Backlink, Badge, Breadcrumb, Breadcrumbs, Button, ButtonContext, Caption, Card, CardLink, Checkbox, CheckboxGroup, Combobox, ListBoxHeader as ComboboxHeader, ListBoxItem as ComboboxItem, ListBoxSection as ComboboxSection, Content, ContentContext, DateFormatter, Description, Disclosure, DisclosureButton, DisclosurePanel, DisclosureStateContext, ErrorMessage, Footer, GrunnmurenProvider, Heading, HeadingContext, Label, LinkList, LinkListContainer, LinkListItem, Media, MediaContext, NumberField, Radio, RadioGroup, Select, ListBoxHeader as SelectHeader, ListBoxItem as SelectItem, ListBoxSection as SelectSection, Tag, TagGroup, TagList, TextArea, TextField, Carousel as UNSAFE_Carousel, CarouselItem as UNSAFE_CarouselItem, CarouselItems as UNSAFE_CarouselItems, Dialog as UNSAFE_Dialog, DialogTrigger as UNSAFE_DialogTrigger, FileUpload as UNSAFE_FileUpload, Hero as UNSAFE_Hero, Link as UNSAFE_Link, Modal as UNSAFE_Modal, ProgressBar as UNSAFE_ProgressBar, ProgressBarValueText as UNSAFE_ProgressBarValueText, Tab as UNSAFE_Tab, TabList as UNSAFE_TabList, TabPanel as UNSAFE_TabPanel, Table as UNSAFE_Table, TableBody as UNSAFE_TableBody, TableCell as UNSAFE_TableCell, TableColumn as UNSAFE_TableColumn, TableColumnResizer as UNSAFE_TableColumnResizer, TableContainer as UNSAFE_TableContainer, TableHeader as UNSAFE_TableHeader, TableRow as UNSAFE_TableRow, Tabs as UNSAFE_Tabs, VideoLoop, _LinkContext, _useLocale as useLocale };
|
|
762
|
-
export type { AccordionItemProps, AccordionProps, Props as AlertboxProps, AvatarProps, BacklinkProps, BadgeProps, BreadcrumbProps, BreadcrumbsProps, ButtonProps, CaptionProps, CardLinkProps, CardProps, CheckboxGroupProps, CheckboxProps, ComboboxProps, ContentProps, DateFormatterProps, DescriptionProps, DisclosureButtonProps, DisclosurePanelProps, DisclosureProps, ErrorMessageProps, FooterProps, GrunnmurenProviderProps, HeadingProps, LinkListContainerProps, LinkListItemProps, LinkListProps, Locale, MediaProps, NumberFieldProps, RadioGroupProps, RadioProps, SelectProps, TagGroupProps, TagListProps, TagProps, TextAreaProps, TextFieldProps, CarouselItemProps as UNSAFE_CarouselItemProps, CarouselItemsProps as UNSAFE_CarouselItemsProps, CarouselProps as UNSAFE_CarouselProps, DialogProps as UNSAFE_DialogProps, DialogTriggerProps as UNSAFE_DialogTriggerProps, FileUploadProps as UNSAFE_FileUploadProps, HeroProps as UNSAFE_HeroProps, LinkProps as UNSAFE_LinkProps, ModalProps as UNSAFE_ModalProps, ProgressBarProps as UNSAFE_ProgressBarProps, ProgressBarValueTextProps as UNSAFE_ProgressBarValueTextProps, TabListProps as UNSAFE_TabListProps, TabPanelProps as UNSAFE_TabPanelProps, TabProps as UNSAFE_TabProps, TableBodyProps as UNSAFE_TableBodyProps, TableCellProps as UNSAFE_TableCellProps, TableColumnProps as UNSAFE_TableColumnProps, TableColumnResizerProps as UNSAFE_TableColumnResizerProps, TableContainerProps as UNSAFE_TableContainerProps, TableHeaderProps as UNSAFE_TableHeaderProps, TableProps as UNSAFE_TableProps, TableRowProps as UNSAFE_TableRowProps, TabsProps as UNSAFE_TabsProps };
|
|
796
|
+
export { Accordion, AccordionItem, Alertbox, Avatar, Backlink, Badge, Breadcrumb, Breadcrumbs, Button, ButtonContext, Caption, Card, CardLink, Checkbox, CheckboxGroup, Combobox, ListBoxHeader as ComboboxHeader, ListBoxItem as ComboboxItem, ListBoxSection as ComboboxSection, Content, ContentContext, DateFormatter, Description, Disclosure, DisclosureButton, DisclosurePanel, DisclosureStateContext, ErrorMessage, Footer, GrunnmurenProvider, Heading, HeadingContext, Label, LinkList, LinkListContainer, LinkListItem, Media, MediaContext, NumberField, Radio, RadioGroup, Select, ListBoxHeader as SelectHeader, ListBoxItem as SelectItem, ListBoxSection as SelectSection, Tag, TagGroup, TagList, TextArea, TextField, Carousel as UNSAFE_Carousel, CarouselButton as UNSAFE_CarouselButton, CarouselControls as UNSAFE_CarouselControls, CarouselItem as UNSAFE_CarouselItem, CarouselItems as UNSAFE_CarouselItems, CarouselItemsContainer as UNSAFE_CarouselItemsContainer, CarouselItemsContainer as UNSAFE_CarouselItemsContainerProps, Dialog as UNSAFE_Dialog, DialogTrigger as UNSAFE_DialogTrigger, FileUpload as UNSAFE_FileUpload, Hero as UNSAFE_Hero, Link as UNSAFE_Link, Modal as UNSAFE_Modal, ProgressBar as UNSAFE_ProgressBar, ProgressBarValueText as UNSAFE_ProgressBarValueText, Tab as UNSAFE_Tab, TabList as UNSAFE_TabList, TabPanel as UNSAFE_TabPanel, Table as UNSAFE_Table, TableBody as UNSAFE_TableBody, TableCell as UNSAFE_TableCell, TableColumn as UNSAFE_TableColumn, TableColumnResizer as UNSAFE_TableColumnResizer, TableContainer as UNSAFE_TableContainer, TableHeader as UNSAFE_TableHeader, TableRow as UNSAFE_TableRow, Tabs as UNSAFE_Tabs, VideoLoop, _LinkContext, _useLocale as useLocale };
|
|
797
|
+
export type { AccordionItemProps, AccordionProps, Props as AlertboxProps, AvatarProps, BacklinkProps, BadgeProps, BreadcrumbProps, BreadcrumbsProps, ButtonProps, CaptionProps, CardLinkProps, CardProps, CheckboxGroupProps, CheckboxProps, ComboboxProps, ContentProps, DateFormatterProps, DescriptionProps, DisclosureButtonProps, DisclosurePanelProps, DisclosureProps, ErrorMessageProps, FooterProps, GrunnmurenProviderProps, HeadingProps, LinkListContainerProps, LinkListItemProps, LinkListProps, Locale, MediaProps, NumberFieldProps, RadioGroupProps, RadioProps, SelectProps, TagGroupProps, TagListProps, TagProps, TextAreaProps, TextFieldProps, CarouselButtonProps as UNSAFE_CarouselButtonProps, CarouselControlsProps as UNSAFE_CarouselControlsProps, CarouselItemProps as UNSAFE_CarouselItemProps, CarouselItemsProps as UNSAFE_CarouselItemsProps, CarouselProps as UNSAFE_CarouselProps, DialogProps as UNSAFE_DialogProps, DialogTriggerProps as UNSAFE_DialogTriggerProps, FileUploadProps as UNSAFE_FileUploadProps, HeroProps as UNSAFE_HeroProps, LinkProps as UNSAFE_LinkProps, ModalProps as UNSAFE_ModalProps, ProgressBarProps as UNSAFE_ProgressBarProps, ProgressBarValueTextProps as UNSAFE_ProgressBarValueTextProps, TabListProps as UNSAFE_TabListProps, TabPanelProps as UNSAFE_TabPanelProps, TabProps as UNSAFE_TabProps, TableBodyProps as UNSAFE_TableBodyProps, TableCellProps as UNSAFE_TableCellProps, TableColumnProps as UNSAFE_TableColumnProps, TableColumnResizerProps as UNSAFE_TableColumnResizerProps, TableContainerProps as UNSAFE_TableContainerProps, TableHeaderProps as UNSAFE_TableHeaderProps, TableProps as UNSAFE_TableProps, TableRowProps as UNSAFE_TableRowProps, TabsProps as UNSAFE_TabsProps };
|
package/dist/index.mjs
CHANGED
|
@@ -3,16 +3,19 @@ import { useContextProps, DisclosureContext, DisclosureGroupStateContext, Provid
|
|
|
3
3
|
export { DisclosureGroup, Form, Group } from 'react-aria-components';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { cva, cx, compose } from 'cva';
|
|
6
|
-
import { createContext, useContext, useId, useRef, Children, useState, useEffect, isValidElement, cloneElement
|
|
6
|
+
import { createContext, useContext, useId, useRef, Children, useState, useEffect, useMemo, useCallback, isValidElement, cloneElement } from 'react';
|
|
7
7
|
import { ChevronDown, Error, Warning, CheckCircle, InfoCircle, Close, User, ChevronLeft, ChevronRight, LoadingSpinner, Check, Trash, ArrowRight, Download, LinkExternal, PlayerPause, PlayerPlay } from '@obosbbl/grunnmuren-icons-react';
|
|
8
|
-
import { filterDOMProps, mergeProps, mergeRefs,
|
|
8
|
+
import { filterDOMProps, mergeProps, mergeRefs, useObjectRef, useFormReset, useUpdateEffect } from '@react-aria/utils';
|
|
9
9
|
import { useFocusRing, useDisclosure, useProgressBar, useDateFormatter, useField } from 'react-aria';
|
|
10
10
|
import { useDisclosureState } from 'react-stately';
|
|
11
|
-
import
|
|
11
|
+
import Autoplay from 'embla-carousel-autoplay';
|
|
12
|
+
import useEmblaCarousel from 'embla-carousel-react';
|
|
13
|
+
import { WheelGesturesPlugin } from 'embla-carousel-wheel-gestures';
|
|
12
14
|
import { useFormValidation } from '@react-aria/form';
|
|
13
15
|
import { useFormValidationState } from '@react-stately/form';
|
|
14
16
|
import { useControlledState } from '@react-stately/utils';
|
|
15
17
|
import { PressResponder } from '@react-aria/interactions';
|
|
18
|
+
import { useDebouncedCallback } from 'use-debounce';
|
|
16
19
|
|
|
17
20
|
const HeadingContext = /*#__PURE__*/ createContext({});
|
|
18
21
|
const headingVariants = cva({
|
|
@@ -354,6 +357,11 @@ const translations$1 = {
|
|
|
354
357
|
sv: 'Nästa',
|
|
355
358
|
en: 'Next'
|
|
356
359
|
},
|
|
360
|
+
carousel: {
|
|
361
|
+
nb: 'Karusell',
|
|
362
|
+
sv: 'Karusell',
|
|
363
|
+
en: 'Carousel'
|
|
364
|
+
},
|
|
357
365
|
externalLink: {
|
|
358
366
|
nb: '(ekstern lenke)',
|
|
359
367
|
sv: '(extern länk)',
|
|
@@ -982,7 +990,9 @@ const cardLinkVariants = cva({
|
|
|
982
990
|
*
|
|
983
991
|
* Keep in mind that this hook relies on a browser API's and doesn't run on the server.
|
|
984
992
|
* You can supply an initial value that will be used for server side rendering.
|
|
985
|
-
|
|
993
|
+
*
|
|
994
|
+
* The default initial value is `false` as this aligns with most users. This is to prevent unecessary rerenders on mount for the common user.
|
|
995
|
+
*/ function usePrefersReducedMotion(initialValue = false) {
|
|
986
996
|
const [prefersReducedMotion, setPrefersReducedMotion] = useState(initialValue);
|
|
987
997
|
useEffect(()=>{
|
|
988
998
|
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
@@ -998,182 +1008,137 @@ const cardLinkVariants = cva({
|
|
|
998
1008
|
return prefersReducedMotion;
|
|
999
1009
|
}
|
|
1000
1010
|
|
|
1001
|
-
const Carousel = ({
|
|
1011
|
+
const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0, orientation = 'horizontal', onSelect, onSettled, loop = false, scrollGestures = false, ref, ...rest })=>{
|
|
1002
1012
|
const carouselRef = useRef(null);
|
|
1003
|
-
const
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
const scrollTimeoutRef = useRef(null);
|
|
1009
|
-
const scrollQueue = useRef([]);
|
|
1010
|
-
const [hasReachedScrollStart, setHasReachedScrollStart] = useState(scrollTargetIndex === 0);
|
|
1011
|
-
const [hasReachedScrollEnd, setHasReachedScrollEnd] = useState(!carouselItemsRef.current || carouselItemsRef.current.children.length - 1 === scrollTargetIndex);
|
|
1012
|
-
const prefersReducedMotion = usePrefersReducedMotion();
|
|
1013
|
-
useEffect(()=>{
|
|
1014
|
-
setHasReachedScrollStart(scrollTargetIndex === 0);
|
|
1015
|
-
setHasReachedScrollEnd(!carouselItemsRef.current || carouselItemsRef.current.children.length - 1 === scrollTargetIndex);
|
|
1016
|
-
}, [
|
|
1017
|
-
scrollTargetIndex
|
|
1018
|
-
]);
|
|
1019
|
-
// Keep track of the previous index to determine if the user is scrolling forward or backward
|
|
1020
|
-
// This is used to determine which callback to call (onPrev or onNext)
|
|
1021
|
-
const prevIndex = useRef(0);
|
|
1022
|
-
// Processes the next scroll action in the queue, if any
|
|
1023
|
-
// All clicks on the prev/next buttons are queued while a programmatic scroll is in progress
|
|
1024
|
-
// This is to ensure that rapid clicks on the buttons do not cause janky scrolling behavior
|
|
1025
|
-
// while still a snappy response to user clicks
|
|
1026
|
-
const processQueue = ()=>{
|
|
1027
|
-
if (scrollQueue.current.length > 0 && !isScrollingProgrammatically.current) {
|
|
1028
|
-
const nextIndex = scrollQueue.current?.shift();
|
|
1029
|
-
if (nextIndex !== undefined) {
|
|
1030
|
-
setScrollTargetIndex(nextIndex);
|
|
1031
|
-
}
|
|
1013
|
+
const prefersReducedMotion = usePrefersReducedMotion() ?? false;
|
|
1014
|
+
const emblaPlugins = useMemo(()=>{
|
|
1015
|
+
const plugins = [];
|
|
1016
|
+
if (scrollGestures) {
|
|
1017
|
+
plugins.push(WheelGesturesPlugin());
|
|
1032
1018
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
if (scrollTimeoutRef.current) {
|
|
1040
|
-
clearTimeout(scrollTimeoutRef.current);
|
|
1041
|
-
}
|
|
1042
|
-
isScrollingProgrammatically.current = true;
|
|
1043
|
-
const elementWithFocusVisible = carouselRef.current?.querySelector(':focus-visible');
|
|
1044
|
-
carouselItemsRef.current.children[scrollTargetIndex]?.scrollIntoView({
|
|
1045
|
-
behavior: prefersReducedMotion ? 'instant' : 'smooth',
|
|
1046
|
-
inline: 'start',
|
|
1047
|
-
block: 'nearest'
|
|
1048
|
-
});
|
|
1049
|
-
if (prevIndex.current !== scrollTargetIndex && onChange) {
|
|
1050
|
-
onChange({
|
|
1051
|
-
index: scrollTargetIndex,
|
|
1052
|
-
id: carouselItemsRef.current.children[scrollTargetIndex]?.id,
|
|
1053
|
-
prevIndex: prevIndex.current,
|
|
1054
|
-
prevId: carouselItemsRef.current.children[prevIndex.current]?.id
|
|
1055
|
-
});
|
|
1019
|
+
if (autoPlayDelay) {
|
|
1020
|
+
plugins.push(Autoplay({
|
|
1021
|
+
delay: autoPlayDelay,
|
|
1022
|
+
stopOnLastSnap: !loop,
|
|
1023
|
+
jump: prefersReducedMotion
|
|
1024
|
+
}));
|
|
1056
1025
|
}
|
|
1057
|
-
|
|
1058
|
-
scrollTimeoutRef.current = setTimeout(()=>{
|
|
1059
|
-
isScrollingProgrammatically.current = false;
|
|
1060
|
-
scrollTimeoutRef.current = null;
|
|
1061
|
-
if (elementWithFocusVisible && !carouselRef.current?.contains(document.activeElement)) {
|
|
1062
|
-
// Restore focus to the appropriate element after scrolling
|
|
1063
|
-
// First check if the prev or next buttons just got hidden due to reaching the start/end of the carousel
|
|
1064
|
-
// If so, move focus to the other button. This is to avoid a scroll jank that occurs if instead focus is restored to the carousel container
|
|
1065
|
-
// This jank happens because of the delays used for scrolling with these buttons (debounce, queuing etc.).
|
|
1066
|
-
switch(elementWithFocusVisible.slot){
|
|
1067
|
-
case 'prev':
|
|
1068
|
-
{
|
|
1069
|
-
// Focus was lost when the prev button turned invisible, set it to the next button
|
|
1070
|
-
const nextButton = carouselRef.current?.querySelector('[slot="next"]');
|
|
1071
|
-
nextButton?.focus();
|
|
1072
|
-
break;
|
|
1073
|
-
}
|
|
1074
|
-
case 'next':
|
|
1075
|
-
{
|
|
1076
|
-
// Focus was lost when the next button turned invisible, set it to the prev button
|
|
1077
|
-
const prevButton = carouselRef.current?.querySelector('[slot="prev"]');
|
|
1078
|
-
prevButton?.focus();
|
|
1079
|
-
break;
|
|
1080
|
-
}
|
|
1081
|
-
default:
|
|
1082
|
-
{
|
|
1083
|
-
// Focus was lost during while scrolling with left/right arrows, restore it to the carousel container
|
|
1084
|
-
carouselItemsRef.current?.focus();
|
|
1085
|
-
break;
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
processQueue(); // Process any queued scrolls
|
|
1090
|
-
}, 500);
|
|
1026
|
+
return plugins;
|
|
1091
1027
|
}, [
|
|
1092
|
-
|
|
1028
|
+
autoPlayDelay,
|
|
1029
|
+
scrollGestures,
|
|
1030
|
+
loop,
|
|
1093
1031
|
prefersReducedMotion
|
|
1094
1032
|
]);
|
|
1095
|
-
|
|
1033
|
+
const [emblaRef, emblaApi] = useEmblaCarousel({
|
|
1034
|
+
align,
|
|
1035
|
+
loop,
|
|
1036
|
+
startIndex: initialIndex,
|
|
1037
|
+
axis: orientation === 'horizontal' ? 'x' : 'y',
|
|
1038
|
+
inViewThreshold: 0.2
|
|
1039
|
+
}, emblaPlugins);
|
|
1040
|
+
const [slidesInView, setSlidesInView] = useState([
|
|
1041
|
+
initialIndex
|
|
1042
|
+
]);
|
|
1043
|
+
const previousSettledScrollIndex = useRef(initialIndex);
|
|
1096
1044
|
useEffect(()=>{
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1045
|
+
if (!emblaApi) {
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
const emblaHandler = (_, type)=>{
|
|
1049
|
+
const scrollSnapIndex = emblaApi.selectedScrollSnap();
|
|
1050
|
+
switch(type){
|
|
1051
|
+
case 'select':
|
|
1052
|
+
onSelect?.(scrollSnapIndex);
|
|
1053
|
+
break;
|
|
1054
|
+
case 'settle':
|
|
1055
|
+
{
|
|
1056
|
+
// We only invoke the callback if the scroll index actually changed from the previous settled index
|
|
1057
|
+
// Otherwise this gets triggered if the user does the tiniest bit of scrolling in the carousel, but doesn't transition to the next slide
|
|
1058
|
+
if (scrollSnapIndex !== previousSettledScrollIndex.current) {
|
|
1059
|
+
previousSettledScrollIndex.current = scrollSnapIndex;
|
|
1060
|
+
onSettled?.(scrollSnapIndex);
|
|
1061
|
+
}
|
|
1062
|
+
break;
|
|
1063
|
+
}
|
|
1064
|
+
case 'slidesInView':
|
|
1065
|
+
{
|
|
1066
|
+
setSlidesInView(emblaApi.slidesInView());
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1100
1069
|
}
|
|
1101
1070
|
};
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1071
|
+
emblaApi.on('select', emblaHandler);
|
|
1072
|
+
emblaApi.on('slidesInView', emblaHandler);
|
|
1073
|
+
emblaApi.on('settle', emblaHandler);
|
|
1074
|
+
return ()=>{
|
|
1075
|
+
emblaApi.off('select', emblaHandler);
|
|
1076
|
+
emblaApi.off('settle', emblaHandler);
|
|
1077
|
+
emblaApi.off('slidesInView', emblaHandler);
|
|
1078
|
+
};
|
|
1079
|
+
}, [
|
|
1080
|
+
emblaApi,
|
|
1081
|
+
onSelect,
|
|
1082
|
+
onSettled
|
|
1083
|
+
]);
|
|
1084
|
+
const handleNextPress = useCallback(()=>{
|
|
1085
|
+
if (!emblaApi) {
|
|
1106
1086
|
return;
|
|
1107
1087
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
//
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
// Check if the item is more than 50% visible within the container
|
|
1114
|
-
const visibleWidth = Math.min(rect.right, containerRect.right) - Math.max(rect.left, containerRect.left);
|
|
1115
|
-
const itemWidth = rect.width;
|
|
1116
|
-
return visibleWidth / itemWidth > 0.5;
|
|
1117
|
-
});
|
|
1118
|
-
if (newScrollTargetIndex !== -1 && newScrollTargetIndex !== scrollTargetIndex) {
|
|
1119
|
-
if (onChange) {
|
|
1120
|
-
onChange({
|
|
1121
|
-
index: newScrollTargetIndex,
|
|
1122
|
-
id: target.children[newScrollTargetIndex]?.id,
|
|
1123
|
-
prevIndex: prevIndex.current,
|
|
1124
|
-
prevId: target.children[prevIndex.current]?.id
|
|
1125
|
-
});
|
|
1126
|
-
}
|
|
1127
|
-
// Update the index and prevIndex
|
|
1128
|
-
setScrollTargetIndex(newScrollTargetIndex);
|
|
1129
|
-
prevIndex.current = newScrollTargetIndex;
|
|
1088
|
+
emblaApi.plugins().autoplay?.stop();
|
|
1089
|
+
emblaApi.scrollNext(prefersReducedMotion);
|
|
1090
|
+
// we need to move focus if we are about to disable this button due to start/end of carousel
|
|
1091
|
+
if (!loop && !emblaApi.canScrollNext() && carouselRef.current?.querySelector('button[slot="next"]')?.matches(':focus-visible')) {
|
|
1092
|
+
carouselRef.current?.querySelector('button[slot="prev"]')?.focus();
|
|
1130
1093
|
}
|
|
1131
|
-
},
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1094
|
+
}, [
|
|
1095
|
+
emblaApi,
|
|
1096
|
+
prefersReducedMotion,
|
|
1097
|
+
loop
|
|
1098
|
+
]);
|
|
1099
|
+
const handlePrevPress = useCallback(()=>{
|
|
1100
|
+
if (!emblaApi) {
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
emblaApi.plugins().autoplay?.stop();
|
|
1104
|
+
emblaApi.scrollPrev(prefersReducedMotion);
|
|
1105
|
+
// we need to move focus if we are about to disable this button due to start/end of carousel
|
|
1106
|
+
if (!loop && !emblaApi.canScrollPrev() && carouselRef.current?.querySelector('button[slot="prev"]')?.matches(':focus-visible')) {
|
|
1107
|
+
carouselRef.current?.querySelector('button[slot="next"]')?.focus();
|
|
1108
|
+
}
|
|
1109
|
+
}, [
|
|
1110
|
+
emblaApi,
|
|
1111
|
+
prefersReducedMotion,
|
|
1112
|
+
loop
|
|
1113
|
+
]);
|
|
1114
|
+
const locale = _useLocale();
|
|
1115
|
+
const handleKeyDown = useCallback((e)=>{
|
|
1116
|
+
if (e.key === 'ArrowRight' && !e.repeat) {
|
|
1117
|
+
handleNextPress();
|
|
1118
|
+
} else if (e.key === 'ArrowLeft' && !e.repeat) {
|
|
1119
|
+
handlePrevPress();
|
|
1120
|
+
}
|
|
1121
|
+
}, [
|
|
1122
|
+
handleNextPress,
|
|
1123
|
+
handlePrevPress
|
|
1124
|
+
]);
|
|
1125
|
+
return(// biome-ignore lint/a11y/useSemanticElements: we want to use a div
|
|
1126
|
+
/*#__PURE__*/ jsx("div", {
|
|
1127
|
+
...rest,
|
|
1128
|
+
"data-orientation": orientation,
|
|
1165
1129
|
"data-slot": "carousel",
|
|
1166
|
-
ref: carouselRef,
|
|
1130
|
+
ref: mergeRefs(ref, carouselRef),
|
|
1131
|
+
onKeyDown: handleKeyDown,
|
|
1132
|
+
role: "region",
|
|
1133
|
+
"aria-label": translations$1.carousel[locale],
|
|
1167
1134
|
children: /*#__PURE__*/ jsx(Provider, {
|
|
1168
1135
|
values: [
|
|
1169
1136
|
[
|
|
1170
|
-
|
|
1137
|
+
CarouselContext,
|
|
1171
1138
|
{
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
handlePrevious,
|
|
1176
|
-
handleNext
|
|
1139
|
+
slidesInView,
|
|
1140
|
+
'~emblaRef': emblaRef,
|
|
1141
|
+
orientation
|
|
1177
1142
|
}
|
|
1178
1143
|
],
|
|
1179
1144
|
[
|
|
@@ -1182,115 +1147,123 @@ const Carousel = ({ className, children, onChange, ...rest })=>{
|
|
|
1182
1147
|
slots: {
|
|
1183
1148
|
[DEFAULT_SLOT]: {},
|
|
1184
1149
|
prev: {
|
|
1185
|
-
'aria-label': previous[locale],
|
|
1186
|
-
|
|
1150
|
+
'aria-label': translations$1.previous[locale],
|
|
1151
|
+
isDisabled: !emblaApi?.canScrollPrev(),
|
|
1152
|
+
onPress: handlePrevPress
|
|
1187
1153
|
},
|
|
1188
1154
|
next: {
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
onPress:
|
|
1155
|
+
'aria-label': translations$1.next[locale],
|
|
1156
|
+
isDisabled: !emblaApi?.canScrollNext(),
|
|
1157
|
+
onPress: handleNextPress
|
|
1192
1158
|
}
|
|
1193
1159
|
}
|
|
1194
1160
|
}
|
|
1195
1161
|
]
|
|
1196
1162
|
],
|
|
1197
|
-
children:
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
})
|
|
1228
|
-
]
|
|
1229
|
-
})
|
|
1163
|
+
children: children
|
|
1164
|
+
})
|
|
1165
|
+
}));
|
|
1166
|
+
};
|
|
1167
|
+
const CarouselContext = /*#__PURE__*/ createContext({
|
|
1168
|
+
'~emblaRef': null,
|
|
1169
|
+
orientation: 'horizontal',
|
|
1170
|
+
slidesInView: []
|
|
1171
|
+
});
|
|
1172
|
+
const CarouselItemsContainer = ({ children, className, ...rest })=>{
|
|
1173
|
+
const { '~emblaRef': emblaRef } = useContext(CarouselContext);
|
|
1174
|
+
return /*#__PURE__*/ jsx("div", {
|
|
1175
|
+
className: cx(className, 'overflow-hidden'),
|
|
1176
|
+
ref: emblaRef,
|
|
1177
|
+
"data-slot": "carousel-items-container",
|
|
1178
|
+
...rest,
|
|
1179
|
+
children: children
|
|
1180
|
+
});
|
|
1181
|
+
};
|
|
1182
|
+
const CarouselItems = ({ className, children })=>{
|
|
1183
|
+
const { slidesInView, orientation } = useContext(CarouselContext);
|
|
1184
|
+
return /*#__PURE__*/ jsx("div", {
|
|
1185
|
+
className: cx(className, 'flex', orientation === 'vertical' && 'flex-col'),
|
|
1186
|
+
"data-slot": "carousel-items",
|
|
1187
|
+
children: Children.map(children, (child, index)=>{
|
|
1188
|
+
if (/*#__PURE__*/ isValidElement(child)) {
|
|
1189
|
+
return /*#__PURE__*/ cloneElement(child, {
|
|
1190
|
+
inert: slidesInView.includes(index) ? undefined : true
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1230
1193
|
})
|
|
1231
1194
|
});
|
|
1232
1195
|
};
|
|
1233
1196
|
/**
|
|
1234
1197
|
* This is internal for now, but we will expose it in the future when we support more flexible positioning of prev/next and other actions.
|
|
1235
1198
|
* It is used to render the prev/next buttons in the carousel for now.
|
|
1236
|
-
*/ const
|
|
1237
|
-
className: cx(className, '
|
|
1238
|
-
'items-end *:h-fit'),
|
|
1199
|
+
*/ const CarouselControls = ({ children, className, ...rest })=>/*#__PURE__*/ jsx("div", {
|
|
1200
|
+
className: cx(className, 'flex justify-end gap-x-2'),
|
|
1239
1201
|
"data-slot": "carousel-controls",
|
|
1202
|
+
...rest,
|
|
1240
1203
|
children: children
|
|
1241
1204
|
});
|
|
1242
|
-
const
|
|
1243
|
-
|
|
1244
|
-
activeIndex: 0
|
|
1205
|
+
const carouselButtonVariants = cva({
|
|
1206
|
+
base: 'group data-disabled:invisible'
|
|
1245
1207
|
});
|
|
1246
|
-
const
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1208
|
+
const carouselButtonIconSlotVariants = cva({
|
|
1209
|
+
base: 'transition-transform',
|
|
1210
|
+
variants: {
|
|
1211
|
+
slot: {
|
|
1212
|
+
next: null,
|
|
1213
|
+
prev: null
|
|
1214
|
+
},
|
|
1215
|
+
orientation: {
|
|
1216
|
+
horizontal: null,
|
|
1217
|
+
vertical: null
|
|
1255
1218
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1219
|
+
},
|
|
1220
|
+
compoundVariants: [
|
|
1221
|
+
// horizontal controls
|
|
1222
|
+
{
|
|
1223
|
+
slot: 'next',
|
|
1224
|
+
orientation: 'horizontal',
|
|
1225
|
+
className: 'group-hover:motion-safe:translate-x-1'
|
|
1226
|
+
},
|
|
1227
|
+
{
|
|
1228
|
+
slot: 'prev',
|
|
1229
|
+
orientation: 'horizontal',
|
|
1230
|
+
className: 'group-hover:motion-safe:-translate-x-1 rotate-180'
|
|
1231
|
+
},
|
|
1232
|
+
// vertical controls
|
|
1233
|
+
{
|
|
1234
|
+
slot: 'next',
|
|
1235
|
+
orientation: 'vertical',
|
|
1236
|
+
className: 'rotate-90 group-hover:motion-safe:translate-y-1'
|
|
1237
|
+
},
|
|
1238
|
+
{
|
|
1239
|
+
slot: 'prev',
|
|
1240
|
+
orientation: 'vertical',
|
|
1241
|
+
className: 'group-hover:motion-safe:-translate-y-1 -rotate-90'
|
|
1265
1242
|
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
return /*#__PURE__*/ cloneElement(child, {
|
|
1285
|
-
inert: activeIndex === index ? undefined : true
|
|
1286
|
-
});
|
|
1287
|
-
}
|
|
1243
|
+
]
|
|
1244
|
+
});
|
|
1245
|
+
const CarouselButton = ({ className, isIconOnly = true, color = 'white', variant = 'primary', slot, ...rest })=>{
|
|
1246
|
+
const { orientation } = useContext(CarouselContext);
|
|
1247
|
+
return /*#__PURE__*/ jsx(Button, {
|
|
1248
|
+
className: carouselButtonVariants({
|
|
1249
|
+
className
|
|
1250
|
+
}),
|
|
1251
|
+
isIconOnly: isIconOnly,
|
|
1252
|
+
slot: slot,
|
|
1253
|
+
variant: variant,
|
|
1254
|
+
color: color,
|
|
1255
|
+
...rest,
|
|
1256
|
+
children: /*#__PURE__*/ jsx(ChevronRight, {
|
|
1257
|
+
className: carouselButtonIconSlotVariants({
|
|
1258
|
+
orientation,
|
|
1259
|
+
slot
|
|
1260
|
+
})
|
|
1288
1261
|
})
|
|
1289
|
-
})
|
|
1262
|
+
});
|
|
1290
1263
|
};
|
|
1291
1264
|
const CarouselItem = ({ className, children, ...rest })=>{
|
|
1292
1265
|
return /*#__PURE__*/ jsx("div", {
|
|
1293
|
-
className: cx(className, '
|
|
1266
|
+
className: cx(className, 'min-w-0 shrink-0 grow-0'),
|
|
1294
1267
|
"data-slot": "carousel-item",
|
|
1295
1268
|
...rest,
|
|
1296
1269
|
children: /*#__PURE__*/ jsx(Provider, {
|
|
@@ -1606,7 +1579,7 @@ function Combobox(props) {
|
|
|
1606
1579
|
/**
|
|
1607
1580
|
* A FileTrigger allows a user to access the file system with any pressable React Aria or React Spectrum component, or custom components built with usePress.
|
|
1608
1581
|
*/ const FileTrigger = (props)=>{
|
|
1609
|
-
const { onSelect, acceptedFileTypes, allowsMultiple, defaultCamera, children, acceptDirectory, ref, isInvalid, isRequired, name,
|
|
1582
|
+
const { onSelect, acceptedFileTypes, allowsMultiple, defaultCamera, children, acceptDirectory, ref, isInvalid, isRequired, name, ...rest } = props;
|
|
1610
1583
|
const inputRef = useObjectRef(ref);
|
|
1611
1584
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
1612
1585
|
children: [
|
|
@@ -1655,6 +1628,46 @@ const translations = {
|
|
|
1655
1628
|
en: 'Remove'
|
|
1656
1629
|
}
|
|
1657
1630
|
};
|
|
1631
|
+
/**
|
|
1632
|
+
* Extracts a simple file extension from a file name or converts MIME type to extension
|
|
1633
|
+
* @param file The file object
|
|
1634
|
+
* @returns A simple file extension (e.g., "pdf", "jpg", "svg")
|
|
1635
|
+
*/ function getFileExtension(file) {
|
|
1636
|
+
const match = file.name.match(/\.([^.]+)$/);
|
|
1637
|
+
if (match) {
|
|
1638
|
+
return match[1].toUpperCase();
|
|
1639
|
+
}
|
|
1640
|
+
const mimeType = file.type;
|
|
1641
|
+
if (!mimeType) {
|
|
1642
|
+
return '';
|
|
1643
|
+
}
|
|
1644
|
+
const parts = mimeType.split('/');
|
|
1645
|
+
if (parts.length === 2) {
|
|
1646
|
+
const subtype = parts[1].split('+')[0]; // Handle cases like "svg+xml"
|
|
1647
|
+
return subtype.toUpperCase();
|
|
1648
|
+
}
|
|
1649
|
+
return '';
|
|
1650
|
+
}
|
|
1651
|
+
/**
|
|
1652
|
+
* Formats a file size in bytes to a human-readable string (B, KB, MB, GB, etc.)
|
|
1653
|
+
* @param bytes The file size in bytes
|
|
1654
|
+
* @returns A formatted string with the appropriate unit
|
|
1655
|
+
*/ function formatFileSize(bytes) {
|
|
1656
|
+
if (bytes === 0) {
|
|
1657
|
+
return '0 B';
|
|
1658
|
+
}
|
|
1659
|
+
const units = [
|
|
1660
|
+
'B',
|
|
1661
|
+
'KB',
|
|
1662
|
+
'MB',
|
|
1663
|
+
'GB',
|
|
1664
|
+
'TB'
|
|
1665
|
+
];
|
|
1666
|
+
const base = 1024;
|
|
1667
|
+
const unitIndex = Math.floor(Math.log(bytes) / Math.log(base));
|
|
1668
|
+
const size = bytes / base ** unitIndex;
|
|
1669
|
+
return `${size.toFixed(2).replace(/\.?0+$/, '')} ${units[unitIndex]}`;
|
|
1670
|
+
}
|
|
1658
1671
|
/**
|
|
1659
1672
|
* Converts an array of files to a DataTransfer object which can be used as a FileList.
|
|
1660
1673
|
* This is necessary for setting the files on a native file input.
|
|
@@ -1682,7 +1695,7 @@ const translations = {
|
|
|
1682
1695
|
const extension = fileName.match(/(\.[^.]+)$/)?.[0] || '';
|
|
1683
1696
|
if (!fileNameCounts[baseName]) {
|
|
1684
1697
|
// Extract any number from the file name (if any, otherwise default to 0)
|
|
1685
|
-
const baseNameCount = Number.parseInt(fileName.match(/\((\d+)\)/)?.[1] ?? '0');
|
|
1698
|
+
const baseNameCount = Number.parseInt(fileName.match(/\((\d+)\)/)?.[1] ?? '0', 10);
|
|
1686
1699
|
fileNameCounts[baseName] = baseNameCount;
|
|
1687
1700
|
}
|
|
1688
1701
|
fileNameCounts[baseName]++;
|
|
@@ -1831,11 +1844,34 @@ const FileUpload = ({ children, files: _files, onChange, validate, isInvalid: _i
|
|
|
1831
1844
|
return /*#__PURE__*/ jsxs("li", {
|
|
1832
1845
|
children: [
|
|
1833
1846
|
/*#__PURE__*/ jsxs("div", {
|
|
1834
|
-
className: cx('flex items-center justify-between gap-
|
|
1847
|
+
className: cx('flex items-center justify-between gap-3 rounded-lg border p-1.5', hasError ? 'border-red bg-red-light' : 'border-gray'),
|
|
1835
1848
|
children: [
|
|
1836
|
-
|
|
1849
|
+
/*#__PURE__*/ jsxs("div", {
|
|
1850
|
+
className: "flex items-center gap-3",
|
|
1851
|
+
children: [
|
|
1852
|
+
/*#__PURE__*/ jsx("div", {
|
|
1853
|
+
className: "footnote rounded-md border border-gray-light bg-gray-lightest px-2.5 py-2",
|
|
1854
|
+
children: getFileExtension(file)
|
|
1855
|
+
}),
|
|
1856
|
+
/*#__PURE__*/ jsxs("div", {
|
|
1857
|
+
className: "flex flex-col",
|
|
1858
|
+
children: [
|
|
1859
|
+
/*#__PURE__*/ jsx("span", {
|
|
1860
|
+
className: "description truncate font-medium",
|
|
1861
|
+
children: fileName
|
|
1862
|
+
}),
|
|
1863
|
+
/*#__PURE__*/ jsx("span", {
|
|
1864
|
+
className: "footnote text-gray-dark",
|
|
1865
|
+
children: formatFileSize(file.size)
|
|
1866
|
+
})
|
|
1867
|
+
]
|
|
1868
|
+
})
|
|
1869
|
+
]
|
|
1870
|
+
}),
|
|
1837
1871
|
/*#__PURE__*/ jsx("button", {
|
|
1838
|
-
|
|
1872
|
+
type: "button",
|
|
1873
|
+
"aria-label": translations.remove[locale],
|
|
1874
|
+
className: cx('-m-2 grid h-11 w-11 shrink-0 cursor-pointer place-items-center rounded-xl', // Focus styles
|
|
1839
1875
|
'focus-visible:-outline-offset-8 focus-visible:outline-focus'),
|
|
1840
1876
|
onClick: ()=>{
|
|
1841
1877
|
// For controlled component
|
|
@@ -1846,8 +1882,6 @@ const FileUpload = ({ children, files: _files, onChange, validate, isInvalid: _i
|
|
|
1846
1882
|
// (without this, the focus will be set to the top of the page for screen readers)
|
|
1847
1883
|
buttonRef.current?.focus();
|
|
1848
1884
|
},
|
|
1849
|
-
"aria-label": translations.remove[locale],
|
|
1850
|
-
type: "button",
|
|
1851
1885
|
children: /*#__PURE__*/ jsx(Trash, {})
|
|
1852
1886
|
})
|
|
1853
1887
|
]
|
|
@@ -1879,7 +1913,6 @@ function GrunnmurenProvider({ children, locale = 'nb', navigate, useHref }) {
|
|
|
1879
1913
|
});
|
|
1880
1914
|
}
|
|
1881
1915
|
|
|
1882
|
-
const roundedMediaCorners = '*:data-[slot="media"]:*:rounded-3xl';
|
|
1883
1916
|
// Common variant for "standard" and "full-bleed" Hero variants
|
|
1884
1917
|
const oneColumnLayout = [
|
|
1885
1918
|
// Vertical spacing in the <Content>
|
|
@@ -1892,7 +1925,7 @@ const oneColumnLayout = [
|
|
|
1892
1925
|
'lg:*:not-data-[slot="content"]:not-data-[slot="media"]:not-data-[slot="carousel"]:col-span-3 lg:*:not-data-[slot="content"]:not-data-[slot="media"]:justify-self-end',
|
|
1893
1926
|
// <Media> and <Carousel> content takes up the full width on medium screens and above
|
|
1894
1927
|
'lg:*:data-[slot="media"]:col-span-full *:data-[slot="media"]:*:w-full',
|
|
1895
|
-
'lg:*:data-[slot="carousel"]:col-span-full
|
|
1928
|
+
'lg:*:data-[slot="carousel"]:col-span-full',
|
|
1896
1929
|
// Aligns <Content> and any element beside it (e.g. <Media>, <Badge>, <CTA> etc.) to the bottom of the <Content> container
|
|
1897
1930
|
'lg:items-end'
|
|
1898
1931
|
];
|
|
@@ -1908,7 +1941,10 @@ const variants = cva({
|
|
|
1908
1941
|
// Vertical spacing in the <Content>
|
|
1909
1942
|
'*:data-[slot="content"]:gap-y-3',
|
|
1910
1943
|
// Make sure <Media> content fills any available vertical and horizontal space
|
|
1911
|
-
'*:data-[slot="media"]:*:object-cover'
|
|
1944
|
+
'*:data-[slot="media"]:*:object-cover',
|
|
1945
|
+
'*:data-[slot="carousel"]:overflow-hidden *:data-[slot="carousel"]:rounded-3xl',
|
|
1946
|
+
// Make the carousel items full width, so we scroll one at a time
|
|
1947
|
+
'**:data-[slot="carousel-item"]:basis-full'
|
|
1912
1948
|
],
|
|
1913
1949
|
variants: {
|
|
1914
1950
|
/**
|
|
@@ -1916,7 +1952,6 @@ const variants = cva({
|
|
|
1916
1952
|
* @default standard
|
|
1917
1953
|
* */ variant: {
|
|
1918
1954
|
standard: [
|
|
1919
|
-
roundedMediaCorners,
|
|
1920
1955
|
oneColumnLayout,
|
|
1921
1956
|
nonFullBleedAspectRatiosForSmallScreens,
|
|
1922
1957
|
'lg:*:data-[slot="media"]:*:aspect-2/1'
|
|
@@ -1926,32 +1961,44 @@ const variants = cva({
|
|
|
1926
1961
|
// Position the media and carousel content to fill the entire viewport width
|
|
1927
1962
|
'*:data-[slot="media"]:*:absolute *:data-[slot="media"]:*:left-0',
|
|
1928
1963
|
// Special case for Carousel, where the Media is nested inside a CarouselItem
|
|
1929
|
-
'*:data-[slot="carousel"]:**:data-[slot="media"]:w-full
|
|
1964
|
+
'*:data-[slot="carousel"]:**:data-[slot="media"]:w-full',
|
|
1930
1965
|
// Match the heights of the <Media> or <Carousel> wrapper for the Media content (e.g. image, VideoLoop, video etc.)
|
|
1931
1966
|
// This is necessary due to the absolute positioning of the media and carousel containers in this variant
|
|
1932
1967
|
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
1933
1968
|
'**:data-[slot="media"]:h-80 sm:**:data-[slot="media"]:h-[25rem] md:**:data-[slot="media"]:h-[30rem] lg:**:data-[slot="media"]:h-[35rem] xl:**:data-[slot="media"]:h-[40rem] 2xl:**:data-[slot="media"]:h-[42rem] 3xl:**:data-[slot="media"]:h-[48rem] 4xl:**:data-[slot="media"]:h-[53rem]',
|
|
1934
|
-
|
|
1935
|
-
'**:data-[slot="media"]:*:h-80 sm:**:data-[slot="media"]:*:h-[25rem] md:**:data-[slot="media"]:*:h-[30rem] lg:**:data-[slot="media"]:*:h-[35rem] xl:**:data-[slot="media"]:*:h-[40rem] 2xl:**:data-[slot="media"]:*:h-[42rem] 3xl:**:data-[slot="media"]:*:h-[48rem] 4xl:**:data-[slot="media"]:*:h-[53rem]',
|
|
1969
|
+
'**:data-[slot="media"]:*:h-[inherit]',
|
|
1936
1970
|
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
1937
1971
|
'*:data-[slot="carousel"]:h-80 sm:*:data-[slot="carousel"]:h-[25rem] md:*:data-[slot="carousel"]:h-[30rem] lg:*:data-[slot="carousel"]:h-[35rem] xl:*:data-[slot="carousel"]:h-[40rem] 2xl:*:data-[slot="carousel"]:h-[42rem] 3xl:*:data-[slot="carousel"]:h-[48rem] 4xl:*:data-[slot="carousel"]:h-[53rem]',
|
|
1972
|
+
'*:data-[slot="carousel"]:w-full!',
|
|
1938
1973
|
// Override aspect ratio of the media and carousel-item slots (since we can not use aspect for full-bleed layout)
|
|
1939
1974
|
'**:data-[slot="carousel-item"]:data-[slot="media"]:*:aspect-none',
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1975
|
+
// break out the carousel out of the container
|
|
1976
|
+
'**:data-[slot="carousel-items-container"]:absolute **:data-[slot="carousel-items-container"]:right-0 **:data-[slot="carousel-items-container"]:left-0 **:data-[slot="carousel-items-container"]:h-[inherit]',
|
|
1977
|
+
// Positions the carousel controls inside the carousel
|
|
1978
|
+
'**:data-[slot="carousel-controls"]:z-10 **:data-[slot="carousel-controls"]:mb-4 *:data-[slot="carousel"]:flex *:data-[slot="carousel"]:items-end *:data-[slot="carousel"]:justify-end'
|
|
1943
1979
|
],
|
|
1944
1980
|
'two-column': [
|
|
1945
1981
|
'lg:items-center lg:*:col-span-6',
|
|
1946
1982
|
// Vertical spacing in the <Content>
|
|
1947
1983
|
'lg:*:data-[slot="content"]:gap-y-7',
|
|
1948
|
-
roundedMediaCorners,
|
|
1949
1984
|
nonFullBleedAspectRatiosForSmallScreens,
|
|
1950
1985
|
// Set media aspect ratio to 1:1 (square)
|
|
1951
|
-
'lg:*:data-[slot="media"]:*:aspect-
|
|
1986
|
+
'lg:*:data-[slot="media"]:*:aspect-square'
|
|
1952
1987
|
]
|
|
1953
1988
|
}
|
|
1954
1989
|
},
|
|
1990
|
+
compoundVariants: [
|
|
1991
|
+
{
|
|
1992
|
+
variant: [
|
|
1993
|
+
'standard',
|
|
1994
|
+
'two-column'
|
|
1995
|
+
],
|
|
1996
|
+
className: [
|
|
1997
|
+
'*:data-[slot="media"]:*:rounded-3xl',
|
|
1998
|
+
'**:data-[slot="carousel-controls"]:absolute *:data-[slot="carousel"]:relative **:data-[slot="carousel-controls"]:right-4 **:data-[slot="carousel-controls"]:bottom-4 **:data-[slot="carousel-container"]:rounded-3xl'
|
|
1999
|
+
]
|
|
2000
|
+
}
|
|
2001
|
+
],
|
|
1955
2002
|
defaultVariants: {
|
|
1956
2003
|
variant: 'standard'
|
|
1957
2004
|
}
|
|
@@ -2104,30 +2151,28 @@ const Modal = ({ isDismissable = true, isOpen, onOpenChange, defaultOpen, classN
|
|
|
2104
2151
|
};
|
|
2105
2152
|
const Dialog = ({ className, children, ...restProps })=>/*#__PURE__*/ jsx(Dialog$1, {
|
|
2106
2153
|
...restProps,
|
|
2107
|
-
className: cx('relative grid gap-y-5 outline-none', // Footer
|
|
2154
|
+
className: cx(className, 'relative grid gap-y-5 outline-none', // Footer
|
|
2108
2155
|
'[&_[data-slot="footer"]]:flex [&_[data-slot="footer"]]:gap-x-2'),
|
|
2109
|
-
children: ({ close })=>/*#__PURE__*/ jsx(
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
className: 'w-fit'
|
|
2124
|
-
}
|
|
2156
|
+
children: ({ close })=>/*#__PURE__*/ jsx(Provider, {
|
|
2157
|
+
values: [
|
|
2158
|
+
[
|
|
2159
|
+
ButtonContext$1,
|
|
2160
|
+
{
|
|
2161
|
+
// This is necessary to support multiple close buttons
|
|
2162
|
+
slots: {
|
|
2163
|
+
// We need to define default slot in order to also support non-slotted buttons (i.e. buttons without slot prop)
|
|
2164
|
+
[DEFAULT_SLOT]: {
|
|
2165
|
+
className: 'w-fit'
|
|
2166
|
+
},
|
|
2167
|
+
close: {
|
|
2168
|
+
onPress: close,
|
|
2169
|
+
className: 'w-fit'
|
|
2125
2170
|
}
|
|
2126
2171
|
}
|
|
2127
|
-
|
|
2128
|
-
]
|
|
2129
|
-
|
|
2130
|
-
|
|
2172
|
+
}
|
|
2173
|
+
]
|
|
2174
|
+
],
|
|
2175
|
+
children: children
|
|
2131
2176
|
})
|
|
2132
2177
|
});
|
|
2133
2178
|
|
|
@@ -2695,7 +2740,7 @@ const tabsVariants = cva({
|
|
|
2695
2740
|
const { className, children, ...restProps } = props;
|
|
2696
2741
|
return /*#__PURE__*/ jsx(Tab$1, {
|
|
2697
2742
|
...restProps,
|
|
2698
|
-
className: cx(className, 'data-focus-visible:-outline-offset-10 data-focus-visible:outline-2 data-focus-visible:outline-black', 'cursor-pointer border-transparent px-4 py-2 font-light
|
|
2743
|
+
className: cx(className, 'data-focus-visible:-outline-offset-10 data-focus-visible:outline-2 data-focus-visible:outline-black', 'description cursor-pointer border-transparent px-4 py-2 font-light', // Transition
|
|
2699
2744
|
'transition-colors duration-150 ease-out', // TODO: Should disabled tabs just be hidden?
|
|
2700
2745
|
'data-disabled:cursor-not-allowed data-disabled:opacity-50', // Selection
|
|
2701
2746
|
'data-selected:font-medium data-selected:text-blue-dark', // Hover with layout shift prevention using pseudo-element
|
|
@@ -2956,4 +3001,4 @@ const VideoLoop = ({ src, format, alt, className })=>{
|
|
|
2956
3001
|
});
|
|
2957
3002
|
};
|
|
2958
3003
|
|
|
2959
|
-
export { Accordion, AccordionItem, Alertbox, Avatar, Backlink, Badge, Breadcrumb, Breadcrumbs, Button, ButtonContext, Caption, Card, CardLink, Checkbox, CheckboxGroup, Combobox, ListBoxHeader as ComboboxHeader, ListBoxItem as ComboboxItem, ListBoxSection as ComboboxSection, Content, ContentContext, DateFormatter, Description, Disclosure, DisclosureButton, DisclosurePanel, DisclosureStateContext, ErrorMessage, Footer, GrunnmurenProvider, Heading, HeadingContext, Label, LinkList, LinkListContainer, LinkListItem, Media, MediaContext, NumberField, Radio, RadioGroup, Select, ListBoxHeader as SelectHeader, ListBoxItem as SelectItem, ListBoxSection as SelectSection, Tag, TagGroup, TagList, TextArea, TextField, Carousel as UNSAFE_Carousel, CarouselItem as UNSAFE_CarouselItem, CarouselItems as UNSAFE_CarouselItems, Dialog as UNSAFE_Dialog, DialogTrigger as UNSAFE_DialogTrigger, FileUpload as UNSAFE_FileUpload, Hero as UNSAFE_Hero, Link as UNSAFE_Link, Modal as UNSAFE_Modal, ProgressBar as UNSAFE_ProgressBar, ProgressBarValueText as UNSAFE_ProgressBarValueText, Tab as UNSAFE_Tab, TabList as UNSAFE_TabList, TabPanel as UNSAFE_TabPanel, Table as UNSAFE_Table, TableBody as UNSAFE_TableBody, TableCell as UNSAFE_TableCell, TableColumn as UNSAFE_TableColumn, TableColumnResizer as UNSAFE_TableColumnResizer, TableContainer as UNSAFE_TableContainer, TableHeader as UNSAFE_TableHeader, TableRow as UNSAFE_TableRow, Tabs as UNSAFE_Tabs, VideoLoop, _LinkContext, _useLocale as useLocale };
|
|
3004
|
+
export { Accordion, AccordionItem, Alertbox, Avatar, Backlink, Badge, Breadcrumb, Breadcrumbs, Button, ButtonContext, Caption, Card, CardLink, Checkbox, CheckboxGroup, Combobox, ListBoxHeader as ComboboxHeader, ListBoxItem as ComboboxItem, ListBoxSection as ComboboxSection, Content, ContentContext, DateFormatter, Description, Disclosure, DisclosureButton, DisclosurePanel, DisclosureStateContext, ErrorMessage, Footer, GrunnmurenProvider, Heading, HeadingContext, Label, LinkList, LinkListContainer, LinkListItem, Media, MediaContext, NumberField, Radio, RadioGroup, Select, ListBoxHeader as SelectHeader, ListBoxItem as SelectItem, ListBoxSection as SelectSection, Tag, TagGroup, TagList, TextArea, TextField, Carousel as UNSAFE_Carousel, CarouselButton as UNSAFE_CarouselButton, CarouselControls as UNSAFE_CarouselControls, CarouselItem as UNSAFE_CarouselItem, CarouselItems as UNSAFE_CarouselItems, CarouselItemsContainer as UNSAFE_CarouselItemsContainer, Dialog as UNSAFE_Dialog, DialogTrigger as UNSAFE_DialogTrigger, FileUpload as UNSAFE_FileUpload, Hero as UNSAFE_Hero, Link as UNSAFE_Link, Modal as UNSAFE_Modal, ProgressBar as UNSAFE_ProgressBar, ProgressBarValueText as UNSAFE_ProgressBarValueText, Tab as UNSAFE_Tab, TabList as UNSAFE_TabList, TabPanel as UNSAFE_TabPanel, Table as UNSAFE_Table, TableBody as UNSAFE_TableBody, TableCell as UNSAFE_TableCell, TableColumn as UNSAFE_TableColumn, TableColumnResizer as UNSAFE_TableColumnResizer, TableContainer as UNSAFE_TableContainer, TableHeader as UNSAFE_TableHeader, TableRow as UNSAFE_TableRow, Tabs as UNSAFE_Tabs, VideoLoop, _LinkContext, _useLocale as useLocale };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obosbbl/grunnmuren-react",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.5",
|
|
4
4
|
"description": "Grunnmuren components in React",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/code-obos/grunnmuren"
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
"@react-stately/form": "^3.1.5",
|
|
26
26
|
"@react-stately/utils": "^3.10.7",
|
|
27
27
|
"cva": "^1.0.0-0",
|
|
28
|
+
"embla-carousel-autoplay": "^8.6.0",
|
|
29
|
+
"embla-carousel-react": "^8.6.0",
|
|
30
|
+
"embla-carousel-wheel-gestures": "^8.1.0",
|
|
28
31
|
"react-aria": "^3.41.1",
|
|
29
32
|
"react-aria-components": "^1.10.1",
|
|
30
33
|
"react-stately": "^3.39.0",
|
|
@@ -35,7 +38,7 @@
|
|
|
35
38
|
},
|
|
36
39
|
"devDependencies": {
|
|
37
40
|
"@types/node": "^24.0.0",
|
|
38
|
-
"tailwindcss": "4.1.
|
|
41
|
+
"tailwindcss": "4.1.18"
|
|
39
42
|
},
|
|
40
43
|
"scripts": {
|
|
41
44
|
"build": "bunchee"
|