@duskmoon-dev/components 0.3.3 → 0.4.0

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 (82) hide show
  1. package/README.md +61 -2
  2. package/dist/classes/chat.d.ts +9 -1
  3. package/dist/classes/console-page.d.ts +16 -0
  4. package/dist/classes/dropdown.d.ts +5 -5
  5. package/dist/classes/fab.d.ts +11 -0
  6. package/dist/classes/index.d.ts +5 -0
  7. package/dist/classes/index.js +180 -34
  8. package/dist/classes/megamenu.d.ts +10 -0
  9. package/dist/classes/otp-input.d.ts +12 -0
  10. package/dist/classes/popover.d.ts +1 -3
  11. package/dist/classes/swap.d.ts +12 -0
  12. package/dist/classes/tree-select.d.ts +6 -6
  13. package/dist/components/app/index.js +128 -68
  14. package/dist/components/avatar/Avatar.types.d.ts +1 -1
  15. package/dist/components/avatar/index.js +2 -1
  16. package/dist/components/badge/index.js +1 -1
  17. package/dist/components/button/Button.d.ts +1 -1
  18. package/dist/components/button/Button.types.d.ts +8 -0
  19. package/dist/components/button/index.js +253 -24
  20. package/dist/components/calendar/index.js +44 -19
  21. package/dist/components/chat/Chat.d.ts +9 -1
  22. package/dist/components/chat/Chat.types.d.ts +26 -0
  23. package/dist/components/chat/index.js +92 -3
  24. package/dist/components/color-picker/ColorPicker.types.d.ts +2 -1
  25. package/dist/components/color-picker/index.js +206 -9
  26. package/dist/components/console-page/ConsolePage.d.ts +2 -0
  27. package/dist/components/console-page/ConsolePage.types.d.ts +29 -0
  28. package/dist/components/console-page/index.d.ts +2 -0
  29. package/dist/components/console-page/index.js +205 -0
  30. package/dist/components/date-picker/DatePicker.types.d.ts +1 -0
  31. package/dist/components/date-picker/index.js +537 -35
  32. package/dist/components/date-picker/usePickerDropdown.d.ts +17 -0
  33. package/dist/components/dm-date-picker/index.js +545 -43
  34. package/dist/components/dm-drawer/index.js +253 -24
  35. package/dist/components/dm-layout/index.js +391 -24
  36. package/dist/components/dm-menu/index.js +380 -13
  37. package/dist/components/dm-page-header/index.js +404 -114
  38. package/dist/components/dm-pro-table/index.js +1183 -368
  39. package/dist/components/dm-query/DmQuery.types.d.ts +1 -1
  40. package/dist/components/dm-query/index.js +931 -188
  41. package/dist/components/dm-search/DmSearch.types.d.ts +4 -0
  42. package/dist/components/dm-search/index.js +917 -163
  43. package/dist/components/dm-table/index.js +1001 -247
  44. package/dist/components/dm-toolbar/index.js +400 -110
  45. package/dist/components/dm-truncate/index.js +115 -35
  46. package/dist/components/dropdown/Dropdown.types.d.ts +1 -1
  47. package/dist/components/dropdown/index.js +400 -110
  48. package/dist/components/fab/Fab.d.ts +4 -0
  49. package/dist/components/fab/Fab.types.d.ts +25 -0
  50. package/dist/components/fab/index.d.ts +2 -0
  51. package/dist/components/fab/index.js +480 -0
  52. package/dist/components/form/Form.types.d.ts +1 -0
  53. package/dist/components/form/index.js +14 -3
  54. package/dist/components/megamenu/Megamenu.d.ts +2 -0
  55. package/dist/components/megamenu/Megamenu.types.d.ts +32 -0
  56. package/dist/components/megamenu/index.d.ts +2 -0
  57. package/dist/components/megamenu/index.js +214 -0
  58. package/dist/components/modal/index.js +128 -68
  59. package/dist/components/otp-input/OtpInput.d.ts +2 -0
  60. package/dist/components/otp-input/OtpInput.types.d.ts +16 -0
  61. package/dist/components/otp-input/index.d.ts +2 -0
  62. package/dist/components/otp-input/index.js +112 -0
  63. package/dist/components/popconfirm/index.js +255 -26
  64. package/dist/components/popover/index.js +24 -4
  65. package/dist/components/swap/Swap.d.ts +3 -0
  66. package/dist/components/swap/Swap.types.d.ts +22 -0
  67. package/dist/components/swap/index.d.ts +2 -0
  68. package/dist/components/swap/index.js +109 -0
  69. package/dist/components/time-picker/TimePicker.types.d.ts +1 -0
  70. package/dist/components/time-picker/index.js +167 -29
  71. package/dist/components/tooltip/Tooltip.types.d.ts +4 -0
  72. package/dist/components/tooltip/index.js +107 -27
  73. package/dist/components/tour/index.js +253 -24
  74. package/dist/components/tree-select/index.js +8 -8
  75. package/dist/components/upload/Upload.types.d.ts +1 -0
  76. package/dist/components/upload/index.js +2 -0
  77. package/dist/generated/version.d.ts +1 -1
  78. package/dist/index.d.ts +5 -0
  79. package/dist/index.js +3330 -1632
  80. package/dist/infrastructure.js +1 -1
  81. package/dist/styles.css +1190 -906
  82. package/package.json +23 -3
