@digdir/designsystemet-react 1.0.0-next.44 → 1.0.0-next.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/cjs/components/Combobox/Combobox.js +1 -1
  2. package/dist/cjs/{utilities/hooks → components/Combobox}/useFormField/useFormField.js +1 -1
  3. package/dist/cjs/components/Field/Field.js +2 -2
  4. package/dist/cjs/components/Pagination/usePagination.js +8 -8
  5. package/dist/cjs/components/Popover/PopoverTrigger.js +7 -3
  6. package/dist/cjs/components/Table/TableHeaderCell.js +1 -1
  7. package/dist/cjs/components/Tag/Tag.js +3 -3
  8. package/dist/cjs/components/Tooltip/Tooltip.js +65 -50
  9. package/dist/cjs/index.js +24 -14
  10. package/dist/cjs/utilities/hooks/useCheckboxGroup/useCheckboxGroup.js +121 -0
  11. package/dist/cjs/utilities/hooks/useMediaQuery/useMediaQuery.js +49 -0
  12. package/dist/cjs/utilities/hooks/usePrevious/usePrevious.js +14 -0
  13. package/dist/cjs/utilities/hooks/useRadioGroup/useRadioGroup.js +99 -0
  14. package/dist/esm/components/Combobox/Combobox.js +1 -1
  15. package/dist/esm/{utilities/hooks → components/Combobox}/useFormField/useFormField.js +1 -1
  16. package/dist/esm/components/Field/Field.js +2 -2
  17. package/dist/esm/components/Pagination/usePagination.js +8 -8
  18. package/dist/esm/components/Popover/PopoverTrigger.js +7 -3
  19. package/dist/esm/components/Table/TableHeaderCell.js +1 -1
  20. package/dist/esm/components/Tag/Tag.js +3 -3
  21. package/dist/esm/components/Tooltip/Tooltip.js +66 -51
  22. package/dist/esm/index.js +11 -6
  23. package/dist/esm/utilities/hooks/useCheckboxGroup/useCheckboxGroup.js +119 -0
  24. package/dist/esm/utilities/hooks/useMediaQuery/useMediaQuery.js +47 -0
  25. package/dist/esm/utilities/hooks/usePrevious/usePrevious.js +12 -0
  26. package/dist/esm/utilities/hooks/useRadioGroup/useRadioGroup.js +97 -0
  27. package/dist/types/components/Avatar/Avatar.d.ts +1 -12
  28. package/dist/types/components/Avatar/Avatar.d.ts.map +1 -1
  29. package/dist/types/components/Badge/Badge.d.ts +1 -10
  30. package/dist/types/components/Badge/Badge.d.ts.map +1 -1
  31. package/dist/types/components/Badge/index.d.ts +1 -2
  32. package/dist/types/components/Badge/index.d.ts.map +1 -1
  33. package/dist/types/components/Breadcrumbs/BreadcrumbsLink.d.ts +1 -2
  34. package/dist/types/components/Breadcrumbs/BreadcrumbsLink.d.ts.map +1 -1
  35. package/dist/types/components/Breadcrumbs/index.d.ts +1 -2
  36. package/dist/types/components/Breadcrumbs/index.d.ts.map +1 -1
  37. package/dist/types/components/Button/Button.d.ts +1 -10
  38. package/dist/types/components/Button/Button.d.ts.map +1 -1
  39. package/dist/types/components/Card/Card.d.ts +2 -3
  40. package/dist/types/components/Card/Card.d.ts.map +1 -1
  41. package/dist/types/components/Card/index.d.ts +1 -1
  42. package/dist/types/components/Checkbox/Checkbox.d.ts +0 -5
  43. package/dist/types/components/Checkbox/Checkbox.d.ts.map +1 -1
  44. package/dist/types/components/Chip/Chips.d.ts +4 -8
  45. package/dist/types/components/Chip/Chips.d.ts.map +1 -1
  46. package/dist/types/components/Chip/index.d.ts +4 -20
  47. package/dist/types/components/Chip/index.d.ts.map +1 -1
  48. package/dist/types/components/Combobox/Combobox.d.ts +24 -7
  49. package/dist/types/components/Combobox/Combobox.d.ts.map +1 -1
  50. package/dist/types/components/Combobox/ComboboxContext.d.ts +1 -1
  51. package/dist/types/components/Combobox/ComboboxContext.d.ts.map +1 -1
  52. package/dist/types/components/Combobox/internal/ComboboxError.d.ts +1 -1
  53. package/dist/types/components/Combobox/internal/ComboboxError.d.ts.map +1 -1
  54. package/dist/types/components/Combobox/internal/ComboboxLabel.d.ts +1 -1
  55. package/dist/types/components/Combobox/internal/ComboboxLabel.d.ts.map +1 -1
  56. package/dist/types/components/{Fieldset → Combobox/useFormField}/FieldsetContext.d.ts +1 -1
  57. package/dist/types/components/Combobox/useFormField/FieldsetContext.d.ts.map +1 -0
  58. package/dist/types/components/Combobox/useFormField/useFormField.d.ts.map +1 -0
  59. package/dist/types/components/Details/Details.d.ts +10 -2
  60. package/dist/types/components/Details/Details.d.ts.map +1 -1
  61. package/dist/types/components/Dropdown/Dropdown.d.ts +1 -8
  62. package/dist/types/components/Dropdown/Dropdown.d.ts.map +1 -1
  63. package/dist/types/components/Dropdown/DropdownHeading.d.ts +1 -1
  64. package/dist/types/components/Dropdown/DropdownTrigger.d.ts +1 -8
  65. package/dist/types/components/Dropdown/DropdownTrigger.d.ts.map +1 -1
  66. package/dist/types/components/Dropdown/index.d.ts +3 -11
  67. package/dist/types/components/Dropdown/index.d.ts.map +1 -1
  68. package/dist/types/components/ErrorSummary/ErrorSummaryHeading.d.ts +1 -1
  69. package/dist/types/components/ErrorSummary/index.d.ts +1 -1
  70. package/dist/types/components/Field/Field.d.ts.map +1 -1
  71. package/dist/types/components/Fieldset/FieldsetDescription.d.ts +1 -1
  72. package/dist/types/components/Fieldset/index.d.ts +1 -1
  73. package/dist/types/components/Heading/Heading.d.ts +2 -2
  74. package/dist/types/components/Heading/Heading.d.ts.map +1 -1
  75. package/dist/types/components/Input/Input.d.ts +1 -12
  76. package/dist/types/components/Input/Input.d.ts.map +1 -1
  77. package/dist/types/components/Link/Link.d.ts +1 -12
  78. package/dist/types/components/Link/Link.d.ts.map +1 -1
  79. package/dist/types/components/Modal/ModalTrigger.d.ts +1 -2
  80. package/dist/types/components/Modal/ModalTrigger.d.ts.map +1 -1
  81. package/dist/types/components/Modal/index.d.ts +1 -2
  82. package/dist/types/components/Modal/index.d.ts.map +1 -1
  83. package/dist/types/components/Pagination/Pagination.d.ts +1 -10
  84. package/dist/types/components/Pagination/Pagination.d.ts.map +1 -1
  85. package/dist/types/components/Pagination/index.d.ts +1 -2
  86. package/dist/types/components/Pagination/index.d.ts.map +1 -1
  87. package/dist/types/components/Pagination/usePagination.d.ts +1 -1
  88. package/dist/types/components/Pagination/usePagination.d.ts.map +1 -1
  89. package/dist/types/components/Paragraph/Paragraph.d.ts +2 -2
  90. package/dist/types/components/Paragraph/Paragraph.d.ts.map +1 -1
  91. package/dist/types/components/Popover/Popover.d.ts +1 -10
  92. package/dist/types/components/Popover/Popover.d.ts.map +1 -1
  93. package/dist/types/components/Popover/PopoverTrigger.d.ts +8 -8
  94. package/dist/types/components/Popover/PopoverTrigger.d.ts.map +1 -1
  95. package/dist/types/components/Radio/Radio.d.ts +0 -5
  96. package/dist/types/components/Radio/Radio.d.ts.map +1 -1
  97. package/dist/types/components/Search/SearchButton.d.ts +1 -2
  98. package/dist/types/components/Search/SearchButton.d.ts.map +1 -1
  99. package/dist/types/components/Search/index.d.ts +1 -2
  100. package/dist/types/components/Search/index.d.ts.map +1 -1
  101. package/dist/types/components/Spinner/Spinner.d.ts +1 -6
  102. package/dist/types/components/Spinner/Spinner.d.ts.map +1 -1
  103. package/dist/types/components/Switch/Switch.d.ts +0 -10
  104. package/dist/types/components/Switch/Switch.d.ts.map +1 -1
  105. package/dist/types/components/Table/TableHeaderCell.d.ts.map +1 -1
  106. package/dist/types/components/Tabs/Tabs.d.ts +1 -8
  107. package/dist/types/components/Tabs/Tabs.d.ts.map +1 -1
  108. package/dist/types/components/Tabs/index.d.ts +1 -2
  109. package/dist/types/components/Tabs/index.d.ts.map +1 -1
  110. package/dist/types/components/Tag/Tag.d.ts +3 -17
  111. package/dist/types/components/Tag/Tag.d.ts.map +1 -1
  112. package/dist/types/components/ToggleGroup/ToggleGroup.d.ts +1 -8
  113. package/dist/types/components/ToggleGroup/ToggleGroup.d.ts.map +1 -1
  114. package/dist/types/components/Tooltip/Tooltip.d.ts +3 -23
  115. package/dist/types/components/Tooltip/Tooltip.d.ts.map +1 -1
  116. package/dist/types/index.d.ts +1 -1
  117. package/dist/types/index.d.ts.map +1 -1
  118. package/dist/types/types.d.ts +6 -11
  119. package/dist/types/types.d.ts.map +1 -1
  120. package/dist/types/utilities/hooks/index.d.ts +2 -2
  121. package/dist/types/utilities/hooks/index.d.ts.map +1 -1
  122. package/dist/types/utilities/hooks/useCheckboxGroup/useCheckboxGroup.d.ts +3 -3
  123. package/dist/types/utilities/hooks/useRadioGroup/useRadioGroup.d.ts +3 -3
  124. package/package.json +1 -1
  125. package/dist/types/components/Fieldset/FieldsetContext.d.ts.map +0 -1
  126. package/dist/types/components/Textarea/useTextarea.d.ts +0 -10
  127. package/dist/types/components/Textarea/useTextarea.d.ts.map +0 -1
  128. package/dist/types/utilities/hooks/useFormField/useFormField.d.ts.map +0 -1
  129. /package/dist/cjs/components/{Fieldset → Combobox/useFormField}/FieldsetContext.js +0 -0
  130. /package/dist/esm/components/{Fieldset → Combobox/useFormField}/FieldsetContext.js +0 -0
  131. /package/dist/types/{utilities/hooks → components/Combobox}/useFormField/useFormField.d.ts +0 -0
