@koobiq/react-components 0.0.1-beta.5 → 0.0.1-beta.7

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.
@@ -8,27 +8,29 @@ import { ListSection } from "./components/ListSection/ListSection.js";
8
8
  import { Typography } from "../Typography/Typography.js";
9
9
  import { ListOption } from "./components/ListOption/ListOption.js";
10
10
  function ListRender(props, ref) {
11
- const { className, label } = props;
11
+ const { label, className, style, slotProps } = props;
12
12
  const domRef = useDOMRef(ref);
13
13
  const state = useListState(props);
14
14
  const { listBoxProps, labelProps } = useListBox(props, state, domRef);
15
+ const titleProps = mergeProps(
16
+ {
17
+ className: s.label,
18
+ variant: "text-normal-strong"
19
+ },
20
+ slotProps?.label,
21
+ labelProps
22
+ );
15
23
  const listProps = mergeProps(
16
24
  {
17
- className: clsx(s.base, className),
18
- ref: domRef
25
+ style,
26
+ ref: domRef,
27
+ className: clsx(s.base, className)
19
28
  },
29
+ slotProps?.list,
20
30
  listBoxProps
21
31
  );
22
32
  return /* @__PURE__ */ jsxs(Fragment, { children: [
23
- isNotNil(label) && /* @__PURE__ */ jsx(
24
- Typography,
25
- {
26
- variant: "text-normal-strong",
27
- className: s.label,
28
- ...labelProps,
29
- children: label
30
- }
31
- ),
33
+ isNotNil(label) && /* @__PURE__ */ jsx(Typography, { ...titleProps, children: label }),
32
34
  /* @__PURE__ */ jsx("ul", { ...listProps, children: [...state.collection].map(
33
35
  (item) => item.type === "section" ? /* @__PURE__ */ jsx(ListSection, { section: item, state }, item.key) : /* @__PURE__ */ jsx(ListOption, { item, state }, item.key)
34
36
  ) })
@@ -1,5 +1,6 @@
1
- import type { ComponentRef, ReactElement, ReactNode, Ref } from 'react';
1
+ import type { ComponentPropsWithRef, ComponentRef, CSSProperties, ReactElement, ReactNode, Ref } from 'react';
2
2
  import type { AriaListBoxProps } from '@koobiq/react-primitives';
3
+ import type { TypographyProps } from '../Typography';
3
4
  export declare const listPropSelectionMode: readonly ["none", "single", "multiple"];
4
5
  export type ListPropSelectionMode = (typeof listPropSelectionMode)[number];
5
6
  export type ListPropItems<T extends object> = AriaListBoxProps<T>['items'];
@@ -14,8 +15,11 @@ export type ListBaseProps<T extends object> = {
14
15
  label?: ReactNode;
15
16
  /** Additional CSS-classes. */
16
17
  className?: string;
18
+ /** Inline styles. */
19
+ style?: CSSProperties;
17
20
  /** The type of selection that is allowed in the collection. */
18
21
  selectionMode?: ListPropSelectionMode;
22
+ /** Ref to the HTML ul-element. */
19
23
  ref?: Ref<HTMLElement>;
20
24
  /** The contents of the collection. */
21
25
  children?: ListPropChildren<T>;
@@ -36,6 +40,11 @@ export type ListBaseProps<T extends object> = {
36
40
  onAction?: ListPropOnAction<T>;
37
41
  /** How multiple selection should behave in the collection. */
38
42
  selectionBehavior?: ListPropSelectionBehavior<T>;
43
+ /** The props used for each slot inside. */
44
+ slotProps?: {
45
+ label?: TypographyProps;
46
+ list?: ComponentPropsWithRef<'div'>;
47
+ };
39
48
  };
40
49
  export type ListProps<T extends object> = ListBaseProps<T>;
41
50
  export type ListRef = ComponentRef<'ul'>;
@@ -9,19 +9,20 @@ import { Backdrop } from "../Backdrop/Backdrop.js";
9
9
  import { Dialog } from "../Dialog/Dialog.js";
10
10
  const Modal = forwardRef((props, ref) => {
11
11
  const {
12
- hideCloseButton = false,
13
12
  size = "medium",
14
- disableExitOnEscapeKeyDown,
15
- disableExitOnClickOutside,
16
- disableFocusManagement,
17
- portalContainer,
18
- open: openProp,
19
- hideBackdrop,
20
- onOpenChange,
21
- defaultOpen,
22
- children,
13
+ hideCloseButton = false,
23
14
  control,
15
+ children,
24
16
  slotProps,
17
+ defaultOpen,
18
+ hideBackdrop,
19
+ onOpenChange,
20
+ open: openProp,
21
+ portalContainer,
22
+ disableFocusManagement,
23
+ disableExitOnClickOutside,
24
+ disableExitOnEscapeKeyDown,
25
+ shouldCloseOnInteractOutside,
25
26
  ...other
26
27
  } = props;
27
28
  const state = useOverlayTriggerState({
@@ -41,6 +42,7 @@ const Modal = forwardRef((props, ref) => {
41
42
  const { modalProps: modalCommonProps, underlayProps } = useModalOverlay(
42
43
  {
43
44
  ...props,
45
+ shouldCloseOnInteractOutside,
44
46
  isDismissable: !disableExitOnClickOutside,
45
47
  isKeyboardDismissDisabled: disableExitOnEscapeKeyDown
46
48
  },
@@ -55,9 +57,9 @@ const Modal = forwardRef((props, ref) => {
55
57
  };
56
58
  const containerProps = mergeProps(
57
59
  {
58
- className: clsx(s.base, s[size]),
59
60
  ref: containerRef,
60
- "data-size": size
61
+ "data-size": size,
62
+ className: clsx(s.base, s[size])
61
63
  },
62
64
  other
63
65
  );
@@ -58,6 +58,13 @@ export type ModalProps = {
58
58
  * @default false
59
59
  */
60
60
  disableFocusManagement?: boolean;
61
+ /**
62
+ * When user interacts with the argument element outside of the overlay ref,
63
+ * return true if onClose should be called. This gives you a chance to filter
64
+ * out interaction with elements that should not dismiss the overlay.
65
+ * By default, onClose will always be called on interaction outside the overlay ref.
66
+ */
67
+ shouldCloseOnInteractOutside?: (element: Element) => boolean;
61
68
  /** The props used for each slot inside. */
62
69
  slotProps?: {
63
70
  dialog?: DialogProps;
@@ -10,34 +10,36 @@ import { Dialog } from "../Dialog/Dialog.js";
10
10
  const Popover = forwardRef(
11
11
  (props, ref) => {
12
12
  const {
13
- placement: placementProp = "top",
14
- arrowBoundaryOffset = 20,
15
- hideArrow = false,
13
+ offset = 0,
16
14
  size = "medium",
17
15
  crossOffset = 0,
18
- offset = 0,
16
+ hideArrow = false,
17
+ containerPadding = 12,
18
+ arrowBoundaryOffset = 20,
19
+ placement: placementProp = "top",
20
+ control,
21
+ children,
22
+ anchorRef,
19
23
  slotProps,
20
- disableExitOnEscapeKeyDown,
21
- disableFocusManagement,
22
- portalContainer,
23
- hideCloseButton,
24
- open: openProp,
25
24
  className,
25
+ isNonModal,
26
26
  defaultOpen,
27
27
  onOpenChange,
28
- isNonModal,
29
- anchorRef,
30
- children,
31
- control,
28
+ open: openProp,
29
+ portalContainer,
30
+ hideCloseButton,
31
+ disableFocusManagement,
32
+ disableExitOnEscapeKeyDown,
33
+ shouldCloseOnInteractOutside,
32
34
  ...other
33
35
  } = props;
34
36
  const showArrow = !hideArrow;
35
37
  const domRef = useDOMRef(ref);
36
38
  const controlRef = useRef(null);
37
39
  const state = useOverlayTriggerState({
38
- isOpen: openProp,
39
- onOpenChange,
40
40
  defaultOpen,
41
+ onOpenChange,
42
+ isOpen: openProp,
41
43
  ...other
42
44
  });
43
45
  const openState = state.isOpen;
@@ -58,12 +60,13 @@ const Popover = forwardRef(
58
60
  isNonModal,
59
61
  crossOffset,
60
62
  maxHeight: 480,
63
+ containerPadding,
61
64
  popoverRef: domRef,
62
65
  arrowBoundaryOffset,
63
- containerPadding: 24,
64
66
  placement: placementProp,
65
- isKeyboardDismissDisabled: disableExitOnEscapeKeyDown,
66
- triggerRef: anchorRef || controlRef
67
+ shouldCloseOnInteractOutside,
68
+ triggerRef: anchorRef || controlRef,
69
+ isKeyboardDismissDisabled: disableExitOnEscapeKeyDown
67
70
  },
68
71
  { ...state, isOpen: opened }
69
72
  );
@@ -82,16 +85,23 @@ const Popover = forwardRef(
82
85
  const dialogProps = mergeProps(
83
86
  {
84
87
  role: "dialog",
88
+ hideCloseButton,
85
89
  className: s.dialog,
86
- onClose: state.close,
87
- hideCloseButton
90
+ onClose: state.close
88
91
  },
89
92
  slotProps?.dialog
90
93
  );
94
+ const backdropProps = mergeProps(
95
+ {
96
+ className: s.underlay
97
+ },
98
+ slotProps?.backdrop,
99
+ underlayProps
100
+ );
91
101
  return /* @__PURE__ */ jsxs(Fragment, { children: [
92
102
  control?.({
93
- onClick: onPress,
94
103
  ref: controlRef,
104
+ onClick: onPress,
95
105
  disabled: isDisabled,
96
106
  ...otherTriggerProps
97
107
  }),
@@ -111,7 +121,7 @@ const Popover = forwardRef(
111
121
  portalContainer,
112
122
  disableFocusManagement,
113
123
  children: [
114
- /* @__PURE__ */ jsx("div", { ...underlayProps, className: s.underlay }),
124
+ /* @__PURE__ */ jsx("div", { ...backdropProps }),
115
125
  /* @__PURE__ */ jsxs(
116
126
  "div",
117
127
  {
@@ -57,7 +57,7 @@ export type PopoverProps = {
57
57
  * */
58
58
  placement?: PopoverPropPlacement;
59
59
  /** The ref for the element which the popover positions itself with respect to. */
60
- anchorRef?: RefObject<HTMLElement>;
60
+ anchorRef?: RefObject<HTMLElement | null>;
61
61
  /**
62
62
  * If `true`, the arrow isn't shown.
63
63
  * @default false
@@ -77,6 +77,12 @@ export type PopoverProps = {
77
77
  * @default 0
78
78
  */
79
79
  arrowBoundaryOffset?: number;
80
+ /**
81
+ * The placement padding that should be applied between the element and its
82
+ * surrounding container.
83
+ * @default 12
84
+ */
85
+ containerPadding?: number;
80
86
  /**
81
87
  * The additional offset applied along the main axis between the element and its
82
88
  * anchor element.
@@ -89,9 +95,17 @@ export type PopoverProps = {
89
95
  * @default 0
90
96
  */
91
97
  crossOffset?: number;
98
+ /**
99
+ * When user interacts with the argument element outside of the popover ref,
100
+ * return true if onClose should be called. This gives you a chance to filter
101
+ * out interaction with elements that should not dismiss the popover.
102
+ * By default, onClose will always be called on interaction outside the popover ref.
103
+ */
104
+ shouldCloseOnInteractOutside?: (element: Element) => boolean;
92
105
  /** The props used for each slot inside. */
93
106
  slotProps?: {
94
107
  dialog?: DialogProps;
95
108
  arrow?: ComponentPropsWithRef<'div'>;
109
+ backdrop?: ComponentPropsWithRef<'div'>;
96
110
  };
97
111
  };
@@ -3,8 +3,9 @@ import type { Breakpoints } from './types';
3
3
  export type BreakpointsProviderProps = {
4
4
  children: ReactNode;
5
5
  breakpoints: Breakpoints;
6
+ defaultMatches?: boolean[];
6
7
  };
7
8
  export declare const BreakpointsProvider: {
8
- ({ children, breakpoints: _breakpoints, }: BreakpointsProviderProps): import("react/jsx-runtime").JSX.Element;
9
+ ({ children, defaultMatches, breakpoints: _breakpoints, }: BreakpointsProviderProps): import("react/jsx-runtime").JSX.Element;
9
10
  displayName: string;
10
11
  };
@@ -4,9 +4,16 @@ import { BreakpointsContext } from "./BreakpointsContext.js";
4
4
  import { useBreakpoints } from "./utils/useBreakpoints.js";
5
5
  const BreakpointsProvider = ({
6
6
  children,
7
+ defaultMatches,
7
8
  breakpoints: _breakpoints
8
9
  }) => {
9
- const breakpoints = useBreakpoints(_breakpoints);
10
+ const breakpoints = useBreakpoints(
11
+ _breakpoints,
12
+ defaultMatches && {
13
+ ssr: true,
14
+ defaultMatches
15
+ }
16
+ );
10
17
  return /* @__PURE__ */ jsx(BreakpointsContext.Provider, { value: breakpoints, children });
11
18
  };
12
19
  BreakpointsProvider.displayName = "BreakpointsProvider";
@@ -1,6 +1,6 @@
1
1
  import type { Breakpoints, ProviderProps } from './types';
2
2
  export declare const defaultBreakpoints: Breakpoints;
3
3
  export declare const Provider: {
4
- ({ breakpoints, children, locale, }: ProviderProps): import("react/jsx-runtime").JSX.Element;
4
+ ({ breakpoints, breakpointsFallback, children, locale, }: ProviderProps): import("react/jsx-runtime").JSX.Element;
5
5
  displayName: string;
6
6
  };
@@ -19,9 +19,17 @@ const defaultBreakpoints = {
19
19
  };
20
20
  const Provider = ({
21
21
  breakpoints = defaultBreakpoints,
22
+ breakpointsFallback,
22
23
  children,
23
24
  locale
24
- }) => /* @__PURE__ */ jsx(ProviderContext.Provider, { value: { breakpoints, locale }, children: /* @__PURE__ */ jsx(I18nProvider, { locale, children: /* @__PURE__ */ jsx(BreakpointsProvider, { breakpoints, children }) }) });
25
+ }) => /* @__PURE__ */ jsx(ProviderContext.Provider, { value: { breakpoints, locale }, children: /* @__PURE__ */ jsx(I18nProvider, { locale, children: /* @__PURE__ */ jsx(
26
+ BreakpointsProvider,
27
+ {
28
+ breakpoints,
29
+ defaultMatches: breakpointsFallback,
30
+ children
31
+ }
32
+ ) }) });
25
33
  Provider.displayName = "Provider";
26
34
  export {
27
35
  Provider,
@@ -10,7 +10,12 @@ export type Breakpoints = {
10
10
  [custom: string]: number | undefined;
11
11
  };
12
12
  export type ProviderProps = {
13
+ /** The content of the component. */
13
14
  children?: ReactNode;
15
+ /** Responsive breakpoints for your application. */
14
16
  breakpoints?: Breakpoints;
17
+ /** SSR-fallback for responsive breakpoints for your application. */
18
+ breakpointsFallback?: boolean[];
19
+ /** The locale for your application as a [BCP 47](https://www.ietf.org/rfc/bcp/bcp47.txt) language code. Defaults to the browser/OS language setting. */
15
20
  locale?: I18nProviderProps['locale'];
16
21
  };
@@ -1,2 +1,3 @@
1
+ import type { UseMediaQueryOptions } from '@koobiq/react-core';
1
2
  import type { Breakpoints } from '../types';
2
- export declare function useBreakpoints(breakpoints: Breakpoints): {};
3
+ export declare function useBreakpoints(breakpoints: Breakpoints, options?: UseMediaQueryOptions): {};
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { useMediaQuery } from "@koobiq/react-core";
3
- function useBreakpoints(breakpoints) {
3
+ function useBreakpoints(breakpoints, options) {
4
4
  const queries = Object.values(breakpoints).map(
5
5
  (width) => `(min-width: ${width}px)`
6
6
  );
7
- const matches = useMediaQuery(queries);
7
+ const matches = useMediaQuery(queries, options);
8
8
  return Object.keys(breakpoints).reduce(
9
9
  (acc, item, index) => ({ ...acc, [item]: matches[index] }),
10
10
  {}
@@ -10,20 +10,21 @@ import { Dialog } from "../Dialog/Dialog.js";
10
10
  const SidePanel = forwardRef(
11
11
  (props, ref) => {
12
12
  const {
13
- hideCloseButton = false,
14
- position = "left",
15
13
  size = "medium",
16
- disableExitOnEscapeKeyDown,
17
- disableExitOnClickOutside,
18
- disableFocusManagement,
19
- portalContainer,
20
- open: openProp,
21
- hideBackdrop,
22
- onOpenChange,
23
- defaultOpen,
24
- children,
14
+ position = "left",
15
+ hideCloseButton = false,
25
16
  control,
17
+ children,
26
18
  slotProps,
19
+ defaultOpen,
20
+ onOpenChange,
21
+ hideBackdrop,
22
+ open: openProp,
23
+ portalContainer,
24
+ disableFocusManagement,
25
+ disableExitOnClickOutside,
26
+ disableExitOnEscapeKeyDown,
27
+ shouldCloseOnInteractOutside,
27
28
  ...other
28
29
  } = props;
29
30
  const state = useOverlayTriggerState({
@@ -43,6 +44,7 @@ const SidePanel = forwardRef(
43
44
  const { modalProps: modalCommonProps, underlayProps } = useModalOverlay(
44
45
  {
45
46
  ...props,
47
+ shouldCloseOnInteractOutside,
46
48
  isDismissable: !disableExitOnClickOutside,
47
49
  isKeyboardDismissDisabled: disableExitOnEscapeKeyDown
48
50
  },
@@ -57,10 +59,10 @@ const SidePanel = forwardRef(
57
59
  };
58
60
  const containerProps = mergeProps(
59
61
  {
60
- className: clsx(s.base, s[size], s[position]),
62
+ ref: containerRef,
61
63
  "data-size": size,
62
64
  "data-position": position,
63
- ref: containerRef
65
+ className: clsx(s.base, s[size], s[position])
64
66
  },
65
67
  other
66
68
  );
@@ -81,8 +83,8 @@ const SidePanel = forwardRef(
81
83
  const panelProps = mergeProps(
82
84
  modalCommonProps,
83
85
  {
84
- className: s.panel,
85
- ref: modalRef
86
+ ref: modalRef,
87
+ className: s.panel
86
88
  },
87
89
  slotProps?.panel
88
90
  );
@@ -65,6 +65,13 @@ export type SidePanelProps = {
65
65
  * @default false
66
66
  */
67
67
  disableFocusManagement?: boolean;
68
+ /**
69
+ * When user interacts with the argument element outside of the overlay ref,
70
+ * return true if onClose should be called. This gives you a chance to filter
71
+ * out interaction with elements that should not dismiss the overlay.
72
+ * By default, onClose will always be called on interaction outside the overlay ref.
73
+ */
74
+ shouldCloseOnInteractOutside?: (element: Element) => boolean;
68
75
  /** The props used for each slot inside. */
69
76
  slotProps?: {
70
77
  dialog?: DialogProps;
@@ -7,7 +7,7 @@ export declare const Tooltip: import("react").ForwardRefExoticComponent<{
7
7
  children?: import("react").ReactNode;
8
8
  control?: import("./types").TooltipPropControl;
9
9
  placement?: import("./types").TooltipPropPlacement;
10
- anchorRef?: import("react").RefObject<HTMLElement>;
10
+ anchorRef?: import("react").RefObject<HTMLElement | null>;
11
11
  arrowBoundaryOffset?: number;
12
12
  offset?: number;
13
13
  crossOffset?: number;
@@ -10,20 +10,20 @@ const Tooltip = forwardRef((props, ref) => {
10
10
  const {
11
11
  delay = 120,
12
12
  disabled = false,
13
- defaultOpen,
14
13
  closeDelay = 120,
15
14
  hideArrow = false,
16
15
  variant = "contrast",
17
- onOpenChange,
18
16
  placement: placementProp = "top",
19
17
  control,
20
18
  children,
21
19
  anchorRef,
22
20
  crossOffset,
21
+ defaultOpen,
22
+ onOpenChange,
23
23
  open: openProp,
24
+ portalContainer,
24
25
  offset: offsetProp,
25
26
  arrowBoundaryOffset,
26
- portalContainer,
27
27
  ...other
28
28
  } = props;
29
29
  const showArrow = !hideArrow;
@@ -34,7 +34,7 @@ export type TooltipProps = {
34
34
  * */
35
35
  placement?: TooltipPropPlacement;
36
36
  /** The ref for the element which the popover positions itself with respect to. */
37
- anchorRef?: RefObject<HTMLElement>;
37
+ anchorRef?: RefObject<HTMLElement | null>;
38
38
  /**
39
39
  * The minimum distance the arrow's edge should be from the edge of the overlay element.
40
40
  * @default 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koobiq/react-components",
3
- "version": "0.0.1-beta.5",
3
+ "version": "0.0.1-beta.7",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
@@ -22,10 +22,10 @@
22
22
  "@koobiq/design-tokens": "^3.12.1",
23
23
  "@types/react-transition-group": "^4.4.12",
24
24
  "react-transition-group": "^4.4.5",
25
- "@koobiq/react-core": "0.0.1-beta.5",
26
- "@koobiq/react-icons": "0.0.1-beta.5",
27
- "@koobiq/logger": "0.0.1-beta.5",
28
- "@koobiq/react-primitives": "0.0.1-beta.5"
25
+ "@koobiq/logger": "0.0.1-beta.7",
26
+ "@koobiq/react-icons": "0.0.1-beta.7",
27
+ "@koobiq/react-core": "0.0.1-beta.7",
28
+ "@koobiq/react-primitives": "0.0.1-beta.7"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@koobiq/design-tokens": "^3.11.2",