@@ -44,6 +44,10 @@ function getDmToolbarItemClasses({
44
44
  return cn(dmToolbarItemClass, primary ? dmToolbarPrimaryItemClass : dmToolbarSecondaryItemClass, className);
45
45
  }
46
46
 
47
+ // src/components/button/Button.tsx
48
+ import React from "react";
49
+ import { createPortal } from "react-dom";
50
+
47
51
  // src/classes/button.ts
48
52
  var buttonBaseClass = "btn";
49
53
  var buttonColorClasses = {
@@ -67,7 +71,7 @@ var buttonAppearanceClasses = {
67
71
  };
68
72
  var buttonShapeClasses = {
69
73
  rect: "",
70
- circle: "btn-circle",
74
+ circle: "btn-circle btn-icon",
71
75
  square: "btn-square"
72
76
  };
73
77
  var buttonSizeClasses = {
@@ -87,11 +91,14 @@ function getButtonClasses({
87
91
  isLoading,
88
92
  className
89
93
  }) {
90
- return cn(buttonBaseClass, buttonColorClasses[color], buttonAppearanceClasses[appearance], buttonShapeClasses[shape], buttonSizeClasses[size], block && buttonBlockClass, isLoading && buttonIsLoadingClass, className);
94
+ return cn(buttonBaseClass, buttonColorClasses[color], buttonAppearanceClasses[appearance], buttonShapeClasses[shape], buttonSizeClasses[size], shape === "circle" && size === "xs" && "btn-icon-sm", shape === "circle" && size === "sm" && "btn-icon-sm", shape === "circle" && size === "lg" && "btn-icon-lg", block && buttonBlockClass, isLoading && buttonIsLoadingClass, className);
91
95
  }
92
96
 
93
97
  // src/components/button/Button.tsx
94
- import { jsx, jsxs } from "react/jsx-runtime";
98
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
99
+ function isPromiseLike(value) {
100
+ return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
101
+ }
95
102
  function Button({
96
103
  color = "primary",
97
104
  appearance = "filled",
@@ -105,8 +112,155 @@ function Button({
105
112
  children,
106
113
  disabled,
107
114
  ref,
115
+ confirm,
116
+ onClick,
108
117
  ...props
109
118
  }) {
119
+ const buttonRef = React.useRef(null);
120
+ const popoverRef = React.useRef(null);
121
+ const cancelRef = React.useRef(null);
122
+ const approvalRef = React.useRef("idle");
123
+ const pendingRef = React.useRef(false);
124
+ const actionRef = React.useRef(0);
125
+ const operationRef = React.useRef(0);
126
+ const mountedRef = React.useRef(false);
127
+ const [portalTarget, setPortalTarget] = React.useState(null);
128
+ const [confirmLoading, setConfirmLoading] = React.useState(false);
129
+ const [confirmError, setConfirmError] = React.useState(false);
130
+ const generatedId = React.useId().replace(/:/g, "");
131
+ const popoverId = `button-confirm-${generatedId}`;
132
+ const titleId = `${popoverId}-title`;
133
+ const descriptionId = `${popoverId}-description`;
134
+ const anchor = `--${popoverId}-anchor`;
135
+ const hasConfirm = Boolean(confirm);
136
+ const confirmation = confirm && typeof confirm === "object" ? confirm : undefined;
137
+ const title = confirmation ? confirmation.title : "Confirm action";
138
+ const hasTitle = title !== undefined && title !== null && title !== false && title !== "";
139
+ const content = confirmation?.component ?? confirmation?.message ?? confirmation?.description;
140
+ const hasContent = content !== undefined && content !== null && content !== false && content !== "";
141
+ const mergedRef = React.useCallback((node) => {
142
+ buttonRef.current = node;
143
+ if (!node) {
144
+ if (typeof ref === "function")
145
+ ref(null);
146
+ else if (ref)
147
+ ref.current = null;
148
+ return;
149
+ }
150
+ const cleanup = typeof ref === "function" ? ref(node) : undefined;
151
+ if (ref && typeof ref !== "function")
152
+ ref.current = node;
153
+ return () => {
154
+ buttonRef.current = null;
155
+ if (typeof cleanup === "function")
156
+ cleanup();
157
+ else if (typeof ref === "function")
158
+ ref(null);
159
+ else if (ref)
160
+ ref.current = null;
161
+ };
162
+ }, [ref]);
163
+ React.useEffect(() => {
164
+ mountedRef.current = true;
165
+ return () => {
166
+ mountedRef.current = false;
167
+ operationRef.current += 1;
168
+ };
169
+ }, []);
170
+ React.useEffect(() => {
171
+ operationRef.current += 1;
172
+ approvalRef.current = "idle";
173
+ setConfirmError(false);
174
+ setPortalTarget(hasConfirm ? document.body : null);
175
+ }, [hasConfirm]);
176
+ function closePopover() {
177
+ if (popoverRef.current?.matches(":popover-open")) {
178
+ popoverRef.current.hidePopover();
179
+ }
180
+ buttonRef.current?.focus();
181
+ }
182
+ function handleClick(event) {
183
+ if (!confirm) {
184
+ onClick?.(event);
185
+ return;
186
+ }
187
+ if (approvalRef.current === "native") {
188
+ approvalRef.current = "idle";
189
+ return;
190
+ }
191
+ if (approvalRef.current === "action") {
192
+ approvalRef.current = "idle";
193
+ let result;
194
+ try {
195
+ result = onClick?.(event);
196
+ } catch {
197
+ event.preventDefault();
198
+ pendingRef.current = false;
199
+ setConfirmError(true);
200
+ return;
201
+ }
202
+ if (!isPromiseLike(result)) {
203
+ pendingRef.current = false;
204
+ closePopover();
205
+ return;
206
+ }
207
+ const userPreventedDefault = event.defaultPrevented;
208
+ event.preventDefault();
209
+ setConfirmLoading(true);
210
+ const action = actionRef.current;
211
+ const operation = operationRef.current;
212
+ Promise.resolve(result).then(() => {
213
+ if (!mountedRef.current || action !== actionRef.current)
214
+ return;
215
+ pendingRef.current = false;
216
+ setConfirmLoading(false);
217
+ if (operation !== operationRef.current)
218
+ return;
219
+ closePopover();
220
+ if (!userPreventedDefault && !buttonRef.current?.disabled) {
221
+ approvalRef.current = "native";
222
+ buttonRef.current?.click();
223
+ approvalRef.current = "idle";
224
+ }
225
+ }, () => {
226
+ if (!mountedRef.current || action !== actionRef.current)
227
+ return;
228
+ pendingRef.current = false;
229
+ setConfirmLoading(false);
230
+ if (operation !== operationRef.current)
231
+ return;
232
+ setConfirmError(true);
233
+ cancelRef.current?.focus();
234
+ });
235
+ return;
236
+ }
237
+ event.preventDefault();
238
+ if (disabled || isLoading || pendingRef.current)
239
+ return;
240
+ if (popoverRef.current?.matches(":popover-open")) {
241
+ closePopover();
242
+ return;
243
+ }
244
+ setConfirmError(false);
245
+ popoverRef.current?.showPopover();
246
+ cancelRef.current?.focus();
247
+ }
248
+ function handleConfirm(event) {
249
+ event.preventDefault();
250
+ event.stopPropagation();
251
+ const trigger = buttonRef.current;
252
+ if (disabled || isLoading || pendingRef.current || !trigger || trigger.disabled || !event.currentTarget.matches(":popover-open"))
253
+ return;
254
+ setConfirmError(false);
255
+ pendingRef.current = true;
256
+ actionRef.current += 1;
257
+ approvalRef.current = "action";
258
+ trigger.click();
259
+ if (approvalRef.current === "action") {
260
+ approvalRef.current = "idle";
261
+ pendingRef.current = false;
262
+ }
263
+ }
110
264
  const classes = getButtonClasses({
111
265
  color,
112
266
  appearance,
@@ -116,29 +270,104 @@ function Button({
116
270
  isLoading,
117
271
  className
118
272
  });
119
- return /* @__PURE__ */ jsxs("button", {
120
- ref,
121
- className: classes,
122
- disabled: disabled || isLoading,
123
- "aria-busy": isLoading,
124
- "aria-disabled": disabled || isLoading,
125
- ...props,
273
+ const confirmClasses = getButtonClasses({
274
+ color,
275
+ size: "sm",
276
+ isLoading: confirmLoading
277
+ });
278
+ return /* @__PURE__ */ jsxs(Fragment, {
126
279
  children: [
127
- isLoading && /* @__PURE__ */ jsx("span", {
128
- className: "btn-spinner"
129
- }),
130
- !isLoading && leftIcon && /* @__PURE__ */ jsx("span", {
131
- className: "btn-icon-left",
132
- children: leftIcon
133
- }),
134
- /* @__PURE__ */ jsx("span", {
135
- className: "btn-content",
136
- children
280
+ /* @__PURE__ */ jsxs("button", {
281
+ ref: confirm ? mergedRef : ref,
282
+ className: classes,
283
+ disabled: disabled || isLoading,
284
+ "aria-busy": isLoading,
285
+ "aria-disabled": disabled || isLoading,
286
+ ...props,
287
+ style: confirm ? { ...props.style, anchorName: anchor } : props.style,
288
+ "aria-haspopup": confirm ? "dialog" : props["aria-haspopup"],
289
+ "aria-controls": confirm ? popoverId : props["aria-controls"],
290
+ onClick: confirm ? handleClick : onClick,
291
+ children: [
292
+ isLoading && /* @__PURE__ */ jsx("span", {
293
+ className: "btn-spinner"
294
+ }),
295
+ !isLoading && leftIcon && /* @__PURE__ */ jsx("span", {
296
+ className: "btn-icon-left",
297
+ children: leftIcon
298
+ }),
299
+ /* @__PURE__ */ jsx("span", {
300
+ className: "btn-content",
301
+ children
302
+ }),
303
+ !isLoading && rightIcon && /* @__PURE__ */ jsx("span", {
304
+ className: "btn-icon-right",
305
+ children: rightIcon
306
+ })
307
+ ]
137
308
  }),
138
- !isLoading && rightIcon && /* @__PURE__ */ jsx("span", {
139
- className: "btn-icon-right",
140
- children: rightIcon
141
- })
309
+ confirm && portalTarget && createPortal(/* @__PURE__ */ jsxs("form", {
310
+ id: popoverId,
311
+ ref: popoverRef,
312
+ popover: "auto",
313
+ role: "dialog",
314
+ "aria-labelledby": hasTitle ? titleId : undefined,
315
+ "aria-label": hasTitle ? undefined : "Confirm action",
316
+ "aria-describedby": hasContent ? descriptionId : undefined,
317
+ className: "popover popover-confirm popover-bottom",
318
+ style: { positionAnchor: anchor },
319
+ onSubmit: handleConfirm,
320
+ onClick: (event) => event.stopPropagation(),
321
+ onToggle: (event) => {
322
+ if (!event.currentTarget.matches(":popover-open")) {
323
+ operationRef.current += 1;
324
+ if (event.currentTarget.contains(document.activeElement) || document.activeElement === document.body) {
325
+ buttonRef.current?.focus();
326
+ }
327
+ }
328
+ },
329
+ children: [
330
+ hasTitle && /* @__PURE__ */ jsx("div", {
331
+ className: "popover-header",
332
+ children: /* @__PURE__ */ jsx("h3", {
333
+ id: titleId,
334
+ className: "popover-title",
335
+ children: title
336
+ })
337
+ }),
338
+ hasContent && /* @__PURE__ */ jsx("div", {
339
+ id: descriptionId,
340
+ className: "popover-body",
341
+ children: content
342
+ }),
343
+ confirmError && /* @__PURE__ */ jsx("div", {
344
+ role: "alert",
345
+ className: "popover-body",
346
+ children: "The action failed. Please try again."
347
+ }),
348
+ /* @__PURE__ */ jsxs("div", {
349
+ className: "popover-footer",
350
+ children: [
351
+ /* @__PURE__ */ jsx("button", {
352
+ ref: cancelRef,
353
+ type: "button",
354
+ className: "btn btn-text btn-sm",
355
+ popoverTarget: popoverId,
356
+ popoverTargetAction: "hide",
357
+ disabled: confirmLoading,
358
+ children: confirmation?.cancelText ?? "Cancel"
359
+ }),
360
+ /* @__PURE__ */ jsx("button", {
361
+ type: "submit",
362
+ className: confirmClasses,
363
+ disabled: disabled || isLoading || confirmLoading,
364
+ "aria-busy": confirmLoading,
365
+ children: confirmation?.confirmText ?? "Confirm"
366
+ })
367
+ ]
368
+ })
369
+ ]
370
+ }), portalTarget)
142
371
  ]
143
372
  });
144
373
  }
@@ -147,34 +376,32 @@ import {
147
376
  cloneElement,
148
377
  forwardRef,
149
378
  isValidElement,
379
+ useEffect,
150
380
  useId,
381
+ useRef,
151
382
  useState
152
383
  } from "react";
153
384
 
154
385
  // src/classes/dropdown.ts
155
- var dropdownWrapperClass = "dropdown-wrapper";
156
- var dropdownBaseClass = "popover dropdown";
157
- var dropdownOpenClass = "popover-show dropdown-open";
158
- var dropdownArrowClass = "popover-arrow dropdown-arrow";
386
+ var dropdownWrapperClass = "dropdown";
387
+ var dropdownBaseClass = "dropdown-content";
388
+ var dropdownArrowClass = "dropdown-arrow";
159
389
  var dropdownMenuClass = "menu dropdown-menu";
160
390
  var dropdownButtonClass = "dropdown-button";
161
391
  var dropdownPlacementClasses = {
162
- top: "popover-top dropdown-top",
163
- bottom: "popover-bottom dropdown-bottom",
164
- left: "popover-left dropdown-left",
165
- right: "popover-right dropdown-right",
166
- topLeft: "popover-top dropdown-top-left",
167
- topRight: "popover-top dropdown-top-right",
168
- bottomLeft: "popover-bottom dropdown-bottom-left",
169
- bottomRight: "popover-bottom dropdown-bottom-right"
392
+ top: "dropdown-block-start",
393
+ bottom: "dropdown-block-end",
394
+ left: "dropdown-inline-start",
395
+ right: "dropdown-inline-end",
396
+ topLeft: "dropdown-block-start",
397
+ topRight: "dropdown-block-start",
398
+ bottomLeft: "dropdown-block-end",
399
+ bottomRight: "dropdown-block-end"
170
400
  };
171
401
  function getDropdownClasses({
172
- placement = "bottomLeft",
173
- open,
174
- arrow,
175
402
  className
176
403
  }) {
177
- return cn(dropdownBaseClass, dropdownPlacementClasses[placement], open && dropdownOpenClass, !arrow && "popover-no-arrow dropdown-no-arrow", className);
404
+ return cn(dropdownBaseClass, className);
178
405
  }
179
406
 
180
407
  // src/classes/menu.ts
@@ -227,9 +454,6 @@ function getMenuItemClasses({
227
454
 
228
455
  // src/components/dropdown/Dropdown.tsx
229
456
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
230
- function hasTrigger(triggers, trigger) {
231
- return (triggers ?? ["hover"]).includes(trigger);
232
- }
233
457
  function callHandler(handler, event) {
234
458
  handler?.(event);
235
459
  }
@@ -281,85 +505,103 @@ var DropdownRoot = forwardRef(({
281
505
  ...props
282
506
  }, ref) => {
283
507
  const [internalOpen, setInternalOpen] = useState(Boolean(defaultOpen));
284
- const isControlled = open !== undefined;
285
- const visible = isControlled ? open : internalOpen;
286
- const overlayId = useId();
287
- function setVisible(nextOpen) {
288
- if (disabled)
508
+ const [nativeOpen, setNativeOpen] = useState(Boolean(open ?? defaultOpen));
509
+ const visible = open ?? internalOpen;
510
+ const popupRef = useRef(null);
511
+ const popupId = useId();
512
+ const anchorName = `--dm-dropdown-${popupId.replace(/[^a-zA-Z0-9_-]/g, "")}`;
513
+ const clickTrigger = trigger.includes("click") || trigger.includes("hover");
514
+ useEffect(() => {
515
+ const popup = popupRef.current;
516
+ if (!popup?.showPopover || !popup?.hidePopover)
289
517
  return;
290
- if (!isControlled) {
518
+ if (visible && !popup.matches(":popover-open"))
519
+ popup.showPopover();
520
+ if (!visible && popup.matches(":popover-open"))
521
+ popup.hidePopover();
522
+ }, [visible]);
523
+ function setVisible(nextOpen) {
524
+ if (open === undefined)
291
525
  setInternalOpen(nextOpen);
292
- }
293
526
  onOpenChange?.(nextOpen);
294
527
  }
295
- const close = () => setVisible(false);
296
- const toggleVisible = () => setVisible(!visible);
528
+ function close() {
529
+ const popup = popupRef.current;
530
+ if (popup?.matches(":popover-open"))
531
+ popup.hidePopover();
532
+ else
533
+ setVisible(false);
534
+ }
297
535
  const menuNode = overlay ?? (menu?.items ? /* @__PURE__ */ jsx2("ul", {
298
536
  className: dropdownMenuClass,
299
537
  children: menu.items.map((item) => renderMenuItem(item, menu.onClick, close))
300
538
  }) : null);
301
539
  const popup = dropdownRender ? dropdownRender(menuNode) : menuNode;
302
- const shouldRenderPopup = !destroyPopupOnHide || visible;
303
- const triggerProps = {
304
- "aria-controls": visible ? overlayId : undefined,
305
- "aria-expanded": visible || undefined,
306
- onMouseEnter: hasTrigger(trigger, "hover") ? () => setVisible(true) : undefined,
307
- onMouseLeave: hasTrigger(trigger, "hover") ? () => setVisible(false) : undefined,
308
- onClick: hasTrigger(trigger, "click") ? toggleVisible : undefined,
309
- onContextMenu: hasTrigger(trigger, "contextMenu") ? (event) => {
310
- event.preventDefault();
311
- toggleVisible();
312
- } : undefined
540
+ const show = () => !disabled && popupRef.current?.showPopover?.();
541
+ const hide = () => !disabled && popupRef.current?.hidePopover?.();
542
+ const toggle = () => {
543
+ if (disabled)
544
+ return;
545
+ if (popupRef.current?.matches(":popover-open"))
546
+ hide();
547
+ else
548
+ show();
313
549
  };
550
+ const childIsButton = isValidElement(children) && (children.type === "button" || children.type === Button);
314
551
  const triggerNode = isValidElement(children) ? cloneElement(children, {
315
- "aria-controls": triggerProps["aria-controls"] ?? children.props["aria-controls"],
316
- "aria-expanded": triggerProps["aria-expanded"] ?? children.props["aria-expanded"],
552
+ popoverTarget: childIsButton && clickTrigger && !disabled ? popupId : undefined,
553
+ style: {
554
+ ...children.props.style,
555
+ anchorName
556
+ },
557
+ "aria-controls": popupId,
558
+ "aria-expanded": nativeOpen,
559
+ disabled: disabled || children.props.disabled,
317
560
  onMouseEnter: (event) => {
318
561
  callHandler(children.props.onMouseEnter, event);
319
- triggerProps.onMouseEnter?.();
562
+ if (trigger.includes("hover"))
563
+ show();
320
564
  onMouseEnter?.(event);
321
565
  },
322
566
  onMouseLeave: (event) => {
323
567
  callHandler(children.props.onMouseLeave, event);
324
- triggerProps.onMouseLeave?.();
325
568
  onMouseLeave?.(event);
326
569
  },
327
570
  onClick: (event) => {
328
571
  callHandler(children.props.onClick, event);
329
- triggerProps.onClick?.();
330
572
  onClick?.(event);
573
+ if (!childIsButton && clickTrigger && !event.defaultPrevented)
574
+ toggle();
331
575
  },
332
576
  onContextMenu: (event) => {
333
577
  callHandler(children.props.onContextMenu, event);
334
- triggerProps.onContextMenu?.(event);
578
+ if (trigger.includes("contextMenu")) {
579
+ event.preventDefault();
580
+ toggle();
581
+ }
335
582
  onContextMenu?.(event);
336
583
  }
337
- }) : /* @__PURE__ */ jsx2("span", {
338
- role: "button",
339
- tabIndex: disabled ? -1 : 0,
340
- "aria-disabled": disabled || undefined,
341
- "aria-controls": triggerProps["aria-controls"],
342
- "aria-expanded": triggerProps["aria-expanded"],
584
+ }) : /* @__PURE__ */ jsx2("button", {
585
+ type: "button",
586
+ disabled,
587
+ popoverTarget: clickTrigger && !disabled ? popupId : undefined,
588
+ style: { anchorName },
589
+ "aria-controls": popupId,
590
+ "aria-expanded": nativeOpen,
343
591
  onMouseEnter: (event) => {
344
- triggerProps.onMouseEnter?.();
592
+ if (trigger.includes("hover"))
593
+ show();
345
594
  onMouseEnter?.(event);
346
595
  },
347
596
  onMouseLeave: (event) => {
348
- triggerProps.onMouseLeave?.();
349
597
  onMouseLeave?.(event);
350
598
  },
351
- onClick: (event) => {
352
- triggerProps.onClick?.();
353
- onClick?.(event);
354
- },
355
- onKeyDown: (event) => {
356
- if (event.key === "Enter" || event.key === " ") {
599
+ onClick,
600
+ onContextMenu: (event) => {
601
+ if (trigger.includes("contextMenu")) {
357
602
  event.preventDefault();
358
- triggerProps.onClick?.();
603
+ toggle();
359
604
  }
360
- },
361
- onContextMenu: (event) => {
362
- triggerProps.onContextMenu?.(event);
363
605
  onContextMenu?.(event);
364
606
  },
365
607
  children
@@ -367,25 +609,30 @@ var DropdownRoot = forwardRef(({
367
609
  return /* @__PURE__ */ jsxs2("span", {
368
610
  ...props,
369
611
  ref,
370
- className: dropdownWrapperClass,
612
+ className: cn(dropdownWrapperClass, dropdownPlacementClasses[placement]),
613
+ onMouseLeave: trigger.includes("hover") ? hide : undefined,
371
614
  children: [
372
615
  triggerNode,
373
- shouldRenderPopup ? /* @__PURE__ */ jsxs2("span", {
374
- id: overlayId,
375
- role: "menu",
376
- className: getDropdownClasses({
377
- placement,
378
- open: visible,
379
- arrow,
380
- className
381
- }),
616
+ /* @__PURE__ */ jsxs2("span", {
617
+ id: popupId,
618
+ ref: popupRef,
619
+ popover: "auto",
620
+ style: { positionAnchor: anchorName },
621
+ className: getDropdownClasses({ className, arrow }),
622
+ onToggle: (event) => {
623
+ if (event.target !== event.currentTarget)
624
+ return;
625
+ const nextOpen = event.nativeEvent.newState === "open";
626
+ setNativeOpen(nextOpen);
627
+ setVisible(nextOpen);
628
+ },
382
629
  children: [
383
- popup,
630
+ !destroyPopupOnHide || visible ? popup : null,
384
631
  arrow ? /* @__PURE__ */ jsx2("span", {
385
632
  className: dropdownArrowClass
386
633
  }) : null
387
634
  ]
388
- }) : null
635
+ })
389
636
  ]
390
637
  });
391
638
  });
@@ -397,31 +644,74 @@ var DropdownButton = forwardRef(({
397
644
  menu,
398
645
  onClick,
399
646
  trigger = ["click"],
647
+ color = "base",
648
+ appearance = "outline",
649
+ size,
650
+ shape,
651
+ block,
652
+ isLoading,
653
+ leftIcon,
654
+ rightIcon,
655
+ confirm,
400
656
  ...props
401
657
  }, ref) => {
658
+ const buttonStyle = { color, appearance, size, shape };
402
659
  const buttons = [
403
660
  /* @__PURE__ */ jsx2(Button, {
661
+ ...buttonStyle,
404
662
  disabled,
663
+ isLoading,
664
+ leftIcon,
665
+ rightIcon,
666
+ confirm,
405
667
  onClick,
406
668
  children
407
669
  }, "primary"),
408
670
  /* @__PURE__ */ jsx2(Button, {
671
+ ...buttonStyle,
672
+ type: "button",
409
673
  "aria-label": "Open dropdown",
410
- disabled,
411
- children: "v"
674
+ disabled: disabled || isLoading,
675
+ children: /* @__PURE__ */ jsxs2("svg", {
676
+ "aria-hidden": "true",
677
+ width: "18",
678
+ height: "18",
679
+ viewBox: "0 0 24 24",
680
+ fill: "currentColor",
681
+ children: [
682
+ /* @__PURE__ */ jsx2("circle", {
683
+ cx: "5",
684
+ cy: "12",
685
+ r: "1.75"
686
+ }),
687
+ /* @__PURE__ */ jsx2("circle", {
688
+ cx: "12",
689
+ cy: "12",
690
+ r: "1.75"
691
+ }),
692
+ /* @__PURE__ */ jsx2("circle", {
693
+ cx: "19",
694
+ cy: "12",
695
+ r: "1.75"
696
+ })
697
+ ]
698
+ })
412
699
  }, "trigger")
413
700
  ];
414
701
  const renderedButtons = buttonsRender ? buttonsRender(buttons) : buttons;
415
- return /* @__PURE__ */ jsx2(DropdownRoot, {
416
- ...props,
702
+ return /* @__PURE__ */ jsxs2("span", {
417
703
  ref,
418
- menu,
419
- trigger,
420
- disabled,
421
- children: /* @__PURE__ */ jsx2("span", {
422
- className: dropdownButtonClass,
423
- children: renderedButtons
424
- })
704
+ className: cn(dropdownButtonClass, block && "dropdown-button-block"),
705
+ children: [
706
+ renderedButtons[0],
707
+ /* @__PURE__ */ jsx2(DropdownRoot, {
708
+ ...props,
709
+ menu,
710
+ trigger,
711
+ disabled: disabled || isLoading,
712
+ children: renderedButtons[1]
713
+ })
714
+ ]
425
715
  });
426
716
  });
427
717
  DropdownButton.displayName = "Dropdown.Button";