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