@wavv/ui 2.4.4-alpha.4 → 2.4.4-alpha.6

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,12 +8,14 @@ import DropdownMenu from "../DropdownMenu.js";
8
8
  import { marginProps } from "../helpers/styledProps.js";
9
9
  import Icon from "../Icon/index.js";
10
10
  import ButtonLoader from "./ButtonLoader.js";
11
+ import dropdown_caret from "./dropdown-caret.js";
11
12
  import Group from "./Group.js";
12
13
  const Button_Button = ({ content, children, dropdown, options, ref, ...rest })=>{
13
14
  const text = content || children;
14
- if (dropdown && options) return /*#__PURE__*/ jsx(DropdownButton, {
15
+ if ((true === dropdown || 'single' === dropdown) && options) return /*#__PURE__*/ jsx(DropdownButton, {
15
16
  ref: ref,
16
17
  options: options,
18
+ dropdown: dropdown,
17
19
  ...rest,
18
20
  children: text
19
21
  });
@@ -66,8 +68,20 @@ const BasicButton = ({ children, onClick, onPress, icon, iconPosition, iconColor
66
68
  ]
67
69
  });
68
70
  };
69
- const DropdownButton = ({ children, options, onClick, onPress, afterShow, afterHide, secondary, negative, positive, caution, outline, subtle, link, size, small, tiny, large, disabled, buttonDisabled, optionsDisabled, loading, direction, collapse, width, hideDivider, gap, ref, ...props })=>{
71
+ const DropdownButton = ({ children, options, dropdown = true, onClick, onPress, afterShow, afterHide, secondary, negative, positive, caution, outline, subtle, link, size, small, tiny, large, disabled, buttonDisabled, optionsDisabled, loading, direction, collapse, width, hideDivider, gap, icon, iconPosition, ref, ...props })=>{
70
72
  const [optionsOpen, setOptionsOpen] = useState(false);
73
+ const isSingle = 'single' === dropdown;
74
+ let buttonSize = size || 'medium';
75
+ if (small) buttonSize = 'small';
76
+ else if (large) buttonSize = 'large';
77
+ else if (tiny) buttonSize = 'tiny';
78
+ const caretDimensions = {
79
+ large: 7,
80
+ medium: 6,
81
+ small: 5,
82
+ tiny: 4
83
+ };
84
+ const caretSize = caretDimensions[buttonSize];
71
85
  const buttonStyleProps = {
72
86
  secondary,
73
87
  negative,
@@ -93,6 +107,38 @@ const DropdownButton = ({ children, options, onClick, onPress, afterShow, afterH
93
107
  if (afterHide) afterHide();
94
108
  setOptionsOpen(false);
95
109
  };
110
+ if (isSingle) return /*#__PURE__*/ jsx(DropdownContainer, {
111
+ children: /*#__PURE__*/ jsx(DropdownMenu, {
112
+ options: options,
113
+ position: `${direction || 'bottom'} right`,
114
+ afterShow: handleShow,
115
+ afterHide: handleHide,
116
+ isTriggerButton: true,
117
+ trigger: /*#__PURE__*/ jsxs(BasicButton, {
118
+ ...buttonStyleProps,
119
+ ...props,
120
+ ref: ref,
121
+ disabled: disabled,
122
+ width: width && !collapse ? '100%' : void 0,
123
+ collapse: collapse,
124
+ loading: loading,
125
+ icon: icon,
126
+ iconPosition: iconPosition,
127
+ children: [
128
+ children && /*#__PURE__*/ jsx(DropdownButtonChildren, {
129
+ children: children
130
+ }),
131
+ /*#__PURE__*/ jsx(CaretIconWrapper, {
132
+ isOpen: optionsOpen,
133
+ children: /*#__PURE__*/ jsx(Icon, {
134
+ svg: /*#__PURE__*/ jsx(dropdown_caret, {}),
135
+ size: caretSize
136
+ })
137
+ })
138
+ ]
139
+ })
140
+ })
141
+ });
96
142
  return /*#__PURE__*/ jsx(DropdownContainer, {
97
143
  children: /*#__PURE__*/ jsxs(Group, {
98
144
  width: collapse ? void 0 : width,
@@ -247,10 +293,23 @@ const DropdownContainer = styled.div({
247
293
  position: 'relative'
248
294
  });
249
295
  const DropdownButtonChildren = styled.div({
250
- marginRight: 8
296
+ marginRight: 8,
297
+ display: 'inline-flex',
298
+ alignItems: 'center'
251
299
  });
300
+ const CaretIconWrapper = styled.span(({ isOpen })=>({
301
+ display: 'inline-flex',
302
+ alignItems: 'center',
303
+ flexShrink: 0,
304
+ '& > div': {
305
+ transform: isOpen ? 'rotate(-180deg)' : 'rotate(0deg)',
306
+ transition: 'transform 0.2s ease-in-out'
307
+ }
308
+ }));
252
309
  const Inner = styled.span({
253
- pointerEvents: 'none'
310
+ pointerEvents: 'none',
311
+ display: 'inline-flex',
312
+ alignItems: 'center'
254
313
  });
255
314
  const components_Button_Button = Object.assign(Button_Button, {
256
315
  Group: Group
@@ -112,7 +112,7 @@ export type DropdownProps = {
112
112
  optionsDisabled?: never;
113
113
  } | {
114
114
  /** Adds a dropdown button to the main button, allowing for multiple button options */
115
- dropdown: true;
115
+ dropdown: true | 'single';
116
116
  /** The dropdown options array of { id: string; label: string; action: () => void; } */
117
117
  options: ListItem[];
118
118
  /** The direction the options should open in relation to the button */
@@ -131,6 +131,7 @@ export type DropdownProps = {
131
131
  optionsDisabled?: boolean;
132
132
  };
133
133
  export type ButtonDropdownProps = {
134
+ dropdown: true | 'single';
134
135
  options: ListItem[];
135
136
  direction?: 'top' | 'bottom';
136
137
  afterShow?: () => void;
@@ -0,0 +1,2 @@
1
+ import dropdown_caret_namespaceObject from "../../static/svg/dropdown-caret.svg";
2
+ export { dropdown_caret_namespaceObject as default };
@@ -1,10 +1,13 @@
1
1
  import type { CSSProperties, ReactNode, RefObject } from 'react';
2
+ import type { IconName } from './Icon/Icon';
2
3
  import type { Attributes } from './typeDefs/elementTypes';
3
4
  import type { MaxWidthHeight, MinWidthHeight, Padding, PositionType, WidthHeight } from './types';
4
5
  type DivAttributes = Attributes<HTMLDivElement>;
5
6
  type DialogProps = {
6
7
  /** The header content displayed at the top of the dialog */
7
8
  header: ReactNode;
9
+ /** The icon displayed to the left of the header text */
10
+ headerIcon?: IconName;
8
11
  /** The main text content displayed in the dialog body */
9
12
  text?: ReactNode;
10
13
  /** Additional children content */
@@ -60,5 +63,5 @@ type DialogProps = {
60
63
  /** The `aria-label` of the dialog */
61
64
  'aria-label'?: string;
62
65
  } & WidthHeight & MaxWidthHeight & MinWidthHeight & Padding & DivAttributes;
63
- declare const Dialog: ({ header, text, children, cancelText, confirmText, middleText, negative, confirmDisabled, confirmLoading, middleDisabled, middleLoading, onConfirm, onMiddle, onCancel, visible, width, height, onClose, closeIcon, preventOverlayClose, overlayBlur, overlayColor, backgroundColor, inert, scopeRef, position, zIndex, ...props }: DialogProps) => import("react/jsx-runtime").JSX.Element;
66
+ declare const Dialog: ({ header, headerIcon, text, children, cancelText, confirmText, middleText, negative, confirmDisabled, confirmLoading, middleDisabled, middleLoading, onConfirm, onMiddle, onCancel, visible, width, height, onClose, closeIcon, preventOverlayClose, overlayBlur, overlayColor, backgroundColor, inert, scopeRef, position, zIndex, ...props }: DialogProps) => import("react/jsx-runtime").JSX.Element;
64
67
  export default Dialog;
@@ -2,10 +2,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import styled from "@emotion/styled";
3
3
  import { Dialog, Heading, Modal, ModalOverlay } from "react-aria-components";
4
4
  import Button from "./Button/index.js";
5
+ import getIcon from "./helpers/getIcon.js";
5
6
  import { body1, head3, maxWidthHeightProps, minWidthHeightProps, paddingProps } from "./helpers/styledProps.js";
6
7
  import Icon from "./Icon/index.js";
7
8
  import PortalScope from "./PortalScope.js";
8
- const Dialog_Dialog = ({ header, text, children, cancelText = 'Cancel', confirmText = 'Okay', middleText, negative, confirmDisabled, confirmLoading, middleDisabled, middleLoading, onConfirm, onMiddle, onCancel, visible, width, height, onClose, closeIcon, preventOverlayClose, overlayBlur = true, overlayColor, backgroundColor, inert, scopeRef, position, zIndex, ...props })=>{
9
+ const Dialog_Dialog = ({ header, headerIcon, text, children, cancelText = 'Cancel', confirmText = 'Okay', middleText, negative, confirmDisabled, confirmLoading, middleDisabled, middleLoading, onConfirm, onMiddle, onCancel, visible, width, height, onClose, closeIcon, preventOverlayClose, overlayBlur = true, overlayColor, backgroundColor, inert, scopeRef, position, zIndex, ...props })=>{
9
10
  const { 'aria-label': ariaLabel, ...rest } = props;
10
11
  const handleOpenChange = (open)=>{
11
12
  if (!open) onClose();
@@ -38,7 +39,12 @@ const Dialog_Dialog = ({ header, text, children, cancelText = 'Cancel', confirmT
38
39
  /*#__PURE__*/ jsxs(DialogHeader, {
39
40
  slot: "title",
40
41
  children: [
41
- header,
42
+ /*#__PURE__*/ jsxs(HeaderContent, {
43
+ children: [
44
+ headerIcon && getIcon(headerIcon),
45
+ header
46
+ ]
47
+ }),
42
48
  closeIcon && /*#__PURE__*/ jsx(CloseInHeader, {
43
49
  children: /*#__PURE__*/ jsx(Icon, {
44
50
  name: "close",
@@ -100,6 +106,11 @@ const DialogHeader = styled(Heading)(({ theme })=>({
100
106
  width: '100%',
101
107
  boxSizing: 'border-box'
102
108
  }), head3);
109
+ const HeaderContent = styled.div({
110
+ display: 'flex',
111
+ alignItems: 'center',
112
+ gap: 8
113
+ });
103
114
  const DialogContent = styled.div(({ theme, hasFooter })=>({
104
115
  color: theme.modal.color.body,
105
116
  padding: hasFooter ? '16px 16px 8px' : 16,
@@ -9,6 +9,14 @@ const Icon = ({ name, svg, external, size, width, height, color, hoverColor, poi
9
9
  let SvgComponent = null;
10
10
  let svgContent = null;
11
11
  let WrappedIconComponent = null;
12
+ const iconSizes = {
13
+ tiny: 12,
14
+ small: 18,
15
+ medium: 24,
16
+ large: 40
17
+ };
18
+ let iconSize = 'number' == typeof size ? size : iconSizes.medium;
19
+ if ('tiny' === size || 'small' === size || 'medium' === size || 'large' === size) iconSize = iconSizes[size];
12
20
  if (name) {
13
21
  if (name in customIcons) SvgComponent = customIcons[name];
14
22
  else if (name in icons) WrappedIconComponent = icons[name];
@@ -16,19 +24,11 @@ const Icon = ({ name, svg, external, size, width, height, color, hoverColor, poi
16
24
  let element = svg;
17
25
  if ('function' == typeof svg) element = svg();
18
26
  const clonedSvg = /*#__PURE__*/ cloneElement(element, {
19
- width: width || size,
20
- height: height || size
27
+ width: width || iconSize,
28
+ height: height || iconSize
21
29
  });
22
30
  svgContent = clonedSvg;
23
31
  }
24
- const iconSizes = {
25
- tiny: 12,
26
- small: 18,
27
- medium: 24,
28
- large: 40
29
- };
30
- let iconSize = 'number' == typeof size ? size : iconSizes.medium;
31
- if ('tiny' === size || 'small' === size || 'medium' === size || 'large' === size) iconSize = iconSizes[size];
32
32
  if (external) return /*#__PURE__*/ jsx(DynamicIcon, {
33
33
  ...props,
34
34
  name: external,
@@ -0,0 +1,3 @@
1
+ <svg width="6" height="4" viewBox="0 0 6 4" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M0.75 0.75L3 3L5.25 0.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wavv/ui",
3
- "version": "2.4.4-alpha.4",
3
+ "version": "2.4.4-alpha.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {