@officesdk/design 0.1.14 → 0.1.16

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.
@@ -1,4 +1,6 @@
1
1
  import React3, { forwardRef, useState, createContext, useEffect, useRef, useCallback, useContext, useMemo } from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import { lightTheme } from '@officesdk/design-theme';
2
4
  import baseStyled, { createGlobalStyle } from 'styled-components';
3
5
  import RcTooltip from 'rc-tooltip';
4
6
  import 'rc-tooltip/assets/bootstrap.css';
@@ -7,7 +9,6 @@ import VirtualList from 'rc-virtual-list';
7
9
  import 'rc-menu/assets/index.css';
8
10
  import RcDropdown from 'rc-dropdown';
9
11
  import 'rc-dropdown/assets/index.css';
10
- import ReactDOM from 'react-dom';
11
12
 
12
13
  var __defProp = Object.defineProperty;
13
14
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -34,11 +35,54 @@ var init_IconProvider = __esm({
34
35
  IconProvider.displayName = "IconProvider";
35
36
  }
36
37
  });
38
+ var globalConfig, globalIconRegistry, globalToastConfig, createDefaultRenderFunction, initUIConfig, getUIConfig, getGlobalIconRegistry, getGlobalToastConfig;
39
+ var init_configManager = __esm({
40
+ "src/UIConfigProvider/configManager.ts"() {
41
+ init_context();
42
+ globalConfig = null;
43
+ globalIconRegistry = null;
44
+ globalToastConfig = null;
45
+ createDefaultRenderFunction = () => {
46
+ return (element, container) => {
47
+ if ("createRoot" in ReactDOM) {
48
+ const { createRoot } = ReactDOM;
49
+ const root = createRoot(container);
50
+ root.render(element);
51
+ } else {
52
+ ReactDOM.render(element, container);
53
+ }
54
+ };
55
+ };
56
+ initUIConfig = (config) => {
57
+ globalConfig = config;
58
+ const renderFunction = createDefaultRenderFunction();
59
+ registerGlobalContext({
60
+ theme: config.theme,
61
+ render: renderFunction
62
+ });
63
+ globalIconRegistry = config.icons || null;
64
+ globalToastConfig = {
65
+ maxCount: config.toast?.maxCount ?? 5,
66
+ defaultDuration: config.toast?.defaultDuration ?? 3e3
67
+ };
68
+ };
69
+ getUIConfig = () => {
70
+ return globalConfig;
71
+ };
72
+ getGlobalIconRegistry = () => {
73
+ return globalIconRegistry;
74
+ };
75
+ getGlobalToastConfig = () => {
76
+ return globalToastConfig;
77
+ };
78
+ }
79
+ });
37
80
  var IconContainer, Icon;
38
81
  var init_Icon = __esm({
39
82
  "src/Icon/Icon.tsx"() {
40
83
  init_styled();
41
84
  init_IconProvider();
85
+ init_configManager();
42
86
  IconContainer = styled.span`
43
87
  display: inline-flex;
44
88
  align-items: center;
@@ -66,7 +110,9 @@ var init_Icon = __esm({
66
110
  style,
67
111
  onClick
68
112
  }) => {
69
- const registry = useIconRegistry();
113
+ const contextRegistry = useIconRegistry();
114
+ const globalRegistry = getGlobalIconRegistry();
115
+ const registry = contextRegistry || globalRegistry;
70
116
  let iconElement = children;
71
117
  if (!iconElement && src) {
72
118
  iconElement = /* @__PURE__ */ React3.createElement(
@@ -83,7 +129,9 @@ var init_Icon = __esm({
83
129
  if (IconComponent) {
84
130
  iconElement = /* @__PURE__ */ React3.createElement(IconComponent, null);
85
131
  } else if (process.env.NODE_ENV !== "production") {
86
- console.warn(`Icon "${name}" not found in registry. Make sure IconProvider is set up.`);
132
+ console.warn(
133
+ `Icon "${name}" not found in registry. Make sure IconProvider is set up or call initUIConfig() with icons.`
134
+ );
87
135
  }
88
136
  }
89
137
  if (!iconElement) {
@@ -511,14 +559,36 @@ var context_exports = {};
511
559
  __export(context_exports, {
512
560
  getGlobalRenderFunction: () => getGlobalRenderFunction,
513
561
  getGlobalTheme: () => getGlobalTheme,
514
- registerGlobalContext: () => registerGlobalContext
562
+ registerGlobalContext: () => registerGlobalContext,
563
+ registerGlobalTheme: () => registerGlobalTheme
515
564
  });
565
+ function deepMerge(target, ...sources) {
566
+ if (!sources.length) return target;
567
+ const source = sources.shift();
568
+ if (isObject(target) && isObject(source)) {
569
+ for (const key in source) {
570
+ if (isObject(source[key])) {
571
+ if (!target[key]) Object.assign(target, { [key]: {} });
572
+ deepMerge(target[key], source[key]);
573
+ } else {
574
+ Object.assign(target, { [key]: source[key] });
575
+ }
576
+ }
577
+ }
578
+ return deepMerge(target, ...sources);
579
+ }
580
+ function isObject(item) {
581
+ return item && typeof item === "object" && !Array.isArray(item);
582
+ }
516
583
  var globalTheme, registerGlobalTheme, getGlobalTheme, globalRenderFunction, getGlobalRenderFunction, registerGlobalContext;
517
584
  var init_context = __esm({
518
585
  "src/utils/context.ts"() {
519
- globalTheme = {};
586
+ globalTheme = lightTheme;
520
587
  registerGlobalTheme = (theme3) => {
521
- Object.assign(globalTheme, { ...globalTheme, ...theme3 });
588
+ deepMerge(
589
+ globalTheme,
590
+ theme3
591
+ );
522
592
  };
523
593
  getGlobalTheme = () => {
524
594
  return globalTheme;
@@ -1140,7 +1210,7 @@ var init_NumberInput = __esm({
1140
1210
  DownArrow = () => /* @__PURE__ */ React3.createElement("svg", { viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React3.createElement("path", { d: "M7 9.5L3.5 5.5H10.5L7 9.5Z", fill: "currentColor" }));
1141
1211
  NumberInput = ({
1142
1212
  value: controlledValue,
1143
- defaultValue = 0,
1213
+ defaultValue,
1144
1214
  min = -Infinity,
1145
1215
  max = Infinity,
1146
1216
  step = 1,
@@ -1151,6 +1221,7 @@ var init_NumberInput = __esm({
1151
1221
  formatter,
1152
1222
  parser,
1153
1223
  unit,
1224
+ placeholder,
1154
1225
  onChange,
1155
1226
  className,
1156
1227
  style
@@ -1162,6 +1233,9 @@ var init_NumberInput = __esm({
1162
1233
  const value = controlledValue !== void 0 ? controlledValue : internalValue;
1163
1234
  const formatValue = useCallback(
1164
1235
  (val) => {
1236
+ if (val === void 0) {
1237
+ return "";
1238
+ }
1165
1239
  if (formatter) {
1166
1240
  return formatter(val);
1167
1241
  }
@@ -1189,6 +1263,9 @@ var init_NumberInput = __esm({
1189
1263
  }, [value, isFocused, formatValue]);
1190
1264
  const clampValue = useCallback(
1191
1265
  (val) => {
1266
+ if (val === void 0) {
1267
+ return void 0;
1268
+ }
1192
1269
  return Math.max(min, Math.min(max, val));
1193
1270
  },
1194
1271
  [min, max]
@@ -1205,27 +1282,39 @@ var init_NumberInput = __esm({
1205
1282
  );
1206
1283
  const increment = useCallback(() => {
1207
1284
  if (disabled) return;
1208
- handleValueChange(value + step);
1285
+ const currentValue = value ?? 0;
1286
+ handleValueChange(currentValue + step);
1209
1287
  }, [disabled, value, step, handleValueChange]);
1210
1288
  const decrement = useCallback(() => {
1211
1289
  if (disabled) return;
1212
- handleValueChange(value - step);
1290
+ const currentValue = value ?? 0;
1291
+ handleValueChange(currentValue - step);
1213
1292
  }, [disabled, value, step, handleValueChange]);
1214
1293
  const handleInputChange = useCallback((e) => {
1215
1294
  setDisplayValue(e.target.value);
1216
1295
  }, []);
1217
1296
  const handleBlur = useCallback(() => {
1218
1297
  setIsFocused(false);
1219
- const parsed = parseValue(displayValue);
1220
- if (parsed !== null) {
1221
- handleValueChange(parsed);
1298
+ const trimmedValue = displayValue.trim();
1299
+ if (trimmedValue === "") {
1300
+ handleValueChange(void 0);
1301
+ setDisplayValue("");
1222
1302
  } else {
1223
- setDisplayValue(formatValue(value));
1303
+ const parsed = parseValue(trimmedValue);
1304
+ if (parsed !== null) {
1305
+ handleValueChange(parsed);
1306
+ } else {
1307
+ setDisplayValue(formatValue(value));
1308
+ }
1224
1309
  }
1225
1310
  }, [displayValue, parseValue, handleValueChange, value, formatValue]);
1226
1311
  const handleFocus = useCallback(() => {
1227
1312
  setIsFocused(true);
1228
- setDisplayValue(String(value));
1313
+ if (value !== void 0) {
1314
+ setDisplayValue(String(value));
1315
+ } else {
1316
+ setDisplayValue("");
1317
+ }
1229
1318
  }, [value]);
1230
1319
  const handleKeyDown = useCallback(
1231
1320
  (e) => {
@@ -1262,6 +1351,7 @@ var init_NumberInput = __esm({
1262
1351
  onBlur: handleBlur,
1263
1352
  onKeyDown: handleKeyDown,
1264
1353
  disabled,
1354
+ placeholder,
1265
1355
  $size: size,
1266
1356
  $disabled: disabled
1267
1357
  }
@@ -1320,7 +1410,7 @@ var init_SpinButton = __esm({
1320
1410
  display: flex;
1321
1411
  align-items: center;
1322
1412
  padding: ${({ $size }) => $size === "small" ? "7px 0" : "7px 0"};
1323
- padding-right: ${({ $size }) => $size === "small" ? "83px" : "72px"};
1413
+ padding-right: ${({ $size }) => $size === "small" ? "8px" : "8px"};
1324
1414
  min-width: 0;
1325
1415
  `;
1326
1416
  SpinButton = ({
@@ -1343,8 +1433,12 @@ var init_SpinButton = __esm({
1343
1433
  const [internalValue, setInternalValue] = useState(controlledValue ?? defaultValue);
1344
1434
  const value = controlledValue !== void 0 ? controlledValue : internalValue;
1345
1435
  const handleValueChange = useCallback(
1346
- (newValue) => {
1347
- if (newValue === null) return;
1436
+ (fixedValue, rawValue) => {
1437
+ const newValue = rawValue === void 0 ? fixedValue ?? 0 : fixedValue ?? 0;
1438
+ if (newValue === null) {
1439
+ onChange?.(null);
1440
+ return;
1441
+ }
1348
1442
  if (controlledValue === void 0) {
1349
1443
  setInternalValue(newValue);
1350
1444
  }
@@ -2654,34 +2748,6 @@ var Tabs = ({
2654
2748
  ))));
2655
2749
  };
2656
2750
  Tabs.displayName = "Tab";
2657
- var Tooltip = ({
2658
- content,
2659
- variant = "black",
2660
- size = "small",
2661
- children,
2662
- placement = "top",
2663
- trigger = ["hover"],
2664
- overlay,
2665
- overlayClassName,
2666
- getPopupContainer,
2667
- ...rest
2668
- }) => {
2669
- const overlayContent = React3.useMemo(() => /* @__PURE__ */ React3.createElement("div", null, content), [content]);
2670
- const variantClass = `tooltip-variant-${variant}`;
2671
- const sizeClass = variant === "white" ? `tooltip-size-${size}` : "";
2672
- const combinedClassName = [variantClass, sizeClass, overlayClassName].filter(Boolean).join(" ");
2673
- const tooltipProps = {
2674
- overlay: overlay ?? overlayContent,
2675
- placement,
2676
- trigger,
2677
- destroyTooltipOnHide: false,
2678
- overlayClassName: combinedClassName,
2679
- ...getPopupContainer && { getPopupContainer },
2680
- ...rest
2681
- };
2682
- return /* @__PURE__ */ React3.createElement(RcTooltip, { ...tooltipProps, prefixCls: "od-tooltip" }, children);
2683
- };
2684
- Tooltip.displayName = "Tooltip";
2685
2751
 
2686
2752
  // src/Tooltip/globalStyle.ts
2687
2753
  init_context();
@@ -3015,6 +3081,86 @@ var TooltipGlobalStyles = createGlobalStyle`
3015
3081
  }
3016
3082
  `;
3017
3083
 
3084
+ // src/utils/styleManager.ts
3085
+ init_context();
3086
+ var injectedStyles = /* @__PURE__ */ new Set();
3087
+ var styleManager = {
3088
+ /**
3089
+ * Inject global styles on demand
3090
+ * @param id Unique identifier for the style (e.g., 'od-tooltip-styles')
3091
+ * @param StyleComponent The styled component to inject
3092
+ */
3093
+ inject: (id, StyleComponent) => {
3094
+ if (injectedStyles.has(id) || typeof document === "undefined") {
3095
+ return;
3096
+ }
3097
+ if (document.getElementById(id)) {
3098
+ injectedStyles.add(id);
3099
+ return;
3100
+ }
3101
+ const renderFunction = getGlobalRenderFunction();
3102
+ if (!renderFunction) {
3103
+ console.warn(
3104
+ `Style injection failed for "${id}": render function not available. Please call initUIConfig() or use UIConfigProvider first.`
3105
+ );
3106
+ return;
3107
+ }
3108
+ const container = document.createElement("div");
3109
+ container.id = id;
3110
+ document.head.appendChild(container);
3111
+ renderFunction(
3112
+ React3.createElement(StyleComponent),
3113
+ container
3114
+ );
3115
+ injectedStyles.add(id);
3116
+ },
3117
+ /**
3118
+ * Check if styles have been injected
3119
+ */
3120
+ isInjected: (id) => {
3121
+ return injectedStyles.has(id) || typeof document !== "undefined" && !!document.getElementById(id);
3122
+ },
3123
+ /**
3124
+ * Reset injected styles (mainly for testing)
3125
+ */
3126
+ reset: () => {
3127
+ injectedStyles.clear();
3128
+ }
3129
+ };
3130
+
3131
+ // src/Tooltip/Tooltip.tsx
3132
+ var Tooltip = ({
3133
+ content,
3134
+ variant = "black",
3135
+ size = "small",
3136
+ children,
3137
+ placement = "top",
3138
+ trigger = ["hover"],
3139
+ overlay,
3140
+ overlayClassName,
3141
+ getPopupContainer,
3142
+ ...rest
3143
+ }) => {
3144
+ useEffect(() => {
3145
+ styleManager.inject("od-tooltip-styles", TooltipGlobalStyles);
3146
+ }, []);
3147
+ const overlayContent = React3.useMemo(() => /* @__PURE__ */ React3.createElement("div", null, content), [content]);
3148
+ const variantClass = `tooltip-variant-${variant}`;
3149
+ const sizeClass = variant === "white" ? `tooltip-size-${size}` : "";
3150
+ const combinedClassName = [variantClass, sizeClass, overlayClassName].filter(Boolean).join(" ");
3151
+ const tooltipProps = {
3152
+ overlay: overlay ?? overlayContent,
3153
+ placement,
3154
+ trigger,
3155
+ destroyTooltipOnHide: false,
3156
+ overlayClassName: combinedClassName,
3157
+ ...getPopupContainer && { getPopupContainer },
3158
+ ...rest
3159
+ };
3160
+ return /* @__PURE__ */ React3.createElement(RcTooltip, { ...tooltipProps, prefixCls: "od-tooltip" }, children);
3161
+ };
3162
+ Tooltip.displayName = "Tooltip";
3163
+
3018
3164
  // src/ToolbarButton/ToolbarButton.tsx
3019
3165
  init_styled();
3020
3166
  var ToolbarButtonContainer = styled.div`
@@ -3382,6 +3528,7 @@ var DropdownButtonContainer = styled.button`
3382
3528
  padding: ${sizeConfig.padding};
3383
3529
  gap: ${sizeConfig.gap};
3384
3530
  font-size: ${sizeConfig.fontSize};
3531
+ border-radius: ${sizeConfig.borderRadius};
3385
3532
  `;
3386
3533
  }}
3387
3534
 
@@ -3393,7 +3540,6 @@ var DropdownButtonContainer = styled.button`
3393
3540
  background = config.background.disabled;
3394
3541
  }
3395
3542
  let border = "none";
3396
- const borderRadius = config.borderRadius || "4px";
3397
3543
  if ($variant === "framed") {
3398
3544
  const borderColor = $error ? theme3.colors?.palettes?.red?.["6"] : theme3.colors?.palettes?.transparency?.["10"];
3399
3545
  border = `1px solid ${borderColor}`;
@@ -3402,7 +3548,6 @@ var DropdownButtonContainer = styled.button`
3402
3548
  return `
3403
3549
  background: ${background};
3404
3550
  border: ${border};
3405
- border-radius: ${borderRadius};
3406
3551
  color: ${color};
3407
3552
 
3408
3553
  &:hover:not(:disabled) {
@@ -3566,501 +3711,110 @@ DropdownButton2.displayName = "DropdownButton";
3566
3711
  // src/dropdown/Menu.tsx
3567
3712
  init_styled();
3568
3713
  init_Icon2();
3569
- var MenuContainer = styled.div`
3570
- display: flex;
3571
- flex-direction: column;
3572
- box-sizing: border-box;
3573
- min-width: 220px;
3574
3714
 
3575
- ${({ theme: theme3 }) => {
3576
- const dropdownConfig = theme3.components?.dropdown;
3577
- const menuConfig = theme3.components?.menu;
3578
- return `
3579
- background: ${dropdownConfig?.background || "#fff"};
3580
- border: ${menuConfig?.border?.width || "1px"} solid ${menuConfig?.border?.color || "rgba(65, 70, 75, 0.1)"};
3581
- border-radius: ${menuConfig?.border?.radius || "4px"};
3582
- box-shadow: ${dropdownConfig?.boxShadow || "0 2px 8px rgba(0, 0, 0, 0.15)"};
3583
- `;
3584
- }}
3715
+ // src/dropdown/globalStyle.ts
3716
+ init_context();
3717
+ var theme2 = getGlobalTheme();
3718
+ var DropdownGlobalStyles = createGlobalStyle`
3719
+ /* Dropdown container */
3720
+ .od-dropdown {
3721
+ position: absolute;
3722
+ z-index: 1050;
3723
+ }
3585
3724
 
3586
- /* Ensure virtual list container has proper width */
3587
- .rc-virtual-list {
3588
- width: 100%;
3725
+ .od-dropdown-hidden {
3726
+ display: none;
3589
3727
  }
3590
3728
 
3591
- .rc-virtual-list-holder {
3592
- width: 100%;
3729
+ /* Dropdown slide animations */
3730
+ .od-dropdown-slide-up-enter,
3731
+ .od-dropdown-slide-up-appear {
3732
+ animation-duration: 0.2s;
3733
+ animation-fill-mode: both;
3734
+ animation-play-state: paused;
3593
3735
  }
3594
3736
 
3595
- .rc-virtual-list-holder-inner {
3596
- width: 100%;
3737
+ .od-dropdown-slide-up-leave {
3738
+ animation-duration: 0.2s;
3739
+ animation-fill-mode: both;
3740
+ animation-play-state: paused;
3741
+ }
3742
+
3743
+ .od-dropdown-slide-up-enter.od-dropdown-slide-up-enter-active,
3744
+ .od-dropdown-slide-up-appear.od-dropdown-slide-up-appear-active {
3745
+ animation-name: rcDropdownSlideUpIn;
3746
+ animation-play-state: running;
3747
+ }
3748
+
3749
+ .od-dropdown-slide-up-leave.od-dropdown-slide-up-leave-active {
3750
+ animation-name: rcDropdownSlideUpOut;
3751
+ animation-play-state: running;
3752
+ }
3753
+
3754
+ @keyframes rcDropdownSlideUpIn {
3755
+ 0% {
3756
+ opacity: 0;
3757
+ transform: scaleY(0.8);
3758
+ }
3759
+ 100% {
3760
+ opacity: 1;
3761
+ transform: scaleY(1);
3762
+ }
3763
+ }
3764
+
3765
+ @keyframes rcDropdownSlideUpOut {
3766
+ 0% {
3767
+ opacity: 1;
3768
+ transform: scaleY(1);
3769
+ }
3770
+ 100% {
3771
+ opacity: 0;
3772
+ transform: scaleY(0.8);
3773
+ }
3597
3774
  }
3598
3775
  `;
3599
- var SearchBoxContainer = styled.div`
3600
- padding: 8px 12px;
3601
- border-bottom: 1px solid ${({ theme: theme3 }) => theme3.colors?.palettes?.transparency?.["10"]};
3602
- `;
3603
- var SearchIcon = () => /* @__PURE__ */ React3.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ React3.createElement(
3604
- "path",
3605
- {
3606
- d: "M7.33333 12.6667C10.2789 12.6667 12.6667 10.2789 12.6667 7.33333C12.6667 4.38781 10.2789 2 7.33333 2C4.38781 2 2 4.38781 2 7.33333C2 10.2789 4.38781 12.6667 7.33333 12.6667Z",
3607
- stroke: "currentColor",
3608
- strokeWidth: "1.5",
3609
- strokeLinecap: "round",
3610
- strokeLinejoin: "round"
3776
+ var MenuGlobalStyles = createGlobalStyle`
3777
+ /* Base menu container */
3778
+ .od-menu {
3779
+ margin: 0;
3780
+ padding: ${() => theme2.components?.dropdown?.padding || "4px 0"};
3781
+ list-style: none;
3782
+ outline: none;
3783
+ box-shadow: none;
3784
+ background: transparent;
3785
+ border: none;
3611
3786
  }
3612
- ), /* @__PURE__ */ React3.createElement(
3613
- "path",
3614
- {
3615
- d: "M14 14L11.1 11.1",
3616
- stroke: "currentColor",
3617
- strokeWidth: "1.5",
3618
- strokeLinecap: "round",
3619
- strokeLinejoin: "round"
3787
+
3788
+ .od-menu-hidden {
3789
+ display: none;
3620
3790
  }
3621
- ));
3622
- var MenuItemContent = styled.div`
3623
- display: flex;
3624
- align-items: center;
3625
- width: 100%;
3626
3791
 
3627
- ${({ theme: theme3 }) => {
3628
- const config = theme3.components?.menu?.menuItem;
3792
+ /* Menu item */
3793
+ .od-menu-item {
3794
+ position: relative;
3795
+ display: flex;
3796
+ align-items: center;
3797
+ margin: 0;
3798
+ cursor: pointer;
3799
+ transition: background-color 0.15s ease;
3800
+ user-select: none;
3801
+ list-style: none;
3802
+
3803
+ ${() => {
3804
+ const config = theme2.components?.menu?.menuItem;
3629
3805
  return `
3630
- gap: ${config?.layout?.gap || "8px"};
3631
- `;
3806
+ padding: ${config?.layout?.padding || "6px 12px"};
3807
+ background: ${config?.background?.normal || "transparent"};
3808
+ `;
3632
3809
  }}
3633
- `;
3634
- var IconContainer2 = styled.div`
3635
- display: flex;
3636
- align-items: center;
3637
- justify-content: center;
3638
- flex-shrink: 0;
3810
+ }
3639
3811
 
3640
- ${({ theme: theme3 }) => {
3641
- const iconSize = theme3.components?.menu?.menuItem?.icon?.size;
3812
+ .od-menu-item:hover {
3813
+ ${() => {
3814
+ const config = theme2.components?.menu?.menuItem;
3642
3815
  return `
3643
- width: ${iconSize?.width || "18px"};
3644
- height: ${iconSize?.height || "18px"};
3645
-
3646
- svg, img {
3647
- width: 100%;
3648
- height: 100%;
3649
- }
3650
- `;
3651
- }}
3652
- `;
3653
- var ContentBlock2 = styled.div`
3654
- display: flex;
3655
- flex: 1;
3656
- align-items: center;
3657
- justify-content: space-between;
3658
- gap: 16px;
3659
- min-width: 0;
3660
- `;
3661
- var LabelText2 = styled.div`
3662
- flex: 1;
3663
- min-width: 0;
3664
- overflow: hidden;
3665
- text-overflow: ellipsis;
3666
- white-space: nowrap;
3667
- line-height: 20px;
3668
-
3669
- ${({ $size, $disabled, theme: theme3 }) => {
3670
- const config = theme3.components?.menu?.menuItem;
3671
- const sizeConfig = config?.size?.[$size];
3672
- const colorConfig = config?.label?.color;
3673
- const fontSize = sizeConfig?.label?.fontSize || "13px";
3674
- const color = $disabled ? colorConfig?.disabled || "rgba(65, 70, 75, 0.3)" : colorConfig?.normal || "#41464b";
3675
- return `
3676
- font-size: ${fontSize};
3677
- color: ${color};
3678
- `;
3679
- }}
3680
- `;
3681
- var DescriptionText = styled.div`
3682
- flex: 0 0 auto;
3683
- white-space: nowrap;
3684
- line-height: 20px;
3685
- text-align: right;
3686
-
3687
- ${({ $size, $disabled, theme: theme3 }) => {
3688
- const config = theme3.components?.menu?.menuItem;
3689
- const sizeConfig = config?.size?.[$size];
3690
- const colorConfig = config?.description?.color;
3691
- const fontSize = sizeConfig?.description?.fontSize || "10px";
3692
- const color = $disabled ? colorConfig?.disabled || "rgba(65, 70, 75, 0.3)" : colorConfig?.normal || "rgba(65, 70, 75, 0.6)";
3693
- return `
3694
- font-size: ${fontSize};
3695
- color: ${color};
3696
- `;
3697
- }}
3698
- `;
3699
- var ActiveIconContainer = styled.div`
3700
- display: flex;
3701
- align-items: center;
3702
- justify-content: center;
3703
- flex-shrink: 0;
3704
-
3705
- ${({ $size, theme: theme3 }) => {
3706
- const sizeConfig = theme3.components?.menu?.menuItem?.size?.[$size];
3707
- const iconSize = sizeConfig?.activeIcon?.size;
3708
- return `
3709
- width: ${iconSize?.width || "18px"};
3710
- height: ${iconSize?.height || "18px"};
3711
- `;
3712
- }}
3713
-
3714
- ${({ $visible, $placeholder }) => {
3715
- if (!$visible && !$placeholder) {
3716
- return "display: none;";
3717
- }
3718
- if ($placeholder && !$visible) {
3719
- return "visibility: hidden;";
3720
- }
3721
- return "";
3722
- }}
3723
- `;
3724
- var NextLevelIconContainer = styled.div`
3725
- display: flex;
3726
- align-items: center;
3727
- justify-content: center;
3728
- flex-shrink: 0;
3729
-
3730
- ${({ $size, theme: theme3 }) => {
3731
- const sizeConfig = theme3.components?.menu?.menuItem?.size?.[$size];
3732
- const iconSize = sizeConfig?.nextLevelIcon?.size;
3733
- return `
3734
- width: ${iconSize?.width || "18px"};
3735
- height: ${iconSize?.height || "18px"};
3736
- `;
3737
- }}
3738
- `;
3739
- var CheckmarkIcon = () => /* @__PURE__ */ React3.createElement("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none" }, /* @__PURE__ */ React3.createElement(
3740
- "path",
3741
- {
3742
- d: "M14.25 5.25L7.125 12.375L3.75 9",
3743
- stroke: "#41464B",
3744
- strokeWidth: "1.5",
3745
- strokeLinecap: "round",
3746
- strokeLinejoin: "round"
3747
- }
3748
- ));
3749
- var ArrowIcon2 = () => /* @__PURE__ */ React3.createElement("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none" }, /* @__PURE__ */ React3.createElement(
3750
- "path",
3751
- {
3752
- d: "M6.75 4.5L11.25 9L6.75 13.5",
3753
- stroke: "#41464B",
3754
- strokeWidth: "1.5",
3755
- strokeLinecap: "round",
3756
- strokeLinejoin: "round"
3757
- }
3758
- ));
3759
- var Menu = ({
3760
- items,
3761
- selectedKeys = [],
3762
- openKeys,
3763
- size = "large",
3764
- searchable = false,
3765
- searchPlaceholder = "Enter search content",
3766
- maxHeight = 300,
3767
- virtual = false,
3768
- reserveActiveIconSpace = true,
3769
- onSelect,
3770
- onSearch,
3771
- onOpenChange,
3772
- className,
3773
- style
3774
- }) => {
3775
- const [searchValue, setSearchValue] = useState("");
3776
- const handleSearch = (value) => {
3777
- setSearchValue(value);
3778
- onSearch?.(value);
3779
- };
3780
- const filteredItems = useMemo(() => {
3781
- if (!searchValue) return items;
3782
- const searchLower = searchValue.toLowerCase();
3783
- const filterMenuItem = (item) => {
3784
- if (item.label.toLowerCase().includes(searchLower) || item.description?.toLowerCase().includes(searchLower)) {
3785
- return item;
3786
- }
3787
- if (item.children && item.children.length > 0) {
3788
- const filteredChildren = item.children.map((child) => filterMenuItem(child)).filter(Boolean);
3789
- if (filteredChildren.length > 0) {
3790
- return { ...item, children: filteredChildren };
3791
- }
3792
- }
3793
- return null;
3794
- };
3795
- const filterItem = (item) => {
3796
- if (item.type === "divider") return null;
3797
- if (item.type === "group") {
3798
- const filteredChildren = item.children.map((child) => filterMenuItem(child)).filter(Boolean);
3799
- if (filteredChildren.length > 0) {
3800
- return { ...item, children: filteredChildren };
3801
- }
3802
- return null;
3803
- }
3804
- return filterMenuItem(item);
3805
- };
3806
- return items.map((item) => filterItem(item)).filter(Boolean);
3807
- }, [items, searchValue]);
3808
- const renderMenuItemContent = (item, reserveSpace) => {
3809
- const isSelected = item.selected || selectedKeys.includes(item.key);
3810
- const isSelectable = item.selectable !== false;
3811
- const shouldShowActiveIcon = isSelectable && isSelected;
3812
- const shouldReserveSpace = reserveSpace || isSelectable;
3813
- const iconElement = item.icon ? /* @__PURE__ */ React3.createElement(IconContainer2, { $size: size }, typeof item.icon === "string" ? /* @__PURE__ */ React3.createElement(Icon, { src: item.icon }) : item.icon) : null;
3814
- return /* @__PURE__ */ React3.createElement(MenuItemContent, { $size: size }, iconElement, /* @__PURE__ */ React3.createElement(ContentBlock2, null, /* @__PURE__ */ React3.createElement(LabelText2, { $size: size, $disabled: !!item.disabled }, item.label), item.description && /* @__PURE__ */ React3.createElement(DescriptionText, { $size: size, $disabled: !!item.disabled }, item.description)), /* @__PURE__ */ React3.createElement(
3815
- ActiveIconContainer,
3816
- {
3817
- $size: size,
3818
- $visible: shouldShowActiveIcon,
3819
- $placeholder: shouldReserveSpace && !shouldShowActiveIcon
3820
- },
3821
- shouldShowActiveIcon && /* @__PURE__ */ React3.createElement(CheckmarkIcon, null)
3822
- ), item.children && item.children.length > 0 && /* @__PURE__ */ React3.createElement(NextLevelIconContainer, { $size: size }, /* @__PURE__ */ React3.createElement(ArrowIcon2, null)));
3823
- };
3824
- const renderItem = (item) => {
3825
- if (item.type === "divider") {
3826
- return /* @__PURE__ */ React3.createElement(Divider$1, { key: item.key });
3827
- }
3828
- if (item.type === "group") {
3829
- return /* @__PURE__ */ React3.createElement(ItemGroup, { key: item.key, title: item.label }, item.children.map((child) => renderMenuItem(child)));
3830
- }
3831
- return renderMenuItem(item);
3832
- };
3833
- const renderMenuItem = (item) => {
3834
- if (item.children && item.children.length > 0) {
3835
- return /* @__PURE__ */ React3.createElement(
3836
- SubMenu,
3837
- {
3838
- key: item.key,
3839
- title: renderMenuItemContent(item, reserveActiveIconSpace),
3840
- disabled: item.disabled,
3841
- popupOffset: [5, 0]
3842
- },
3843
- item.children.map((child) => renderMenuItem(child))
3844
- );
3845
- }
3846
- return /* @__PURE__ */ React3.createElement(
3847
- MenuItem,
3848
- {
3849
- key: item.key,
3850
- disabled: item.disabled,
3851
- onClick: () => {
3852
- item.onClick?.(item.key);
3853
- onSelect?.(item.key);
3854
- }
3855
- },
3856
- renderMenuItemContent(item, reserveActiveIconSpace)
3857
- );
3858
- };
3859
- const itemHeight = size === "medium" ? 28 : 36;
3860
- const menuKey = openKeys?.join(",") || "menu";
3861
- return /* @__PURE__ */ React3.createElement(MenuContainer, { className, style }, searchable && /* @__PURE__ */ React3.createElement(SearchBoxContainer, null, /* @__PURE__ */ React3.createElement(
3862
- Input,
3863
- {
3864
- lineType: "underlined",
3865
- size: "small",
3866
- placeholder: searchPlaceholder,
3867
- value: searchValue,
3868
- onChange: (e) => handleSearch(e.target.value),
3869
- clearable: true,
3870
- onClear: () => handleSearch(""),
3871
- prefixNode: /* @__PURE__ */ React3.createElement(SearchIcon, null)
3872
- }
3873
- )), virtual && filteredItems.length > 10 ? /* @__PURE__ */ React3.createElement(
3874
- VirtualList,
3875
- {
3876
- data: filteredItems,
3877
- height: maxHeight,
3878
- itemHeight,
3879
- itemKey: "key",
3880
- fullHeight: false,
3881
- style: { width: "100%" }
3882
- },
3883
- (item) => /* @__PURE__ */ React3.createElement(
3884
- RcMenu,
3885
- {
3886
- key: menuKey,
3887
- prefixCls: "od-menu",
3888
- mode: "vertical",
3889
- selectedKeys,
3890
- openKeys,
3891
- onOpenChange,
3892
- triggerSubMenuAction: "hover",
3893
- expandIcon: null,
3894
- style: {
3895
- border: "none",
3896
- background: "transparent",
3897
- padding: 0
3898
- }
3899
- },
3900
- renderItem(item)
3901
- )
3902
- ) : /* @__PURE__ */ React3.createElement(
3903
- RcMenu,
3904
- {
3905
- key: menuKey,
3906
- prefixCls: "od-menu",
3907
- mode: "vertical",
3908
- selectedKeys,
3909
- openKeys,
3910
- onOpenChange,
3911
- triggerSubMenuAction: "hover",
3912
- expandIcon: null,
3913
- style: {
3914
- border: "none",
3915
- background: "transparent"
3916
- }
3917
- },
3918
- filteredItems.map(renderItem)
3919
- ));
3920
- };
3921
- Menu.displayName = "Menu";
3922
- var Dropdown = ({
3923
- overlay,
3924
- trigger = ["click"],
3925
- placement = "bottomLeft",
3926
- visible: controlledVisible,
3927
- defaultVisible = false,
3928
- onVisibleChange,
3929
- children,
3930
- overlayClassName,
3931
- getPopupContainer,
3932
- ...rest
3933
- }) => {
3934
- const [internalVisible, setInternalVisible] = useState(defaultVisible);
3935
- const isControlled = controlledVisible !== void 0;
3936
- const isVisible = isControlled ? controlledVisible : internalVisible;
3937
- const handleVisibleChange = (visible) => {
3938
- if (!isControlled) {
3939
- setInternalVisible(visible);
3940
- }
3941
- onVisibleChange?.(visible);
3942
- };
3943
- return /* @__PURE__ */ React3.createElement(
3944
- RcDropdown,
3945
- {
3946
- overlay: overlay || /* @__PURE__ */ React3.createElement("div", null),
3947
- trigger,
3948
- placement,
3949
- visible: isVisible,
3950
- onVisibleChange: handleVisibleChange,
3951
- prefixCls: "od-dropdown",
3952
- overlayClassName,
3953
- getPopupContainer,
3954
- ...rest
3955
- },
3956
- children
3957
- );
3958
- };
3959
- Dropdown.displayName = "Dropdown";
3960
-
3961
- // src/dropdown/globalStyle.ts
3962
- init_context();
3963
- var theme2 = getGlobalTheme();
3964
- var DropdownGlobalStyles = createGlobalStyle`
3965
- /* Dropdown container */
3966
- .od-dropdown {
3967
- position: absolute;
3968
- z-index: 1050;
3969
- }
3970
-
3971
- .od-dropdown-hidden {
3972
- display: none;
3973
- }
3974
-
3975
- /* Dropdown slide animations */
3976
- .od-dropdown-slide-up-enter,
3977
- .od-dropdown-slide-up-appear {
3978
- animation-duration: 0.2s;
3979
- animation-fill-mode: both;
3980
- animation-play-state: paused;
3981
- }
3982
-
3983
- .od-dropdown-slide-up-leave {
3984
- animation-duration: 0.2s;
3985
- animation-fill-mode: both;
3986
- animation-play-state: paused;
3987
- }
3988
-
3989
- .od-dropdown-slide-up-enter.od-dropdown-slide-up-enter-active,
3990
- .od-dropdown-slide-up-appear.od-dropdown-slide-up-appear-active {
3991
- animation-name: rcDropdownSlideUpIn;
3992
- animation-play-state: running;
3993
- }
3994
-
3995
- .od-dropdown-slide-up-leave.od-dropdown-slide-up-leave-active {
3996
- animation-name: rcDropdownSlideUpOut;
3997
- animation-play-state: running;
3998
- }
3999
-
4000
- @keyframes rcDropdownSlideUpIn {
4001
- 0% {
4002
- opacity: 0;
4003
- transform: scaleY(0.8);
4004
- }
4005
- 100% {
4006
- opacity: 1;
4007
- transform: scaleY(1);
4008
- }
4009
- }
4010
-
4011
- @keyframes rcDropdownSlideUpOut {
4012
- 0% {
4013
- opacity: 1;
4014
- transform: scaleY(1);
4015
- }
4016
- 100% {
4017
- opacity: 0;
4018
- transform: scaleY(0.8);
4019
- }
4020
- }
4021
- `;
4022
- var MenuGlobalStyles = createGlobalStyle`
4023
- /* Base menu container */
4024
- .od-menu {
4025
- margin: 0;
4026
- padding: ${() => theme2.components?.dropdown?.padding || "4px 0"};
4027
- list-style: none;
4028
- outline: none;
4029
- box-shadow: none;
4030
- background: transparent;
4031
- border: none;
4032
- }
4033
-
4034
- .od-menu-hidden {
4035
- display: none;
4036
- }
4037
-
4038
- /* Menu item */
4039
- .od-menu-item {
4040
- position: relative;
4041
- display: flex;
4042
- align-items: center;
4043
- margin: 0;
4044
- cursor: pointer;
4045
- transition: background-color 0.15s ease;
4046
- user-select: none;
4047
- list-style: none;
4048
-
4049
- ${() => {
4050
- const config = theme2.components?.menu?.menuItem;
4051
- return `
4052
- padding: ${config?.layout?.padding || "6px 12px"};
4053
- background: ${config?.background?.normal || "transparent"};
4054
- `;
4055
- }}
4056
- }
4057
-
4058
- .od-menu-item:hover {
4059
- ${() => {
4060
- const config = theme2.components?.menu?.menuItem;
4061
- return `
4062
- background: ${config?.background?.hover || "rgba(65, 70, 75, 0.05)"};
4063
- `;
3816
+ background: ${config?.background?.hover || "rgba(65, 70, 75, 0.05)"};
3817
+ `;
4064
3818
  }}
4065
3819
  }
4066
3820
 
@@ -4233,38 +3987,438 @@ var MenuGlobalStyles = createGlobalStyle`
4233
3987
  transition: max-height 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
4234
3988
  }
4235
3989
 
4236
- .od-menu-submenu-inline-collapsed-active {
4237
- max-height: 1000px;
4238
- }
3990
+ .od-menu-submenu-inline-collapsed-active {
3991
+ max-height: 1000px;
3992
+ }
3993
+ `;
3994
+
3995
+ // src/dropdown/Menu.tsx
3996
+ var MenuContainer = styled.div`
3997
+ display: flex;
3998
+ flex-direction: column;
3999
+ box-sizing: border-box;
4000
+ min-width: 220px;
4001
+
4002
+ ${({ theme: theme3 }) => {
4003
+ const dropdownConfig = theme3.components?.dropdown;
4004
+ const menuConfig = theme3.components?.menu;
4005
+ return `
4006
+ background: ${dropdownConfig?.background || "#fff"};
4007
+ border: ${menuConfig?.border?.width || "1px"} solid ${menuConfig?.border?.color || "rgba(65, 70, 75, 0.1)"};
4008
+ border-radius: ${menuConfig?.border?.radius || "4px"};
4009
+ box-shadow: ${dropdownConfig?.boxShadow || "0 2px 8px rgba(0, 0, 0, 0.15)"};
4010
+ `;
4011
+ }}
4012
+
4013
+ /* Ensure virtual list container has proper width */
4014
+ .rc-virtual-list {
4015
+ width: 100%;
4016
+ }
4017
+
4018
+ .rc-virtual-list-holder {
4019
+ width: 100%;
4020
+ }
4021
+
4022
+ .rc-virtual-list-holder-inner {
4023
+ width: 100%;
4024
+ }
4025
+ `;
4026
+ var SearchBoxContainer = styled.div`
4027
+ padding: 8px 12px;
4028
+ border-bottom: 1px solid ${({ theme: theme3 }) => theme3.colors?.palettes?.transparency?.["10"]};
4029
+ `;
4030
+ var SearchIcon = () => /* @__PURE__ */ React3.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ React3.createElement(
4031
+ "path",
4032
+ {
4033
+ d: "M7.33333 12.6667C10.2789 12.6667 12.6667 10.2789 12.6667 7.33333C12.6667 4.38781 10.2789 2 7.33333 2C4.38781 2 2 4.38781 2 7.33333C2 10.2789 4.38781 12.6667 7.33333 12.6667Z",
4034
+ stroke: "currentColor",
4035
+ strokeWidth: "1.5",
4036
+ strokeLinecap: "round",
4037
+ strokeLinejoin: "round"
4038
+ }
4039
+ ), /* @__PURE__ */ React3.createElement(
4040
+ "path",
4041
+ {
4042
+ d: "M14 14L11.1 11.1",
4043
+ stroke: "currentColor",
4044
+ strokeWidth: "1.5",
4045
+ strokeLinecap: "round",
4046
+ strokeLinejoin: "round"
4047
+ }
4048
+ ));
4049
+ var MenuItemContent = styled.div`
4050
+ display: flex;
4051
+ align-items: center;
4052
+ width: 100%;
4053
+
4054
+ ${({ theme: theme3 }) => {
4055
+ const config = theme3.components?.menu?.menuItem;
4056
+ return `
4057
+ gap: ${config?.layout?.gap || "8px"};
4058
+ `;
4059
+ }}
4060
+ `;
4061
+ var IconContainer2 = styled.div`
4062
+ display: flex;
4063
+ align-items: center;
4064
+ justify-content: center;
4065
+ flex-shrink: 0;
4066
+
4067
+ ${({ theme: theme3 }) => {
4068
+ const iconSize = theme3.components?.menu?.menuItem?.icon?.size;
4069
+ return `
4070
+ width: ${iconSize?.width || "18px"};
4071
+ height: ${iconSize?.height || "18px"};
4072
+
4073
+ svg, img {
4074
+ width: 100%;
4075
+ height: 100%;
4076
+ }
4077
+ `;
4078
+ }}
4079
+ `;
4080
+ var ContentBlock2 = styled.div`
4081
+ display: flex;
4082
+ flex: 1;
4083
+ align-items: center;
4084
+ justify-content: space-between;
4085
+ gap: 16px;
4086
+ min-width: 0;
4087
+ `;
4088
+ var LabelText2 = styled.div`
4089
+ flex: 1;
4090
+ min-width: 0;
4091
+ overflow: hidden;
4092
+ text-overflow: ellipsis;
4093
+ white-space: nowrap;
4094
+ line-height: 20px;
4095
+
4096
+ ${({ $size, $disabled, theme: theme3 }) => {
4097
+ const config = theme3.components?.menu?.menuItem;
4098
+ const sizeConfig = config?.size?.[$size];
4099
+ const colorConfig = config?.label?.color;
4100
+ const fontSize = sizeConfig?.label?.fontSize || "13px";
4101
+ const color = $disabled ? colorConfig?.disabled || "rgba(65, 70, 75, 0.3)" : colorConfig?.normal || "#41464b";
4102
+ return `
4103
+ font-size: ${fontSize};
4104
+ color: ${color};
4105
+ `;
4106
+ }}
4107
+ `;
4108
+ var DescriptionText = styled.div`
4109
+ flex: 0 0 auto;
4110
+ white-space: nowrap;
4111
+ line-height: 20px;
4112
+ text-align: right;
4113
+
4114
+ ${({ $size, $disabled, theme: theme3 }) => {
4115
+ const config = theme3.components?.menu?.menuItem;
4116
+ const sizeConfig = config?.size?.[$size];
4117
+ const colorConfig = config?.description?.color;
4118
+ const fontSize = sizeConfig?.description?.fontSize || "10px";
4119
+ const color = $disabled ? colorConfig?.disabled || "rgba(65, 70, 75, 0.3)" : colorConfig?.normal || "rgba(65, 70, 75, 0.6)";
4120
+ return `
4121
+ font-size: ${fontSize};
4122
+ color: ${color};
4123
+ `;
4124
+ }}
4125
+ `;
4126
+ var ActiveIconContainer = styled.div`
4127
+ display: flex;
4128
+ align-items: center;
4129
+ justify-content: center;
4130
+ flex-shrink: 0;
4131
+
4132
+ ${({ $size, theme: theme3 }) => {
4133
+ const sizeConfig = theme3.components?.menu?.menuItem?.size?.[$size];
4134
+ const iconSize = sizeConfig?.activeIcon?.size;
4135
+ return `
4136
+ width: ${iconSize?.width || "18px"};
4137
+ height: ${iconSize?.height || "18px"};
4138
+ `;
4139
+ }}
4140
+
4141
+ ${({ $visible, $placeholder }) => {
4142
+ if (!$visible && !$placeholder) {
4143
+ return "display: none;";
4144
+ }
4145
+ if ($placeholder && !$visible) {
4146
+ return "visibility: hidden;";
4147
+ }
4148
+ return "";
4149
+ }}
4150
+ `;
4151
+ var NextLevelIconContainer = styled.div`
4152
+ display: flex;
4153
+ align-items: center;
4154
+ justify-content: center;
4155
+ flex-shrink: 0;
4156
+
4157
+ ${({ $size, theme: theme3 }) => {
4158
+ const sizeConfig = theme3.components?.menu?.menuItem?.size?.[$size];
4159
+ const iconSize = sizeConfig?.nextLevelIcon?.size;
4160
+ return `
4161
+ width: ${iconSize?.width || "18px"};
4162
+ height: ${iconSize?.height || "18px"};
4163
+ `;
4164
+ }}
4239
4165
  `;
4166
+ var CheckmarkIcon = () => /* @__PURE__ */ React3.createElement("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none" }, /* @__PURE__ */ React3.createElement(
4167
+ "path",
4168
+ {
4169
+ d: "M14.25 5.25L7.125 12.375L3.75 9",
4170
+ stroke: "#41464B",
4171
+ strokeWidth: "1.5",
4172
+ strokeLinecap: "round",
4173
+ strokeLinejoin: "round"
4174
+ }
4175
+ ));
4176
+ var ArrowIcon2 = () => /* @__PURE__ */ React3.createElement("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none" }, /* @__PURE__ */ React3.createElement(
4177
+ "path",
4178
+ {
4179
+ d: "M6.75 4.5L11.25 9L6.75 13.5",
4180
+ stroke: "#41464B",
4181
+ strokeWidth: "1.5",
4182
+ strokeLinecap: "round",
4183
+ strokeLinejoin: "round"
4184
+ }
4185
+ ));
4186
+ var Menu = ({
4187
+ items,
4188
+ selectedKeys = [],
4189
+ openKeys,
4190
+ size = "large",
4191
+ searchable = false,
4192
+ searchPlaceholder = "Enter search content",
4193
+ maxHeight = 300,
4194
+ virtual = false,
4195
+ reserveActiveIconSpace = true,
4196
+ onSelect,
4197
+ onSearch,
4198
+ onOpenChange,
4199
+ className,
4200
+ style
4201
+ }) => {
4202
+ useEffect(() => {
4203
+ styleManager.inject("od-menu-styles", MenuGlobalStyles);
4204
+ }, []);
4205
+ const [searchValue, setSearchValue] = useState("");
4206
+ const handleSearch = (value) => {
4207
+ setSearchValue(value);
4208
+ onSearch?.(value);
4209
+ };
4210
+ const filteredItems = useMemo(() => {
4211
+ if (!searchValue) return items;
4212
+ const searchLower = searchValue.toLowerCase();
4213
+ const filterMenuItem = (item) => {
4214
+ if (item.label.toLowerCase().includes(searchLower) || item.description?.toLowerCase().includes(searchLower)) {
4215
+ return item;
4216
+ }
4217
+ if (item.children && item.children.length > 0) {
4218
+ const filteredChildren = item.children.map((child) => filterMenuItem(child)).filter(Boolean);
4219
+ if (filteredChildren.length > 0) {
4220
+ return { ...item, children: filteredChildren };
4221
+ }
4222
+ }
4223
+ return null;
4224
+ };
4225
+ const filterItem = (item) => {
4226
+ if (item.type === "divider") return null;
4227
+ if (item.type === "group") {
4228
+ const filteredChildren = item.children.map((child) => filterMenuItem(child)).filter(Boolean);
4229
+ if (filteredChildren.length > 0) {
4230
+ return { ...item, children: filteredChildren };
4231
+ }
4232
+ return null;
4233
+ }
4234
+ return filterMenuItem(item);
4235
+ };
4236
+ return items.map((item) => filterItem(item)).filter(Boolean);
4237
+ }, [items, searchValue]);
4238
+ const renderMenuItemContent = (item, reserveSpace) => {
4239
+ const isSelected = item.selected || selectedKeys.includes(item.key);
4240
+ const isSelectable = item.selectable !== false;
4241
+ const shouldShowActiveIcon = isSelectable && isSelected;
4242
+ const shouldReserveSpace = reserveSpace || isSelectable;
4243
+ const iconElement = item.icon ? /* @__PURE__ */ React3.createElement(IconContainer2, { $size: size }, typeof item.icon === "string" ? /* @__PURE__ */ React3.createElement(Icon, { src: item.icon }) : item.icon) : null;
4244
+ return /* @__PURE__ */ React3.createElement(MenuItemContent, { $size: size }, iconElement, /* @__PURE__ */ React3.createElement(ContentBlock2, null, /* @__PURE__ */ React3.createElement(LabelText2, { $size: size, $disabled: !!item.disabled }, item.label), item.description && /* @__PURE__ */ React3.createElement(DescriptionText, { $size: size, $disabled: !!item.disabled }, item.description)), /* @__PURE__ */ React3.createElement(
4245
+ ActiveIconContainer,
4246
+ {
4247
+ $size: size,
4248
+ $visible: shouldShowActiveIcon,
4249
+ $placeholder: shouldReserveSpace && !shouldShowActiveIcon
4250
+ },
4251
+ shouldShowActiveIcon && /* @__PURE__ */ React3.createElement(CheckmarkIcon, null)
4252
+ ), item.children && item.children.length > 0 && /* @__PURE__ */ React3.createElement(NextLevelIconContainer, { $size: size }, /* @__PURE__ */ React3.createElement(ArrowIcon2, null)));
4253
+ };
4254
+ const renderItem = (item) => {
4255
+ if (item.type === "divider") {
4256
+ return /* @__PURE__ */ React3.createElement(Divider$1, { key: item.key });
4257
+ }
4258
+ if (item.type === "group") {
4259
+ return /* @__PURE__ */ React3.createElement(ItemGroup, { key: item.key, title: item.label }, item.children.map((child) => renderMenuItem(child)));
4260
+ }
4261
+ return renderMenuItem(item);
4262
+ };
4263
+ const renderMenuItem = (item) => {
4264
+ if (item.children && item.children.length > 0) {
4265
+ return /* @__PURE__ */ React3.createElement(
4266
+ SubMenu,
4267
+ {
4268
+ key: item.key,
4269
+ title: renderMenuItemContent(item, reserveActiveIconSpace),
4270
+ disabled: item.disabled,
4271
+ popupOffset: [5, 0]
4272
+ },
4273
+ item.children.map((child) => renderMenuItem(child))
4274
+ );
4275
+ }
4276
+ return /* @__PURE__ */ React3.createElement(
4277
+ MenuItem,
4278
+ {
4279
+ key: item.key,
4280
+ disabled: item.disabled,
4281
+ onClick: () => {
4282
+ item.onClick?.(item.key);
4283
+ onSelect?.(item.key);
4284
+ }
4285
+ },
4286
+ renderMenuItemContent(item, reserveActiveIconSpace)
4287
+ );
4288
+ };
4289
+ const itemHeight = size === "medium" ? 28 : 36;
4290
+ const menuKey = openKeys?.join(",") || "menu";
4291
+ return /* @__PURE__ */ React3.createElement(MenuContainer, { className, style }, searchable && /* @__PURE__ */ React3.createElement(SearchBoxContainer, null, /* @__PURE__ */ React3.createElement(
4292
+ Input,
4293
+ {
4294
+ lineType: "underlined",
4295
+ size: "small",
4296
+ placeholder: searchPlaceholder,
4297
+ value: searchValue,
4298
+ onChange: (e) => handleSearch(e.target.value),
4299
+ clearable: true,
4300
+ onClear: () => handleSearch(""),
4301
+ prefixNode: /* @__PURE__ */ React3.createElement(SearchIcon, null)
4302
+ }
4303
+ )), virtual && filteredItems.length > 10 ? /* @__PURE__ */ React3.createElement(
4304
+ VirtualList,
4305
+ {
4306
+ data: filteredItems,
4307
+ height: maxHeight,
4308
+ itemHeight,
4309
+ itemKey: "key",
4310
+ fullHeight: false,
4311
+ style: { width: "100%" }
4312
+ },
4313
+ (item) => /* @__PURE__ */ React3.createElement(
4314
+ RcMenu,
4315
+ {
4316
+ key: menuKey,
4317
+ prefixCls: "od-menu",
4318
+ mode: "vertical",
4319
+ selectedKeys,
4320
+ openKeys,
4321
+ onOpenChange,
4322
+ triggerSubMenuAction: "hover",
4323
+ expandIcon: null,
4324
+ style: {
4325
+ border: "none",
4326
+ background: "transparent",
4327
+ padding: 0
4328
+ }
4329
+ },
4330
+ renderItem(item)
4331
+ )
4332
+ ) : /* @__PURE__ */ React3.createElement(
4333
+ RcMenu,
4334
+ {
4335
+ key: menuKey,
4336
+ prefixCls: "od-menu",
4337
+ mode: "vertical",
4338
+ selectedKeys,
4339
+ openKeys,
4340
+ onOpenChange,
4341
+ triggerSubMenuAction: "hover",
4342
+ expandIcon: null,
4343
+ style: {
4344
+ border: "none",
4345
+ background: "transparent"
4346
+ }
4347
+ },
4348
+ filteredItems.map(renderItem)
4349
+ ));
4350
+ };
4351
+ Menu.displayName = "Menu";
4352
+ var Dropdown = ({
4353
+ overlay,
4354
+ trigger = ["click"],
4355
+ placement = "bottomLeft",
4356
+ visible: controlledVisible,
4357
+ defaultVisible = false,
4358
+ onVisibleChange,
4359
+ children,
4360
+ overlayClassName,
4361
+ getPopupContainer,
4362
+ ...rest
4363
+ }) => {
4364
+ useEffect(() => {
4365
+ styleManager.inject("od-dropdown-styles", DropdownGlobalStyles);
4366
+ }, []);
4367
+ const [internalVisible, setInternalVisible] = useState(defaultVisible);
4368
+ const isControlled = controlledVisible !== void 0;
4369
+ const isVisible = isControlled ? controlledVisible : internalVisible;
4370
+ const handleVisibleChange = (visible) => {
4371
+ if (!isControlled) {
4372
+ setInternalVisible(visible);
4373
+ }
4374
+ onVisibleChange?.(visible);
4375
+ };
4376
+ return /* @__PURE__ */ React3.createElement(
4377
+ RcDropdown,
4378
+ {
4379
+ overlay: overlay || /* @__PURE__ */ React3.createElement("div", null),
4380
+ trigger,
4381
+ placement,
4382
+ visible: isVisible,
4383
+ onVisibleChange: handleVisibleChange,
4384
+ prefixCls: "od-dropdown",
4385
+ overlayClassName,
4386
+ getPopupContainer,
4387
+ ...rest
4388
+ },
4389
+ children
4390
+ );
4391
+ };
4392
+ Dropdown.displayName = "Dropdown";
4240
4393
 
4241
4394
  // src/UIConfigProvider/UIConfigProvider.tsx
4242
4395
  init_IconProvider();
4396
+ init_configManager();
4243
4397
  init_context();
4244
4398
  var UIConfigContext = createContext(null);
4245
4399
  var UIConfigProvider = ({ config, children }) => {
4246
- const { icons = {}, toast: toast2 = {} } = config;
4247
- const renderFunction = (element, container) => {
4248
- if ("createRoot" in ReactDOM) {
4249
- const { createRoot } = ReactDOM;
4250
- const root = createRoot(container);
4251
- root.render(element);
4252
- } else {
4253
- ReactDOM.render(element, container);
4254
- }
4255
- };
4256
- registerGlobalContext({
4257
- theme: config.theme,
4258
- render: renderFunction
4259
- });
4400
+ useEffect(() => {
4401
+ const renderFunction = (element, container) => {
4402
+ if ("createRoot" in ReactDOM) {
4403
+ const { createRoot } = ReactDOM;
4404
+ const root = createRoot(container);
4405
+ root.render(element);
4406
+ } else {
4407
+ ReactDOM.render(element, container);
4408
+ }
4409
+ };
4410
+ registerGlobalContext({
4411
+ theme: config.theme,
4412
+ render: renderFunction
4413
+ });
4414
+ initUIConfig(config);
4415
+ }, [config]);
4416
+ const { icons = {} } = config;
4260
4417
  const toastConfig = {
4261
- maxCount: toast2.maxCount ?? 5,
4262
- defaultDuration: toast2.defaultDuration ?? 3e3
4418
+ maxCount: config.toast?.maxCount ?? 5,
4419
+ defaultDuration: config.toast?.defaultDuration ?? 3e3
4263
4420
  };
4264
- const TooltipStyles = TooltipGlobalStyles;
4265
- const MenuStyles = MenuGlobalStyles;
4266
- const DropdownStyles = DropdownGlobalStyles;
4267
- return /* @__PURE__ */ React3.createElement(UIConfigContext.Provider, { value: config }, /* @__PURE__ */ React3.createElement(TooltipStyles, null), /* @__PURE__ */ React3.createElement(MenuStyles, null), /* @__PURE__ */ React3.createElement(DropdownStyles, null), /* @__PURE__ */ React3.createElement(IconProvider, { icons }, /* @__PURE__ */ React3.createElement(
4421
+ return /* @__PURE__ */ React3.createElement(UIConfigContext.Provider, { value: config }, /* @__PURE__ */ React3.createElement(IconProvider, { icons }, /* @__PURE__ */ React3.createElement(
4268
4422
  ToastContainer2,
4269
4423
  {
4270
4424
  maxCount: toastConfig.maxCount,
@@ -4275,10 +4429,7 @@ var UIConfigProvider = ({ config, children }) => {
4275
4429
  };
4276
4430
  var useUIConfig = () => {
4277
4431
  const context = useContext(UIConfigContext);
4278
- if (!context) {
4279
- throw new Error("useUIConfig must be used within UIConfigProvider");
4280
- }
4281
- return context;
4432
+ return context || getUIConfig();
4282
4433
  };
4283
4434
  UIConfigProvider.displayName = "UIConfigProvider";
4284
4435
 
@@ -4349,10 +4500,13 @@ var mergeUIConfig = (baseConfig, ...configs) => {
4349
4500
  return merged;
4350
4501
  };
4351
4502
 
4503
+ // src/UIConfigProvider/index.ts
4504
+ init_configManager();
4505
+
4352
4506
  // src/index.ts
4353
4507
  init_styled();
4354
4508
  init_context();
4355
4509
 
4356
- export { Button, Checkbox, Dropdown, DropdownButton2 as DropdownButton, DropdownGlobalStyles, Icon, IconProvider, Input, Menu, MenuGlobalStyles, NumberInput, Radio, SearchInput, Slider, SpinButton, Switch, Tabs, Toast, ToastContainer2 as ToastContainer, ToolbarButton, Tooltip, UIConfigProvider, UnderlinedInput, createUIConfig, getGlobalTheme, mergeUIConfig, styled, toast, useIconRegistry, useToast, useUIConfig };
4510
+ export { Button, Checkbox, Dropdown, DropdownButton2 as DropdownButton, DropdownGlobalStyles, Icon, IconProvider, Input, Menu, MenuGlobalStyles, NumberInput, Radio, SearchInput, Slider, SpinButton, Switch, Tabs, Toast, ToastContainer2 as ToastContainer, ToolbarButton, Tooltip, UIConfigProvider, UnderlinedInput, createUIConfig, getGlobalIconRegistry, getGlobalTheme, getGlobalToastConfig, getUIConfig, initUIConfig, mergeUIConfig, styled, toast, useIconRegistry, useToast, useUIConfig };
4357
4511
  //# sourceMappingURL=index.js.map
4358
4512
  //# sourceMappingURL=index.js.map