@obosbbl/grunnmuren-react 3.4.3 → 3.4.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__/form-validation.stories.cjs +50 -39
- package/dist/__stories__/form-validation.stories.js +36 -25
- package/dist/__stories__/icons.stories.cjs +1 -1
- package/dist/__stories__/icons.stories.js +1 -1
- package/dist/__stories__/layout.stories.cjs +80 -45
- package/dist/__stories__/layout.stories.d.cts +2 -1
- package/dist/__stories__/layout.stories.d.ts +2 -1
- package/dist/__stories__/layout.stories.js +73 -39
- package/dist/__stories__/typography.stories.cjs +1 -1
- package/dist/__stories__/typography.stories.js +1 -1
- package/dist/index.d.mts +37 -9
- package/dist/index.mjs +175 -130
- package/package.json +13 -18
package/dist/index.mjs
CHANGED
|
@@ -1,21 +1,60 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
2
|
+
import { RouterProvider } from 'react-aria-components';
|
|
3
|
+
export { 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
6
|
import { createContext, useContext, useId, useRef, Children, useState, useEffect, useMemo, useCallback, isValidElement, cloneElement, use } from 'react';
|
|
7
|
+
import { useContextProps, Provider, DEFAULT_SLOT, useSlottedContext } from 'react-aria-components/slots';
|
|
7
8
|
import { ChevronDown, Error, Warning, CheckCircle, InfoCircle, Close, User, ChevronLeft, ChevronRight, LoadingSpinner, Check, Trash, Download, LinkExternal, ArrowRight, Edit, PlayerPause, PlayerPlay } from '@obosbbl/grunnmuren-icons-react';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import { ButtonContext as ButtonContext$1, Button as Button$1 } from 'react-aria-components/Button';
|
|
10
|
+
import { DisclosureContext, DisclosureGroupStateContext } from 'react-aria-components/DisclosureGroup';
|
|
11
|
+
export { DisclosureGroup } from 'react-aria-components/DisclosureGroup';
|
|
12
|
+
import { filterDOMProps } from 'react-aria/filterDOMProps';
|
|
13
|
+
import { mergeProps } from 'react-aria/mergeProps';
|
|
14
|
+
import { mergeRefs } from 'react-aria/mergeRefs';
|
|
15
|
+
import { useDisclosure } from 'react-aria/useDisclosure';
|
|
16
|
+
import { useFocusRing } from 'react-aria/useFocusRing';
|
|
17
|
+
import { useDisclosureState } from 'react-stately/useDisclosureState';
|
|
18
|
+
import { useLocale, I18nProvider } from 'react-aria-components/I18nProvider';
|
|
19
|
+
import { Link as Link$1, LinkContext } from 'react-aria-components/Link';
|
|
20
|
+
import { Breadcrumb as Breadcrumb$1, Breadcrumbs as Breadcrumbs$1 } from 'react-aria-components/Breadcrumbs';
|
|
21
|
+
import { useProgressBar } from 'react-aria/useProgressBar';
|
|
11
22
|
import Autoplay from 'embla-carousel-autoplay';
|
|
12
23
|
import useEmblaCarousel from 'embla-carousel-react';
|
|
13
24
|
import { WheelGesturesPlugin } from 'embla-carousel-wheel-gestures';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
25
|
+
import { GroupContext, Group } from 'react-aria-components/Group';
|
|
26
|
+
import { CheckboxContext, Checkbox as Checkbox$1 } from 'react-aria-components/Checkbox';
|
|
27
|
+
import { Text } from 'react-aria-components/Text';
|
|
28
|
+
import { CheckboxGroup as CheckboxGroup$1 } from 'react-aria-components/CheckboxGroup';
|
|
29
|
+
import { FieldError, FieldErrorContext } from 'react-aria-components/FieldError';
|
|
30
|
+
import { Label as Label$1, LabelContext } from 'react-aria-components/Label';
|
|
31
|
+
import { ComboBox } from 'react-aria-components/ComboBox';
|
|
32
|
+
import { Input, InputContext } from 'react-aria-components/Input';
|
|
33
|
+
import { Popover } from 'react-aria-components/Popover';
|
|
34
|
+
import { Header } from 'react-aria-components/Header';
|
|
35
|
+
import { ListBoxItem as ListBoxItem$1, ListBoxSection as ListBoxSection$1, ListBox as ListBox$1 } from 'react-aria-components/ListBox';
|
|
36
|
+
import { useDateFormatter } from 'react-aria/useDateFormatter';
|
|
37
|
+
import { FormContext } from 'react-aria-components/Form';
|
|
38
|
+
import { useFormValidation } from 'react-aria/private/form/useFormValidation';
|
|
39
|
+
import { useFormReset } from 'react-aria/private/utils/useFormReset';
|
|
40
|
+
import { useUpdateEffect } from 'react-aria/private/utils/useUpdateEffect';
|
|
41
|
+
import { useField } from 'react-aria/useField';
|
|
42
|
+
import { useFormValidationState } from 'react-stately/private/form/useFormValidationState';
|
|
43
|
+
import { useControlledState } from 'react-stately/useControlledState';
|
|
44
|
+
import { PressResponder } from 'react-aria/private/interactions/PressResponder';
|
|
45
|
+
import { useObjectRef } from 'react-aria/useObjectRef';
|
|
46
|
+
import { Dialog as Dialog$1, DialogTrigger as DialogTrigger$1 } from 'react-aria-components/Dialog';
|
|
47
|
+
import { Modal as Modal$1, ModalOverlay } from 'react-aria-components/Modal';
|
|
48
|
+
import { NumberField as NumberField$1 } from 'react-aria-components/NumberField';
|
|
49
|
+
import { Radio as Radio$1, RadioGroup as RadioGroup$1 } from 'react-aria-components/RadioGroup';
|
|
50
|
+
import { Select as Select$1, SelectValue } from 'react-aria-components/Select';
|
|
51
|
+
import { ProgressBar as ProgressBar$1 } from 'react-aria-components/ProgressBar';
|
|
18
52
|
import { useDebouncedCallback } from 'use-debounce';
|
|
53
|
+
import { ColumnResizer, Table as Table$1, TableBody as TableBody$1, Cell, Column, ResizableTableContainer, TableHeader as TableHeader$1, Row } from 'react-aria-components/Table';
|
|
54
|
+
import { Tab as Tab$1, TabListStateContext, TabList as TabList$1, TabPanel as TabPanel$1, Tabs as Tabs$1 } from 'react-aria-components/Tabs';
|
|
55
|
+
import { TagGroup as TagGroup$1, TagList as TagList$1, Tag as Tag$1 } from 'react-aria-components/TagGroup';
|
|
56
|
+
import { TextArea as TextArea$1 } from 'react-aria-components/TextArea';
|
|
57
|
+
import { TextField as TextField$1 } from 'react-aria-components/TextField';
|
|
19
58
|
|
|
20
59
|
const HeadingContext = /*#__PURE__*/ createContext({});
|
|
21
60
|
const headingVariants = cva({
|
|
@@ -95,7 +134,7 @@ const Footer = (props)=>/*#__PURE__*/ jsx("div", {
|
|
|
95
134
|
|
|
96
135
|
const disclosureButtonVariants = cva({
|
|
97
136
|
base: [
|
|
98
|
-
'inline-flex cursor-pointer items-center justify-between rounded-lg focus-visible:outline-current
|
|
137
|
+
'focus-visible:outline-focus inline-flex cursor-pointer items-center justify-between rounded-lg focus-visible:outline-current',
|
|
99
138
|
// Ensure a minimum click area of 44x44px, while making it look like it only has the size of the content
|
|
100
139
|
'p-2.5 focus-visible:outline-offset-[-0.625rem]',
|
|
101
140
|
'data-accordion:-m-2.5'
|
|
@@ -109,7 +148,7 @@ const disclosureButtonVariants = cva({
|
|
|
109
148
|
* When the button is without text, but with a single icon.
|
|
110
149
|
* @default false
|
|
111
150
|
*/ isIconOnly: {
|
|
112
|
-
true: '[&>svg]:
|
|
151
|
+
true: '[&>svg]:size-7',
|
|
113
152
|
false: 'gap-2.5'
|
|
114
153
|
}
|
|
115
154
|
},
|
|
@@ -270,7 +309,7 @@ function Accordion(props) {
|
|
|
270
309
|
child,
|
|
271
310
|
index < childCount - 1 && // Margin is added to enable support for containers with a background color
|
|
272
311
|
/*#__PURE__*/ jsx("hr", {
|
|
273
|
-
className: "
|
|
312
|
+
className: "border-gray-light mx-2",
|
|
274
313
|
"aria-hidden": true
|
|
275
314
|
})
|
|
276
315
|
]
|
|
@@ -300,7 +339,7 @@ function AccordionItem(props) {
|
|
|
300
339
|
level: 3,
|
|
301
340
|
_innerWrapper: (children)=>/*#__PURE__*/ jsx(DisclosureButton, {
|
|
302
341
|
// Use outline with offset as focus indicator, this does not cover the left sky border on the expanded content and works with or without a background color on the accordion container
|
|
303
|
-
className: "flex min-h-11 w-full gap-1.5 rounded-lg px-2 py-3.5 text-left
|
|
342
|
+
className: "focus-visible:outline-focus-inset! flex min-h-11 w-full gap-1.5 rounded-lg px-2 py-3.5 text-left",
|
|
304
343
|
type: "button",
|
|
305
344
|
withChevron: true,
|
|
306
345
|
id: buttonId,
|
|
@@ -394,21 +433,21 @@ const alertVariants = cva({
|
|
|
394
433
|
// Icon styles:
|
|
395
434
|
'[&:has([data-slot="heading"])>svg]:mt-0.5',
|
|
396
435
|
// Heading styles:
|
|
397
|
-
'**:data-[slot="heading"]:
|
|
436
|
+
'**:data-[slot="heading"]:text-base **:data-[slot="heading"]:leading-7 **:data-[slot="heading"]:font-medium',
|
|
398
437
|
// Content styles:
|
|
399
438
|
'**:data-[slot="content"]:text-sm **:data-[slot="content"]:leading-6 [&:has([data-slot="heading"])_[data-slot="content"]]:col-span-full',
|
|
400
439
|
// Footer styles:
|
|
401
|
-
'**:data-[slot="footer"]:col-span-full **:data-[slot="footer"]:
|
|
440
|
+
'**:data-[slot="footer"]:col-span-full **:data-[slot="footer"]:text-xs **:data-[slot="footer"]:leading-6 **:data-[slot="footer"]:font-light'
|
|
402
441
|
],
|
|
403
442
|
variants: {
|
|
404
443
|
/**
|
|
405
444
|
* The variant of the alert
|
|
406
445
|
* @default info
|
|
407
446
|
*/ variant: {
|
|
408
|
-
info: 'border-[#1A7FA7]
|
|
409
|
-
success: 'border-[#0F9B6E]
|
|
447
|
+
info: 'bg-sky-light border-[#1A7FA7]',
|
|
448
|
+
success: 'bg-mint-light border-[#0F9B6E]',
|
|
410
449
|
warning: 'border-[#C57C13] bg-[#FFF2DE]',
|
|
411
|
-
danger: 'border-[#C0385D]
|
|
450
|
+
danger: 'bg-red-light border-[#C0385D]'
|
|
412
451
|
}
|
|
413
452
|
},
|
|
414
453
|
defaultVariants: {
|
|
@@ -449,15 +488,15 @@ const Alertbox = ({ children, role, className, icon, variant = 'info', isDismiss
|
|
|
449
488
|
/*#__PURE__*/ jsx(Icon, {}),
|
|
450
489
|
firstChild,
|
|
451
490
|
isDismissable && /*#__PURE__*/ jsx("button", {
|
|
452
|
-
className: cx('-m-2 grid
|
|
491
|
+
className: cx('-m-2 grid size-11 place-items-center rounded-xl', 'focus-visible:outline-focus cursor-pointer focus-visible:-outline-offset-8'),
|
|
453
492
|
onClick: close,
|
|
454
493
|
"aria-label": translations$1.close[locale],
|
|
455
494
|
type: "button",
|
|
456
495
|
children: /*#__PURE__*/ jsx(Close, {})
|
|
457
496
|
}),
|
|
458
497
|
isExpandable && /*#__PURE__*/ jsxs("button", {
|
|
459
|
-
className: cx('
|
|
460
|
-
'outline-none after:absolute after:
|
|
498
|
+
className: cx('relative col-span-full row-start-2 -my-3 inline-flex max-w-fit cursor-pointer items-center gap-1 py-3 text-sm/6', // Focus styles:
|
|
499
|
+
'outline-none after:absolute after:inset-x-0 after:bottom-3 after:h-0', 'focus-visible:after:h-0.5 focus-visible:after:bg-black'),
|
|
461
500
|
onClick: ()=>setIsExpanded((prevState)=>!prevState),
|
|
462
501
|
"aria-expanded": isExpanded,
|
|
463
502
|
"aria-controls": id,
|
|
@@ -493,7 +532,7 @@ const Avatar = ({ src, alt = '', className, onError, loading = 'lazy', ...rest }
|
|
|
493
532
|
setHasError(true);
|
|
494
533
|
}
|
|
495
534
|
}) : /*#__PURE__*/ jsx("div", {
|
|
496
|
-
className: cx(className, baseClassName, '
|
|
535
|
+
className: cx(className, baseClassName, 'bg-gray-light text-gray-dark grid place-items-center'),
|
|
497
536
|
children: /*#__PURE__*/ jsx(User, {
|
|
498
537
|
className: "scale-[2.25]"
|
|
499
538
|
})
|
|
@@ -501,7 +540,7 @@ const Avatar = ({ src, alt = '', className, onError, loading = 'lazy', ...rest }
|
|
|
501
540
|
};
|
|
502
541
|
|
|
503
542
|
const formField = cx('group flex flex-col gap-2');
|
|
504
|
-
const formFieldError = cx('
|
|
543
|
+
const formFieldError = cx('bg-red-light text-red w-fit px-2 py-1 text-sm/6', 'group-data-[slot=file-upload]:rounded-lg');
|
|
505
544
|
const input = cva({
|
|
506
545
|
base: [
|
|
507
546
|
// All inputs should always have a white background (this also ensures that type="search" on Safri doesn't get a gray background)
|
|
@@ -510,7 +549,7 @@ const input = cva({
|
|
|
510
549
|
// Setting min-height to prevent the input from collapsing in Safari
|
|
511
550
|
// Combining these with a padding-y as base classes makes it easier to standardize the height (44px) of all inputs
|
|
512
551
|
'box-content min-h-6 py-2.5',
|
|
513
|
-
'rounded-md
|
|
552
|
+
'rounded-md text-base leading-6 font-normal placeholder-[#727070] ring-1 ring-black outline-hidden',
|
|
514
553
|
// invalid styles
|
|
515
554
|
'group-data-invalid:ring-focus group-data-invalid:ring-red',
|
|
516
555
|
// Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
|
|
@@ -519,12 +558,12 @@ const input = cva({
|
|
|
519
558
|
variants: {
|
|
520
559
|
// Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
|
|
521
560
|
focusModifier: {
|
|
522
|
-
focus: 'focus:ring-focus group-data-invalid:focus:ring-
|
|
523
|
-
visible: 'data-focus-visible:ring-focus group-data-invalid:data-focus-visible:ring-
|
|
561
|
+
focus: 'focus:ring-focus group-data-invalid:focus:ring-red group-data-invalid:focus:ring-3',
|
|
562
|
+
visible: 'data-focus-visible:ring-focus group-data-invalid:data-focus-visible:ring-red group-data-invalid:data-focus-visible:ring-3'
|
|
524
563
|
},
|
|
525
564
|
isGrouped: {
|
|
526
565
|
false: 'px-3',
|
|
527
|
-
true: '
|
|
566
|
+
true: 'flex-1 ring-0!'
|
|
528
567
|
}
|
|
529
568
|
},
|
|
530
569
|
defaultVariants: {
|
|
@@ -533,11 +572,11 @@ const input = cva({
|
|
|
533
572
|
}
|
|
534
573
|
});
|
|
535
574
|
const inputGroup = cx([
|
|
536
|
-
'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black
|
|
537
|
-
'group-data-invalid:ring-focus group-data-invalid:ring-red group-data-invalid:focus-within:ring-
|
|
575
|
+
'focus-within:ring-focus inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black',
|
|
576
|
+
'group-data-invalid:ring-focus group-data-invalid:ring-red group-data-invalid:focus-within:ring-red group-data-invalid:focus-within:ring-3'
|
|
538
577
|
]);
|
|
539
578
|
const dropdown = {
|
|
540
|
-
popover: cx('data-entering:fade-in data-exiting:fade-out min-w-(--trigger-width) overflow-y-auto rounded-md border border-black bg-white shadow-sm
|
|
579
|
+
popover: cx('data-entering:fade-in data-exiting:fade-out data-entering:animate-in data-exiting:animate-out min-w-(--trigger-width) overflow-y-auto rounded-md border border-black bg-white shadow-sm'),
|
|
541
580
|
// overflow-x-hidden is needed to prevent visible vertical scrollbars from overflowing the border radius of the popover
|
|
542
581
|
listbox: cx('max-h-100 overflow-x-hidden text-sm outline-hidden'),
|
|
543
582
|
chevronIcon: cx('text-base transition-transform duration-150 group-data-open:rotate-180 motion-reduce:transition-none')
|
|
@@ -550,7 +589,7 @@ const animateIconVariants = cva({
|
|
|
550
589
|
left: 'hover:*:[svg]:motion-safe:-translate-x-1',
|
|
551
590
|
down: 'hover:*:[svg]:motion-safe:translate-y-1',
|
|
552
591
|
up: 'hover:*:[svg]:motion-safe:-translate-y-1',
|
|
553
|
-
'up-right': 'hover:*:[svg]:motion-safe
|
|
592
|
+
'up-right': 'hover:*:[svg]:motion-safe:translate-x-0.5 hover:*:[svg]:motion-safe:-translate-y-0.5'
|
|
554
593
|
}
|
|
555
594
|
}
|
|
556
595
|
});
|
|
@@ -562,7 +601,7 @@ function Backlink(props) {
|
|
|
562
601
|
const { className, children, withUnderline, ref, ...restProps } = props;
|
|
563
602
|
const _className = cx(className, animateIconVariants({
|
|
564
603
|
animateIcon: 'left'
|
|
565
|
-
}), 'group flex max-w-fit cursor-pointer items-center gap-3 rounded-md p-2.5 font-normal no-underline
|
|
604
|
+
}), 'group focus-visible:outline-focus flex max-w-fit cursor-pointer items-center gap-3 rounded-md p-2.5 font-normal no-underline');
|
|
566
605
|
const content = /*#__PURE__*/ jsxs(Fragment, {
|
|
567
606
|
children: [
|
|
568
607
|
/*#__PURE__*/ jsx(ChevronLeft, {
|
|
@@ -570,7 +609,7 @@ function Backlink(props) {
|
|
|
570
609
|
}),
|
|
571
610
|
/*#__PURE__*/ jsx("span", {
|
|
572
611
|
children: /*#__PURE__*/ jsx("span", {
|
|
573
|
-
className: cx('border-
|
|
612
|
+
className: cx('border-y border-transparent transition-colors duration-300', withUnderline ? 'border-b-black' : 'group-hover:border-b-black'),
|
|
574
613
|
children: children
|
|
575
614
|
})
|
|
576
615
|
})
|
|
@@ -606,9 +645,9 @@ const badgeVariants = cva({
|
|
|
606
645
|
'green-dark': 'bg-green-dark text-white'
|
|
607
646
|
},
|
|
608
647
|
size: {
|
|
609
|
-
small: 'description px-2 py-0.5 [&_svg]:
|
|
610
|
-
medium: 'description px-2.5 py-1.5 [&_svg]:
|
|
611
|
-
large: 'paragraph px-3 py-2 [&_svg]:
|
|
648
|
+
small: 'description px-2 py-0.5 [&_svg]:size-4',
|
|
649
|
+
medium: 'description px-2.5 py-1.5 [&_svg]:size-4',
|
|
650
|
+
large: 'paragraph px-3 py-2 [&_svg]:size-5'
|
|
612
651
|
}
|
|
613
652
|
},
|
|
614
653
|
defaultVariants: {
|
|
@@ -630,7 +669,7 @@ function Badge(props) {
|
|
|
630
669
|
}
|
|
631
670
|
|
|
632
671
|
const linkVariants = compose(animateIconVariants, cva({
|
|
633
|
-
base: 'inline-flex cursor-pointer items-center gap-1 font-medium hover:no-underline focus-visible:outline-current
|
|
672
|
+
base: 'focus-visible:outline-focus-offset inline-flex cursor-pointer items-center gap-1 font-medium hover:no-underline focus-visible:outline-current data-disabled:cursor-default data-disabled:font-normal data-disabled:no-underline'
|
|
634
673
|
}));
|
|
635
674
|
const Link = ({ animateIcon, children, className, '~iconRight': iconRight, ...props })=>{
|
|
636
675
|
const locale = _useLocale();
|
|
@@ -662,7 +701,7 @@ function Breadcrumb(props) {
|
|
|
662
701
|
href ? /*#__PURE__*/ jsx(Link, {
|
|
663
702
|
href: href,
|
|
664
703
|
// use outline instead of ring-3 for focus marker that can be offset without creating a white background between the focus marker and the element content
|
|
665
|
-
className: "rounded-xs font-normal
|
|
704
|
+
className: "focus-visible:outline-focus rounded-xs font-normal group-last:no-underline hover:underline",
|
|
666
705
|
children: children
|
|
667
706
|
}) : children,
|
|
668
707
|
/*#__PURE__*/ jsx(ChevronRight, {
|
|
@@ -676,7 +715,7 @@ function Breadcrumbs(props) {
|
|
|
676
715
|
const { className, children, ...restProps } = props;
|
|
677
716
|
return /*#__PURE__*/ jsx(Breadcrumbs$1, {
|
|
678
717
|
...restProps,
|
|
679
|
-
className: cx(className, 'flex flex-wrap text-sm
|
|
718
|
+
className: cx(className, 'flex flex-wrap text-sm/6'),
|
|
680
719
|
children: children
|
|
681
720
|
});
|
|
682
721
|
}
|
|
@@ -685,7 +724,7 @@ function Breadcrumbs(props) {
|
|
|
685
724
|
* Figma: https://www.figma.com/file/9OvSg0ZXI5E1eQYi7AWiWn/Grunnmuren-2.0-%E2%94%82-Designsystem?node-id=30%3A2574&mode=dev
|
|
686
725
|
*/ const buttonVariants = compose(animateIconVariants, cva({
|
|
687
726
|
base: [
|
|
688
|
-
'inline-flex min-h-[44px] cursor-pointer items-center justify-center
|
|
727
|
+
'focus-visible:outline-focus-offset inline-flex min-h-[44px] cursor-pointer items-center justify-center rounded-lg font-medium whitespace-nowrap transition-colors duration-200'
|
|
689
728
|
],
|
|
690
729
|
variants: {
|
|
691
730
|
/**
|
|
@@ -709,7 +748,7 @@ function Breadcrumbs(props) {
|
|
|
709
748
|
* When the button is without text, but with a single icon.
|
|
710
749
|
* @default false
|
|
711
750
|
*/ isIconOnly: {
|
|
712
|
-
true: 'p-2 [&>svg]:
|
|
751
|
+
true: 'p-2 [&>svg]:size-7',
|
|
713
752
|
false: 'gap-2.5 px-4 py-2'
|
|
714
753
|
},
|
|
715
754
|
// Make the content of the button transparent to hide it's content, but keep the button width
|
|
@@ -723,48 +762,48 @@ function Breadcrumbs(props) {
|
|
|
723
762
|
color: 'blue',
|
|
724
763
|
variant: 'primary',
|
|
725
764
|
// Darken bg by 20% on hover. The color is manually crafted
|
|
726
|
-
className: 'bg-blue-dark
|
|
765
|
+
className: 'bg-blue-dark hover:bg-blue text-white active:bg-[#0536A0] active:text-white **:[[role="progressbar"]]:text-white'
|
|
727
766
|
},
|
|
728
767
|
{
|
|
729
768
|
color: 'blue',
|
|
730
769
|
variant: 'secondary',
|
|
731
|
-
className: 'text-blue-dark hover:
|
|
770
|
+
className: 'text-blue-dark hover:bg-blue hover:text-blue-dark **:[[role="progressbar"]]:text-blue-dark hover:border-transparent hover:text-white active:bg-[#0536A0] [&:hover_[role="progressbar"]]:text-white'
|
|
732
771
|
},
|
|
733
772
|
{
|
|
734
773
|
color: 'blue',
|
|
735
774
|
variant: 'tertiary',
|
|
736
|
-
className: '[
|
|
775
|
+
className: '**:[[role="progressbar"]]:text-black'
|
|
737
776
|
},
|
|
738
777
|
{
|
|
739
778
|
color: 'mint',
|
|
740
779
|
variant: 'primary',
|
|
741
780
|
// Darken bg by 20% on hover. The color is manually crafted
|
|
742
|
-
className: 'bg-mint text-black hover:bg-[#8dd4bd]
|
|
781
|
+
className: 'bg-mint active:[#9ddac6] text-black hover:bg-[#8dd4bd] **:[[role="progressbar"]]:text-black'
|
|
743
782
|
},
|
|
744
783
|
{
|
|
745
784
|
color: 'mint',
|
|
746
785
|
variant: 'secondary',
|
|
747
|
-
className: 'text-mint hover:bg-mint
|
|
786
|
+
className: 'text-mint hover:bg-mint **:[[role="progressbar"]]:text-mint hover:text-black [&:hover_[role="progressbar"]]:text-black'
|
|
748
787
|
},
|
|
749
788
|
{
|
|
750
789
|
color: 'mint',
|
|
751
790
|
variant: 'tertiary',
|
|
752
|
-
className: 'text-mint [
|
|
791
|
+
className: 'text-mint **:[[role="progressbar"]]:text-mint'
|
|
753
792
|
},
|
|
754
793
|
{
|
|
755
794
|
color: 'white',
|
|
756
795
|
variant: 'primary',
|
|
757
|
-
className: '
|
|
796
|
+
className: 'hover:bg-sky active:bg-sky-light bg-white text-black **:[[role="progressbar"]]:text-black'
|
|
758
797
|
},
|
|
759
798
|
{
|
|
760
799
|
color: 'white',
|
|
761
800
|
variant: 'secondary',
|
|
762
|
-
className: 'text-white hover:bg-white hover:text-black [&:hover_[role="progressbar"]]:text-black [
|
|
801
|
+
className: 'text-white hover:bg-white hover:text-black [&:hover_[role="progressbar"]]:text-black **:[[role="progressbar"]]:text-white'
|
|
763
802
|
},
|
|
764
803
|
{
|
|
765
804
|
color: 'white',
|
|
766
805
|
variant: 'tertiary',
|
|
767
|
-
className: 'text-white [
|
|
806
|
+
className: 'text-white **:[[role="progressbar"]]:text-white'
|
|
768
807
|
}
|
|
769
808
|
],
|
|
770
809
|
defaultVariants: {
|
|
@@ -845,7 +884,7 @@ const cardVariants = cva({
|
|
|
845
884
|
// **** Fail-safe for interactive elements ****
|
|
846
885
|
// Make interactive elements clickable by themselves, while the rest of the card is clickable as a whole
|
|
847
886
|
// The card is made clickable by a pseudo-element on the heading that covers the entire card
|
|
848
|
-
'[&:not(:has([data-slot="card-link"]_a))_a:not([data-slot="card-link"])]:relative
|
|
887
|
+
'[&_button]:relative [&_input]:relative [&:not(:has([data-slot="card-link"]_a))_a:not([data-slot="card-link"])]:relative',
|
|
849
888
|
// Our Button component has position: relative by default, so we need to override that if it is used in a CardLink (to make the entire card clickable)
|
|
850
889
|
'[&_[data-slot="card-link"]_a]:static',
|
|
851
890
|
// Place other interactive on top of the pseudo-element that makes the entire card clickable
|
|
@@ -876,7 +915,7 @@ const cardVariants = cva({
|
|
|
876
915
|
subtle: [
|
|
877
916
|
'border-transparent',
|
|
878
917
|
// **** Media styles ****
|
|
879
|
-
'
|
|
918
|
+
'**:data-[slot="media"]:rounded-2xl'
|
|
880
919
|
],
|
|
881
920
|
outlined: 'border border-black'
|
|
882
921
|
},
|
|
@@ -887,7 +926,7 @@ const cardVariants = cva({
|
|
|
887
926
|
vertical: [
|
|
888
927
|
'flex-col',
|
|
889
928
|
// **** Media ****
|
|
890
|
-
'
|
|
929
|
+
'**:data-[slot="media"]:rounded-t-2xl'
|
|
891
930
|
],
|
|
892
931
|
horizontal: [
|
|
893
932
|
// Use more gap for horizontal cards that have media
|
|
@@ -895,7 +934,7 @@ const cardVariants = cva({
|
|
|
895
934
|
'has-data-[slot=media]:layout-gap-x not-has-data-[slot=media]:gap-x-4',
|
|
896
935
|
// **** With Media ****
|
|
897
936
|
'[&:has(>[data-slot="media"]:last-child)]:flex-col-reverse',
|
|
898
|
-
'has-data-[slot=media]:@2xl
|
|
937
|
+
'has-data-[slot=media]:@2xl:flex-row!',
|
|
899
938
|
'*:data-[slot=media]:@2xl:h-fit',
|
|
900
939
|
'has-data-[slot=media]:*:@2xl:basis-1/2',
|
|
901
940
|
// Position media at the edges of the card
|
|
@@ -904,7 +943,7 @@ const cardVariants = cva({
|
|
|
904
943
|
'*:data-[slot=media]:last:@2xl:ml-0',
|
|
905
944
|
// Make sure the card link is clickable when the media is on the right side
|
|
906
945
|
// This is necessary because the media content is positioned after the card link in the DOM
|
|
907
|
-
'[&:has(>[data-slot="media"]:last-child)_[data-slot="card-link"]]:z-
|
|
946
|
+
'[&:has(>[data-slot="media"]:last-child)_[data-slot="card-link"]]:z-1',
|
|
908
947
|
// **** Without Media ****
|
|
909
948
|
'not-has-data-[slot=media]:@md:flex-row',
|
|
910
949
|
// Make the layout responsive: when the Content reaches a minimum width of 12rem, the layout switches to vertical. Also makes sure Content takes up the remaining space available.
|
|
@@ -925,7 +964,7 @@ const cardVariants = cva({
|
|
|
925
964
|
className: [
|
|
926
965
|
// **** Media ****
|
|
927
966
|
// Some rounded corners are removed when the card is outlined
|
|
928
|
-
'
|
|
967
|
+
'**:data-[slot="media"]:rounded-t-2xl',
|
|
929
968
|
'*:data-[slot=media]:first:@2xl:rounded-tr-none *:data-[slot=media]:first:@2xl:rounded-bl-2xl',
|
|
930
969
|
'*:data-[slot=media]:last:@2xl:rounded-tl-none *:data-[slot=media]:last:@2xl:rounded-br-2xl',
|
|
931
970
|
// **** Badge ****
|
|
@@ -990,8 +1029,8 @@ const cardLinkVariants = cva({
|
|
|
990
1029
|
// **** Clickarea ****
|
|
991
1030
|
'cursor-pointer',
|
|
992
1031
|
'after:absolute',
|
|
993
|
-
'after
|
|
994
|
-
'after:rounded-[calc(
|
|
1032
|
+
'after:-inset-px',
|
|
1033
|
+
'after:rounded-[calc(var(--radius-2xl)-theme(borderWidth.DEFAULT))]',
|
|
995
1034
|
// **** Focus ****
|
|
996
1035
|
'focus-visible:outline-none',
|
|
997
1036
|
'data-focus-visible:after:outline-focus',
|
|
@@ -1005,8 +1044,8 @@ const cardLinkVariants = cva({
|
|
|
1005
1044
|
// **** Clickarea ****
|
|
1006
1045
|
'[&_a]:after:cursor-pointer',
|
|
1007
1046
|
'[&_a]:after:absolute',
|
|
1008
|
-
'[&_a]:after
|
|
1009
|
-
'[&_a]:after:rounded-[calc(
|
|
1047
|
+
'[&_a]:after:-inset-px',
|
|
1048
|
+
'[&_a]:after:rounded-[calc(var(--radius-2xl)-theme(borderWidth.DEFAULT))]',
|
|
1010
1049
|
// **** Focus ****
|
|
1011
1050
|
'[&_a[data-focus-visible]]:outline-none',
|
|
1012
1051
|
'[&_a[data-focus-visible]]:after:outline-focus',
|
|
@@ -1047,20 +1086,20 @@ const HeroContext = /*#__PURE__*/ createContext(null);
|
|
|
1047
1086
|
// Common variant for "standard" and "full-bleed" Hero variants
|
|
1048
1087
|
const oneColumnLayout = [
|
|
1049
1088
|
// Vertical spacing in the <Content>
|
|
1050
|
-
'lg:*:data-[slot=
|
|
1089
|
+
'lg:*:data-[slot=content]:gap-y-4',
|
|
1051
1090
|
// Main text content takes up 9 columns on medium screens and above
|
|
1052
|
-
'lg:*:data-[slot=
|
|
1091
|
+
'lg:*:data-[slot=content]:col-span-9',
|
|
1053
1092
|
// Make sure other elements than <Content> and <Media> (i.e CTA) does not span the full width on small screens
|
|
1054
|
-
'*:not-data-[slot=
|
|
1093
|
+
'*:not-data-[slot=content]:not-data-[slot=media]:w-fit',
|
|
1055
1094
|
// Other elements than <Content> and <Media> (e.g. CTA, SVG logo or Badge) take up 3 columns on medium screens and above, and are right aligned
|
|
1056
|
-
'lg:*:not-data-[slot=
|
|
1095
|
+
'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',
|
|
1057
1096
|
// <Media> and <Carousel> content takes up the full width on medium screens and above
|
|
1058
|
-
'lg:*:data-[slot=
|
|
1059
|
-
'lg:*:data-[slot=
|
|
1097
|
+
'lg:*:data-[slot=media]:col-span-full *:data-[slot=media]:*:w-full',
|
|
1098
|
+
'lg:*:data-[slot=carousel]:col-span-full',
|
|
1060
1099
|
// Aligns <Content> and any element beside it (e.g. <Media>, <Badge>, <CTA> etc.) to the bottom of the <Content> container
|
|
1061
1100
|
'lg:items-end'
|
|
1062
1101
|
];
|
|
1063
|
-
const nonFullBleedAspectRatiosForSmallScreens = '*:data-[slot=
|
|
1102
|
+
const nonFullBleedAspectRatiosForSmallScreens = '*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-[1/1] sm:*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-4/3 md:*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-3/2';
|
|
1064
1103
|
const variants = cva({
|
|
1065
1104
|
base: [
|
|
1066
1105
|
'container px-0',
|
|
@@ -1068,14 +1107,14 @@ const variants = cva({
|
|
|
1068
1107
|
'grid lg:grid-cols-12 lg:gap-x-12 xl:gap-x-16',
|
|
1069
1108
|
'gap-y-10 lg:gap-y-12',
|
|
1070
1109
|
// Enable vertical gap within <Content>
|
|
1071
|
-
'*:data-[slot=
|
|
1110
|
+
'*:data-[slot=content]:grid',
|
|
1072
1111
|
// Vertical spacing in the <Content>
|
|
1073
|
-
'*:data-[slot=
|
|
1112
|
+
'*:data-[slot=content]:gap-y-3',
|
|
1074
1113
|
// Make sure <Media> content fills any available vertical and horizontal space
|
|
1075
|
-
'*:data-[slot=
|
|
1076
|
-
'*:data-[slot=
|
|
1114
|
+
'*:data-[slot=media]:*:object-cover',
|
|
1115
|
+
'*:data-[slot=carousel]:overflow-hidden *:data-[slot=carousel]:rounded-3xl',
|
|
1077
1116
|
// Make the carousel items full width, so we scroll one at a time
|
|
1078
|
-
'**:data-[slot=
|
|
1117
|
+
'**:data-[slot=carousel-item]:basis-full'
|
|
1079
1118
|
],
|
|
1080
1119
|
variants: {
|
|
1081
1120
|
/**
|
|
@@ -1085,36 +1124,36 @@ const variants = cva({
|
|
|
1085
1124
|
standard: [
|
|
1086
1125
|
oneColumnLayout,
|
|
1087
1126
|
nonFullBleedAspectRatiosForSmallScreens,
|
|
1088
|
-
'lg:*:data-[slot=
|
|
1127
|
+
'lg:*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-2/1'
|
|
1089
1128
|
],
|
|
1090
1129
|
'full-bleed': [
|
|
1091
1130
|
oneColumnLayout,
|
|
1092
1131
|
// Position the media and carousel content to fill the entire viewport width
|
|
1093
|
-
'*:data-[slot=
|
|
1132
|
+
'*:data-[slot=media]:*:absolute *:data-[slot=media]:*:left-0',
|
|
1094
1133
|
// Special case for Carousel, where the Media is nested inside a CarouselItem
|
|
1095
|
-
'*:data-[slot=
|
|
1134
|
+
'*:data-[slot=carousel]:**:data-[slot=media]:w-full',
|
|
1096
1135
|
// Match the heights of the <Media> or <Carousel> wrapper for the Media content (e.g. image, VideoLoop, video etc.)
|
|
1097
1136
|
// This is necessary due to the absolute positioning of the media and carousel containers in this variant
|
|
1098
1137
|
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
1099
|
-
'
|
|
1100
|
-
'**:data-[slot=
|
|
1138
|
+
'3xl:**:data-[slot=media]:h-192 4xl:**:data-[slot=media]:h-212 **:data-[slot=media]:h-80 sm:**:data-[slot=media]:h-100 md:**:data-[slot=media]:h-120 lg:**:data-[slot=media]:h-140 xl:**:data-[slot=media]:h-160 2xl:**:data-[slot=media]:h-168',
|
|
1139
|
+
'**:data-[slot=media]:*:h-[inherit]',
|
|
1101
1140
|
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
1102
|
-
'
|
|
1103
|
-
'*:data-[slot=
|
|
1141
|
+
'3xl:*:data-[slot=carousel]:h-192 4xl:*:data-[slot=carousel]:h-212 *:data-[slot=carousel]:h-80 sm:*:data-[slot=carousel]:h-100 md:*:data-[slot=carousel]:h-120 lg:*:data-[slot=carousel]:h-140 xl:*:data-[slot=carousel]:h-160 2xl:*:data-[slot=carousel]:h-168',
|
|
1142
|
+
'*:data-[slot=carousel]:w-full!',
|
|
1104
1143
|
// Override aspect ratio of the media and carousel-item slots (since we can not use aspect for full-bleed layout)
|
|
1105
|
-
'**:data-[slot=
|
|
1144
|
+
'**:data-[slot=carousel-item]:data-[slot=media]:*:aspect-none',
|
|
1106
1145
|
// break out the carousel out of the container
|
|
1107
|
-
'**:data-[slot=
|
|
1146
|
+
'**:data-[slot=carousel-items-container]:absolute **:data-[slot=carousel-items-container]:inset-x-0 **:data-[slot=carousel-items-container]:h-[inherit]',
|
|
1108
1147
|
// Positions the carousel controls inside the carousel
|
|
1109
|
-
'
|
|
1148
|
+
'*:data-[slot=carousel]:flex *:data-[slot=carousel]:items-end *:data-[slot=carousel]:justify-end **:data-[slot=carousel-controls]:z-10 **:data-[slot=carousel-controls]:mb-4'
|
|
1110
1149
|
],
|
|
1111
1150
|
'two-column': [
|
|
1112
1151
|
'lg:items-center lg:*:col-span-6',
|
|
1113
1152
|
// Vertical spacing in the <Content>
|
|
1114
|
-
'lg:*:data-[slot=
|
|
1153
|
+
'lg:*:data-[slot=content]:gap-y-7',
|
|
1115
1154
|
nonFullBleedAspectRatiosForSmallScreens,
|
|
1116
1155
|
// Set media aspect ratio to 1:1 (square)
|
|
1117
|
-
'lg:*:data-[slot=
|
|
1156
|
+
'lg:*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-square'
|
|
1118
1157
|
]
|
|
1119
1158
|
}
|
|
1120
1159
|
},
|
|
@@ -1125,8 +1164,8 @@ const variants = cva({
|
|
|
1125
1164
|
'two-column'
|
|
1126
1165
|
],
|
|
1127
1166
|
className: [
|
|
1128
|
-
'*:data-[slot=
|
|
1129
|
-
'
|
|
1167
|
+
'*:data-[slot=media]:*:rounded-3xl',
|
|
1168
|
+
'*:data-[slot=carousel]:relative **:data-[slot=carousel-container]:rounded-3xl **:data-[slot=carousel-controls]:absolute **:data-[slot=carousel-controls]:right-4 **:data-[slot=carousel-controls]:bottom-4'
|
|
1130
1169
|
]
|
|
1131
1170
|
}
|
|
1132
1171
|
],
|
|
@@ -1369,7 +1408,7 @@ const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0,
|
|
|
1369
1408
|
} : {
|
|
1370
1409
|
variant: 'tertiary'
|
|
1371
1410
|
};
|
|
1372
|
-
return(//
|
|
1411
|
+
return(// oxlint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
1373
1412
|
/*#__PURE__*/ jsx("div", {
|
|
1374
1413
|
...rest,
|
|
1375
1414
|
"data-orientation": orientation,
|
|
@@ -1470,7 +1509,7 @@ const carouselButtonIconSlotVariants = cva({
|
|
|
1470
1509
|
{
|
|
1471
1510
|
slot: 'prev',
|
|
1472
1511
|
orientation: 'horizontal',
|
|
1473
|
-
className: 'group-hover:motion-safe:-translate-x-1
|
|
1512
|
+
className: 'rotate-180 group-hover:motion-safe:-translate-x-1'
|
|
1474
1513
|
},
|
|
1475
1514
|
// vertical controls
|
|
1476
1515
|
{
|
|
@@ -1481,7 +1520,7 @@ const carouselButtonIconSlotVariants = cva({
|
|
|
1481
1520
|
{
|
|
1482
1521
|
slot: 'prev',
|
|
1483
1522
|
orientation: 'vertical',
|
|
1484
|
-
className: 'group-hover:motion-safe:-translate-y-1
|
|
1523
|
+
className: '-rotate-90 group-hover:motion-safe:-translate-y-1'
|
|
1485
1524
|
}
|
|
1486
1525
|
]
|
|
1487
1526
|
});
|
|
@@ -1532,7 +1571,7 @@ function ErrorMessage(props) {
|
|
|
1532
1571
|
}
|
|
1533
1572
|
|
|
1534
1573
|
const defaultClasses$1 = cx([
|
|
1535
|
-
'group -mx-2.5
|
|
1574
|
+
'group relative left-0 -mx-2.5 inline-flex max-w-fit cursor-pointer items-start gap-4 p-2.5 leading-7'
|
|
1536
1575
|
]);
|
|
1537
1576
|
// Pulling this out into it's own component. Will probably export it in the future
|
|
1538
1577
|
// so it can be used in other views, outside of an input of type checkbox, like in table rows.
|
|
@@ -1544,7 +1583,7 @@ function CheckmarkBox() {
|
|
|
1544
1583
|
// For the ::before psuedo element the line height of the label is always 1em.
|
|
1545
1584
|
// When we know the height of the label we use the height of the radio to push it down to align with the label's first line
|
|
1546
1585
|
// TODO: 1.75 here is the unit less lineheight, altough we use 1.75rem as the line height, so there is a mismatch here. Revisit this when we've worked on typography in v2. Should this be a CSS custom property instead?
|
|
1547
|
-
'mt-[calc((
|
|
1586
|
+
'mt-[calc((1em*1.75-24px)/2)] h-[24px] w-[24px]',
|
|
1548
1587
|
// selected
|
|
1549
1588
|
'group-data-selected:group-not-data-hovered:group-not-data-invalid:border-blue group-data-selected:group-not-data-hovered:group-not-data-invalid:bg-blue',
|
|
1550
1589
|
'group-data-selected:group-not-data-hovered:group-data-invalid:border-red group-data-selected:group-not-data-hovered:group-data-invalid:bg-red',
|
|
@@ -1558,10 +1597,10 @@ function CheckmarkBox() {
|
|
|
1558
1597
|
'group-data-hovered:group-data-selected:group-not-data-invalid:bg-blue-dark',
|
|
1559
1598
|
// invalid - The border is 1 px thicker when invalid. We don't actually want to change the border width, as that causes the element's size to change
|
|
1560
1599
|
// so we use an inner shadow of 1 px instead to pad the actual border
|
|
1561
|
-
'group-data-invalid:border-red group-data-invalid:shadow-
|
|
1600
|
+
'group-data-invalid:border-red group-data-invalid:shadow-red group-data-invalid:shadow-[inset_0_0_0_1px]'
|
|
1562
1601
|
]),
|
|
1563
1602
|
children: /*#__PURE__*/ jsx(Check, {
|
|
1564
|
-
className: "
|
|
1603
|
+
className: "group-data-invalid:group-data-hovered:group-data-selected:text-red size-full opacity-0 group-data-selected:opacity-100"
|
|
1565
1604
|
})
|
|
1566
1605
|
});
|
|
1567
1606
|
}
|
|
@@ -1627,7 +1666,7 @@ function Description(props) {
|
|
|
1627
1666
|
function Label(props) {
|
|
1628
1667
|
const { children, className, ...restProps } = props;
|
|
1629
1668
|
return /*#__PURE__*/ jsx(Label$1, {
|
|
1630
|
-
className: cx(className, 'font-medium
|
|
1669
|
+
className: cx(className, 'leading-7 font-medium'),
|
|
1631
1670
|
...restProps,
|
|
1632
1671
|
children: children
|
|
1633
1672
|
});
|
|
@@ -1678,7 +1717,7 @@ const ListBoxItem = (props)=>{
|
|
|
1678
1717
|
}
|
|
1679
1718
|
return /*#__PURE__*/ jsx(ListBoxItem$1, {
|
|
1680
1719
|
...props,
|
|
1681
|
-
className: cx(props.className, 'flex cursor-pointer px-6 py-3 leading-6 outline-none
|
|
1720
|
+
className: cx(props.className, 'data-focused:bg-sky-lightest flex cursor-pointer px-6 py-3 leading-6 outline-none'),
|
|
1682
1721
|
textValue: textValue,
|
|
1683
1722
|
children: ({ isSelected })=>/*#__PURE__*/ jsxs(Fragment, {
|
|
1684
1723
|
children: [
|
|
@@ -1702,7 +1741,7 @@ const ListBoxItem = (props)=>{
|
|
|
1702
1741
|
* This component can be used to label grouped items in a `ListBoxSection` with a heading
|
|
1703
1742
|
*/ const ListBoxHeader = (props)=>/*#__PURE__*/ jsx(Header, {
|
|
1704
1743
|
...props,
|
|
1705
|
-
className: cx(props.className, 'mx-6 cursor-default py-2 font-medium
|
|
1744
|
+
className: cx(props.className, 'text-blue-dark mx-6 cursor-default py-2 leading-6 font-medium')
|
|
1706
1745
|
});
|
|
1707
1746
|
|
|
1708
1747
|
function Combobox(props) {
|
|
@@ -1802,8 +1841,9 @@ function Combobox(props) {
|
|
|
1802
1841
|
onChange: (e)=>onSelect?.(e.target.files),
|
|
1803
1842
|
capture: defaultCamera,
|
|
1804
1843
|
multiple: allowsMultiple,
|
|
1805
|
-
|
|
1806
|
-
|
|
1844
|
+
...acceptDirectory ? {
|
|
1845
|
+
webkitdirectory: ''
|
|
1846
|
+
} : {},
|
|
1807
1847
|
// This is a work around to prevent error in the console when attempting to submit a form with a required and empty file input
|
|
1808
1848
|
// RAC uses display: none, which prevents the file input from being focused.
|
|
1809
1849
|
// What we do instead is to hide it visually using custom CSS, so that the native HTML validation messages are still hidden. Which is why
|
|
@@ -2047,7 +2087,7 @@ const FileUpload = ({ children, files: _files, onChange, validate, isInvalid: _i
|
|
|
2047
2087
|
className: "flex items-center gap-3",
|
|
2048
2088
|
children: [
|
|
2049
2089
|
/*#__PURE__*/ jsx("div", {
|
|
2050
|
-
className: "footnote
|
|
2090
|
+
className: "footnote border-gray-light bg-gray-lightest rounded-md border px-2.5 py-2",
|
|
2051
2091
|
children: getFileExtension(file)
|
|
2052
2092
|
}),
|
|
2053
2093
|
/*#__PURE__*/ jsxs("div", {
|
|
@@ -2068,8 +2108,8 @@ const FileUpload = ({ children, files: _files, onChange, validate, isInvalid: _i
|
|
|
2068
2108
|
/*#__PURE__*/ jsx("button", {
|
|
2069
2109
|
type: "button",
|
|
2070
2110
|
"aria-label": translations.remove[locale],
|
|
2071
|
-
className: cx('-m-2 grid
|
|
2072
|
-
'focus-visible
|
|
2111
|
+
className: cx('-m-2 grid size-11 shrink-0 cursor-pointer place-items-center rounded-xl', // Focus styles
|
|
2112
|
+
'focus-visible:outline-focus focus-visible:-outline-offset-8'),
|
|
2073
2113
|
onClick: ()=>{
|
|
2074
2114
|
// For controlled component
|
|
2075
2115
|
onChange?.((prevFiles)=>prevFiles.filter((_, index)=>index !== fileIndex));
|
|
@@ -2173,7 +2213,7 @@ const LinkListItem = ({ children, className, ...props })=>{
|
|
|
2173
2213
|
const iconRight = childProps['~iconRight'] || childProps.download ? /*#__PURE__*/ jsx(Download, {}) : childProps.rel?.includes('external') ? /*#__PURE__*/ jsx(LinkExternal, {}) : /*#__PURE__*/ jsx(ArrowRight, {});
|
|
2174
2214
|
return /*#__PURE__*/ jsx("li", {
|
|
2175
2215
|
...props,
|
|
2176
|
-
className: cx(className, 'after
|
|
2216
|
+
className: cx(className, 'after:bg-gray-light relative p-1.25 after:absolute after:inset-x-0 after:-top-px after:h-px after:w-full', '*:data-[slot=link]:paragraph', ...linkStyles),
|
|
2177
2217
|
"data-slot": "link-list-item",
|
|
2178
2218
|
children: /*#__PURE__*/ isValidElement(child) && /*#__PURE__*/ cloneElement(child, {
|
|
2179
2219
|
animateIcon,
|
|
@@ -2212,7 +2252,7 @@ const Modal = ({ isDismissable = true, isOpen, onOpenChange, defaultOpen, classN
|
|
|
2212
2252
|
isDismissable && /*#__PURE__*/ jsx(Button, {
|
|
2213
2253
|
slot: "close",
|
|
2214
2254
|
variant: "tertiary",
|
|
2215
|
-
className: "
|
|
2255
|
+
className: "data-focus-visible:outline-focus-inset px-2.5!",
|
|
2216
2256
|
"aria-label": translations$1.close[locale],
|
|
2217
2257
|
onPress: ()=>onOpenChange?.(false),
|
|
2218
2258
|
children: /*#__PURE__*/ jsx(Close, {})
|
|
@@ -2241,7 +2281,7 @@ const Modal = ({ isDismissable = true, isOpen, onOpenChange, defaultOpen, classN
|
|
|
2241
2281
|
const Dialog = ({ className, children, ...restProps })=>/*#__PURE__*/ jsx(Dialog$1, {
|
|
2242
2282
|
...restProps,
|
|
2243
2283
|
className: cx(className, 'relative grid gap-y-5 outline-none', // Footer
|
|
2244
|
-
'
|
|
2284
|
+
'**:data-[slot="footer"]:flex **:data-[slot="footer"]:gap-x-2'),
|
|
2245
2285
|
children: ({ close })=>/*#__PURE__*/ jsx(Provider, {
|
|
2246
2286
|
values: [
|
|
2247
2287
|
[
|
|
@@ -2330,23 +2370,23 @@ function NumberField(props) {
|
|
|
2330
2370
|
}
|
|
2331
2371
|
|
|
2332
2372
|
const defaultClasses = cx([
|
|
2333
|
-
'-ml-2.5
|
|
2373
|
+
'relative -ml-2.5 inline-flex max-w-fit cursor-pointer items-start gap-4 py-2.5 pl-2.5 leading-7',
|
|
2334
2374
|
// the radio button itself
|
|
2335
2375
|
'before:flex-none before:rounded-full before:border-2 before:border-black',
|
|
2336
2376
|
// to vertically align the radio we need to calculate the label's height, which is equal to it's font size multiplied by the line height.
|
|
2337
2377
|
// For the ::before psuedo element the line height of the label is always 1em.
|
|
2338
2378
|
// When we know the height of the label we use the height of the radio to push it down to align with the label's first line
|
|
2339
2379
|
// TODO: 1.75 here is the unit less lineheight, altough we use 1.75rem as the line height, so there is a mismatch here. Revisit this when we've worked on typography in v2. Should this be a CSS custom property instead?
|
|
2340
|
-
'before:mt-[calc((
|
|
2380
|
+
'before:mt-[calc((1em*1.75-24px)/2)] before:h-[24px] before:w-[24px]',
|
|
2341
2381
|
// selected
|
|
2342
|
-
'data-selected:before:
|
|
2382
|
+
'data-selected:before:bg-blue data-selected:before:border-black data-selected:before:shadow-[inset_0_0_0_4px_rgb(255,255,255)]',
|
|
2343
2383
|
// hover
|
|
2344
2384
|
'data-hovered:data-selected:before:border-blue-dark data-hovered:data-invalid:before:bg-red-light data-hovered:data-selected:before:bg-blue-dark data-hovered:before:border-blue data-hovered:before:bg-sky',
|
|
2345
2385
|
// focus
|
|
2346
2386
|
'data-focus-visible:before:ring-focus-offset',
|
|
2347
2387
|
// invalid - The border is 1 px thicker when invalid. We don't actually want to change the border width, as that causes the element's size to change
|
|
2348
2388
|
// so we use an inner outline to artifically pad the border
|
|
2349
|
-
'data-invalid:data-selected:before
|
|
2389
|
+
'data-invalid:data-selected:before:bg-red! data-invalid:before:border-red data-invalid:before:outline-red data-invalid:before:outline data-invalid:before:outline-[3px] data-invalid:before:outline-offset-[-3px] data-invalid:before:outline-solid'
|
|
2350
2390
|
]);
|
|
2351
2391
|
function Radio(props) {
|
|
2352
2392
|
const { children, className, description, ...restProps } = props;
|
|
@@ -2417,7 +2457,7 @@ function Select(props) {
|
|
|
2417
2457
|
ref: ref,
|
|
2418
2458
|
children: [
|
|
2419
2459
|
/*#__PURE__*/ jsx(SelectValue, {
|
|
2420
|
-
className: "flex-1 truncate text-left data-
|
|
2460
|
+
className: "flex-1 truncate text-left data-placeholder:text-[#727070]"
|
|
2421
2461
|
}),
|
|
2422
2462
|
/*#__PURE__*/ jsx(ChevronDown, {
|
|
2423
2463
|
className: dropdown.chevronIcon
|
|
@@ -2454,9 +2494,9 @@ const ProgressBar = ({ children, className, ...restProps })=>{
|
|
|
2454
2494
|
...restArgs
|
|
2455
2495
|
}) : children,
|
|
2456
2496
|
/*#__PURE__*/ jsx("div", {
|
|
2457
|
-
className: "
|
|
2497
|
+
className: "border-blue-dark bg-gray-light relative rounded border",
|
|
2458
2498
|
children: /*#__PURE__*/ jsx("div", {
|
|
2459
|
-
className: "h-1 rounded
|
|
2499
|
+
className: "bg-blue-dark h-1 rounded transition-all duration-300 ease-in-out",
|
|
2460
2500
|
style: {
|
|
2461
2501
|
width: `${percentage}%`
|
|
2462
2502
|
}
|
|
@@ -2469,14 +2509,13 @@ const ProgressBar = ({ children, className, ...restProps })=>{
|
|
|
2469
2509
|
|
|
2470
2510
|
function ScrollButton({ direction, onClick, isVisible, hasScrollingOccurred, className }) {
|
|
2471
2511
|
const Icon = direction === 'left' ? ChevronLeft : ChevronRight;
|
|
2472
|
-
return(//
|
|
2473
|
-
// biome-ignore lint/a11y/noStaticElementInteractions: This button is only for mouse interaction to help users scroll. Keyboard and screen reader users can navigate the content directly without needing these scroll helpers.
|
|
2512
|
+
return(// oxlint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
2474
2513
|
/*#__PURE__*/ jsx("div", {
|
|
2475
2514
|
onClick: onClick,
|
|
2476
2515
|
className: cx(// Base scroll button styling
|
|
2477
2516
|
'flex cursor-pointer items-center justify-center', 'absolute top-0 size-11', 'group/scroll-button text-black', direction === 'left' ? 'bg-[linear-gradient(90deg,white,white_calc(100%-10px),transparent)]' : 'bg-[linear-gradient(90deg,transparent,white_calc(10px),white)]', // Animation
|
|
2478
2517
|
hasScrollingOccurred && 'duration-100 ease-in motion-safe:transition-transform', // Hide/show animation
|
|
2479
|
-
direction === 'left' ? !isVisible && '-translate-x-full
|
|
2518
|
+
direction === 'left' ? !isVisible && 'pointer-events-none -translate-x-full' : !isVisible && 'pointer-events-none translate-x-full', direction === 'left' ? '-left-3' : '-right-3', className),
|
|
2480
2519
|
children: /*#__PURE__*/ jsx(Icon, {
|
|
2481
2520
|
className: cx('motion-safe:transition-all', direction === 'left' ? 'group-hover/scroll-button:-translate-x-1' : 'group-hover/scroll-button:translate-x-1')
|
|
2482
2521
|
})
|
|
@@ -2507,11 +2546,14 @@ function ScrollButton({ direction, onClick, isVisible, hasScrollingOccurred, cla
|
|
|
2507
2546
|
}));
|
|
2508
2547
|
}, []);
|
|
2509
2548
|
const debouncedUpdateScrollState = useDebouncedCallback(updateScrollState, 100);
|
|
2510
|
-
//
|
|
2549
|
+
// The linter struggles here, so need to enable and disable to get it to pass...
|
|
2550
|
+
// useEffect with a usecallback.....
|
|
2551
|
+
// this feels wrong, but not touching this right now since we're just changing the lint setup
|
|
2552
|
+
/* oxlint-disable react-hooks/exhaustive-deps */ // Initial check and react to dependency changes
|
|
2511
2553
|
useEffect(updateScrollState, [
|
|
2512
2554
|
...scrollStateDeps
|
|
2513
2555
|
]);
|
|
2514
|
-
useEffect(()=>{
|
|
2556
|
+
/* oxlint-enable react-hooks/exhaustive-deps */ useEffect(()=>{
|
|
2515
2557
|
const container = scrollContainerRef.current;
|
|
2516
2558
|
if (!container) {
|
|
2517
2559
|
return;
|
|
@@ -2744,7 +2786,7 @@ const TableScrollContainerContext = /*#__PURE__*/ createContext({
|
|
|
2744
2786
|
*/ function TableHeader({ className, children, ...restProps }) {
|
|
2745
2787
|
return /*#__PURE__*/ jsx(TableHeader$1, {
|
|
2746
2788
|
...restProps,
|
|
2747
|
-
className: cx(className, 'border-
|
|
2789
|
+
className: cx(className, 'border-b border-black'),
|
|
2748
2790
|
children: children
|
|
2749
2791
|
});
|
|
2750
2792
|
}
|
|
@@ -2752,14 +2794,14 @@ function TableColumn(props) {
|
|
|
2752
2794
|
const { className, children, ...restProps } = props;
|
|
2753
2795
|
return /*#__PURE__*/ jsx(Column, {
|
|
2754
2796
|
...restProps,
|
|
2755
|
-
className: cx(className, 'px-4 py-3 text-left font-medium text-black
|
|
2797
|
+
className: cx(className, 'px-4 py-3 text-left text-sm font-medium text-black', 'data-focus-visible:outline-focus-inset', '[&_:not([data-slot="table-column-resizer"]):focus-visible]:outline-focus-offset', 'min-w-fit whitespace-nowrap', 'has-data-[slot=table-column-resizer]:*:data-[slot=content]:flex has-data-[slot=table-column-resizer]:*:data-[slot=content]:justify-between has-data-[slot=table-column-resizer]:*:data-[slot=content]:gap-2'),
|
|
2756
2798
|
"data-slot": "table-column",
|
|
2757
2799
|
children: children
|
|
2758
2800
|
});
|
|
2759
2801
|
}
|
|
2760
2802
|
const TableColumnResizer = ({ className, ...restProps })=>/*#__PURE__*/ jsx(ColumnResizer, {
|
|
2761
2803
|
...restProps,
|
|
2762
|
-
className: cx(className, '-my-3 -mr-4.5 size-11 flex-none', 'cursor-ew-resize', 'relative after:absolute after:
|
|
2804
|
+
className: cx(className, '-my-3 -mr-4.5 size-11 flex-none', 'cursor-ew-resize', 'relative after:absolute after:inset-y-2 after:right-5 after:w-px after:bg-black', 'data-focused:after:outline-focus-offset'),
|
|
2763
2805
|
"data-slot": "table-column-resizer"
|
|
2764
2806
|
});
|
|
2765
2807
|
/**
|
|
@@ -2785,7 +2827,7 @@ function TableCell(props) {
|
|
|
2785
2827
|
const { className, children, ...restProps } = props;
|
|
2786
2828
|
return /*#__PURE__*/ jsx(Cell, {
|
|
2787
2829
|
...restProps,
|
|
2788
|
-
className: cx(className, 'px-4 py-3 text-
|
|
2830
|
+
className: cx(className, 'px-4 py-3 text-sm/relaxed text-black', 'min-w-fit whitespace-nowrap', 'align-top', 'data-focus-visible:outline-focus-inset'),
|
|
2789
2831
|
"data-slot": "table-cell",
|
|
2790
2832
|
children: children
|
|
2791
2833
|
});
|
|
@@ -2908,7 +2950,7 @@ const tabsVariants = cva({
|
|
|
2908
2950
|
"data-scroll-animation": false,
|
|
2909
2951
|
className: cx(className, 'group/tablist', // Ensure the tab list is scrollable
|
|
2910
2952
|
'scrollbar-hidden overflow-x-auto', 'flex w-fit max-w-full', // Ensure tabs don't shrink and maintain min-width
|
|
2911
|
-
'
|
|
2953
|
+
'*:min-w-fit *:shrink-0', // Divider line
|
|
2912
2954
|
'border-gray-light', 'data-[orientation=horizontal]:border-b', 'data-[orientation=vertical]:border-r', // Selection highlight based on orientation
|
|
2913
2955
|
'data-[orientation=horizontal]:*:border-y-2', 'data-[orientation=horizontal]:*:data-selected:border-b-blue-dark', 'data-[orientation=vertical]:*:border-r-2', 'data-[orientation=vertical]:*:data-selected:border-r-blue-dark', // Flex direction based on orientation
|
|
2914
2956
|
'data-[orientation=vertical]:flex-col'),
|
|
@@ -2938,12 +2980,12 @@ const tabsVariants = cva({
|
|
|
2938
2980
|
const { className, children, ...restProps } = props;
|
|
2939
2981
|
return /*#__PURE__*/ jsx(Tab$1, {
|
|
2940
2982
|
...restProps,
|
|
2941
|
-
className: cx(className, 'data-focus-visible
|
|
2983
|
+
className: cx(className, 'data-focus-visible:outline-focus data-focus-visible:-outline-offset-10', 'description h-11 cursor-pointer border-transparent px-4 py-[0.71875rem] font-light', // Transition
|
|
2942
2984
|
'transition-colors duration-150 ease-out', // TODO: Should disabled tabs just be hidden?
|
|
2943
2985
|
'data-disabled:cursor-not-allowed data-disabled:opacity-50', // Selection
|
|
2944
|
-
'data-selected:
|
|
2986
|
+
'data-selected:text-blue-dark data-selected:font-medium', // Hover with layout shift prevention using pseudo-element
|
|
2945
2987
|
'after:invisible after:block after:h-0 after:overflow-hidden after:font-medium after:content-[attr(data-text)]', 'data-hovered:font-medium', // Pressed
|
|
2946
|
-
'data-pressed:
|
|
2988
|
+
'data-pressed:text-blue-dark data-pressed:font-medium'),
|
|
2947
2989
|
"data-text": typeof children === 'string' ? children : '',
|
|
2948
2990
|
children: children
|
|
2949
2991
|
});
|
|
@@ -2955,14 +2997,14 @@ const tabsVariants = cva({
|
|
|
2955
2997
|
return /*#__PURE__*/ jsx(TabPanel$1, {
|
|
2956
2998
|
...restProps,
|
|
2957
2999
|
shouldForceMount: true,
|
|
2958
|
-
className: cx(className, '
|
|
3000
|
+
className: cx(className, 'data-focus-visible:outline-focus-offset flex-1 data-inert:hidden'),
|
|
2959
3001
|
children: children
|
|
2960
3002
|
});
|
|
2961
3003
|
}
|
|
2962
3004
|
|
|
2963
3005
|
const tagVariants = cva({
|
|
2964
3006
|
base: [
|
|
2965
|
-
'relative flex cursor-pointer items-center gap-1 rounded-lg px-2 py-1 font-medium
|
|
3007
|
+
'relative flex cursor-pointer items-center gap-1 rounded-lg px-2 py-1 text-sm font-medium transition-colors duration-200',
|
|
2966
3008
|
// Resting
|
|
2967
3009
|
'border-2 border-black bg-white text-black',
|
|
2968
3010
|
//Focus
|
|
@@ -3021,7 +3063,7 @@ const tagVariants = cva({
|
|
|
3021
3063
|
children: [
|
|
3022
3064
|
children,
|
|
3023
3065
|
/*#__PURE__*/ jsx(Button$1, {
|
|
3024
|
-
className: "cursor-pointer outline-none after:absolute after:
|
|
3066
|
+
className: "cursor-pointer outline-none after:absolute after:inset-0",
|
|
3025
3067
|
slot: "remove",
|
|
3026
3068
|
children: /*#__PURE__*/ jsx(Close, {
|
|
3027
3069
|
className: "ml-1"
|
|
@@ -3151,12 +3193,13 @@ const VideoLoop = ({ src, format, alt, className })=>{
|
|
|
3151
3193
|
]);
|
|
3152
3194
|
return /*#__PURE__*/ jsxs("div", {
|
|
3153
3195
|
className: cx(className, 'relative', prefersReducedMotion === null && 'opacity-0'),
|
|
3196
|
+
"data-slot": "video-loop",
|
|
3154
3197
|
children: [
|
|
3155
3198
|
/*#__PURE__*/ jsx("video", {
|
|
3156
3199
|
"aria-hidden": true,
|
|
3157
3200
|
ref: videoRef,
|
|
3158
3201
|
// cursor-pointer is not working on the button below, so we add it here for the same effect
|
|
3159
|
-
className: "
|
|
3202
|
+
className: "size-full max-h-[inherit] cursor-pointer rounded-[inherit] object-cover",
|
|
3160
3203
|
playsInline: true,
|
|
3161
3204
|
loop: prefersReducedMotion === false,
|
|
3162
3205
|
autoPlay: prefersReducedMotion === false,
|
|
@@ -3169,6 +3212,7 @@ const VideoLoop = ({ src, format, alt, className })=>{
|
|
|
3169
3212
|
setIsPlaying(false);
|
|
3170
3213
|
}
|
|
3171
3214
|
},
|
|
3215
|
+
"data-slot": "video",
|
|
3172
3216
|
children: /*#__PURE__*/ jsx("source", {
|
|
3173
3217
|
src: src,
|
|
3174
3218
|
type: `video/${format}`
|
|
@@ -3176,10 +3220,11 @@ const VideoLoop = ({ src, format, alt, className })=>{
|
|
|
3176
3220
|
}),
|
|
3177
3221
|
prefersReducedMotion !== null && /*#__PURE__*/ jsx("button", {
|
|
3178
3222
|
"data-slot": "video-loop-button",
|
|
3223
|
+
// oxlint-disable-next-line jsx-a11y/no-aria-hidden-on-focusable
|
|
3179
3224
|
"aria-hidden": true,
|
|
3180
3225
|
type: "button",
|
|
3181
3226
|
onClick: ()=>setShouldPlay((prevState)=>!prevState),
|
|
3182
|
-
className: cx('absolute
|
|
3227
|
+
className: cx('absolute inset-0 m-auto grid place-items-center', 'focus-visible:outline-focus focus-visible:outline-focus-offset', 'rounded-[inherit]', // Setting the opacity to 0 before applying the transition below will ensure the button only fades in after the video has started playing
|
|
3183
3228
|
shouldPlay && 'opacity-0', isPlaying && [
|
|
3184
3229
|
'transition-opacity duration-200',
|
|
3185
3230
|
// Only show the pause button when the video is hovered or focused
|
|
@@ -3187,7 +3232,7 @@ const VideoLoop = ({ src, format, alt, className })=>{
|
|
|
3187
3232
|
'hover:opacity-100'
|
|
3188
3233
|
]),
|
|
3189
3234
|
children: /*#__PURE__*/ jsx("span", {
|
|
3190
|
-
className: "grid
|
|
3235
|
+
className: "grid size-12 place-items-center rounded-full bg-white outline-hidden",
|
|
3191
3236
|
children: isPlaying ? /*#__PURE__*/ jsx(PlayerPause, {}) : /*#__PURE__*/ jsx(PlayerPlay, {})
|
|
3192
3237
|
})
|
|
3193
3238
|
}),
|