@@ -26,15 +26,15 @@ const usePagination = ({ currentPage = 1, setCurrentPage, onChange, totalPages,
26
26
  return {
27
27
  /** Number of steps */
28
28
  pages: getSteps(currentPage, totalPages, showPages).map((page, index) => ({
29
- page: page || '',
29
+ page: page || 'ellipsis',
30
30
  itemKey: page ? `page-${page}` : `ellipsis-${index}`, // React key utility
31
- buttonProps: {
32
- 'aria-current': page === currentPage ? 'page' : undefined,
33
- 'aria-hidden': !page || undefined, // Hide ellipsis from screen reader
34
- onClick: handleClick(page),
35
- tabIndex: page ? undefined : -1, // Hide ellipsis keyboard
36
- variant: page === currentPage ? 'primary' : 'tertiary',
37
- },
31
+ buttonProps: (page
32
+ ? {
33
+ 'aria-current': page === currentPage ? 'page' : undefined,
34
+ onClick: handleClick(page),
35
+ variant: page === currentPage ? 'primary' : 'tertiary',
36
+ }
37
+ : null),
38
38
  })),
39
39
  /** Properties to spread on Pagination.Button used for previous naviagation */
40
40
  prevButtonProps: {
@@ -5,10 +5,14 @@ import { forwardRef, useContext } from 'react';
5
5
  import { Button } from '../Button/Button.js';
6
6
  import { Context } from './PopoverTriggerContext.js';
7
7
 
8
- const PopoverTrigger = forwardRef(function PopoverTrigger({ id, asChild, ...rest }, ref) {
8
+ const PopoverTrigger = forwardRef(function PopoverTrigger({ id, inline, asChild, ...rest }, ref) {
9
9
  const { popoverId } = useContext(Context);
10
- const Component = asChild ? Slot : Button;
11
- return jsx(Component, { ref: ref, popovertarget: popoverId, ...rest });
10
+ const Component = asChild ? Slot : inline ? 'button' : Button;
11
+ return (jsx(Component, { ref: ref, popovertarget: popoverId, ...(inline
12
+ ? {
13
+ 'data-popover': 'inline',
14
+ }
15
+ : {}), ...rest }));
12
16
  });
13
17
 
14
18
  export { PopoverTrigger };
@@ -3,7 +3,7 @@ import { jsx } from 'react/jsx-runtime';
3
3
  import { forwardRef } from 'react';
4
4
 
5
5
  const TableHeaderCell = forwardRef(function TableHeaderCell({ sort, children, ...rest }, ref) {
6
- return (jsx("th", { "aria-sort": sort, ref: ref, ...rest, children: sort ? (jsx("button", { type: 'button', className: 'ds-focus', children: children })) : (children) }));
6
+ return (jsx("th", { "aria-sort": sort, ref: ref, ...rest, children: sort ? jsx("button", { type: 'button', children: children }) : children }));
7
7
  });
8
8
 
9
9
  export { TableHeaderCell };
@@ -6,10 +6,10 @@ import { forwardRef } from 'react';
6
6
  /**
7
7
  * Use `Tag` to display a small piece of information.
8
8
  * @example
9
- * <Tag color='success'>Success</Tag>
9
+ * <Tag>Success</Tag>
10
10
  */
11
- const Tag = forwardRef(function Tag({ color = 'neutral', className, ...rest }, ref) {
12
- return (jsx("span", { className: cl('ds-tag', className), "data-color": color, ref: ref, ...rest }));
11
+ const Tag = forwardRef(function Tag({ className, ...rest }, ref) {
12
+ return jsx("span", { className: cl('ds-tag', className), ref: ref, ...rest });
13
13
  });
14
14
 
15
15
  export { Tag };
@@ -1,9 +1,10 @@
1
1
  'use client';
2
2
  import { jsxs, Fragment as Fragment$1, jsx } from 'react/jsx-runtime';
3
- import { useFloating, autoUpdate, offset, flip, shift, useTransitionStyles, useInteractions, useHover, useFocus, useDismiss, useRole, useMergeRefs, FloatingPortal } from '@floating-ui/react';
3
+ import { autoUpdate, computePosition, offset, flip, shift } from '@floating-ui/dom';
4
4
  import { Slot } from '@radix-ui/react-slot';
5
5
  import cl from 'clsx/lite';
6
- import { forwardRef, useState, Fragment } from 'react';
6
+ import { forwardRef, useId, useState, useRef, useEffect, Fragment } from 'react';
7
+ import { useMergeRefs } from '@floating-ui/react';
7
8
 
8
9
  /**
9
10
  * Tooltip component that displays a small piece of information when hovering or focusing on an element.
@@ -17,46 +18,61 @@ import { forwardRef, useState, Fragment } from 'react';
17
18
  * Hover me
18
19
  * </Tooltip>
19
20
  */
20
- const Tooltip = forwardRef(function Tooltip({ children, content, placement = 'top', delay = 150, open: userOpen, defaultOpen = false, portal = false, className, style, ...rest }, ref) {
21
- const [isOpen, setIsOpen] = useState(defaultOpen);
22
- const internalOpen = userOpen ?? isOpen;
23
- const Container = portal ? FloatingPortal : Fragment;
24
- const { refs, floatingStyles, context } = useFloating({
25
- open: internalOpen,
26
- onOpenChange: setIsOpen,
27
- placement,
28
- whileElementsMounted: autoUpdate,
29
- middleware: [
30
- offset((data) => {
31
- // get pseudo element arrow size
32
- const styles = getComputedStyle(data.elements.floating, '::before');
33
- return parseFloat(styles.height);
34
- }),
35
- flip({
36
- fallbackAxisSideDirection: 'start',
37
- }),
38
- shift(),
39
- arrowPseudoElement,
40
- ],
41
- });
42
- const { styles: animationStyles } = useTransitionStyles(context, {
43
- initial: {
44
- opacity: 0,
45
- },
46
- });
47
- const { getReferenceProps, getFloatingProps } = useInteractions([
48
- // Event listeners to change the open state
49
- useHover(context, { move: false, delay }),
50
- useFocus(context),
51
- useDismiss(context),
52
- useRole(context, { role: 'tooltip' }),
53
- ]);
54
- const mergedRef = useMergeRefs([ref, refs.setFloating]);
55
- const childMergedRef = useMergeRefs([
56
- children
57
- .ref,
58
- refs.setReference,
59
- ]);
21
+ const Tooltip = forwardRef(function Tooltip({ id, children, content, placement = 'top', open, className, ...rest }, ref) {
22
+ const randomTooltipId = useId();
23
+ const [internalOpen, setInternalOpen] = useState(false);
24
+ const triggerRef = useRef(null);
25
+ const tooltipRef = useRef(null);
26
+ const mergedRefs = useMergeRefs([tooltipRef, ref]);
27
+ const controlledOpen = open ?? internalOpen;
28
+ const setOpen = () => {
29
+ setInternalOpen(true);
30
+ };
31
+ const setClose = () => {
32
+ setInternalOpen(false);
33
+ };
34
+ // Position with floating-ui
35
+ useEffect(() => {
36
+ const tooltip = tooltipRef.current;
37
+ const trigger = triggerRef.current;
38
+ tooltip?.togglePopover?.(controlledOpen);
39
+ if (tooltip)
40
+ tooltip.style.opacity = controlledOpen ? '1' : '0';
41
+ if (tooltip && trigger && controlledOpen) {
42
+ return autoUpdate(trigger, tooltip, () => {
43
+ computePosition(trigger, tooltip, {
44
+ placement,
45
+ strategy: 'fixed',
46
+ middleware: [
47
+ offset((data) => {
48
+ // get pseudo element arrow size
49
+ const styles = getComputedStyle(data.elements.floating, '::before');
50
+ return parseFloat(styles.height);
51
+ }),
52
+ flip({
53
+ fallbackAxisSideDirection: 'start',
54
+ }),
55
+ shift(),
56
+ arrowPseudoElement,
57
+ ],
58
+ }).then(({ x, y }) => {
59
+ tooltip.style.translate = `${x}px ${y}px`;
60
+ });
61
+ });
62
+ }
63
+ }, [controlledOpen, placement]);
64
+ /* Add listener for ESC to dismiss */
65
+ useEffect(() => {
66
+ const handleKeyDown = (event) => {
67
+ if (event.key === 'Escape') {
68
+ setInternalOpen(false);
69
+ }
70
+ };
71
+ window.addEventListener('keydown', handleKeyDown);
72
+ return () => {
73
+ window.removeEventListener('keydown', handleKeyDown);
74
+ };
75
+ }, []);
60
76
  /* If children is only a string, make a span */
61
77
  const ChildContainer = typeof children === 'string' ? 'span' : Slot;
62
78
  /* Make sure it is valid */
@@ -64,13 +80,12 @@ const Tooltip = forwardRef(function Tooltip({ children, content, placement = 'to
64
80
  console.error('<Tooltip> children needs to be a single ReactElement that can receive a ref and not: <Fragment/> | <></>');
65
81
  return null;
66
82
  }
67
- return (jsxs(Fragment$1, { children: [jsx(ChildContainer, { ...getReferenceProps({
68
- ref: childMergedRef,
69
- }), children: children }), internalOpen && (jsx(Container, { children: jsx("div", { ref: refs.setFloating, style: { ...floatingStyles, ...animationStyles, ...style }, role: 'tooltip', ...getFloatingProps({
70
- className: cl('ds-tooltip', className),
71
- ref: mergedRef,
72
- ...rest,
73
- }), children: content }) }))] }));
83
+ return (jsxs(Fragment$1, { children: [jsx(ChildContainer, { ref: triggerRef, popovertarget: id ?? randomTooltipId,
84
+ // We set this to not close on click, since it should always show on hover
85
+ // @ts-ignore @types/react-dom does not understand popovertargetaction yet
86
+ popovertargetaction: 'show', onMouseEnter: setOpen, onMouseLeave: setClose, onFocus: setOpen, onBlur: setClose, children: children }), jsx("div", { ref: mergedRefs, role: 'tooltip', className: cl('ds-tooltip', className), id: id ?? randomTooltipId,
87
+ // @ts-ignore @types/react-dom does not understand popover yet
88
+ popover: 'manual', ...rest, children: content })] }));
74
89
  });
75
90
  const arrowPseudoElement = {
76
91
  name: 'ArrowPseudoElement',
@@ -92,8 +107,8 @@ const arrowPseudoElement = {
92
107
  arrowX = '100%';
93
108
  break;
94
109
  }
95
- elements.floating.style.setProperty('--ds-tooltip-arrow-x', arrowX);
96
- elements.floating.style.setProperty('--ds-tooltip-arrow-y', arrowY);
110
+ elements.floating.style.setProperty('--dsc-tooltip-arrow-x', arrowX);
111
+ elements.floating.style.setProperty('--dsc-tooltip-arrow-y', arrowY);
97
112
  return data;
98
113
  },
99
114
  };
package/dist/esm/index.js CHANGED
@@ -1,10 +1,4 @@
1
1
  'use client';
2
- export { useSynchronizedAnimation } from './utilities/hooks/useSynchronizedAnimation/useSynchronizedAnimation.js';
3
- export { useIsomorphicLayoutEffect } from './utilities/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.js';
4
- export { RovingFocusRoot } from './utilities/RovingFocus/RovingFocusRoot.js';
5
- export { useRovingFocus } from './utilities/RovingFocus/useRovingFocus.js';
6
- export { RovingFocusItem, getNextFocusableValue, getPrevFocusableValue } from './utilities/RovingFocus/RovingFocusItem.js';
7
- export { omit } from './utilities/omit/omit.js';
8
2
  export { Avatar } from './components/Avatar/Avatar.js';
9
3
  export { Button } from './components/Button/Button.js';
10
4
  export { Badge } from './components/Badge/index.js';
@@ -95,3 +89,14 @@ export { ErrorSummary } from './components/ErrorSummary/index.js';
95
89
  export { ErrorSummaryItem } from './components/ErrorSummary/ErrorSummaryItem.js';
96
90
  export { ErrorSummaryHeading } from './components/ErrorSummary/ErrorSummaryHeading.js';
97
91
  export { ErrorSummaryList } from './components/ErrorSummary/ErrorSummaryList.js';
92
+ export { omit } from './utilities/omit/omit.js';
93
+ export { useCheckboxGroup } from './utilities/hooks/useCheckboxGroup/useCheckboxGroup.js';
94
+ export { useDebounceCallback } from './utilities/hooks/useDebounceCallback/useDebounceCallback.js';
95
+ export { useIsomorphicLayoutEffect } from './utilities/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.js';
96
+ export { useMediaQuery } from './utilities/hooks/useMediaQuery/useMediaQuery.js';
97
+ export { usePrevious } from './utilities/hooks/usePrevious/usePrevious.js';
98
+ export { useRadioGroup } from './utilities/hooks/useRadioGroup/useRadioGroup.js';
99
+ export { useSynchronizedAnimation } from './utilities/hooks/useSynchronizedAnimation/useSynchronizedAnimation.js';
100
+ export { RovingFocusRoot } from './utilities/RovingFocus/RovingFocusRoot.js';
101
+ export { useRovingFocus } from './utilities/RovingFocus/useRovingFocus.js';
102
+ export { RovingFocusItem, getNextFocusableValue, getPrevFocusableValue } from './utilities/RovingFocus/RovingFocusItem.js';
@@ -0,0 +1,119 @@
1
+ 'use client';
2
+ import { useMergeRefs } from '@floating-ui/react';
3
+ import { useState, useId, useRef, useEffect } from 'react';
4
+
5
+ const toggleIndeterminate = (getIndeterminateInputs, getInputs) => {
6
+ const inputs = getIndeterminateInputs();
7
+ const checked = !!getInputs(true).length;
8
+ const unchecked = !!getInputs(false).length;
9
+ for (const input of inputs) {
10
+ input.indeterminate = unchecked && checked;
11
+ input.checked = !unchecked && checked;
12
+ }
13
+ };
14
+ function useCheckboxGroup(props) {
15
+ const { error, name: groupName, onChange, value = [], disabled, readOnly, required, } = props || {};
16
+ const [groupValue, setGroupValue] = useState(value);
17
+ const namedId = useId();
18
+ const errorId = useId();
19
+ const checkboxRefs = useRef(new Set());
20
+ const indeterminateRefs = useRef(new Set());
21
+ const getInputs = (checked) => Array.from(checkboxRefs.current.values()).filter((input) => input.checked === checked);
22
+ const getIndeterminateInputs = () => Array.from(indeterminateRefs.current.values());
23
+ return {
24
+ /**
25
+ * Current value of the group.
26
+ */
27
+ value: groupValue,
28
+ /**
29
+ * Set the value of the group.
30
+ *
31
+ * @param value string[]
32
+ * @returns void
33
+ */
34
+ setValue: setGroupValue,
35
+ /**
36
+ * Props to send to the `Checkbox` component.
37
+ * Accepts value or object
38
+ * @example
39
+ * <Checkbox {...getCheckboxProps('value')} />
40
+ *
41
+ * @example allow indeterminate
42
+ * <Checkbox {...getCheckboxProps({ value: 'all', allowIndeterminate: true })} />
43
+ */
44
+ getCheckboxProps: (propsOrValue) => {
45
+ const props = typeof propsOrValue === 'string'
46
+ ? { value: propsOrValue }
47
+ : propsOrValue || {};
48
+ const { allowIndeterminate = false, ref = undefined, value = '', ...rest } = props;
49
+ const inputRef = useRef(null);
50
+ const mergedRefs = useMergeRefs([ref, inputRef]);
51
+ const handleChange = () => {
52
+ const nextGroupValue = Array.from(getInputs(true), ({ value }) => value);
53
+ setGroupValue(nextGroupValue);
54
+ onChange?.(nextGroupValue, groupValue);
55
+ };
56
+ const indeterminateChange = () => {
57
+ if (!inputRef.current)
58
+ return;
59
+ const checked = !!inputRef.current.checked;
60
+ for (const input of getInputs(!checked)) {
61
+ /* We use click to send both event and change checked state */
62
+ input.click();
63
+ }
64
+ };
65
+ useEffect(() => {
66
+ if (!allowIndeterminate)
67
+ return;
68
+ toggleIndeterminate(getIndeterminateInputs, getInputs);
69
+ }, [groupValue]);
70
+ useEffect(() => {
71
+ if (!inputRef.current)
72
+ return;
73
+ const input = inputRef.current;
74
+ const refs = allowIndeterminate ? indeterminateRefs : checkboxRefs;
75
+ refs.current.add(input);
76
+ if (getIndeterminateInputs().length)
77
+ toggleIndeterminate(getIndeterminateInputs, getInputs);
78
+ return () => {
79
+ refs.current.delete(input);
80
+ };
81
+ }, [value]);
82
+ return {
83
+ /* Spread anything the user has set first */
84
+ ...rest,
85
+ /* Concat ours with the user prop */
86
+ 'aria-describedby': `${error ? errorId : ''} ${rest['aria-describedby'] || ''}`.trim() ||
87
+ undefined,
88
+ 'aria-invalid': !!error || rest['aria-invalid'],
89
+ checked: allowIndeterminate ? undefined : groupValue.includes(value),
90
+ name: rest.name || groupName || namedId,
91
+ onChange: (e) => {
92
+ rest.onChange?.(e);
93
+ if (e.defaultPrevented)
94
+ return;
95
+ allowIndeterminate && indeterminateChange();
96
+ handleChange();
97
+ },
98
+ ref: mergedRefs,
99
+ value,
100
+ disabled: disabled || rest.disabled,
101
+ readOnly: readOnly || rest.readOnly,
102
+ required: required || rest.required,
103
+ };
104
+ },
105
+ /**
106
+ * Props to send to the `ValidationMessage` component.
107
+ *
108
+ * @example
109
+ * <ValidationMessage {...validationMessageProps} />
110
+ */
111
+ validationMessageProps: {
112
+ children: error,
113
+ hidden: !error,
114
+ id: errorId,
115
+ },
116
+ };
117
+ }
118
+
119
+ export { useCheckboxGroup };
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+ import { useState } from 'react';
3
+ import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.js';
4
+
5
+ // from https://usehooks-ts.com/react-hook/use-media-query
6
+ const IS_SERVER = typeof window === 'undefined';
7
+ function useMediaQuery(query, { defaultValue = false, initializeWithValue = true, } = {}) {
8
+ const getMatches = (query) => {
9
+ if (IS_SERVER) {
10
+ return defaultValue;
11
+ }
12
+ return window.matchMedia(query).matches;
13
+ };
14
+ const [matches, setMatches] = useState(() => {
15
+ if (initializeWithValue) {
16
+ return getMatches(query);
17
+ }
18
+ return defaultValue;
19
+ });
20
+ // Handles the change event of the media query.
21
+ function handleChange() {
22
+ setMatches(getMatches(query));
23
+ }
24
+ useIsomorphicLayoutEffect(() => {
25
+ const matchMedia = window.matchMedia(query);
26
+ // Triggered at the first client-side load and if query changes
27
+ handleChange();
28
+ // Use deprecated `addListener` and `removeListener` to support Safari < 14 (#135)
29
+ if (matchMedia.addListener) {
30
+ matchMedia.addListener(handleChange);
31
+ }
32
+ else {
33
+ matchMedia.addEventListener('change', handleChange);
34
+ }
35
+ return () => {
36
+ if (matchMedia.removeListener) {
37
+ matchMedia.removeListener(handleChange);
38
+ }
39
+ else {
40
+ matchMedia.removeEventListener('change', handleChange);
41
+ }
42
+ };
43
+ }, [query]);
44
+ return matches;
45
+ }
46
+
47
+ export { useMediaQuery };
@@ -0,0 +1,12 @@
1
+ 'use client';
2
+ import { useRef, useEffect } from 'react';
3
+
4
+ function usePrevious(value) {
5
+ const ref = useRef();
6
+ useEffect(() => {
7
+ ref.current = value;
8
+ }, [value]);
9
+ return ref.current;
10
+ }
11
+
12
+ export { usePrevious };
@@ -0,0 +1,97 @@
1
+ 'use client';
2
+ import { useMergeRefs } from '@floating-ui/react';
3
+ import { useState, useId, useRef, useEffect } from 'react';
4
+
5
+ /**
6
+ * useRadioGroup is used to group multiple <Radio> components
7
+ * @example
8
+ * const { getRadioProps, validationMessageProps, value, setValue } = useRadioGroup({
9
+ * disabled: false,
10
+ * error: 'Validation message text',
11
+ * name: 'group-name',
12
+ * onChange: (nextValue, prevValue) => {},
13
+ * readOnly: false,
14
+ * required: true,
15
+ * value: '',
16
+ * });
17
+ */
18
+ function useRadioGroup({ error, readOnly, required, disabled, name, onChange, value: initalValue = '', } = {}) {
19
+ const [groupValue, setGroupValue] = useState(initalValue);
20
+ const errorId = useId();
21
+ const namedId = useId();
22
+ const radioGroupName = name || namedId;
23
+ return {
24
+ /**
25
+ * Current value of the group.
26
+ */
27
+ value: groupValue,
28
+ /**
29
+ * Set the value of the group.
30
+ *
31
+ * @param value string[]
32
+ * @returns void
33
+ */
34
+ setValue: setGroupValue,
35
+ /**
36
+ * Props to send to the `Radio` component.
37
+ * @example
38
+ * <Radio label="Option 1" {...getRadioProps('option-1')} />
39
+ */
40
+ getRadioProps: (propsOrValue) => {
41
+ const props = typeof propsOrValue === 'string'
42
+ ? { value: propsOrValue }
43
+ : propsOrValue;
44
+ const { ref = undefined, value = '', ...rest } = props;
45
+ const localRef = useRef(null);
46
+ const mergedRefs = useMergeRefs([ref, localRef]);
47
+ const handleChange = () => {
48
+ const input = localRef.current;
49
+ const isInput = input instanceof HTMLInputElement;
50
+ if (isInput && input.name === radioGroupName) {
51
+ setGroupValue((prevValue) => {
52
+ onChange?.(input.value, prevValue);
53
+ return input.value;
54
+ });
55
+ }
56
+ };
57
+ useEffect(() => {
58
+ if (!localRef.current)
59
+ return;
60
+ localRef.current.checked = value === groupValue;
61
+ }, [groupValue, value]);
62
+ return {
63
+ /* Spread anything the user has set first */
64
+ ...rest,
65
+ /* Concat ours with the user prop */
66
+ name: radioGroupName,
67
+ 'aria-describedby': `${error ? errorId : ''} ${rest['aria-describedby'] || ''}`.trim() ||
68
+ undefined,
69
+ 'aria-invalid': !!error || rest['aria-invalid'],
70
+ value,
71
+ ref: mergedRefs,
72
+ required: required || rest.required,
73
+ readOnly: readOnly || rest.readOnly,
74
+ disabled: disabled || rest.disabled,
75
+ onChange: (e) => {
76
+ rest.onChange?.(e);
77
+ if (e.defaultPrevented)
78
+ return;
79
+ handleChange();
80
+ },
81
+ };
82
+ },
83
+ /**
84
+ * Props to send to the `ValidationMessage` component.
85
+ *
86
+ * @example
87
+ * <ValidationMessage {...validationMessageProps} />
88
+ */
89
+ validationMessageProps: {
90
+ children: error,
91
+ hidden: !error,
92
+ id: errorId,
93
+ },
94
+ };
95
+ }
96
+
97
+ export { useRadioGroup };
@@ -1,5 +1,4 @@
1
1
  import type { HTMLAttributes, ReactNode } from 'react';
2
- import type { Color } from '../../colors';
3
2
  import type { DefaultProps, Size } from '../../types';
4
3
  import type { MergeRight } from '../../utilities';
5
4
  export type AvatarProps = MergeRight<DefaultProps & HTMLAttributes<HTMLSpanElement>, {
@@ -7,11 +6,6 @@ export type AvatarProps = MergeRight<DefaultProps & HTMLAttributes<HTMLSpanEleme
7
6
  * The name of the person the avatar represents.
8
7
  */
9
8
  'aria-label': string;
10
- /**
11
- * The color of the avatar.
12
- * @default accent
13
- */
14
- 'data-color'?: Color;
15
9
  /**
16
10
  * The size of the avatar.
17
11
  */
@@ -49,16 +43,11 @@ export type AvatarProps = MergeRight<DefaultProps & HTMLAttributes<HTMLSpanEleme
49
43
  * <Icon />
50
44
  * </Avatar>
51
45
  */
52
- export declare const Avatar: React.ForwardRefExoticComponent<Omit<DefaultProps & HTMLAttributes<HTMLSpanElement>, "data-size" | "data-color" | "aria-label" | "children" | "variant" | "initials"> & {
46
+ export declare const Avatar: React.ForwardRefExoticComponent<Omit<DefaultProps & HTMLAttributes<HTMLSpanElement>, "data-size" | "aria-label" | "children" | "variant" | "initials"> & {
53
47
  /**
54
48
  * The name of the person the avatar represents.
55
49
  */
56
50
  'aria-label': string;
57
- /**
58
- * The color of the avatar.
59
- * @default accent
60
- */
61
- 'data-color'?: Color;
62
51
  /**
63
52
  * The size of the avatar.
64
53
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/Avatar/Avatar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,UAAU,CAClC,YAAY,GAAG,cAAc,CAAC,eAAe,CAAC,EAC9C;IACE;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC9B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CACF,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,MAAM;IAhDf;;OAEG;kBACW,MAAM;IACpB;;;OAGG;mBACY,KAAK;IACpB;;OAEG;kBACW,IAAI,GAAG,IAAI;IACzB;;;;OAIG;cACO,QAAQ,GAAG,QAAQ;IAC7B;;OAEG;eACQ,MAAM;IACjB;;;;OAIG;eACQ,SAAS;yCAiDtB,CAAC"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/Avatar/Avatar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,UAAU,CAClC,YAAY,GAAG,cAAc,CAAC,eAAe,CAAC,EAC9C;IACE;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC9B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CACF,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,MAAM;IA3Cf;;OAEG;kBACW,MAAM;IACpB;;OAEG;kBACW,IAAI,GAAG,IAAI;IACzB;;;;OAIG;cACO,QAAQ,GAAG,QAAQ;IAC7B;;OAEG;eACQ,MAAM;IACjB;;;;OAIG;eACQ,SAAS;yCAiDtB,CAAC"}
@@ -1,12 +1,7 @@
1
1
  import { type HTMLAttributes } from 'react';
2
- import type { Color } from '../../colors';
3
2
  import type { DefaultProps } from '../../types';
4
3
  import type { MergeRight } from '../../utilities';
5
4
  export type BadgeProps = MergeRight<DefaultProps & HTMLAttributes<HTMLSpanElement>, {
6
- /**
7
- * The color of the badge. If left unspecified, the color is inherited from the nearest ancestor with data-color.
8
- */
9
- 'data-color'?: Color;
10
5
  /**
11
6
  * The number to display in the badge
12
7
  */
@@ -32,11 +27,7 @@ export type BadgeProps = MergeRight<DefaultProps & HTMLAttributes<HTMLSpanElemen
32
27
  * </Badge>
33
28
  * ```
34
29
  */
35
- export declare const Badge: React.ForwardRefExoticComponent<Omit<DefaultProps & HTMLAttributes<HTMLSpanElement>, "data-color" | "children" | "count" | "maxCount"> & {
36
- /**
37
- * The color of the badge. If left unspecified, the color is inherited from the nearest ancestor with data-color.
38
- */
39
- 'data-color'?: Color;
30
+ export declare const Badge: React.ForwardRefExoticComponent<Omit<DefaultProps & HTMLAttributes<HTMLSpanElement>, "children" | "count" | "maxCount"> & {
40
31
  /**
41
32
  * The number to display in the badge
42
33
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/Badge/Badge.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAc,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,UAAU,GAAG,UAAU,CACjC,YAAY,GAAG,cAAc,CAAC,eAAe,CAAC,EAC9C;IACE;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB,CACF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,KAAK;IA/Bd;;OAEG;mBACY,KAAK;IACpB;;OAEG;YACK,MAAM;IACd;;OAEG;eACQ,MAAM;eACN,KAAK;yCAiClB,CAAC"}
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/Badge/Badge.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAc,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,UAAU,GAAG,UAAU,CACjC,YAAY,GAAG,cAAc,CAAC,eAAe,CAAC,EAC9C;IACE;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB,CACF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,KAAK;IA3Bd;;OAEG;YACK,MAAM;IACd;;OAEG;eACQ,MAAM;eACN,KAAK;yCAiClB,CAAC"}
@@ -1,6 +1,5 @@
1
1
  import { BadgePosition } from './BadgePosition';
2
- declare const Badge: React.ForwardRefExoticComponent<Omit<import("../../types").DefaultProps & React.HTMLAttributes<HTMLSpanElement>, "data-color" | "children" | "count" | "maxCount"> & {
3
- 'data-color'?: import("../../colors").Color;
2
+ declare const Badge: React.ForwardRefExoticComponent<Omit<import("../../types").DefaultProps & React.HTMLAttributes<HTMLSpanElement>, "children" | "count" | "maxCount"> & {
4
3
  count?: number;
5
4
  maxCount?: number;
6
5
  children?: never;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Badge/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,QAAA,MAAM,KAAK;;;;;;;;;;CAAuD,CAAC;AAInE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Badge/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,QAAA,MAAM,KAAK;;;;;;;;;CAAuD,CAAC;AAInE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,9 +1,8 @@
1
1
  import type { LinkProps } from '../Link';
2
2
  export type BreadcrumbsLinkProps = LinkProps;
3
- export declare const BreadcrumbsLink: React.ForwardRefExoticComponent<Omit<import("../../types").DefaultProps & React.AnchorHTMLAttributes<HTMLAnchorElement>, "className" | "data-color" | "children" | "asChild" | "href"> & {
3
+ export declare const BreadcrumbsLink: React.ForwardRefExoticComponent<Omit<import("../../types").DefaultProps & React.AnchorHTMLAttributes<HTMLAnchorElement>, "className" | "children" | "asChild" | "href"> & {
4
4
  children: React.ReactNode;
5
5
  className?: string;
6
- 'data-color'?: import("../../colors").Color;
7
6
  href?: string;
8
7
  asChild?: boolean;
9
8
  } & React.RefAttributes<HTMLAnchorElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"BreadcrumbsLink.d.ts","sourceRoot":"","sources":["../../../src/components/Breadcrumbs/BreadcrumbsLink.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAE7C,eAAO,MAAM,eAAe;;;;;;2CAK1B,CAAC"}
1
+ {"version":3,"file":"BreadcrumbsLink.d.ts","sourceRoot":"","sources":["../../../src/components/Breadcrumbs/BreadcrumbsLink.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAE7C,eAAO,MAAM,eAAe;;;;;2CAK1B,CAAC"}
@@ -19,10 +19,9 @@ export declare const Breadcrumbs: React.ForwardRefExoticComponent<Omit<import(".
19
19
  } & React.RefAttributes<HTMLElement>> & {
20
20
  List: React.ForwardRefExoticComponent<import("./BreadcrumbsList").BreadcrumbsListProps & React.RefAttributes<HTMLOListElement>>;
21
21
  Item: React.ForwardRefExoticComponent<import("./BreadcrumbsItem").BreadcrumbsItemProps & React.RefAttributes<HTMLLIElement>>;
22
- Link: React.ForwardRefExoticComponent<Omit<import("../../types").DefaultProps & React.AnchorHTMLAttributes<HTMLAnchorElement>, "className" | "data-color" | "children" | "asChild" | "href"> & {
22
+ Link: React.ForwardRefExoticComponent<Omit<import("../../types").DefaultProps & React.AnchorHTMLAttributes<HTMLAnchorElement>, "className" | "children" | "asChild" | "href"> & {
23
23
  children: React.ReactNode;
24
24
  className?: string;
25
- 'data-color'?: import("../../colors").Color;
26
25
  href?: string;
27
26
  asChild?: boolean;
28
27
  } & React.RefAttributes<HTMLAnchorElement>>;