@lobehub/ui 5.43.1 → 5.45.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 (51) hide show
  1. package/es/base-ui/Accordion/atoms.mjs +8 -3
  2. package/es/base-ui/Accordion/atoms.mjs.map +1 -1
  3. package/es/base-ui/Accordion/style.d.mts +1 -0
  4. package/es/base-ui/Accordion/style.mjs +10 -0
  5. package/es/base-ui/Accordion/style.mjs.map +1 -1
  6. package/es/base-ui/Accordion/type.d.mts +1 -1
  7. package/es/base-ui/ContextMenu/ContextMenuHost.mjs +5 -1
  8. package/es/base-ui/ContextMenu/ContextMenuHost.mjs.map +1 -1
  9. package/es/base-ui/ContextMenu/ContextMenuTrigger.d.mts +3 -1
  10. package/es/base-ui/ContextMenu/ContextMenuTrigger.mjs +7 -3
  11. package/es/base-ui/ContextMenu/ContextMenuTrigger.mjs.map +1 -1
  12. package/es/base-ui/ContextMenu/store.d.mts +3 -1
  13. package/es/base-ui/ContextMenu/store.mjs +6 -2
  14. package/es/base-ui/ContextMenu/store.mjs.map +1 -1
  15. package/es/base-ui/DropdownMenu/DropdownMenu.mjs +6 -2
  16. package/es/base-ui/DropdownMenu/DropdownMenu.mjs.map +1 -1
  17. package/es/base-ui/DropdownMenu/atoms.d.mts +4 -2
  18. package/es/base-ui/DropdownMenu/atoms.mjs +17 -5
  19. package/es/base-ui/DropdownMenu/atoms.mjs.map +1 -1
  20. package/es/base-ui/DropdownMenu/sharedStyle.mjs +26 -3
  21. package/es/base-ui/DropdownMenu/sharedStyle.mjs.map +1 -1
  22. package/es/base-ui/DropdownMenu/type.d.mts +3 -1
  23. package/es/base-ui/ScrollArea/atoms.mjs +4 -4
  24. package/es/base-ui/ScrollArea/atoms.mjs.map +1 -1
  25. package/es/base-ui/Select/Select.mjs +1 -3
  26. package/es/base-ui/Select/Select.mjs.map +1 -1
  27. package/es/base-ui/Select/hooks.mjs +1 -40
  28. package/es/base-ui/Select/hooks.mjs.map +1 -1
  29. package/es/base-ui/Select/parts.mjs +20 -18
  30. package/es/base-ui/Select/parts.mjs.map +1 -1
  31. package/es/base-ui/Select/renderOptions.mjs +1 -2
  32. package/es/base-ui/Select/renderOptions.mjs.map +1 -1
  33. package/es/base-ui/Select/style.mjs +2 -4
  34. package/es/base-ui/Select/style.mjs.map +1 -1
  35. package/es/base-ui/Select/type.d.mts +3 -3
  36. package/es/base-ui/index.d.mts +4 -2
  37. package/es/base-ui/index.mjs +1 -1
  38. package/es/base-ui/virtual/MenuVirtualList.d.mts +3 -0
  39. package/es/base-ui/virtual/MenuVirtualList.mjs +28 -0
  40. package/es/base-ui/virtual/MenuVirtualList.mjs.map +1 -0
  41. package/es/base-ui/virtual/VirtualScrollArea.d.mts +3 -0
  42. package/es/base-ui/virtual/VirtualScrollArea.mjs +82 -0
  43. package/es/base-ui/virtual/VirtualScrollArea.mjs.map +1 -0
  44. package/es/base-ui/virtual/index.d.mts +5 -0
  45. package/es/base-ui/virtual/type.d.mts +26 -0
  46. package/es/base-ui/virtual/useMenuVirtualList.d.mts +3 -0
  47. package/es/base-ui/virtual/useMenuVirtualList.mjs +256 -0
  48. package/es/base-ui/virtual/useMenuVirtualList.mjs.map +1 -0
  49. package/es/index.d.mts +1 -1
  50. package/es/index.mjs +1 -1
  51. package/package.json +1 -1
@@ -28,12 +28,23 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
28
28
  padding-block: 8px;
29
29
  padding-inline: 12px;
30
30
  border-block-start: 1px solid ${cssVar.colorBorder};
31
+
32
+ /* A menu item pinned in a slot keeps the same inset as the rows above it. */
33
+ &:has(> [role^='menuitem']) {
34
+ padding-block: 4px;
35
+ padding-inline: 0;
36
+ }
31
37
  `,
32
38
  header: css`
33
39
  flex-shrink: 0;
34
40
  padding-block: 8px;
35
41
  padding-inline: 12px;
36
42
  border-block-end: 1px solid ${cssVar.colorBorder};
43
+
44
+ &:has(> [role^='menuitem']) {
45
+ padding-block: 4px;
46
+ padding-inline: 0;
47
+ }
37
48
  `,
38
49
  groupLabel: css`
39
50
  user-select: none;
@@ -164,11 +175,13 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
164
175
  white-space: nowrap;
165
176
  `,
166
177
  popup: css`
178
+ --lobe-menu-popup-padding: 4px;
179
+
167
180
  overflow-y: auto;
168
181
 
169
182
  min-width: 220px;
170
183
  max-height: var(--available-height);
171
- padding: 4px;
184
+ padding: var(--lobe-menu-popup-padding);
172
185
  border-radius: ${cssVar.borderRadius};
173
186
 
174
187
  background: ${cssVar.colorBgElevated};
@@ -178,14 +191,24 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
178
191
  0 4px 12px 0 rgb(0 0 0 / 8%),
179
192
  0 1px 3px 0 rgb(0 0 0 / 6%);
180
193
 
181
- &[data-has-header] {
194
+ &[data-has-header],
195
+ &:has(> [data-slot='header']) {
182
196
  padding-block-start: 0;
183
197
  }
184
198
 
185
- &[data-has-footer] {
199
+ &[data-has-footer],
200
+ &:has(> [data-slot='footer']) {
186
201
  padding-block-end: 0;
187
202
  }
188
203
 
204
+ &:has(> [data-virtual]) {
205
+ --lobe-virtual-scroll-inset: var(--lobe-menu-popup-padding);
206
+
207
+ overflow: hidden;
208
+ display: flex;
209
+ flex-direction: column;
210
+ }
211
+
189
212
  /* Base UI moves data-highlighted with the arrow keys, but :hover keeps painting
190
213
  whatever the resting cursor sits on, so two items light up at once. */
191
214
  &:has([data-highlighted]) {
@@ -1 +1 @@
1
- {"version":3,"file":"sharedStyle.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/sharedStyle.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n danger: css`\n --lobe-menu-icon-color: ${cssVar.colorError};\n\n color: ${cssVar.colorError} !important;\n\n &:hover {\n background: ${cssVar.colorErrorBg} !important;\n }\n `,\n\n empty: css`\n cursor: default;\n font-style: italic;\n color: ${cssVar.colorTextTertiary};\n `,\n\n extra: css`\n margin-inline-start: auto;\n padding-inline-start: 16px;\n\n font-family: ${cssVar.fontFamilyCode};\n font-size: 12px;\n color: ${cssVar.colorTextTertiary};\n `,\n\n footer: css`\n flex-shrink: 0;\n padding-block: 8px;\n padding-inline: 12px;\n border-block-start: 1px solid ${cssVar.colorBorder};\n `,\n\n header: css`\n flex-shrink: 0;\n padding-block: 8px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorBorder};\n `,\n\n groupLabel: css`\n user-select: none;\n\n padding-block: 8px 4px;\n padding-inline: 12px;\n\n font-size: 10px;\n font-weight: 600;\n line-height: 14px;\n color: ${cssVar.colorTextTertiary};\n text-transform: uppercase;\n letter-spacing: 0.6px;\n\n [role='group']:first-child > & {\n padding-block-start: 4px;\n }\n `,\n\n icon: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 14px;\n height: 14px;\n margin-inline-end: 12px;\n\n color: var(--lobe-menu-icon-color, ${cssVar.colorTextSecondary});\n\n & svg {\n width: 100%;\n height: 100%;\n }\n `,\n\n item: css`\n user-select: none;\n\n position: relative;\n\n overflow: hidden;\n display: flex;\n align-items: center;\n\n width: 100%;\n min-height: 32px;\n padding-block: 6px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadiusSM};\n\n font-size: 14px;\n line-height: 20px;\n color: ${cssVar.colorText};\n\n outline: none;\n\n transition: all 150ms ${cssVar.motionEaseOut};\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &:active {\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: ${cssVar.colorTextDisabled};\n opacity: 0.5;\n\n &:hover {\n background: transparent;\n }\n }\n\n &[data-highlighted]:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-state='open']:not([data-disabled]),\n &[data-open]:not([data-disabled]),\n &[aria-expanded='true']:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n `,\n\n itemContent: css`\n display: flex;\n flex: 1;\n gap: 0;\n align-items: center;\n `,\n\n itemContentAlignStart: css`\n align-items: flex-start;\n `,\n\n iconAlignStart: css`\n align-self: flex-start;\n margin-block-start: 2px;\n `,\n\n label: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n & a,\n & a:visited,\n & a:hover,\n & a:active {\n color: inherit;\n }\n `,\n\n labelGroup: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-width: 0;\n `,\n\n desc: css`\n overflow: hidden;\n\n font-size: 12px;\n line-height: 16px;\n color: ${cssVar.colorTextTertiary};\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n\n popup: css`\n overflow-y: auto;\n\n min-width: 220px;\n max-height: var(--available-height);\n padding: 4px;\n border-radius: ${cssVar.borderRadius};\n\n background: ${cssVar.colorBgElevated};\n outline: none;\n box-shadow:\n 0 0 0 1px ${cssVar.colorBorder},\n 0 4px 12px 0 rgb(0 0 0 / 8%),\n 0 1px 3px 0 rgb(0 0 0 / 6%);\n\n &[data-has-header] {\n padding-block-start: 0;\n }\n\n &[data-has-footer] {\n padding-block-end: 0;\n }\n\n /* Base UI moves data-highlighted with the arrow keys, but :hover keeps painting\n whatever the resting cursor sits on, so two items light up at once. */\n &:has([data-highlighted]) {\n [role^='menuitem']:hover:not([data-highlighted]),\n [role='option']:hover:not([data-highlighted]) {\n background: transparent !important;\n }\n }\n `,\n\n popupWithSlots: css`\n overflow: hidden;\n display: flex;\n flex-direction: column;\n max-height: var(--available-height);\n `,\n\n slotViewport: css`\n overflow-y: auto;\n flex: 1;\n min-height: 0;\n `,\n\n positioner: css`\n --lobe-dropdown-animation-duration: 140ms;\n --lobe-dropdown-animation-scale-y: 0.92;\n --lobe-dropdown-animation-ease-in: ease-in;\n --lobe-dropdown-animation-ease-out: ${cssVar.motionEaseOut};\n\n z-index: 1100;\n\n & > * {\n will-change: opacity, transform;\n transform-origin: var(--transform-origin);\n animation: none;\n }\n\n &[data-open] > * {\n transform: scaleY(1);\n opacity: 1;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out);\n }\n\n &[data-open] > *[data-starting-style] {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n }\n\n &[data-closed] > * {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in);\n }\n\n &[data-hover-trigger] {\n --lobe-dropdown-animation-duration: 140ms;\n }\n\n &[data-submenu],\n &[data-nested] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n\n z-index: 1199;\n }\n\n &[data-side='left'],\n &[data-side='right'] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n }\n `,\n\n separator: css`\n height: 1px;\n margin-block: 4px;\n margin-inline: 0;\n background: ${cssVar.colorBorder};\n `,\n\n submenuArrow: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 16px;\n height: 16px;\n margin-inline-start: 8px;\n\n color: var(--lobe-menu-icon-color, ${cssVar.colorTextSecondary});\n\n & svg {\n width: 12px;\n height: 12px;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,QAAQ,GAAG;8BACiB,OAAO,WAAW;;aAEnC,OAAO,WAAW;;;oBAGX,OAAO,aAAa;;;CAItC,OAAO,GAAG;;;aAGC,OAAO,kBAAkB;;CAGpC,OAAO,GAAG;;;;mBAIO,OAAO,eAAe;;aAE5B,OAAO,kBAAkB;;CAGpC,QAAQ,GAAG;;;;oCAIuB,OAAO,YAAY;;CAGrD,QAAQ,GAAG;;;;kCAIqB,OAAO,YAAY;;CAGnD,YAAY,GAAG;;;;;;;;;aASJ,OAAO,kBAAkB;;;;;;;;CASpC,MAAM,GAAG;;;;;;;;;;yCAU8B,OAAO,mBAAmB;;;;;;;CAQjE,MAAM,GAAG;;;;;;;;;;;;;qBAaU,OAAO,eAAe;;;;aAI9B,OAAO,UAAU;;;;4BAIF,OAAO,cAAc;;;oBAG7B,OAAO,kBAAkB;;;;oBAIzB,OAAO,mBAAmB;;;;;eAK/B,OAAO,kBAAkB;;;;;;;;;oBASpB,OAAO,kBAAkB;;;;;;oBAMzB,OAAO,kBAAkB;;;CAI3C,aAAa,GAAG;;;;;;CAOhB,uBAAuB,GAAG;;;CAI1B,gBAAgB,GAAG;;;;CAKnB,OAAO,GAAG;;;;;;;;;;;;;CAcV,YAAY,GAAG;;;;;;;;CASf,MAAM,GAAG;;;;;aAKE,OAAO,kBAAkB;;;;CAKpC,OAAO,GAAG;;;;;;qBAMS,OAAO,aAAa;;kBAEvB,OAAO,gBAAgB;;;kBAGvB,OAAO,YAAY;;;;;;;;;;;;;;;;;;;;;CAsBnC,gBAAgB,GAAG;;;;;;CAOnB,cAAc,GAAG;;;;;CAMjB,YAAY,GAAG;;;;0CAIyB,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkD7D,WAAW,GAAG;;;;kBAIE,OAAO,YAAY;;CAGnC,cAAc,GAAG;;;;;;;;;;yCAUsB,OAAO,mBAAmB;;;;;;;AAOnE,EAAE"}
1
+ {"version":3,"file":"sharedStyle.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/sharedStyle.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n danger: css`\n --lobe-menu-icon-color: ${cssVar.colorError};\n\n color: ${cssVar.colorError} !important;\n\n &:hover {\n background: ${cssVar.colorErrorBg} !important;\n }\n `,\n\n empty: css`\n cursor: default;\n font-style: italic;\n color: ${cssVar.colorTextTertiary};\n `,\n\n extra: css`\n margin-inline-start: auto;\n padding-inline-start: 16px;\n\n font-family: ${cssVar.fontFamilyCode};\n font-size: 12px;\n color: ${cssVar.colorTextTertiary};\n `,\n\n footer: css`\n flex-shrink: 0;\n padding-block: 8px;\n padding-inline: 12px;\n border-block-start: 1px solid ${cssVar.colorBorder};\n\n /* A menu item pinned in a slot keeps the same inset as the rows above it. */\n &:has(> [role^='menuitem']) {\n padding-block: 4px;\n padding-inline: 0;\n }\n `,\n\n header: css`\n flex-shrink: 0;\n padding-block: 8px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorBorder};\n\n &:has(> [role^='menuitem']) {\n padding-block: 4px;\n padding-inline: 0;\n }\n `,\n\n groupLabel: css`\n user-select: none;\n\n padding-block: 8px 4px;\n padding-inline: 12px;\n\n font-size: 10px;\n font-weight: 600;\n line-height: 14px;\n color: ${cssVar.colorTextTertiary};\n text-transform: uppercase;\n letter-spacing: 0.6px;\n\n [role='group']:first-child > & {\n padding-block-start: 4px;\n }\n `,\n\n icon: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 14px;\n height: 14px;\n margin-inline-end: 12px;\n\n color: var(--lobe-menu-icon-color, ${cssVar.colorTextSecondary});\n\n & svg {\n width: 100%;\n height: 100%;\n }\n `,\n\n item: css`\n user-select: none;\n\n position: relative;\n\n overflow: hidden;\n display: flex;\n align-items: center;\n\n width: 100%;\n min-height: 32px;\n padding-block: 6px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadiusSM};\n\n font-size: 14px;\n line-height: 20px;\n color: ${cssVar.colorText};\n\n outline: none;\n\n transition: all 150ms ${cssVar.motionEaseOut};\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &:active {\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: ${cssVar.colorTextDisabled};\n opacity: 0.5;\n\n &:hover {\n background: transparent;\n }\n }\n\n &[data-highlighted]:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-state='open']:not([data-disabled]),\n &[data-open]:not([data-disabled]),\n &[aria-expanded='true']:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n `,\n\n itemContent: css`\n display: flex;\n flex: 1;\n gap: 0;\n align-items: center;\n `,\n\n itemContentAlignStart: css`\n align-items: flex-start;\n `,\n\n iconAlignStart: css`\n align-self: flex-start;\n margin-block-start: 2px;\n `,\n\n label: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n & a,\n & a:visited,\n & a:hover,\n & a:active {\n color: inherit;\n }\n `,\n\n labelGroup: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-width: 0;\n `,\n\n desc: css`\n overflow: hidden;\n\n font-size: 12px;\n line-height: 16px;\n color: ${cssVar.colorTextTertiary};\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n\n popup: css`\n --lobe-menu-popup-padding: 4px;\n\n overflow-y: auto;\n\n min-width: 220px;\n max-height: var(--available-height);\n padding: var(--lobe-menu-popup-padding);\n border-radius: ${cssVar.borderRadius};\n\n background: ${cssVar.colorBgElevated};\n outline: none;\n box-shadow:\n 0 0 0 1px ${cssVar.colorBorder},\n 0 4px 12px 0 rgb(0 0 0 / 8%),\n 0 1px 3px 0 rgb(0 0 0 / 6%);\n\n &[data-has-header],\n &:has(> [data-slot='header']) {\n padding-block-start: 0;\n }\n\n &[data-has-footer],\n &:has(> [data-slot='footer']) {\n padding-block-end: 0;\n }\n\n &:has(> [data-virtual]) {\n --lobe-virtual-scroll-inset: var(--lobe-menu-popup-padding);\n\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n /* Base UI moves data-highlighted with the arrow keys, but :hover keeps painting\n whatever the resting cursor sits on, so two items light up at once. */\n &:has([data-highlighted]) {\n [role^='menuitem']:hover:not([data-highlighted]),\n [role='option']:hover:not([data-highlighted]) {\n background: transparent !important;\n }\n }\n `,\n\n popupWithSlots: css`\n overflow: hidden;\n display: flex;\n flex-direction: column;\n max-height: var(--available-height);\n `,\n\n slotViewport: css`\n overflow-y: auto;\n flex: 1;\n min-height: 0;\n `,\n\n positioner: css`\n --lobe-dropdown-animation-duration: 140ms;\n --lobe-dropdown-animation-scale-y: 0.92;\n --lobe-dropdown-animation-ease-in: ease-in;\n --lobe-dropdown-animation-ease-out: ${cssVar.motionEaseOut};\n\n z-index: 1100;\n\n & > * {\n will-change: opacity, transform;\n transform-origin: var(--transform-origin);\n animation: none;\n }\n\n &[data-open] > * {\n transform: scaleY(1);\n opacity: 1;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out);\n }\n\n &[data-open] > *[data-starting-style] {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n }\n\n &[data-closed] > * {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in);\n }\n\n &[data-hover-trigger] {\n --lobe-dropdown-animation-duration: 140ms;\n }\n\n &[data-submenu],\n &[data-nested] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n\n z-index: 1199;\n }\n\n &[data-side='left'],\n &[data-side='right'] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n }\n `,\n\n separator: css`\n height: 1px;\n margin-block: 4px;\n margin-inline: 0;\n background: ${cssVar.colorBorder};\n `,\n\n submenuArrow: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 16px;\n height: 16px;\n margin-inline-start: 8px;\n\n color: var(--lobe-menu-icon-color, ${cssVar.colorTextSecondary});\n\n & svg {\n width: 12px;\n height: 12px;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,QAAQ,GAAG;8BACiB,OAAO,WAAW;;aAEnC,OAAO,WAAW;;;oBAGX,OAAO,aAAa;;;CAItC,OAAO,GAAG;;;aAGC,OAAO,kBAAkB;;CAGpC,OAAO,GAAG;;;;mBAIO,OAAO,eAAe;;aAE5B,OAAO,kBAAkB;;CAGpC,QAAQ,GAAG;;;;oCAIuB,OAAO,YAAY;;;;;;;;CASrD,QAAQ,GAAG;;;;kCAIqB,OAAO,YAAY;;;;;;;CAQnD,YAAY,GAAG;;;;;;;;;aASJ,OAAO,kBAAkB;;;;;;;;CASpC,MAAM,GAAG;;;;;;;;;;yCAU8B,OAAO,mBAAmB;;;;;;;CAQjE,MAAM,GAAG;;;;;;;;;;;;;qBAaU,OAAO,eAAe;;;;aAI9B,OAAO,UAAU;;;;4BAIF,OAAO,cAAc;;;oBAG7B,OAAO,kBAAkB;;;;oBAIzB,OAAO,mBAAmB;;;;;eAK/B,OAAO,kBAAkB;;;;;;;;;oBASpB,OAAO,kBAAkB;;;;;;oBAMzB,OAAO,kBAAkB;;;CAI3C,aAAa,GAAG;;;;;;CAOhB,uBAAuB,GAAG;;;CAI1B,gBAAgB,GAAG;;;;CAKnB,OAAO,GAAG;;;;;;;;;;;;;CAcV,YAAY,GAAG;;;;;;;;CASf,MAAM,GAAG;;;;;aAKE,OAAO,kBAAkB;;;;CAKpC,OAAO,GAAG;;;;;;;;qBAQS,OAAO,aAAa;;kBAEvB,OAAO,gBAAgB;;;kBAGvB,OAAO,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCnC,gBAAgB,GAAG;;;;;;CAOnB,cAAc,GAAG;;;;;CAMjB,YAAY,GAAG;;;;0CAIyB,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkD7D,WAAW,GAAG;;;;kBAIE,OAAO,YAAY;;CAGnC,cAAc,GAAG;;;;;;;;;;yCAUsB,OAAO,mBAAmB;;;;;;;AAOnE,EAAE"}
@@ -1,6 +1,8 @@
1
1
  import { Trigger } from "../../types/trigger.mjs";
2
2
  import "../../types/index.mjs";
3
3
  import { Placement } from "../../utils/placement.mjs";
4
+ import { VirtualListProps } from "../virtual/type.mjs";
5
+ import "../virtual/index.mjs";
4
6
  import { MenuCheckboxItemType } from "../../Menu/checkboxItem.mjs";
5
7
  import { MenuSwitchItemType } from "../../Menu/switchItem.mjs";
6
8
  import { BaseMenuItemType } from "../../Menu/baseItem.mjs";
@@ -14,7 +16,7 @@ type DropdownMenuPlacement = Placement;
14
16
  type DropdownMenuCheckboxItem = MenuCheckboxItemType;
15
17
  type DropdownMenuSwitchItem = MenuSwitchItemType;
16
18
  type DropdownItem = BaseMenuItemType;
17
- interface DropdownMenuProps<Payload = unknown> extends Omit<MenuRootProps<Payload>, 'children'> {
19
+ interface DropdownMenuProps<Payload = unknown> extends Omit<MenuRootProps<Payload>, 'children'>, Pick<VirtualListProps, 'virtual' | 'listItemHeight'> {
18
20
  children: ReactNode;
19
21
  /**
20
22
  * 底部固定插槽,渲染于可滚动的 items 区域下方,自带分隔边框
@@ -10,10 +10,10 @@ const mergeStateClassName = (base, className) => {
10
10
  return cx(base, className);
11
11
  };
12
12
  const ScrollAreaRoot = ({ className, ...rest }) => {
13
- return /* @__PURE__ */ jsx(ScrollArea.Root, {
13
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ScrollAreaGlobalStyle, {}), /* @__PURE__ */ jsx(ScrollArea.Root, {
14
14
  ...rest,
15
15
  className: mergeStateClassName(styles.root, className)
16
- });
16
+ })] });
17
17
  };
18
18
  ScrollAreaRoot.displayName = "ScrollAreaRoot";
19
19
  const resolveFadeClass = (scrollFade) => {
@@ -24,10 +24,10 @@ const resolveFadeClass = (scrollFade) => {
24
24
  return styles.viewportFade;
25
25
  };
26
26
  const ScrollAreaViewport = ({ className, scrollFade = false, ...rest }) => {
27
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ScrollAreaGlobalStyle, {}), /* @__PURE__ */ jsx(ScrollArea.Viewport, {
27
+ return /* @__PURE__ */ jsx(ScrollArea.Viewport, {
28
28
  ...rest,
29
29
  className: mergeStateClassName(cx(styles.viewport, resolveFadeClass(scrollFade)), className)
30
- })] });
30
+ });
31
31
  };
32
32
  ScrollAreaViewport.displayName = "ScrollAreaViewport";
33
33
  const ScrollAreaContent = ScrollArea.Content;
@@ -1 +1 @@
1
- {"version":3,"file":"atoms.mjs","names":["BaseScrollArea"],"sources":["../../../src/base-ui/ScrollArea/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { ScrollArea as BaseScrollArea } from '@base-ui/react/scroll-area';\nimport { cx } from 'antd-style';\nimport type React from 'react';\n\nimport ScrollAreaGlobalStyle from './globalStyle';\nimport { styles } from './style';\n\nconst mergeStateClassName = <TState,>(\n base: string,\n className: string | ((state: TState) => string | undefined) | undefined,\n) => {\n if (typeof className === 'function') return (state: TState) => cx(base, className(state));\n return cx(base, className);\n};\n\nexport type ScrollAreaRootProps = React.ComponentProps<typeof BaseScrollArea.Root>;\n\nexport type ScrollAreaFadeOrientation = 'vertical' | 'horizontal' | 'both';\n\nexport type ScrollAreaViewportProps = React.ComponentProps<typeof BaseScrollArea.Viewport> & {\n /**\n * Enable gradient scroll fade on the viewport edges.\n *\n * - `true` / `'vertical'`: fade top and bottom edges.\n * - `'horizontal'`: fade start and end edges.\n * - `'both'`: fade all four edges (combined via `mask-composite: intersect`).\n * - `false`: no fade.\n *\n * @default false\n */\n scrollFade?: boolean | ScrollAreaFadeOrientation;\n};\nexport type ScrollAreaContentProps = React.ComponentProps<typeof BaseScrollArea.Content>;\nexport type ScrollAreaScrollbarProps = React.ComponentProps<typeof BaseScrollArea.Scrollbar>;\nexport type ScrollAreaThumbProps = React.ComponentProps<typeof BaseScrollArea.Thumb>;\nexport type ScrollAreaCornerProps = React.ComponentProps<typeof BaseScrollArea.Corner>;\n\nexport const ScrollAreaRoot = ({ className, ...rest }: ScrollAreaRootProps) => {\n return (\n <BaseScrollArea.Root {...rest} className={mergeStateClassName(styles.root, className) as any} />\n );\n};\n\nScrollAreaRoot.displayName = 'ScrollAreaRoot';\n\nconst resolveFadeClass = (\n scrollFade: ScrollAreaViewportProps['scrollFade'],\n): string | undefined => {\n if (!scrollFade) return undefined;\n const orientation: ScrollAreaFadeOrientation = scrollFade === true ? 'vertical' : scrollFade;\n if (orientation === 'horizontal') return styles.viewportFadeHorizontal;\n if (orientation === 'both') return styles.viewportFadeBoth;\n return styles.viewportFade;\n};\n\nexport const ScrollAreaViewport = ({\n className,\n scrollFade = false,\n ...rest\n}: ScrollAreaViewportProps) => {\n return (\n <>\n <ScrollAreaGlobalStyle />\n <BaseScrollArea.Viewport\n {...rest}\n className={\n mergeStateClassName(cx(styles.viewport, resolveFadeClass(scrollFade)), className) as any\n }\n />\n </>\n );\n};\n\nScrollAreaViewport.displayName = 'ScrollAreaViewport';\n\nexport const ScrollAreaContent = BaseScrollArea.Content;\n\nexport const ScrollAreaScrollbar = ({ className, ...rest }: ScrollAreaScrollbarProps) => {\n return (\n <BaseScrollArea.Scrollbar\n {...rest}\n className={mergeStateClassName(styles.scrollbar, className) as any}\n />\n );\n};\n\nScrollAreaScrollbar.displayName = 'ScrollAreaScrollbar';\n\nexport const ScrollAreaThumb = ({ className, ...rest }: ScrollAreaThumbProps) => {\n return (\n <BaseScrollArea.Thumb\n {...rest}\n className={mergeStateClassName(styles.thumb, className) as any}\n />\n );\n};\n\nScrollAreaThumb.displayName = 'ScrollAreaThumb';\n\nexport const ScrollAreaCorner = ({ className, ...rest }: ScrollAreaCornerProps) => {\n return (\n <BaseScrollArea.Corner\n {...rest}\n className={mergeStateClassName(styles.corner, className) as any}\n />\n );\n};\n\nScrollAreaCorner.displayName = 'ScrollAreaCorner';\n"],"mappings":";;;;;;;AASA,MAAM,uBACJ,MACA,cACG;CACH,IAAI,OAAO,cAAc,YAAY,QAAQ,UAAkB,GAAG,MAAM,UAAU,KAAK,CAAC;CACxF,OAAO,GAAG,MAAM,SAAS;AAC3B;AAwBA,MAAa,kBAAkB,EAAE,WAAW,GAAG,WAAgC;CAC7E,OACE,oBAACA,WAAe,MAAhB;EAAqB,GAAI;EAAM,WAAW,oBAAoB,OAAO,MAAM,SAAS;CAAW,CAAA;AAEnG;AAEA,eAAe,cAAc;AAE7B,MAAM,oBACJ,eACuB;CACvB,IAAI,CAAC,YAAY,OAAO,KAAA;CACxB,MAAM,cAAyC,eAAe,OAAO,aAAa;CAClF,IAAI,gBAAgB,cAAc,OAAO,OAAO;CAChD,IAAI,gBAAgB,QAAQ,OAAO,OAAO;CAC1C,OAAO,OAAO;AAChB;AAEA,MAAa,sBAAsB,EACjC,WACA,aAAa,OACb,GAAG,WAC0B;CAC7B,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,uBAAD,CAAwB,CAAA,GACxB,oBAACA,WAAe,UAAhB;EACE,GAAI;EACJ,WACE,oBAAoB,GAAG,OAAO,UAAU,iBAAiB,UAAU,CAAC,GAAG,SAAS;CAEnF,CAAA,CACD,EAAA,CAAA;AAEN;AAEA,mBAAmB,cAAc;AAEjC,MAAa,oBAAoBA,WAAe;AAEhD,MAAa,uBAAuB,EAAE,WAAW,GAAG,WAAqC;CACvF,OACE,oBAACA,WAAe,WAAhB;EACE,GAAI;EACJ,WAAW,oBAAoB,OAAO,WAAW,SAAS;CAC3D,CAAA;AAEL;AAEA,oBAAoB,cAAc;AAElC,MAAa,mBAAmB,EAAE,WAAW,GAAG,WAAiC;CAC/E,OACE,oBAACA,WAAe,OAAhB;EACE,GAAI;EACJ,WAAW,oBAAoB,OAAO,OAAO,SAAS;CACvD,CAAA;AAEL;AAEA,gBAAgB,cAAc;AAE9B,MAAa,oBAAoB,EAAE,WAAW,GAAG,WAAkC;CACjF,OACE,oBAACA,WAAe,QAAhB;EACE,GAAI;EACJ,WAAW,oBAAoB,OAAO,QAAQ,SAAS;CACxD,CAAA;AAEL;AAEA,iBAAiB,cAAc"}
1
+ {"version":3,"file":"atoms.mjs","names":["BaseScrollArea"],"sources":["../../../src/base-ui/ScrollArea/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { ScrollArea as BaseScrollArea } from '@base-ui/react/scroll-area';\nimport { cx } from 'antd-style';\nimport type React from 'react';\n\nimport ScrollAreaGlobalStyle from './globalStyle';\nimport { styles } from './style';\n\nconst mergeStateClassName = <TState,>(\n base: string,\n className: string | ((state: TState) => string | undefined) | undefined,\n) => {\n if (typeof className === 'function') return (state: TState) => cx(base, className(state));\n return cx(base, className);\n};\n\nexport type ScrollAreaRootProps = React.ComponentProps<typeof BaseScrollArea.Root>;\n\nexport type ScrollAreaFadeOrientation = 'vertical' | 'horizontal' | 'both';\n\nexport type ScrollAreaViewportProps = React.ComponentProps<typeof BaseScrollArea.Viewport> & {\n /**\n * Enable gradient scroll fade on the viewport edges.\n *\n * - `true` / `'vertical'`: fade top and bottom edges.\n * - `'horizontal'`: fade start and end edges.\n * - `'both'`: fade all four edges (combined via `mask-composite: intersect`).\n * - `false`: no fade.\n *\n * @default false\n */\n scrollFade?: boolean | ScrollAreaFadeOrientation;\n};\nexport type ScrollAreaContentProps = React.ComponentProps<typeof BaseScrollArea.Content>;\nexport type ScrollAreaScrollbarProps = React.ComponentProps<typeof BaseScrollArea.Scrollbar>;\nexport type ScrollAreaThumbProps = React.ComponentProps<typeof BaseScrollArea.Thumb>;\nexport type ScrollAreaCornerProps = React.ComponentProps<typeof BaseScrollArea.Corner>;\n\nexport const ScrollAreaRoot = ({ className, ...rest }: ScrollAreaRootProps) => {\n return (\n <>\n <ScrollAreaGlobalStyle />\n <BaseScrollArea.Root\n {...rest}\n className={mergeStateClassName(styles.root, className) as any}\n />\n </>\n );\n};\n\nScrollAreaRoot.displayName = 'ScrollAreaRoot';\n\nconst resolveFadeClass = (\n scrollFade: ScrollAreaViewportProps['scrollFade'],\n): string | undefined => {\n if (!scrollFade) return undefined;\n const orientation: ScrollAreaFadeOrientation = scrollFade === true ? 'vertical' : scrollFade;\n if (orientation === 'horizontal') return styles.viewportFadeHorizontal;\n if (orientation === 'both') return styles.viewportFadeBoth;\n return styles.viewportFade;\n};\n\nexport const ScrollAreaViewport = ({\n className,\n scrollFade = false,\n ...rest\n}: ScrollAreaViewportProps) => {\n return (\n <BaseScrollArea.Viewport\n {...rest}\n className={\n mergeStateClassName(cx(styles.viewport, resolveFadeClass(scrollFade)), className) as any\n }\n />\n );\n};\n\nScrollAreaViewport.displayName = 'ScrollAreaViewport';\n\nexport const ScrollAreaContent = BaseScrollArea.Content;\n\nexport const ScrollAreaScrollbar = ({ className, ...rest }: ScrollAreaScrollbarProps) => {\n return (\n <BaseScrollArea.Scrollbar\n {...rest}\n className={mergeStateClassName(styles.scrollbar, className) as any}\n />\n );\n};\n\nScrollAreaScrollbar.displayName = 'ScrollAreaScrollbar';\n\nexport const ScrollAreaThumb = ({ className, ...rest }: ScrollAreaThumbProps) => {\n return (\n <BaseScrollArea.Thumb\n {...rest}\n className={mergeStateClassName(styles.thumb, className) as any}\n />\n );\n};\n\nScrollAreaThumb.displayName = 'ScrollAreaThumb';\n\nexport const ScrollAreaCorner = ({ className, ...rest }: ScrollAreaCornerProps) => {\n return (\n <BaseScrollArea.Corner\n {...rest}\n className={mergeStateClassName(styles.corner, className) as any}\n />\n );\n};\n\nScrollAreaCorner.displayName = 'ScrollAreaCorner';\n"],"mappings":";;;;;;;AASA,MAAM,uBACJ,MACA,cACG;CACH,IAAI,OAAO,cAAc,YAAY,QAAQ,UAAkB,GAAG,MAAM,UAAU,KAAK,CAAC;CACxF,OAAO,GAAG,MAAM,SAAS;AAC3B;AAwBA,MAAa,kBAAkB,EAAE,WAAW,GAAG,WAAgC;CAC7E,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,uBAAD,CAAwB,CAAA,GACxB,oBAACA,WAAe,MAAhB;EACE,GAAI;EACJ,WAAW,oBAAoB,OAAO,MAAM,SAAS;CACtD,CAAA,CACD,EAAA,CAAA;AAEN;AAEA,eAAe,cAAc;AAE7B,MAAM,oBACJ,eACuB;CACvB,IAAI,CAAC,YAAY,OAAO,KAAA;CACxB,MAAM,cAAyC,eAAe,OAAO,aAAa;CAClF,IAAI,gBAAgB,cAAc,OAAO,OAAO;CAChD,IAAI,gBAAgB,QAAQ,OAAO,OAAO;CAC1C,OAAO,OAAO;AAChB;AAEA,MAAa,sBAAsB,EACjC,WACA,aAAa,OACb,GAAG,WAC0B;CAC7B,OACE,oBAACA,WAAe,UAAhB;EACE,GAAI;EACJ,WACE,oBAAoB,GAAG,OAAO,UAAU,iBAAiB,UAAU,CAAC,GAAG,SAAS;CAEnF,CAAA;AAEL;AAEA,mBAAmB,cAAc;AAEjC,MAAa,oBAAoBA,WAAe;AAEhD,MAAa,uBAAuB,EAAE,WAAW,GAAG,WAAqC;CACvF,OACE,oBAACA,WAAe,WAAhB;EACE,GAAI;EACJ,WAAW,oBAAoB,OAAO,WAAW,SAAS;CAC3D,CAAA;AAEL;AAEA,oBAAoB,cAAc;AAElC,MAAa,mBAAmB,EAAE,WAAW,GAAG,WAAiC;CAC/E,OACE,oBAACA,WAAe,OAAhB;EACE,GAAI;EACJ,WAAW,oBAAoB,OAAO,OAAO,SAAS;CACvD,CAAA;AAEL;AAEA,gBAAgB,cAAc;AAE9B,MAAa,oBAAoB,EAAE,WAAW,GAAG,WAAkC;CACjF,OACE,oBAACA,WAAe,QAAhB;EACE,GAAI;EACJ,WAAW,oBAAoB,OAAO,QAAQ,SAAS;CACxD,CAAA;AAEL;AAEA,iBAAiB,cAAc"}
@@ -128,9 +128,7 @@ const Select$1 = memo(({ allowClear, autoFocus, className, classNames, defaultOp
128
128
  items: filteredOptions,
129
129
  itemTextClassName,
130
130
  listItemHeight,
131
- optionRender,
132
- renderVirtualItem: virtualState.renderVirtualItem,
133
- virtual
131
+ optionRender
134
132
  });
135
133
  return /* @__PURE__ */ jsxs(Select.Root, {
136
134
  disabled,
@@ -1 +1 @@
1
- {"version":3,"file":"Select.mjs","names":["Select","menuStyles","styles","BaseSelect"],"sources":["../../../src/base-ui/Select/Select.tsx"],"sourcesContent":["'use client';\n\nimport { Select as BaseSelect } from '@base-ui/react/select';\nimport { cx, useThemeMode } from 'antd-style';\nimport { type MouseEvent } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { styles as menuStyles } from '@/base-ui/DropdownMenu/sharedStyle';\n\nimport { SelectPositioner } from './atoms';\nimport { isValueEmpty } from './helpers';\nimport {\n usePortalContainer,\n useSelectOpen,\n useSelectSearch,\n useSelectValue,\n useSelectVirtual,\n} from './hooks';\nimport {\n createTriggerValueRenderer,\n EmptyContent,\n resolveIconNode,\n resolveSuffixIcon,\n SelectListSection,\n SelectSearchInput,\n SelectTriggerSuffix,\n} from './parts';\nimport { renderOptions } from './renderOptions';\nimport { styles, triggerVariants } from './style';\nimport { type SelectOption, type SelectProps } from './type';\n\nconst Select = memo<SelectProps<any>>(\n ({\n allowClear,\n autoFocus,\n className,\n classNames,\n defaultOpen,\n defaultValue,\n disabled,\n id,\n labelRender,\n listHeight = 512,\n listItemHeight,\n loading,\n mode,\n name,\n onChange,\n onOpenChange,\n onSelect,\n open,\n optionRender,\n options,\n placeholder,\n popupClassName,\n popupMatchSelectWidth,\n prefix,\n readOnly,\n required,\n behaviorVariant = 'default',\n selectedIndicatorVariant = 'check',\n shadow,\n showSearch,\n size = 'middle',\n style,\n suffixIcon,\n suffixIconProps,\n tokenSeparators,\n value,\n variant,\n virtual,\n }) => {\n const { isDarkMode } = useThemeMode();\n const resolvedVariant = variant ?? (isDarkMode ? 'filled' : 'outlined');\n const isTags = mode === 'tags';\n const isMultiple = mode === 'multiple' || mode === 'tags';\n const isItemAligned = behaviorVariant === 'item-aligned';\n\n const [extraOptions, setExtraOptions] = useState<SelectOption<any>[]>([]);\n\n useEffect(() => {\n if (mode !== 'tags' && extraOptions.length > 0) {\n setExtraOptions([]);\n }\n }, [mode, extraOptions.length]);\n\n const {\n appendTagValues,\n getOption,\n handleValueChange,\n normalizedValue,\n normalizeValue,\n removeLastTagValue,\n resolvedOptions,\n valueArray,\n } = useSelectValue({\n defaultValue,\n extraOptions,\n isMultiple,\n onChange,\n onSelect,\n options,\n setExtraOptions,\n value,\n });\n\n const { handleOpenChange, mergedOpen } = useSelectOpen({ defaultOpen, onOpenChange, open });\n\n const handleRootValueChange = useCallback(\n (nextValue: any) => {\n if (!(isTags && !mergedOpen)) handleValueChange(nextValue);\n },\n [handleValueChange, isTags, mergedOpen],\n );\n\n const handleRemoveTag = useCallback(\n (index: number) =>\n handleValueChange(valueArray.filter((_, itemIndex) => itemIndex !== index)),\n [handleValueChange, valueArray],\n );\n\n const {\n filteredOptions,\n handleSearchChange,\n handleSearchKeyDown,\n searchValue,\n shouldShowSearch,\n stopSearchPropagation,\n } = useSelectSearch({\n appendTagValues,\n handleOpenChange,\n mergedOpen,\n mode,\n removeLastTagValue,\n resolvedOptions,\n showSearch,\n tokenSeparators,\n });\n\n const virtualState = useSelectVirtual({\n filteredOptions,\n listItemHeight,\n size,\n valueArray,\n virtual,\n });\n\n const portalContainer = usePortalContainer();\n\n const renderValue = useMemo(\n () =>\n createTriggerValueRenderer({\n getOption,\n isMultiple,\n isTags,\n labelRender,\n normalizeValue,\n onRemoveValue: handleRemoveTag,\n placeholder: isTags ? undefined : placeholder,\n }),\n [getOption, handleRemoveTag, isMultiple, isTags, labelRender, normalizeValue, placeholder],\n );\n\n const hasValue = isMultiple ? valueArray.length > 0 : !isValueEmpty(normalizedValue);\n const showClear = Boolean(allowClear && hasValue && !disabled && !readOnly);\n\n const handleClear = useCallback(\n (event: MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n handleValueChange(isMultiple ? [] : null);\n },\n [handleValueChange, isMultiple],\n );\n\n const prefixNode = useMemo(() => resolveIconNode(prefix), [prefix]);\n const suffixIconNode = useMemo(\n () => resolveSuffixIcon(suffixIcon, suffixIconProps, loading),\n [loading, suffixIcon, suffixIconProps],\n );\n\n const popupStyle = useMemo(() => {\n const maxHeight = isItemAligned ? '80vh' : `${listHeight}px`;\n const baseStyle: React.CSSProperties = {\n maxWidth: 'var(--available-width)',\n minWidth: 'var(--anchor-width)',\n ['--lobe-select-popup-max-height' as any]: maxHeight,\n };\n\n if (popupMatchSelectWidth === undefined || popupMatchSelectWidth === true) {\n return baseStyle;\n }\n if (typeof popupMatchSelectWidth === 'number') {\n return {\n ...baseStyle,\n minWidth: popupMatchSelectWidth,\n width: popupMatchSelectWidth,\n };\n }\n return { ...baseStyle, minWidth: 'max-content' };\n }, [isItemAligned, listHeight, popupMatchSelectWidth]);\n\n const triggerClassName = cx(\n triggerVariants({ shadow, size, variant: resolvedVariant }),\n className,\n classNames?.root,\n classNames?.trigger,\n );\n\n const isBoldIndicator = selectedIndicatorVariant === 'bold';\n const itemTextClassName = cx(\n optionRender ? menuStyles.itemContent : menuStyles.label,\n styles.itemText,\n classNames?.itemText,\n );\n\n const isEmpty = filteredOptions.length === 0;\n const listContent = isEmpty ? (\n <EmptyContent classNames={classNames} />\n ) : (\n renderOptions({\n classNames,\n isBoldIndicator,\n items: filteredOptions,\n itemTextClassName,\n listItemHeight,\n optionRender,\n renderVirtualItem: virtualState.renderVirtualItem,\n virtual,\n })\n );\n\n return (\n <BaseSelect.Root\n disabled={disabled}\n id={id}\n modal={isItemAligned}\n multiple={isMultiple}\n name={name}\n open={mergedOpen}\n readOnly={readOnly}\n required={required}\n value={normalizedValue}\n onOpenChange={handleOpenChange}\n onValueChange={handleRootValueChange}\n >\n <BaseSelect.Trigger\n autoFocus={!isTags && autoFocus}\n className={triggerClassName}\n disabled={disabled}\n nativeButton={!isTags}\n render={isTags ? <div /> : undefined}\n style={style}\n >\n {prefixNode !== null && prefixNode !== undefined && (\n <span className={cx(styles.prefix, classNames?.prefix)}>{prefixNode}</span>\n )}\n <BaseSelect.Value\n className={cx(styles.value, isTags && styles.tagsValue, classNames?.value)}\n >\n {renderValue}\n </BaseSelect.Value>\n {isTags && (\n <SelectSearchInput\n inline\n autoFocus={autoFocus}\n classNames={classNames}\n disabled={disabled}\n placeholder={valueArray.length === 0 ? placeholder : undefined}\n readOnly={readOnly}\n stopPropagation={stopSearchPropagation}\n value={searchValue}\n onChange={handleSearchChange}\n onKeyDown={handleSearchKeyDown}\n />\n )}\n <SelectTriggerSuffix\n classNames={classNames}\n showClear={showClear}\n suffixIconNode={suffixIconNode}\n onClear={handleClear}\n />\n </BaseSelect.Trigger>\n\n <BaseSelect.Portal container={portalContainer}>\n <SelectPositioner\n align=\"start\"\n alignItemWithTrigger={isItemAligned}\n className={styles.positioner}\n side=\"bottom\"\n sideOffset={6}\n >\n <BaseSelect.Popup\n style={popupStyle}\n className={cx(\n menuStyles.popup,\n styles.popup,\n popupClassName,\n classNames?.popup,\n classNames?.dropdown,\n )}\n >\n {shouldShowSearch && !isTags && (\n <SelectSearchInput\n classNames={classNames}\n placeholder={placeholder}\n stopPropagation={stopSearchPropagation}\n value={searchValue}\n onChange={handleSearchChange}\n onKeyDown={handleSearchKeyDown}\n />\n )}\n <SelectListSection\n classNames={classNames}\n hasSearch={shouldShowSearch && !isTags}\n isEmpty={isEmpty}\n listContent={listContent}\n listItemHeight={listItemHeight}\n virtual={virtual}\n virtualState={virtualState}\n />\n </BaseSelect.Popup>\n </SelectPositioner>\n </BaseSelect.Portal>\n </BaseSelect.Root>\n );\n },\n);\n\nSelect.displayName = 'Select';\n\nexport default Select;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Select.mjs","names":["Select","menuStyles","styles","BaseSelect"],"sources":["../../../src/base-ui/Select/Select.tsx"],"sourcesContent":["'use client';\n\nimport { Select as BaseSelect } from '@base-ui/react/select';\nimport { cx, useThemeMode } from 'antd-style';\nimport { type MouseEvent } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { styles as menuStyles } from '@/base-ui/DropdownMenu/sharedStyle';\n\nimport { SelectPositioner } from './atoms';\nimport { isValueEmpty } from './helpers';\nimport {\n usePortalContainer,\n useSelectOpen,\n useSelectSearch,\n useSelectValue,\n useSelectVirtual,\n} from './hooks';\nimport {\n createTriggerValueRenderer,\n EmptyContent,\n resolveIconNode,\n resolveSuffixIcon,\n SelectListSection,\n SelectSearchInput,\n SelectTriggerSuffix,\n} from './parts';\nimport { renderOptions } from './renderOptions';\nimport { styles, triggerVariants } from './style';\nimport { type SelectOption, type SelectProps } from './type';\n\nconst Select = memo<SelectProps<any>>(\n ({\n allowClear,\n autoFocus,\n className,\n classNames,\n defaultOpen,\n defaultValue,\n disabled,\n id,\n labelRender,\n listHeight = 512,\n listItemHeight,\n loading,\n mode,\n name,\n onChange,\n onOpenChange,\n onSelect,\n open,\n optionRender,\n options,\n placeholder,\n popupClassName,\n popupMatchSelectWidth,\n prefix,\n readOnly,\n required,\n behaviorVariant = 'default',\n selectedIndicatorVariant = 'check',\n shadow,\n showSearch,\n size = 'middle',\n style,\n suffixIcon,\n suffixIconProps,\n tokenSeparators,\n value,\n variant,\n virtual,\n }) => {\n const { isDarkMode } = useThemeMode();\n const resolvedVariant = variant ?? (isDarkMode ? 'filled' : 'outlined');\n const isTags = mode === 'tags';\n const isMultiple = mode === 'multiple' || mode === 'tags';\n const isItemAligned = behaviorVariant === 'item-aligned';\n\n const [extraOptions, setExtraOptions] = useState<SelectOption<any>[]>([]);\n\n useEffect(() => {\n if (mode !== 'tags' && extraOptions.length > 0) {\n setExtraOptions([]);\n }\n }, [mode, extraOptions.length]);\n\n const {\n appendTagValues,\n getOption,\n handleValueChange,\n normalizedValue,\n normalizeValue,\n removeLastTagValue,\n resolvedOptions,\n valueArray,\n } = useSelectValue({\n defaultValue,\n extraOptions,\n isMultiple,\n onChange,\n onSelect,\n options,\n setExtraOptions,\n value,\n });\n\n const { handleOpenChange, mergedOpen } = useSelectOpen({ defaultOpen, onOpenChange, open });\n\n const handleRootValueChange = useCallback(\n (nextValue: any) => {\n if (!(isTags && !mergedOpen)) handleValueChange(nextValue);\n },\n [handleValueChange, isTags, mergedOpen],\n );\n\n const handleRemoveTag = useCallback(\n (index: number) =>\n handleValueChange(valueArray.filter((_, itemIndex) => itemIndex !== index)),\n [handleValueChange, valueArray],\n );\n\n const {\n filteredOptions,\n handleSearchChange,\n handleSearchKeyDown,\n searchValue,\n shouldShowSearch,\n stopSearchPropagation,\n } = useSelectSearch({\n appendTagValues,\n handleOpenChange,\n mergedOpen,\n mode,\n removeLastTagValue,\n resolvedOptions,\n showSearch,\n tokenSeparators,\n });\n\n const virtualState = useSelectVirtual({\n filteredOptions,\n listItemHeight,\n size,\n valueArray,\n virtual,\n });\n\n const portalContainer = usePortalContainer();\n\n const renderValue = useMemo(\n () =>\n createTriggerValueRenderer({\n getOption,\n isMultiple,\n isTags,\n labelRender,\n normalizeValue,\n onRemoveValue: handleRemoveTag,\n placeholder: isTags ? undefined : placeholder,\n }),\n [getOption, handleRemoveTag, isMultiple, isTags, labelRender, normalizeValue, placeholder],\n );\n\n const hasValue = isMultiple ? valueArray.length > 0 : !isValueEmpty(normalizedValue);\n const showClear = Boolean(allowClear && hasValue && !disabled && !readOnly);\n\n const handleClear = useCallback(\n (event: MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n handleValueChange(isMultiple ? [] : null);\n },\n [handleValueChange, isMultiple],\n );\n\n const prefixNode = useMemo(() => resolveIconNode(prefix), [prefix]);\n const suffixIconNode = useMemo(\n () => resolveSuffixIcon(suffixIcon, suffixIconProps, loading),\n [loading, suffixIcon, suffixIconProps],\n );\n\n const popupStyle = useMemo(() => {\n const maxHeight = isItemAligned ? '80vh' : `${listHeight}px`;\n const baseStyle: React.CSSProperties = {\n maxWidth: 'var(--available-width)',\n minWidth: 'var(--anchor-width)',\n ['--lobe-select-popup-max-height' as any]: maxHeight,\n };\n\n if (popupMatchSelectWidth === undefined || popupMatchSelectWidth === true) {\n return baseStyle;\n }\n if (typeof popupMatchSelectWidth === 'number') {\n return {\n ...baseStyle,\n minWidth: popupMatchSelectWidth,\n width: popupMatchSelectWidth,\n };\n }\n return { ...baseStyle, minWidth: 'max-content' };\n }, [isItemAligned, listHeight, popupMatchSelectWidth]);\n\n const triggerClassName = cx(\n triggerVariants({ shadow, size, variant: resolvedVariant }),\n className,\n classNames?.root,\n classNames?.trigger,\n );\n\n const isBoldIndicator = selectedIndicatorVariant === 'bold';\n const itemTextClassName = cx(\n optionRender ? menuStyles.itemContent : menuStyles.label,\n styles.itemText,\n classNames?.itemText,\n );\n\n const isEmpty = filteredOptions.length === 0;\n const listContent = isEmpty ? (\n <EmptyContent classNames={classNames} />\n ) : (\n renderOptions({\n classNames,\n isBoldIndicator,\n items: filteredOptions,\n itemTextClassName,\n listItemHeight,\n optionRender,\n })\n );\n\n return (\n <BaseSelect.Root\n disabled={disabled}\n id={id}\n modal={isItemAligned}\n multiple={isMultiple}\n name={name}\n open={mergedOpen}\n readOnly={readOnly}\n required={required}\n value={normalizedValue}\n onOpenChange={handleOpenChange}\n onValueChange={handleRootValueChange}\n >\n <BaseSelect.Trigger\n autoFocus={!isTags && autoFocus}\n className={triggerClassName}\n disabled={disabled}\n nativeButton={!isTags}\n render={isTags ? <div /> : undefined}\n style={style}\n >\n {prefixNode !== null && prefixNode !== undefined && (\n <span className={cx(styles.prefix, classNames?.prefix)}>{prefixNode}</span>\n )}\n <BaseSelect.Value\n className={cx(styles.value, isTags && styles.tagsValue, classNames?.value)}\n >\n {renderValue}\n </BaseSelect.Value>\n {isTags && (\n <SelectSearchInput\n inline\n autoFocus={autoFocus}\n classNames={classNames}\n disabled={disabled}\n placeholder={valueArray.length === 0 ? placeholder : undefined}\n readOnly={readOnly}\n stopPropagation={stopSearchPropagation}\n value={searchValue}\n onChange={handleSearchChange}\n onKeyDown={handleSearchKeyDown}\n />\n )}\n <SelectTriggerSuffix\n classNames={classNames}\n showClear={showClear}\n suffixIconNode={suffixIconNode}\n onClear={handleClear}\n />\n </BaseSelect.Trigger>\n\n <BaseSelect.Portal container={portalContainer}>\n <SelectPositioner\n align=\"start\"\n alignItemWithTrigger={isItemAligned}\n className={styles.positioner}\n side=\"bottom\"\n sideOffset={6}\n >\n <BaseSelect.Popup\n style={popupStyle}\n className={cx(\n menuStyles.popup,\n styles.popup,\n popupClassName,\n classNames?.popup,\n classNames?.dropdown,\n )}\n >\n {shouldShowSearch && !isTags && (\n <SelectSearchInput\n classNames={classNames}\n placeholder={placeholder}\n stopPropagation={stopSearchPropagation}\n value={searchValue}\n onChange={handleSearchChange}\n onKeyDown={handleSearchKeyDown}\n />\n )}\n <SelectListSection\n classNames={classNames}\n hasSearch={shouldShowSearch && !isTags}\n isEmpty={isEmpty}\n listContent={listContent}\n listItemHeight={listItemHeight}\n virtual={virtual}\n virtualState={virtualState}\n />\n </BaseSelect.Popup>\n </SelectPositioner>\n </BaseSelect.Portal>\n </BaseSelect.Root>\n );\n },\n);\n\nSelect.displayName = 'Select';\n\nexport default Select;\n"],"mappings":"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"}
@@ -2,7 +2,6 @@
2
2
  import { useAppElement } from "../../ThemeProvider/AppElementContext.mjs";
3
3
  import { countVirtualItems, getOptionSearchText, isGroupOption, isValueEmpty, normalizeValueFor, splitBySeparators } from "./helpers.mjs";
4
4
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
- import { jsx } from "react/jsx-runtime";
6
5
  //#region src/base-ui/Select/hooks.tsx
7
6
  function useSelectValue({ defaultValue, extraOptions, isMultiple, onChange, onSelect, options, setExtraOptions, value }) {
8
7
  const [uncontrolledValue, setUncontrolledValue] = useState(() => {
@@ -217,40 +216,6 @@ function useSelectSearch({ appendTagValues, handleOpenChange, mergedOpen, mode,
217
216
  };
218
217
  }
219
218
  function useSelectVirtual({ filteredOptions, listItemHeight, size, valueArray, virtual }) {
220
- const listRef = useRef(null);
221
- const pointerScrollRef = useRef(false);
222
- const pointerScrollTimeoutRef = useRef(null);
223
- const renderVirtualItem = useCallback((props) => {
224
- const { ref, ...rest } = props;
225
- return /* @__PURE__ */ jsx("div", {
226
- ...rest,
227
- ref: (node) => {
228
- if (node) node.scrollIntoView = (...args) => {
229
- if (!pointerScrollRef.current) HTMLElement.prototype.scrollIntoView.call(node, ...args);
230
- };
231
- if (typeof ref === "function") ref(node);
232
- else if (ref && "current" in ref) ref.current = node;
233
- }
234
- });
235
- }, []);
236
- const markPointerScroll = useCallback(() => {
237
- pointerScrollRef.current = true;
238
- if (pointerScrollTimeoutRef.current) clearTimeout(pointerScrollTimeoutRef.current);
239
- pointerScrollTimeoutRef.current = setTimeout(() => {
240
- pointerScrollRef.current = false;
241
- }, 120);
242
- }, []);
243
- const handleListScroll = useCallback(() => {
244
- if (!virtual || !pointerScrollRef.current) return;
245
- const listElement = listRef.current;
246
- const activeElement = document.activeElement;
247
- if (listElement && activeElement && listElement.contains(activeElement)) listElement.focus({ preventScroll: true });
248
- }, [virtual]);
249
- useEffect(() => {
250
- return () => {
251
- if (pointerScrollTimeoutRef.current) clearTimeout(pointerScrollTimeoutRef.current);
252
- };
253
- }, []);
254
219
  const virtualListStyle = useMemo(() => {
255
220
  if (!virtual) return void 0;
256
221
  const rowCount = countVirtualItems(filteredOptions);
@@ -262,8 +227,7 @@ function useSelectVirtual({ filteredOptions, listItemHeight, size, valueArray, v
262
227
  virtual
263
228
  ]);
264
229
  return {
265
- handleListScroll,
266
- keepMountedIndices: useMemo(() => {
230
+ selectedIndices: useMemo(() => {
267
231
  if (!virtual || valueArray.length === 0) return void 0;
268
232
  const selectedSet = new Set(valueArray);
269
233
  const indices = [];
@@ -283,9 +247,6 @@ function useSelectVirtual({ filteredOptions, listItemHeight, size, valueArray, v
283
247
  valueArray,
284
248
  virtual
285
249
  ]),
286
- listRef,
287
- markPointerScroll,
288
- renderVirtualItem,
289
250
  virtualListStyle
290
251
  };
291
252
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.mjs","names":[],"sources":["../../../src/base-ui/Select/hooks.tsx"],"sourcesContent":["'use client';\n\nimport {\n type ChangeEvent,\n type HTMLAttributes,\n type KeyboardEvent,\n type MutableRefObject,\n type Ref,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { useAppElement } from '@/ThemeProvider';\n\nimport {\n countVirtualItems,\n getOptionSearchText,\n isGroupOption,\n isValueEmpty,\n normalizeValueFor,\n splitBySeparators,\n} from './helpers';\nimport {\n type SelectOption,\n type SelectOptions,\n type SelectProps,\n type SelectRootChangeEventDetails,\n type SelectSize,\n} from './type';\n\ninterface UseSelectValueParams {\n defaultValue: SelectProps['defaultValue'];\n extraOptions: SelectOption<any>[];\n isMultiple: boolean;\n onChange: SelectProps['onChange'];\n onSelect: SelectProps['onSelect'];\n options: SelectOptions<any> | undefined;\n setExtraOptions: React.Dispatch<React.SetStateAction<SelectOption<any>[]>>;\n value: SelectProps['value'];\n}\n\nexport function useSelectValue({\n defaultValue,\n extraOptions,\n isMultiple,\n onChange,\n onSelect,\n options,\n setExtraOptions,\n value,\n}: UseSelectValueParams) {\n const [uncontrolledValue, setUncontrolledValue] = useState<any>(() => {\n if (defaultValue !== undefined) return defaultValue;\n return isMultiple ? [] : null;\n });\n\n const normalizeValue = useMemo(() => normalizeValueFor(isMultiple), [isMultiple]);\n\n const mergedValue = value !== undefined ? value : uncontrolledValue;\n const normalizedValue = useMemo(() => normalizeValue(mergedValue), [mergedValue, normalizeValue]);\n\n const valueArray = useMemo(() => {\n if (isMultiple) return normalizedValue as any[];\n return isValueEmpty(normalizedValue) ? [] : [normalizedValue];\n }, [isMultiple, normalizedValue]);\n\n const { optionMap, resolvedOptions } = useMemo(() => {\n const baseOptions = options ?? [];\n const optionValueMap = new Map<any, SelectOption<any>>();\n\n const addOption = (item: SelectOption<any>) => {\n if (!optionValueMap.has(item.value)) {\n optionValueMap.set(item.value, item);\n }\n };\n\n baseOptions.forEach((item) => {\n if (isGroupOption(item)) {\n item.options.forEach(addOption);\n } else {\n addOption(item);\n }\n });\n\n const filteredExtraOptions = extraOptions.filter((item) => !optionValueMap.has(item.value));\n filteredExtraOptions.forEach(addOption);\n const mergedOptions: SelectOptions<any> = [...baseOptions, ...filteredExtraOptions];\n\n const missingValueOptions: SelectOption<any>[] = valueArray\n .filter((val) => !optionValueMap.has(val))\n .map((val) => ({ label: String(val), value: val }));\n missingValueOptions.forEach(addOption);\n\n return {\n optionMap: optionValueMap,\n resolvedOptions: missingValueOptions.length\n ? [...mergedOptions, ...missingValueOptions]\n : mergedOptions,\n };\n }, [extraOptions, options, valueArray]);\n\n const getOption = useCallback(\n (optionValue: any): SelectOption<any> => {\n const matched = optionMap.get(optionValue);\n if (matched) return matched;\n if (optionValue && typeof optionValue === 'object' && 'label' in optionValue) {\n return { label: (optionValue as any).label, value: optionValue };\n }\n return { label: String(optionValue), value: optionValue };\n },\n [optionMap],\n );\n\n const previousValueRef = useRef<any>(normalizedValue);\n useEffect(() => {\n previousValueRef.current = normalizedValue;\n }, [normalizedValue]);\n\n const handleValueChange = useCallback(\n (nextValue: any) => {\n const normalizedNextValue = normalizeValue(nextValue);\n const previousValue = previousValueRef.current;\n\n if (isMultiple) {\n const prevValues = Array.isArray(previousValue) ? previousValue : [];\n const nextValues = Array.isArray(normalizedNextValue) ? normalizedNextValue : [];\n const addedValues = nextValues.filter(\n (val) => !prevValues.some((prev) => Object.is(prev, val)),\n );\n addedValues.forEach((val) => onSelect?.(val, getOption(val)));\n\n if (value === undefined) setUncontrolledValue(nextValues);\n onChange?.(\n nextValues,\n nextValues.map((val) => getOption(val)),\n );\n } else {\n if (!isValueEmpty(normalizedNextValue) && !Object.is(previousValue, normalizedNextValue)) {\n onSelect?.(normalizedNextValue, getOption(normalizedNextValue));\n }\n if (value === undefined) setUncontrolledValue(normalizedNextValue);\n onChange?.(\n isValueEmpty(normalizedNextValue) ? undefined : normalizedNextValue,\n isValueEmpty(normalizedNextValue) ? undefined : getOption(normalizedNextValue),\n );\n }\n\n previousValueRef.current = normalizedNextValue;\n },\n [getOption, isMultiple, normalizeValue, onChange, onSelect, value],\n );\n\n const appendTagValues = useCallback(\n (rawValues: string[]) => {\n const valuesToAdd = rawValues.map((val) => val.trim()).filter(Boolean);\n if (!valuesToAdd.length) return;\n\n const currentValues = Array.isArray(previousValueRef.current)\n ? previousValueRef.current\n : valueArray;\n const nextValues = [...currentValues];\n const newOptionValues = valuesToAdd.filter((val) => !optionMap.has(val));\n\n if (newOptionValues.length > 0) {\n setExtraOptions((prev) => {\n const existingValues = new Set(prev.map((item) => item.value));\n const merged = [...prev];\n newOptionValues.forEach((val) => {\n if (!existingValues.has(val)) {\n merged.push({ label: val, value: val });\n }\n });\n return merged;\n });\n }\n\n valuesToAdd.forEach((val) => {\n if (!nextValues.some((item) => Object.is(item, val))) {\n nextValues.push(val);\n }\n });\n\n if (nextValues.length !== valueArray.length) {\n handleValueChange(nextValues);\n }\n },\n [handleValueChange, optionMap, setExtraOptions, valueArray],\n );\n\n const removeLastTagValue = useCallback(() => {\n const currentValues = Array.isArray(previousValueRef.current)\n ? previousValueRef.current\n : valueArray;\n if (currentValues.length > 0) handleValueChange(currentValues.slice(0, -1));\n }, [handleValueChange, valueArray]);\n\n return {\n appendTagValues,\n getOption,\n handleValueChange,\n normalizedValue,\n normalizeValue,\n optionMap,\n resolvedOptions,\n removeLastTagValue,\n valueArray,\n };\n}\n\ninterface UseSelectOpenParams {\n defaultOpen: boolean | undefined;\n onOpenChange: SelectProps['onOpenChange'];\n open: boolean | undefined;\n}\n\nexport function useSelectOpen({ defaultOpen, onOpenChange, open }: UseSelectOpenParams) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));\n\n useEffect(() => {\n if (open !== undefined) setUncontrolledOpen(open);\n }, [open]);\n\n const mergedOpen = open ?? uncontrolledOpen;\n\n const handleOpenChange = useCallback(\n (nextOpen: boolean, eventDetails?: SelectRootChangeEventDetails) => {\n onOpenChange?.(nextOpen, eventDetails);\n if (open === undefined) setUncontrolledOpen(nextOpen);\n },\n [onOpenChange, open],\n );\n\n return { handleOpenChange, mergedOpen };\n}\n\ninterface UseSelectSearchParams {\n appendTagValues: (values: string[]) => void;\n handleOpenChange: (nextOpen: boolean) => void;\n mergedOpen: boolean;\n mode: SelectProps['mode'];\n removeLastTagValue: () => void;\n resolvedOptions: SelectOptions;\n showSearch: boolean | undefined;\n tokenSeparators: string[] | undefined;\n}\n\nexport function useSelectSearch({\n appendTagValues,\n handleOpenChange,\n mergedOpen,\n mode,\n removeLastTagValue,\n resolvedOptions,\n showSearch,\n tokenSeparators,\n}: UseSelectSearchParams) {\n const [searchValue, setSearchValue] = useState('');\n const shouldShowSearch = Boolean(showSearch || mode === 'tags');\n\n useEffect(() => {\n if (!mergedOpen) setSearchValue('');\n }, [mergedOpen]);\n\n const handleSearchChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n const nextValue = event.target.value;\n if (mode === 'tags') {\n const parts = splitBySeparators(nextValue, tokenSeparators);\n if (parts.length > 1) {\n const pending = parts.pop() ?? '';\n appendTagValues(parts.filter(Boolean));\n setSearchValue(pending);\n return;\n }\n }\n setSearchValue(nextValue);\n },\n [appendTagValues, mode, tokenSeparators],\n );\n\n const handleSearchKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n event.stopPropagation();\n\n if (event.key === 'Escape') {\n handleOpenChange(false);\n return;\n }\n if (mode !== 'tags') return;\n\n if (event.key === 'Backspace' && !searchValue) {\n event.preventDefault();\n removeLastTagValue();\n return;\n }\n\n const isSeparator = tokenSeparators?.includes(event.key);\n if (event.key === 'Enter' || isSeparator) {\n event.preventDefault();\n event.stopPropagation();\n appendTagValues([searchValue]);\n setSearchValue('');\n }\n },\n [appendTagValues, handleOpenChange, mode, removeLastTagValue, searchValue, tokenSeparators],\n );\n\n // Stop propagation in capture phase + on keyup to block base-ui Popup-level\n // `useTypeahead` (and any ancestor typeahead) from hijacking the search\n // input's first-letter focus behavior. Do not remove.\n const stopSearchPropagation = useCallback((event: KeyboardEvent<HTMLInputElement>) => {\n event.stopPropagation();\n }, []);\n\n const filteredOptions = useMemo(() => {\n if (!shouldShowSearch || !searchValue.trim()) return resolvedOptions;\n const query = searchValue.trim().toLowerCase();\n\n return resolvedOptions\n .map((item) => {\n if (isGroupOption(item)) {\n const groupItems = item.options.filter((option) =>\n getOptionSearchText(option).toLowerCase().includes(query),\n );\n if (!groupItems.length) return null;\n return { ...item, options: groupItems };\n }\n return getOptionSearchText(item).toLowerCase().includes(query) ? item : null;\n })\n .filter(Boolean) as SelectOptions;\n }, [resolvedOptions, searchValue, shouldShowSearch]);\n\n return {\n filteredOptions,\n handleSearchChange,\n handleSearchKeyDown,\n searchValue,\n shouldShowSearch,\n stopSearchPropagation,\n };\n}\n\ninterface UseSelectVirtualParams {\n filteredOptions: SelectOptions;\n listItemHeight: number | undefined;\n size: SelectSize;\n valueArray: any[];\n virtual: boolean | undefined;\n}\n\nexport function useSelectVirtual({\n filteredOptions,\n listItemHeight,\n size,\n valueArray,\n virtual,\n}: UseSelectVirtualParams) {\n const listRef = useRef<HTMLDivElement | null>(null);\n const pointerScrollRef = useRef(false);\n const pointerScrollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const renderVirtualItem = useCallback((props: HTMLAttributes<HTMLDivElement>) => {\n const { ref, ...rest } = props as HTMLAttributes<HTMLDivElement> & {\n ref?: Ref<HTMLDivElement>;\n };\n\n return (\n <div\n {...rest}\n ref={(node) => {\n if (node) {\n node.scrollIntoView = (...args) => {\n if (!pointerScrollRef.current) {\n HTMLElement.prototype.scrollIntoView.call(node, ...args);\n }\n };\n }\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref && 'current' in ref) {\n (ref as MutableRefObject<HTMLDivElement | null>).current = node;\n }\n }}\n />\n );\n }, []);\n\n const markPointerScroll = useCallback(() => {\n pointerScrollRef.current = true;\n if (pointerScrollTimeoutRef.current) {\n clearTimeout(pointerScrollTimeoutRef.current);\n }\n pointerScrollTimeoutRef.current = setTimeout(() => {\n pointerScrollRef.current = false;\n }, 120);\n }, []);\n\n const handleListScroll = useCallback(() => {\n if (!virtual || !pointerScrollRef.current) return;\n const listElement = listRef.current;\n const activeElement = document.activeElement;\n if (listElement && activeElement && listElement.contains(activeElement)) {\n listElement.focus({ preventScroll: true });\n }\n }, [virtual]);\n\n useEffect(() => {\n return () => {\n if (pointerScrollTimeoutRef.current) {\n clearTimeout(pointerScrollTimeoutRef.current);\n }\n };\n }, []);\n\n const virtualListStyle = useMemo(() => {\n if (!virtual) return undefined;\n const rowCount = countVirtualItems(filteredOptions);\n const maxVisibleRows = 6;\n const estimatedRowHeight =\n listItemHeight ?? (size === 'large' ? 40 : size === 'small' ? 28 : 32);\n const visibleRows = Math.min(Math.max(rowCount, 1), maxVisibleRows);\n const estimatedHeight = visibleRows * estimatedRowHeight + 8;\n\n return {\n height: `min(${estimatedHeight}px, var(--lobe-select-available-height, var(--available-height)))`,\n };\n }, [filteredOptions, listItemHeight, size, virtual]);\n\n const keepMountedIndices = useMemo(() => {\n if (!virtual || valueArray.length === 0) return undefined;\n const selectedSet = new Set(valueArray);\n const indices: number[] = [];\n let index = 0;\n\n filteredOptions.forEach((item) => {\n if (isGroupOption(item)) {\n if (item.options.some((option) => selectedSet.has(option.value))) {\n indices.push(index);\n }\n index += 1;\n return;\n }\n if (selectedSet.has(item.value)) indices.push(index);\n index += 1;\n });\n\n return indices.length ? indices : undefined;\n }, [filteredOptions, valueArray, virtual]);\n\n return {\n handleListScroll,\n keepMountedIndices,\n listRef,\n markPointerScroll,\n renderVirtualItem,\n virtualListStyle,\n };\n}\n\nexport function usePortalContainer() {\n const appElement = useAppElement();\n // `appElement` is the ThemeProvider wrapper div, which uses `display: contents`\n // so it has no layout box. `@base-ui/react/select` fails to mount its Popup\n // into a `display: contents` container in certain hosts (editor/chat inputs\n // with focus traps). Fall back to `document.body` in that case; keep the\n // original behavior when the wrapper has a real layout (older themes, SSR\n // snapshot, etc.).\n return useMemo(() => {\n if (typeof window === 'undefined') return appElement;\n if (!(appElement instanceof HTMLElement)) return undefined;\n const display = window.getComputedStyle(appElement).display;\n return display === 'contents' ? document.body : appElement;\n }, [appElement]);\n}\n"],"mappings":";;;;;;AA4CA,SAAgB,eAAe,EAC7B,cACA,cACA,YACA,UACA,UACA,SACA,iBACA,SACuB;CACvB,MAAM,CAAC,mBAAmB,wBAAwB,eAAoB;EACpE,IAAI,iBAAiB,KAAA,GAAW,OAAO;EACvC,OAAO,aAAa,CAAC,IAAI;CAC3B,CAAC;CAED,MAAM,iBAAiB,cAAc,kBAAkB,UAAU,GAAG,CAAC,UAAU,CAAC;CAEhF,MAAM,cAAc,UAAU,KAAA,IAAY,QAAQ;CAClD,MAAM,kBAAkB,cAAc,eAAe,WAAW,GAAG,CAAC,aAAa,cAAc,CAAC;CAEhG,MAAM,aAAa,cAAc;EAC/B,IAAI,YAAY,OAAO;EACvB,OAAO,aAAa,eAAe,IAAI,CAAC,IAAI,CAAC,eAAe;CAC9D,GAAG,CAAC,YAAY,eAAe,CAAC;CAEhC,MAAM,EAAE,WAAW,oBAAoB,cAAc;EACnD,MAAM,cAAc,WAAW,CAAC;EAChC,MAAM,iCAAiB,IAAI,IAA4B;EAEvD,MAAM,aAAa,SAA4B;GAC7C,IAAI,CAAC,eAAe,IAAI,KAAK,KAAK,GAChC,eAAe,IAAI,KAAK,OAAO,IAAI;EAEvC;EAEA,YAAY,SAAS,SAAS;GAC5B,IAAI,cAAc,IAAI,GACpB,KAAK,QAAQ,QAAQ,SAAS;QAE9B,UAAU,IAAI;EAElB,CAAC;EAED,MAAM,uBAAuB,aAAa,QAAQ,SAAS,CAAC,eAAe,IAAI,KAAK,KAAK,CAAC;EAC1F,qBAAqB,QAAQ,SAAS;EACtC,MAAM,gBAAoC,CAAC,GAAG,aAAa,GAAG,oBAAoB;EAElF,MAAM,sBAA2C,WAC9C,QAAQ,QAAQ,CAAC,eAAe,IAAI,GAAG,CAAC,CAAC,CACzC,KAAK,SAAS;GAAE,OAAO,OAAO,GAAG;GAAG,OAAO;EAAI,EAAE;EACpD,oBAAoB,QAAQ,SAAS;EAErC,OAAO;GACL,WAAW;GACX,iBAAiB,oBAAoB,SACjC,CAAC,GAAG,eAAe,GAAG,mBAAmB,IACzC;EACN;CACF,GAAG;EAAC;EAAc;EAAS;CAAU,CAAC;CAEtC,MAAM,YAAY,aACf,gBAAwC;EACvC,MAAM,UAAU,UAAU,IAAI,WAAW;EACzC,IAAI,SAAS,OAAO;EACpB,IAAI,eAAe,OAAO,gBAAgB,YAAY,WAAW,aAC/D,OAAO;GAAE,OAAQ,YAAoB;GAAO,OAAO;EAAY;EAEjE,OAAO;GAAE,OAAO,OAAO,WAAW;GAAG,OAAO;EAAY;CAC1D,GACA,CAAC,SAAS,CACZ;CAEA,MAAM,mBAAmB,OAAY,eAAe;CACpD,gBAAgB;EACd,iBAAiB,UAAU;CAC7B,GAAG,CAAC,eAAe,CAAC;CAEpB,MAAM,oBAAoB,aACvB,cAAmB;EAClB,MAAM,sBAAsB,eAAe,SAAS;EACpD,MAAM,gBAAgB,iBAAiB;EAEvC,IAAI,YAAY;GACd,MAAM,aAAa,MAAM,QAAQ,aAAa,IAAI,gBAAgB,CAAC;GACnE,MAAM,aAAa,MAAM,QAAQ,mBAAmB,IAAI,sBAAsB,CAAC;GAI/E,WAH+B,QAC5B,QAAQ,CAAC,WAAW,MAAM,SAAS,OAAO,GAAG,MAAM,GAAG,CAAC,CAEhD,CAAC,CAAC,SAAS,QAAQ,WAAW,KAAK,UAAU,GAAG,CAAC,CAAC;GAE5D,IAAI,UAAU,KAAA,GAAW,qBAAqB,UAAU;GACxD,WACE,YACA,WAAW,KAAK,QAAQ,UAAU,GAAG,CAAC,CACxC;EACF,OAAO;GACL,IAAI,CAAC,aAAa,mBAAmB,KAAK,CAAC,OAAO,GAAG,eAAe,mBAAmB,GACrF,WAAW,qBAAqB,UAAU,mBAAmB,CAAC;GAEhE,IAAI,UAAU,KAAA,GAAW,qBAAqB,mBAAmB;GACjE,WACE,aAAa,mBAAmB,IAAI,KAAA,IAAY,qBAChD,aAAa,mBAAmB,IAAI,KAAA,IAAY,UAAU,mBAAmB,CAC/E;EACF;EAEA,iBAAiB,UAAU;CAC7B,GACA;EAAC;EAAW;EAAY;EAAgB;EAAU;EAAU;CAAK,CACnE;CA8CA,OAAO;EACL,iBA7CsB,aACrB,cAAwB;GACvB,MAAM,cAAc,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO;GACrE,IAAI,CAAC,YAAY,QAAQ;GAKzB,MAAM,aAAa,CAAC,GAHE,MAAM,QAAQ,iBAAiB,OAAO,IACxD,iBAAiB,UACjB,UACgC;GACpC,MAAM,kBAAkB,YAAY,QAAQ,QAAQ,CAAC,UAAU,IAAI,GAAG,CAAC;GAEvE,IAAI,gBAAgB,SAAS,GAC3B,iBAAiB,SAAS;IACxB,MAAM,iBAAiB,IAAI,IAAI,KAAK,KAAK,SAAS,KAAK,KAAK,CAAC;IAC7D,MAAM,SAAS,CAAC,GAAG,IAAI;IACvB,gBAAgB,SAAS,QAAQ;KAC/B,IAAI,CAAC,eAAe,IAAI,GAAG,GACzB,OAAO,KAAK;MAAE,OAAO;MAAK,OAAO;KAAI,CAAC;IAE1C,CAAC;IACD,OAAO;GACT,CAAC;GAGH,YAAY,SAAS,QAAQ;IAC3B,IAAI,CAAC,WAAW,MAAM,SAAS,OAAO,GAAG,MAAM,GAAG,CAAC,GACjD,WAAW,KAAK,GAAG;GAEvB,CAAC;GAED,IAAI,WAAW,WAAW,WAAW,QACnC,kBAAkB,UAAU;EAEhC,GACA;GAAC;GAAmB;GAAW;GAAiB;EAAU,CAW5C;EACd;EACA;EACA;EACA;EACA;EACA;EACA,oBAfyB,kBAAkB;GAC3C,MAAM,gBAAgB,MAAM,QAAQ,iBAAiB,OAAO,IACxD,iBAAiB,UACjB;GACJ,IAAI,cAAc,SAAS,GAAG,kBAAkB,cAAc,MAAM,GAAG,EAAE,CAAC;EAC5E,GAAG,CAAC,mBAAmB,UAAU,CAUd;EACjB;CACF;AACF;AAQA,SAAgB,cAAc,EAAE,aAAa,cAAc,QAA6B;CACtF,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,QAAQ,WAAW,CAAC;CAE7E,gBAAgB;EACd,IAAI,SAAS,KAAA,GAAW,oBAAoB,IAAI;CAClD,GAAG,CAAC,IAAI,CAAC;CAET,MAAM,aAAa,QAAQ;CAU3B,OAAO;EAAE,kBARgB,aACtB,UAAmB,iBAAgD;GAClE,eAAe,UAAU,YAAY;GACrC,IAAI,SAAS,KAAA,GAAW,oBAAoB,QAAQ;EACtD,GACA,CAAC,cAAc,IAAI,CAGG;EAAG;CAAW;AACxC;AAaA,SAAgB,gBAAgB,EAC9B,iBACA,kBACA,YACA,MACA,oBACA,iBACA,YACA,mBACwB;CACxB,MAAM,CAAC,aAAa,kBAAkB,SAAS,EAAE;CACjD,MAAM,mBAAmB,QAAQ,cAAc,SAAS,MAAM;CAE9D,gBAAgB;EACd,IAAI,CAAC,YAAY,eAAe,EAAE;CACpC,GAAG,CAAC,UAAU,CAAC;CAEf,MAAM,qBAAqB,aACxB,UAAyC;EACxC,MAAM,YAAY,MAAM,OAAO;EAC/B,IAAI,SAAS,QAAQ;GACnB,MAAM,QAAQ,kBAAkB,WAAW,eAAe;GAC1D,IAAI,MAAM,SAAS,GAAG;IACpB,MAAM,UAAU,MAAM,IAAI,KAAK;IAC/B,gBAAgB,MAAM,OAAO,OAAO,CAAC;IACrC,eAAe,OAAO;IACtB;GACF;EACF;EACA,eAAe,SAAS;CAC1B,GACA;EAAC;EAAiB;EAAM;CAAe,CACzC;CAEA,MAAM,sBAAsB,aACzB,UAA2C;EAC1C,MAAM,gBAAgB;EAEtB,IAAI,MAAM,QAAQ,UAAU;GAC1B,iBAAiB,KAAK;GACtB;EACF;EACA,IAAI,SAAS,QAAQ;EAErB,IAAI,MAAM,QAAQ,eAAe,CAAC,aAAa;GAC7C,MAAM,eAAe;GACrB,mBAAmB;GACnB;EACF;EAEA,MAAM,cAAc,iBAAiB,SAAS,MAAM,GAAG;EACvD,IAAI,MAAM,QAAQ,WAAW,aAAa;GACxC,MAAM,eAAe;GACrB,MAAM,gBAAgB;GACtB,gBAAgB,CAAC,WAAW,CAAC;GAC7B,eAAe,EAAE;EACnB;CACF,GACA;EAAC;EAAiB;EAAkB;EAAM;EAAoB;EAAa;CAAe,CAC5F;CAKA,MAAM,wBAAwB,aAAa,UAA2C;EACpF,MAAM,gBAAgB;CACxB,GAAG,CAAC,CAAC;CAoBL,OAAO;EACL,iBAnBsB,cAAc;GACpC,IAAI,CAAC,oBAAoB,CAAC,YAAY,KAAK,GAAG,OAAO;GACrD,MAAM,QAAQ,YAAY,KAAK,CAAC,CAAC,YAAY;GAE7C,OAAO,gBACJ,KAAK,SAAS;IACb,IAAI,cAAc,IAAI,GAAG;KACvB,MAAM,aAAa,KAAK,QAAQ,QAAQ,WACtC,oBAAoB,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,KAAK,CAC1D;KACA,IAAI,CAAC,WAAW,QAAQ,OAAO;KAC/B,OAAO;MAAE,GAAG;MAAM,SAAS;KAAW;IACxC;IACA,OAAO,oBAAoB,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,KAAK,IAAI,OAAO;GAC1E,CAAC,CAAC,CACD,OAAO,OAAO;EACnB,GAAG;GAAC;GAAiB;GAAa;EAAgB,CAGlC;EACd;EACA;EACA;EACA;EACA;CACF;AACF;AAUA,SAAgB,iBAAiB,EAC/B,iBACA,gBACA,MACA,YACA,WACyB;CACzB,MAAM,UAAU,OAA8B,IAAI;CAClD,MAAM,mBAAmB,OAAO,KAAK;CACrC,MAAM,0BAA0B,OAA6C,IAAI;CAEjF,MAAM,oBAAoB,aAAa,UAA0C;EAC/E,MAAM,EAAE,KAAK,GAAG,SAAS;EAIzB,OACE,oBAAC,OAAD;GACE,GAAI;GACJ,MAAM,SAAS;IACb,IAAI,MACF,KAAK,kBAAkB,GAAG,SAAS;KACjC,IAAI,CAAC,iBAAiB,SACpB,YAAY,UAAU,eAAe,KAAK,MAAM,GAAG,IAAI;IAE3D;IAEF,IAAI,OAAO,QAAQ,YACjB,IAAI,IAAI;SACH,IAAI,OAAO,aAAa,KAC7B,IAAiD,UAAU;GAE/D;EACD,CAAA;CAEL,GAAG,CAAC,CAAC;CAEL,MAAM,oBAAoB,kBAAkB;EAC1C,iBAAiB,UAAU;EAC3B,IAAI,wBAAwB,SAC1B,aAAa,wBAAwB,OAAO;EAE9C,wBAAwB,UAAU,iBAAiB;GACjD,iBAAiB,UAAU;EAC7B,GAAG,GAAG;CACR,GAAG,CAAC,CAAC;CAEL,MAAM,mBAAmB,kBAAkB;EACzC,IAAI,CAAC,WAAW,CAAC,iBAAiB,SAAS;EAC3C,MAAM,cAAc,QAAQ;EAC5B,MAAM,gBAAgB,SAAS;EAC/B,IAAI,eAAe,iBAAiB,YAAY,SAAS,aAAa,GACpE,YAAY,MAAM,EAAE,eAAe,KAAK,CAAC;CAE7C,GAAG,CAAC,OAAO,CAAC;CAEZ,gBAAgB;EACd,aAAa;GACX,IAAI,wBAAwB,SAC1B,aAAa,wBAAwB,OAAO;EAEhD;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,mBAAmB,cAAc;EACrC,IAAI,CAAC,SAAS,OAAO,KAAA;EACrB,MAAM,WAAW,kBAAkB,eAAe;EAOlD,OAAO,EACL,QAAQ,OAJU,KAAK,IAAI,KAAK,IAAI,UAAU,CAAC,GAAG,CAClB,KAFhC,mBAAmB,SAAS,UAAU,KAAK,SAAS,UAAU,KAAK,OAEV,EAG1B,mEACjC;CACF,GAAG;EAAC;EAAiB;EAAgB;EAAM;CAAO,CAAC;CAuBnD,OAAO;EACL;EACA,oBAvByB,cAAc;GACvC,IAAI,CAAC,WAAW,WAAW,WAAW,GAAG,OAAO,KAAA;GAChD,MAAM,cAAc,IAAI,IAAI,UAAU;GACtC,MAAM,UAAoB,CAAC;GAC3B,IAAI,QAAQ;GAEZ,gBAAgB,SAAS,SAAS;IAChC,IAAI,cAAc,IAAI,GAAG;KACvB,IAAI,KAAK,QAAQ,MAAM,WAAW,YAAY,IAAI,OAAO,KAAK,CAAC,GAC7D,QAAQ,KAAK,KAAK;KAEpB,SAAS;KACT;IACF;IACA,IAAI,YAAY,IAAI,KAAK,KAAK,GAAG,QAAQ,KAAK,KAAK;IACnD,SAAS;GACX,CAAC;GAED,OAAO,QAAQ,SAAS,UAAU,KAAA;EACpC,GAAG;GAAC;GAAiB;GAAY;EAAO,CAIrB;EACjB;EACA;EACA;EACA;CACF;AACF;AAEA,SAAgB,qBAAqB;CACnC,MAAM,aAAa,cAAc;CAOjC,OAAO,cAAc;EACnB,IAAI,OAAO,WAAW,aAAa,OAAO;EAC1C,IAAI,EAAE,sBAAsB,cAAc,OAAO,KAAA;EAEjD,OADgB,OAAO,iBAAiB,UAAU,CAAC,CAAC,YACjC,aAAa,SAAS,OAAO;CAClD,GAAG,CAAC,UAAU,CAAC;AACjB"}
1
+ {"version":3,"file":"hooks.mjs","names":[],"sources":["../../../src/base-ui/Select/hooks.tsx"],"sourcesContent":["'use client';\n\nimport {\n type ChangeEvent,\n type KeyboardEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { useAppElement } from '@/ThemeProvider';\n\nimport {\n countVirtualItems,\n getOptionSearchText,\n isGroupOption,\n isValueEmpty,\n normalizeValueFor,\n splitBySeparators,\n} from './helpers';\nimport {\n type SelectOption,\n type SelectOptions,\n type SelectProps,\n type SelectRootChangeEventDetails,\n type SelectSize,\n} from './type';\n\ninterface UseSelectValueParams {\n defaultValue: SelectProps['defaultValue'];\n extraOptions: SelectOption<any>[];\n isMultiple: boolean;\n onChange: SelectProps['onChange'];\n onSelect: SelectProps['onSelect'];\n options: SelectOptions<any> | undefined;\n setExtraOptions: React.Dispatch<React.SetStateAction<SelectOption<any>[]>>;\n value: SelectProps['value'];\n}\n\nexport function useSelectValue({\n defaultValue,\n extraOptions,\n isMultiple,\n onChange,\n onSelect,\n options,\n setExtraOptions,\n value,\n}: UseSelectValueParams) {\n const [uncontrolledValue, setUncontrolledValue] = useState<any>(() => {\n if (defaultValue !== undefined) return defaultValue;\n return isMultiple ? [] : null;\n });\n\n const normalizeValue = useMemo(() => normalizeValueFor(isMultiple), [isMultiple]);\n\n const mergedValue = value !== undefined ? value : uncontrolledValue;\n const normalizedValue = useMemo(() => normalizeValue(mergedValue), [mergedValue, normalizeValue]);\n\n const valueArray = useMemo(() => {\n if (isMultiple) return normalizedValue as any[];\n return isValueEmpty(normalizedValue) ? [] : [normalizedValue];\n }, [isMultiple, normalizedValue]);\n\n const { optionMap, resolvedOptions } = useMemo(() => {\n const baseOptions = options ?? [];\n const optionValueMap = new Map<any, SelectOption<any>>();\n\n const addOption = (item: SelectOption<any>) => {\n if (!optionValueMap.has(item.value)) {\n optionValueMap.set(item.value, item);\n }\n };\n\n baseOptions.forEach((item) => {\n if (isGroupOption(item)) {\n item.options.forEach(addOption);\n } else {\n addOption(item);\n }\n });\n\n const filteredExtraOptions = extraOptions.filter((item) => !optionValueMap.has(item.value));\n filteredExtraOptions.forEach(addOption);\n const mergedOptions: SelectOptions<any> = [...baseOptions, ...filteredExtraOptions];\n\n const missingValueOptions: SelectOption<any>[] = valueArray\n .filter((val) => !optionValueMap.has(val))\n .map((val) => ({ label: String(val), value: val }));\n missingValueOptions.forEach(addOption);\n\n return {\n optionMap: optionValueMap,\n resolvedOptions: missingValueOptions.length\n ? [...mergedOptions, ...missingValueOptions]\n : mergedOptions,\n };\n }, [extraOptions, options, valueArray]);\n\n const getOption = useCallback(\n (optionValue: any): SelectOption<any> => {\n const matched = optionMap.get(optionValue);\n if (matched) return matched;\n if (optionValue && typeof optionValue === 'object' && 'label' in optionValue) {\n return { label: (optionValue as any).label, value: optionValue };\n }\n return { label: String(optionValue), value: optionValue };\n },\n [optionMap],\n );\n\n const previousValueRef = useRef<any>(normalizedValue);\n useEffect(() => {\n previousValueRef.current = normalizedValue;\n }, [normalizedValue]);\n\n const handleValueChange = useCallback(\n (nextValue: any) => {\n const normalizedNextValue = normalizeValue(nextValue);\n const previousValue = previousValueRef.current;\n\n if (isMultiple) {\n const prevValues = Array.isArray(previousValue) ? previousValue : [];\n const nextValues = Array.isArray(normalizedNextValue) ? normalizedNextValue : [];\n const addedValues = nextValues.filter(\n (val) => !prevValues.some((prev) => Object.is(prev, val)),\n );\n addedValues.forEach((val) => onSelect?.(val, getOption(val)));\n\n if (value === undefined) setUncontrolledValue(nextValues);\n onChange?.(\n nextValues,\n nextValues.map((val) => getOption(val)),\n );\n } else {\n if (!isValueEmpty(normalizedNextValue) && !Object.is(previousValue, normalizedNextValue)) {\n onSelect?.(normalizedNextValue, getOption(normalizedNextValue));\n }\n if (value === undefined) setUncontrolledValue(normalizedNextValue);\n onChange?.(\n isValueEmpty(normalizedNextValue) ? undefined : normalizedNextValue,\n isValueEmpty(normalizedNextValue) ? undefined : getOption(normalizedNextValue),\n );\n }\n\n previousValueRef.current = normalizedNextValue;\n },\n [getOption, isMultiple, normalizeValue, onChange, onSelect, value],\n );\n\n const appendTagValues = useCallback(\n (rawValues: string[]) => {\n const valuesToAdd = rawValues.map((val) => val.trim()).filter(Boolean);\n if (!valuesToAdd.length) return;\n\n const currentValues = Array.isArray(previousValueRef.current)\n ? previousValueRef.current\n : valueArray;\n const nextValues = [...currentValues];\n const newOptionValues = valuesToAdd.filter((val) => !optionMap.has(val));\n\n if (newOptionValues.length > 0) {\n setExtraOptions((prev) => {\n const existingValues = new Set(prev.map((item) => item.value));\n const merged = [...prev];\n newOptionValues.forEach((val) => {\n if (!existingValues.has(val)) {\n merged.push({ label: val, value: val });\n }\n });\n return merged;\n });\n }\n\n valuesToAdd.forEach((val) => {\n if (!nextValues.some((item) => Object.is(item, val))) {\n nextValues.push(val);\n }\n });\n\n if (nextValues.length !== valueArray.length) {\n handleValueChange(nextValues);\n }\n },\n [handleValueChange, optionMap, setExtraOptions, valueArray],\n );\n\n const removeLastTagValue = useCallback(() => {\n const currentValues = Array.isArray(previousValueRef.current)\n ? previousValueRef.current\n : valueArray;\n if (currentValues.length > 0) handleValueChange(currentValues.slice(0, -1));\n }, [handleValueChange, valueArray]);\n\n return {\n appendTagValues,\n getOption,\n handleValueChange,\n normalizedValue,\n normalizeValue,\n optionMap,\n resolvedOptions,\n removeLastTagValue,\n valueArray,\n };\n}\n\ninterface UseSelectOpenParams {\n defaultOpen: boolean | undefined;\n onOpenChange: SelectProps['onOpenChange'];\n open: boolean | undefined;\n}\n\nexport function useSelectOpen({ defaultOpen, onOpenChange, open }: UseSelectOpenParams) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));\n\n useEffect(() => {\n if (open !== undefined) setUncontrolledOpen(open);\n }, [open]);\n\n const mergedOpen = open ?? uncontrolledOpen;\n\n const handleOpenChange = useCallback(\n (nextOpen: boolean, eventDetails?: SelectRootChangeEventDetails) => {\n onOpenChange?.(nextOpen, eventDetails);\n if (open === undefined) setUncontrolledOpen(nextOpen);\n },\n [onOpenChange, open],\n );\n\n return { handleOpenChange, mergedOpen };\n}\n\ninterface UseSelectSearchParams {\n appendTagValues: (values: string[]) => void;\n handleOpenChange: (nextOpen: boolean) => void;\n mergedOpen: boolean;\n mode: SelectProps['mode'];\n removeLastTagValue: () => void;\n resolvedOptions: SelectOptions;\n showSearch: boolean | undefined;\n tokenSeparators: string[] | undefined;\n}\n\nexport function useSelectSearch({\n appendTagValues,\n handleOpenChange,\n mergedOpen,\n mode,\n removeLastTagValue,\n resolvedOptions,\n showSearch,\n tokenSeparators,\n}: UseSelectSearchParams) {\n const [searchValue, setSearchValue] = useState('');\n const shouldShowSearch = Boolean(showSearch || mode === 'tags');\n\n useEffect(() => {\n if (!mergedOpen) setSearchValue('');\n }, [mergedOpen]);\n\n const handleSearchChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n const nextValue = event.target.value;\n if (mode === 'tags') {\n const parts = splitBySeparators(nextValue, tokenSeparators);\n if (parts.length > 1) {\n const pending = parts.pop() ?? '';\n appendTagValues(parts.filter(Boolean));\n setSearchValue(pending);\n return;\n }\n }\n setSearchValue(nextValue);\n },\n [appendTagValues, mode, tokenSeparators],\n );\n\n const handleSearchKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n event.stopPropagation();\n\n if (event.key === 'Escape') {\n handleOpenChange(false);\n return;\n }\n if (mode !== 'tags') return;\n\n if (event.key === 'Backspace' && !searchValue) {\n event.preventDefault();\n removeLastTagValue();\n return;\n }\n\n const isSeparator = tokenSeparators?.includes(event.key);\n if (event.key === 'Enter' || isSeparator) {\n event.preventDefault();\n event.stopPropagation();\n appendTagValues([searchValue]);\n setSearchValue('');\n }\n },\n [appendTagValues, handleOpenChange, mode, removeLastTagValue, searchValue, tokenSeparators],\n );\n\n // Stop propagation in capture phase + on keyup to block base-ui Popup-level\n // `useTypeahead` (and any ancestor typeahead) from hijacking the search\n // input's first-letter focus behavior. Do not remove.\n const stopSearchPropagation = useCallback((event: KeyboardEvent<HTMLInputElement>) => {\n event.stopPropagation();\n }, []);\n\n const filteredOptions = useMemo(() => {\n if (!shouldShowSearch || !searchValue.trim()) return resolvedOptions;\n const query = searchValue.trim().toLowerCase();\n\n return resolvedOptions\n .map((item) => {\n if (isGroupOption(item)) {\n const groupItems = item.options.filter((option) =>\n getOptionSearchText(option).toLowerCase().includes(query),\n );\n if (!groupItems.length) return null;\n return { ...item, options: groupItems };\n }\n return getOptionSearchText(item).toLowerCase().includes(query) ? item : null;\n })\n .filter(Boolean) as SelectOptions;\n }, [resolvedOptions, searchValue, shouldShowSearch]);\n\n return {\n filteredOptions,\n handleSearchChange,\n handleSearchKeyDown,\n searchValue,\n shouldShowSearch,\n stopSearchPropagation,\n };\n}\n\ninterface UseSelectVirtualParams {\n filteredOptions: SelectOptions;\n listItemHeight: number | undefined;\n size: SelectSize;\n valueArray: any[];\n virtual: boolean | undefined;\n}\n\nexport function useSelectVirtual({\n filteredOptions,\n listItemHeight,\n size,\n valueArray,\n virtual,\n}: UseSelectVirtualParams) {\n const virtualListStyle = useMemo(() => {\n if (!virtual) return undefined;\n const rowCount = countVirtualItems(filteredOptions);\n const maxVisibleRows = 6;\n const estimatedRowHeight =\n listItemHeight ?? (size === 'large' ? 40 : size === 'small' ? 28 : 32);\n const visibleRows = Math.min(Math.max(rowCount, 1), maxVisibleRows);\n const estimatedHeight = visibleRows * estimatedRowHeight + 8;\n\n return {\n height: `min(${estimatedHeight}px, var(--lobe-select-available-height, var(--available-height)))`,\n };\n }, [filteredOptions, listItemHeight, size, virtual]);\n\n const selectedIndices = useMemo(() => {\n if (!virtual || valueArray.length === 0) return undefined;\n const selectedSet = new Set(valueArray);\n const indices: number[] = [];\n let index = 0;\n\n filteredOptions.forEach((item) => {\n if (isGroupOption(item)) {\n if (item.options.some((option) => selectedSet.has(option.value))) {\n indices.push(index);\n }\n index += 1;\n return;\n }\n if (selectedSet.has(item.value)) indices.push(index);\n index += 1;\n });\n\n return indices.length ? indices : undefined;\n }, [filteredOptions, valueArray, virtual]);\n\n return { selectedIndices, virtualListStyle };\n}\n\nexport function usePortalContainer() {\n const appElement = useAppElement();\n // `appElement` is the ThemeProvider wrapper div, which uses `display: contents`\n // so it has no layout box. `@base-ui/react/select` fails to mount its Popup\n // into a `display: contents` container in certain hosts (editor/chat inputs\n // with focus traps). Fall back to `document.body` in that case; keep the\n // original behavior when the wrapper has a real layout (older themes, SSR\n // snapshot, etc.).\n return useMemo(() => {\n if (typeof window === 'undefined') return appElement;\n if (!(appElement instanceof HTMLElement)) return undefined;\n const display = window.getComputedStyle(appElement).display;\n return display === 'contents' ? document.body : appElement;\n }, [appElement]);\n}\n"],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  "use client";
2
2
  import Icon from "../../Icon/Icon.mjs";
3
+ import { VirtualScrollArea } from "../virtual/VirtualScrollArea.mjs";
4
+ import { useMenuVirtualList } from "../virtual/useMenuVirtualList.mjs";
3
5
  import { styles } from "../DropdownMenu/sharedStyle.mjs";
4
6
  import { styles as styles$1 } from "./style.mjs";
5
7
  import { isValueEmpty } from "./helpers.mjs";
@@ -8,7 +10,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
8
10
  import { cx } from "antd-style";
9
11
  import { ChevronDown, Loader2, X } from "lucide-react";
10
12
  import { Select } from "@base-ui/react/select";
11
- import { Virtualizer } from "virtua";
12
13
  //#region src/base-ui/Select/parts.tsx
13
14
  function resolveIconNode(node) {
14
15
  if (node === void 0 || node === null) return null;
@@ -86,27 +87,28 @@ function createTriggerValueRenderer({ getOption, isMultiple, isTags, labelRender
86
87
  }
87
88
  function SelectListSection({ classNames, hasSearch, isEmpty, listContent, listItemHeight, virtual, virtualState }) {
88
89
  const listClassName = cx(styles$1.list, hasSearch && styles$1.listWithSearch, classNames?.list);
89
- if (!virtual || isEmpty) return /* @__PURE__ */ jsx(Select.List, {
90
+ const enabled = Boolean(virtual) && !isEmpty;
91
+ const { keepMountedIndices, viewportProps, viewportRef, virtualChildren, virtualizerRef } = useMenuVirtualList({
92
+ children: listContent,
93
+ enabled,
94
+ keepMounted: virtualState.selectedIndices
95
+ });
96
+ if (!enabled) return /* @__PURE__ */ jsx(Select.List, {
90
97
  className: listClassName,
91
98
  "data-virtual": virtual || void 0,
92
99
  children: listContent
93
100
  });
94
- const { handleListScroll, keepMountedIndices, listRef, markPointerScroll, virtualListStyle } = virtualState;
95
- return /* @__PURE__ */ jsx(Select.List, {
96
- "data-virtual": true,
97
- className: listClassName,
98
- ref: listRef,
99
- style: virtualListStyle,
100
- tabIndex: -1,
101
- onPointerDown: markPointerScroll,
102
- onScroll: handleListScroll,
103
- onTouchMove: markPointerScroll,
104
- onWheel: markPointerScroll,
105
- children: /* @__PURE__ */ jsx(Virtualizer, {
106
- itemSize: listItemHeight,
107
- keepMounted: keepMountedIndices,
108
- children: listContent
109
- })
101
+ return /* @__PURE__ */ jsx(VirtualScrollArea, {
102
+ itemSize: listItemHeight,
103
+ keepMounted: keepMountedIndices,
104
+ style: virtualState.virtualListStyle,
105
+ viewport: /* @__PURE__ */ jsx(Select.List, { className: listClassName }),
106
+ viewportProps: {
107
+ ref: viewportRef,
108
+ ...viewportProps
109
+ },
110
+ virtualizerRef,
111
+ children: virtualChildren
110
112
  });
111
113
  }
112
114
  function EmptyContent({ classNames }) {
@@ -1 +1 @@
1
- {"version":3,"file":"parts.mjs","names":["styles","BaseSelect","menuStyles"],"sources":["../../../src/base-ui/Select/parts.tsx"],"sourcesContent":["'use client';\n\nimport { Select as BaseSelect } from '@base-ui/react/select';\nimport { cx } from 'antd-style';\nimport { ChevronDown, Loader2, X } from 'lucide-react';\nimport {\n type ChangeEvent,\n isValidElement,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n} from 'react';\nimport { Virtualizer } from 'virtua';\n\nimport { styles as menuStyles } from '@/base-ui/DropdownMenu/sharedStyle';\nimport Icon, { type IconProps } from '@/Icon';\n\nimport { isValueEmpty } from './helpers';\nimport { type useSelectVirtual } from './hooks';\nimport { styles } from './style';\nimport { type SelectClassNames, type SelectOption, type SelectProps } from './type';\n\nexport function resolveIconNode(node: ReactNode | IconProps['icon'] | undefined | null) {\n if (node === undefined || node === null) return null;\n if (isValidElement(node) || typeof node === 'string' || typeof node === 'number') {\n return node;\n }\n return <Icon icon={node as any} size={'small'} />;\n}\n\nexport function resolveSuffixIcon(\n suffixIcon: SelectProps['suffixIcon'],\n suffixIconProps: SelectProps['suffixIconProps'],\n loading: boolean | undefined,\n) {\n if (loading) return <Icon spin icon={Loader2} size={'small'} />;\n if (suffixIcon === null) return null;\n if (\n isValidElement(suffixIcon) ||\n typeof suffixIcon === 'string' ||\n typeof suffixIcon === 'number'\n ) {\n return suffixIcon;\n }\n return (\n <Icon\n icon={(suffixIcon as any) || ChevronDown}\n size={'small'}\n {...suffixIconProps}\n style={{\n pointerEvents: 'none',\n ...suffixIconProps?.style,\n }}\n />\n );\n}\n\ninterface TriggerValueRendererParams {\n getOption: (value: any) => SelectOption<any>;\n isMultiple: boolean;\n isTags: boolean;\n labelRender: SelectProps['labelRender'];\n normalizeValue: (value: any) => any;\n onRemoveValue: (index: number) => void;\n placeholder: ReactNode;\n}\n\nexport function createTriggerValueRenderer({\n getOption,\n isMultiple,\n isTags,\n labelRender,\n normalizeValue,\n onRemoveValue,\n placeholder,\n}: TriggerValueRendererParams) {\n return function renderValue(currentValue: any): ReactNode {\n const resolved = normalizeValue(currentValue);\n const placeholderNode =\n placeholder === undefined ? null : <span className={styles.valueText}>{placeholder}</span>;\n\n if (isMultiple) {\n const values = Array.isArray(resolved) ? resolved : [];\n if (values.length === 0) return placeholderNode;\n return (\n <span className={styles.tags}>\n {values.map((val, index) => {\n const option = getOption(val);\n const content = labelRender ? labelRender(option) : (option.label ?? String(val));\n return (\n <span\n className={styles.tag}\n data-role=\"lobe-select-tag\"\n key={`${String(val)}-${index}`}\n >\n {content}\n {isTags && (\n <span\n aria-label={`Remove ${String(val)}`}\n className={styles.tagClose}\n data-role=\"lobe-select-tag-remove\"\n role=\"button\"\n tabIndex={0}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onRemoveValue(index);\n }}\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n >\n <X size={12} />\n </span>\n )}\n </span>\n );\n })}\n </span>\n );\n }\n\n if (isValueEmpty(resolved)) return placeholderNode;\n const option = getOption(resolved);\n const content = labelRender ? labelRender(option) : (option.label ?? String(resolved));\n return <span className={styles.valueText}>{content}</span>;\n };\n}\n\ntype SelectVirtualReturn = ReturnType<typeof useSelectVirtual>;\n\ninterface SelectListSectionProps {\n classNames: SelectClassNames | undefined;\n hasSearch: boolean;\n isEmpty: boolean;\n listContent: ReactNode;\n listItemHeight: number | undefined;\n virtual: boolean | undefined;\n virtualState: SelectVirtualReturn;\n}\n\nexport function SelectListSection({\n classNames,\n hasSearch,\n isEmpty,\n listContent,\n listItemHeight,\n virtual,\n virtualState,\n}: SelectListSectionProps) {\n const listClassName = cx(styles.list, hasSearch && styles.listWithSearch, classNames?.list);\n\n if (!virtual || isEmpty) {\n return (\n <BaseSelect.List className={listClassName} data-virtual={virtual || undefined}>\n {listContent}\n </BaseSelect.List>\n );\n }\n\n const { handleListScroll, keepMountedIndices, listRef, markPointerScroll, virtualListStyle } =\n virtualState;\n\n return (\n <BaseSelect.List\n data-virtual\n className={listClassName}\n ref={listRef}\n style={virtualListStyle}\n tabIndex={-1}\n onPointerDown={markPointerScroll}\n onScroll={handleListScroll}\n onTouchMove={markPointerScroll}\n onWheel={markPointerScroll}\n >\n <Virtualizer itemSize={listItemHeight} keepMounted={keepMountedIndices}>\n {listContent}\n </Virtualizer>\n </BaseSelect.List>\n );\n}\n\ninterface EmptyContentProps {\n classNames: SelectClassNames | undefined;\n}\n\nexport function EmptyContent({ classNames }: EmptyContentProps) {\n return (\n <div className={cx(menuStyles.item, menuStyles.empty, styles.empty, classNames?.empty)}>\n No data\n </div>\n );\n}\n\ninterface SelectSearchInputProps {\n autoFocus?: boolean;\n classNames: SelectClassNames | undefined;\n disabled?: boolean;\n inline?: boolean;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void;\n placeholder: ReactNode;\n readOnly?: boolean;\n stopPropagation: (event: KeyboardEvent<HTMLInputElement>) => void;\n value: string;\n}\n\nexport function SelectSearchInput({\n autoFocus,\n classNames,\n disabled,\n inline,\n onChange,\n onKeyDown,\n placeholder,\n readOnly,\n stopPropagation,\n value,\n}: SelectSearchInputProps) {\n return (\n <div className={cx(inline ? styles.tagsSearch : styles.search, classNames?.search)}>\n <input\n autoFocus={autoFocus}\n className={styles.searchInput}\n disabled={disabled}\n placeholder={typeof placeholder === 'string' ? placeholder : undefined}\n readOnly={readOnly}\n value={value}\n onChange={onChange}\n onKeyDownCapture={onKeyDown}\n onKeyUp={stopPropagation}\n onKeyUpCapture={stopPropagation}\n />\n </div>\n );\n}\n\ninterface SelectTriggerSuffixProps {\n classNames: SelectClassNames | undefined;\n onClear: (event: MouseEvent) => void;\n showClear: boolean;\n suffixIconNode: ReactNode;\n}\n\nexport function SelectTriggerSuffix({\n classNames,\n onClear,\n showClear,\n suffixIconNode,\n}: SelectTriggerSuffixProps) {\n return (\n <span className={cx(styles.suffix, classNames?.suffix)}>\n {showClear && (\n <span\n className={cx(styles.clear, classNames?.clear)}\n data-role=\"lobe-select-clear\"\n onClick={onClear}\n >\n <Icon icon={X} size={'small'} />\n </span>\n )}\n {suffixIconNode !== null && suffixIconNode !== undefined && (\n <BaseSelect.Icon className={cx(styles.icon, classNames?.icon)}>\n {suffixIconNode}\n </BaseSelect.Icon>\n )}\n </span>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"parts.mjs","names":["styles","BaseSelect","menuStyles"],"sources":["../../../src/base-ui/Select/parts.tsx"],"sourcesContent":["'use client';\n\nimport { Select as BaseSelect } from '@base-ui/react/select';\nimport { cx } from 'antd-style';\nimport { ChevronDown, Loader2, X } from 'lucide-react';\nimport {\n type ChangeEvent,\n isValidElement,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n} from 'react';\n\nimport { styles as menuStyles } from '@/base-ui/DropdownMenu/sharedStyle';\nimport { useMenuVirtualList, VirtualScrollArea } from '@/base-ui/virtual';\nimport Icon, { type IconProps } from '@/Icon';\n\nimport { isValueEmpty } from './helpers';\nimport { type useSelectVirtual } from './hooks';\nimport { styles } from './style';\nimport { type SelectClassNames, type SelectOption, type SelectProps } from './type';\n\nexport function resolveIconNode(node: ReactNode | IconProps['icon'] | undefined | null) {\n if (node === undefined || node === null) return null;\n if (isValidElement(node) || typeof node === 'string' || typeof node === 'number') {\n return node;\n }\n return <Icon icon={node as any} size={'small'} />;\n}\n\nexport function resolveSuffixIcon(\n suffixIcon: SelectProps['suffixIcon'],\n suffixIconProps: SelectProps['suffixIconProps'],\n loading: boolean | undefined,\n) {\n if (loading) return <Icon spin icon={Loader2} size={'small'} />;\n if (suffixIcon === null) return null;\n if (\n isValidElement(suffixIcon) ||\n typeof suffixIcon === 'string' ||\n typeof suffixIcon === 'number'\n ) {\n return suffixIcon;\n }\n return (\n <Icon\n icon={(suffixIcon as any) || ChevronDown}\n size={'small'}\n {...suffixIconProps}\n style={{\n pointerEvents: 'none',\n ...suffixIconProps?.style,\n }}\n />\n );\n}\n\ninterface TriggerValueRendererParams {\n getOption: (value: any) => SelectOption<any>;\n isMultiple: boolean;\n isTags: boolean;\n labelRender: SelectProps['labelRender'];\n normalizeValue: (value: any) => any;\n onRemoveValue: (index: number) => void;\n placeholder: ReactNode;\n}\n\nexport function createTriggerValueRenderer({\n getOption,\n isMultiple,\n isTags,\n labelRender,\n normalizeValue,\n onRemoveValue,\n placeholder,\n}: TriggerValueRendererParams) {\n return function renderValue(currentValue: any): ReactNode {\n const resolved = normalizeValue(currentValue);\n const placeholderNode =\n placeholder === undefined ? null : <span className={styles.valueText}>{placeholder}</span>;\n\n if (isMultiple) {\n const values = Array.isArray(resolved) ? resolved : [];\n if (values.length === 0) return placeholderNode;\n return (\n <span className={styles.tags}>\n {values.map((val, index) => {\n const option = getOption(val);\n const content = labelRender ? labelRender(option) : (option.label ?? String(val));\n return (\n <span\n className={styles.tag}\n data-role=\"lobe-select-tag\"\n key={`${String(val)}-${index}`}\n >\n {content}\n {isTags && (\n <span\n aria-label={`Remove ${String(val)}`}\n className={styles.tagClose}\n data-role=\"lobe-select-tag-remove\"\n role=\"button\"\n tabIndex={0}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onRemoveValue(index);\n }}\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n >\n <X size={12} />\n </span>\n )}\n </span>\n );\n })}\n </span>\n );\n }\n\n if (isValueEmpty(resolved)) return placeholderNode;\n const option = getOption(resolved);\n const content = labelRender ? labelRender(option) : (option.label ?? String(resolved));\n return <span className={styles.valueText}>{content}</span>;\n };\n}\n\ntype SelectVirtualReturn = ReturnType<typeof useSelectVirtual>;\n\ninterface SelectListSectionProps {\n classNames: SelectClassNames | undefined;\n hasSearch: boolean;\n isEmpty: boolean;\n listContent: ReactNode;\n listItemHeight: number | undefined;\n virtual: boolean | undefined;\n virtualState: SelectVirtualReturn;\n}\n\nexport function SelectListSection({\n classNames,\n hasSearch,\n isEmpty,\n listContent,\n listItemHeight,\n virtual,\n virtualState,\n}: SelectListSectionProps) {\n const listClassName = cx(styles.list, hasSearch && styles.listWithSearch, classNames?.list);\n const enabled = Boolean(virtual) && !isEmpty;\n const { keepMountedIndices, viewportProps, viewportRef, virtualChildren, virtualizerRef } =\n useMenuVirtualList({\n children: listContent,\n enabled,\n keepMounted: virtualState.selectedIndices,\n });\n\n if (!enabled) {\n return (\n <BaseSelect.List className={listClassName} data-virtual={virtual || undefined}>\n {listContent}\n </BaseSelect.List>\n );\n }\n\n return (\n <VirtualScrollArea\n itemSize={listItemHeight}\n keepMounted={keepMountedIndices}\n style={virtualState.virtualListStyle}\n viewport={<BaseSelect.List className={listClassName} />}\n viewportProps={{ ref: viewportRef, ...viewportProps }}\n virtualizerRef={virtualizerRef}\n >\n {virtualChildren}\n </VirtualScrollArea>\n );\n}\n\ninterface EmptyContentProps {\n classNames: SelectClassNames | undefined;\n}\n\nexport function EmptyContent({ classNames }: EmptyContentProps) {\n return (\n <div className={cx(menuStyles.item, menuStyles.empty, styles.empty, classNames?.empty)}>\n No data\n </div>\n );\n}\n\ninterface SelectSearchInputProps {\n autoFocus?: boolean;\n classNames: SelectClassNames | undefined;\n disabled?: boolean;\n inline?: boolean;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void;\n placeholder: ReactNode;\n readOnly?: boolean;\n stopPropagation: (event: KeyboardEvent<HTMLInputElement>) => void;\n value: string;\n}\n\nexport function SelectSearchInput({\n autoFocus,\n classNames,\n disabled,\n inline,\n onChange,\n onKeyDown,\n placeholder,\n readOnly,\n stopPropagation,\n value,\n}: SelectSearchInputProps) {\n return (\n <div className={cx(inline ? styles.tagsSearch : styles.search, classNames?.search)}>\n <input\n autoFocus={autoFocus}\n className={styles.searchInput}\n disabled={disabled}\n placeholder={typeof placeholder === 'string' ? placeholder : undefined}\n readOnly={readOnly}\n value={value}\n onChange={onChange}\n onKeyDownCapture={onKeyDown}\n onKeyUp={stopPropagation}\n onKeyUpCapture={stopPropagation}\n />\n </div>\n );\n}\n\ninterface SelectTriggerSuffixProps {\n classNames: SelectClassNames | undefined;\n onClear: (event: MouseEvent) => void;\n showClear: boolean;\n suffixIconNode: ReactNode;\n}\n\nexport function SelectTriggerSuffix({\n classNames,\n onClear,\n showClear,\n suffixIconNode,\n}: SelectTriggerSuffixProps) {\n return (\n <span className={cx(styles.suffix, classNames?.suffix)}>\n {showClear && (\n <span\n className={cx(styles.clear, classNames?.clear)}\n data-role=\"lobe-select-clear\"\n onClick={onClear}\n >\n <Icon icon={X} size={'small'} />\n </span>\n )}\n {suffixIconNode !== null && suffixIconNode !== undefined && (\n <BaseSelect.Icon className={cx(styles.icon, classNames?.icon)}>\n {suffixIconNode}\n </BaseSelect.Icon>\n )}\n </span>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAsBA,SAAgB,gBAAgB,MAAwD;CACtF,IAAI,SAAS,KAAA,KAAa,SAAS,MAAM,OAAO;CAChD,IAAI,eAAe,IAAI,KAAK,OAAO,SAAS,YAAY,OAAO,SAAS,UACtE,OAAO;CAET,OAAO,oBAAC,MAAD;EAAM,MAAM;EAAa,MAAM;CAAU,CAAA;AAClD;AAEA,SAAgB,kBACd,YACA,iBACA,SACA;CACA,IAAI,SAAS,OAAO,oBAAC,MAAD;EAAM,MAAA;EAAK,MAAM;EAAS,MAAM;CAAU,CAAA;CAC9D,IAAI,eAAe,MAAM,OAAO;CAChC,IACE,eAAe,UAAU,KACzB,OAAO,eAAe,YACtB,OAAO,eAAe,UAEtB,OAAO;CAET,OACE,oBAAC,MAAD;EACE,MAAO,cAAsB;EAC7B,MAAM;EACN,GAAI;EACJ,OAAO;GACL,eAAe;GACf,GAAG,iBAAiB;EACtB;CACD,CAAA;AAEL;AAYA,SAAgB,2BAA2B,EACzC,WACA,YACA,QACA,aACA,gBACA,eACA,eAC6B;CAC7B,OAAO,SAAS,YAAY,cAA8B;EACxD,MAAM,WAAW,eAAe,YAAY;EAC5C,MAAM,kBACJ,gBAAgB,KAAA,IAAY,OAAO,oBAAC,QAAD;GAAM,WAAWA,SAAO;GAAY,UAAA;EAAkB,CAAA;EAE3F,IAAI,YAAY;GACd,MAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC;GACrD,IAAI,OAAO,WAAW,GAAG,OAAO;GAChC,OACE,oBAAC,QAAD;IAAM,WAAWA,SAAO;IACrB,UAAA,OAAO,KAAK,KAAK,UAAU;KAC1B,MAAM,SAAS,UAAU,GAAG;KAC5B,MAAM,UAAU,cAAc,YAAY,MAAM,IAAK,OAAO,SAAS,OAAO,GAAG;KAC/E,OACE,qBAAC,QAAD;MACE,WAAWA,SAAO;MAClB,aAAU;MAFZ,UAAA,CAKG,SACA,UACC,oBAAC,QAAD;OACE,cAAY,UAAU,OAAO,GAAG;OAChC,WAAWA,SAAO;OAClB,aAAU;OACV,MAAK;OACL,UAAU;OACV,UAAU,UAAU;QAClB,MAAM,eAAe;QACrB,MAAM,gBAAgB;QACtB,cAAc,KAAK;OACrB;OACA,gBAAgB,UAAU;QACxB,MAAM,eAAe;QACrB,MAAM,gBAAgB;OACxB;OAEA,UAAA,oBAAC,GAAD,EAAG,MAAM,GAAK,CAAA;MACV,CAAA,CAEJ;KAvBC,GAAA,GAAG,OAAO,GAAG,EAAE,GAAG,OAuBnB;IAEV,CAAC;GACG,CAAA;EAEV;EAEA,IAAI,aAAa,QAAQ,GAAG,OAAO;EACnC,MAAM,SAAS,UAAU,QAAQ;EACjC,MAAM,UAAU,cAAc,YAAY,MAAM,IAAK,OAAO,SAAS,OAAO,QAAQ;EACpF,OAAO,oBAAC,QAAD;GAAM,WAAWA,SAAO;GAAY,UAAA;EAAc,CAAA;CAC3D;AACF;AAcA,SAAgB,kBAAkB,EAChC,YACA,WACA,SACA,aACA,gBACA,SACA,gBACyB;CACzB,MAAM,gBAAgB,GAAGA,SAAO,MAAM,aAAaA,SAAO,gBAAgB,YAAY,IAAI;CAC1F,MAAM,UAAU,QAAQ,OAAO,KAAK,CAAC;CACrC,MAAM,EAAE,oBAAoB,eAAe,aAAa,iBAAiB,mBACvE,mBAAmB;EACjB,UAAU;EACV;EACA,aAAa,aAAa;CAC5B,CAAC;CAEH,IAAI,CAAC,SACH,OACE,oBAACC,OAAW,MAAZ;EAAiB,WAAW;EAAe,gBAAc,WAAW,KAAA;EACjE,UAAA;CACc,CAAA;CAIrB,OACE,oBAAC,mBAAD;EACE,UAAU;EACV,aAAa;EACb,OAAO,aAAa;EACpB,UAAU,oBAACA,OAAW,MAAZ,EAAiB,WAAW,cAAgB,CAAA;EACtD,eAAe;GAAE,KAAK;GAAa,GAAG;EAAc;EACpC;EAEf,UAAA;CACgB,CAAA;AAEvB;AAMA,SAAgB,aAAa,EAAE,cAAiC;CAC9D,OACE,oBAAC,OAAD;EAAK,WAAW,GAAGC,OAAW,MAAMA,OAAW,OAAOF,SAAO,OAAO,YAAY,KAAK;EAAG,UAAA;CAEnF,CAAA;AAET;AAeA,SAAgB,kBAAkB,EAChC,WACA,YACA,UACA,QACA,UACA,WACA,aACA,UACA,iBACA,SACyB;CACzB,OACE,oBAAC,OAAD;EAAK,WAAW,GAAG,SAASA,SAAO,aAAaA,SAAO,QAAQ,YAAY,MAAM;EAC/E,UAAA,oBAAC,SAAD;GACa;GACX,WAAWA,SAAO;GACR;GACV,aAAa,OAAO,gBAAgB,WAAW,cAAc,KAAA;GACnD;GACH;GACG;GACV,kBAAkB;GAClB,SAAS;GACT,gBAAgB;EACjB,CAAA;CACE,CAAA;AAET;AASA,SAAgB,oBAAoB,EAClC,YACA,SACA,WACA,kBAC2B;CAC3B,OACE,qBAAC,QAAD;EAAM,WAAW,GAAGA,SAAO,QAAQ,YAAY,MAAM;EAArD,UAAA,CACG,aACC,oBAAC,QAAD;GACE,WAAW,GAAGA,SAAO,OAAO,YAAY,KAAK;GAC7C,aAAU;GACV,SAAS;GAET,UAAA,oBAAC,MAAD;IAAM,MAAM;IAAG,MAAM;GAAU,CAAA;EAC3B,CAAA,GAEP,mBAAmB,QAAQ,mBAAmB,KAAA,KAC7C,oBAACC,OAAW,MAAZ;GAAiB,WAAW,GAAGD,SAAO,MAAM,YAAY,IAAI;GACzD,UAAA;EACc,CAAA,CAEf;;AAEV"}
@@ -9,11 +9,10 @@ import { Check } from "lucide-react";
9
9
  import { Select } from "@base-ui/react/select";
10
10
  //#region src/base-ui/Select/renderOptions.tsx
11
11
  function renderItem(option, index, params) {
12
- const { classNames, isBoldIndicator, itemTextClassName, listItemHeight, optionRender, renderVirtualItem, virtual } = params;
12
+ const { classNames, isBoldIndicator, itemTextClassName, listItemHeight, optionRender } = params;
13
13
  return /* @__PURE__ */ jsxs(Select.Item, {
14
14
  disabled: option.disabled,
15
15
  label: getOptionSearchText(option),
16
- render: virtual ? renderVirtualItem : void 0,
17
16
  value: option.value,
18
17
  className: cx(styles.item, styles$1.item, isBoldIndicator && styles$1.itemBoldSelected, classNames?.item, classNames?.option, option.className),
19
18
  style: {
@@ -1 +1 @@
1
- {"version":3,"file":"renderOptions.mjs","names":["BaseSelect","menuStyles","styles"],"sources":["../../../src/base-ui/Select/renderOptions.tsx"],"sourcesContent":["'use client';\n\nimport { Select as BaseSelect } from '@base-ui/react/select';\nimport { cx } from 'antd-style';\nimport { Check } from 'lucide-react';\nimport { type ComponentProps } from 'react';\n\nimport { styles as menuStyles } from '@/base-ui/DropdownMenu/sharedStyle';\nimport Icon from '@/Icon';\n\nimport { getOptionSearchText, isGroupOption } from './helpers';\nimport { styles } from './style';\nimport {\n type SelectClassNames,\n type SelectOption,\n type SelectOptions,\n type SelectProps,\n} from './type';\n\ninterface RenderOptionsParams {\n classNames: SelectClassNames | undefined;\n isBoldIndicator: boolean;\n items: SelectOptions<any>;\n itemTextClassName: string;\n listItemHeight: number | undefined;\n optionRender: SelectProps['optionRender'];\n renderVirtualItem: NonNullable<ComponentProps<typeof BaseSelect.Item>['render']>;\n virtual: boolean | undefined;\n}\n\nfunction renderItem(\n option: SelectOption<any>,\n index: number,\n params: Omit<RenderOptionsParams, 'items'>,\n) {\n const {\n classNames,\n isBoldIndicator,\n itemTextClassName,\n listItemHeight,\n optionRender,\n renderVirtualItem,\n virtual,\n } = params;\n\n return (\n <BaseSelect.Item\n disabled={option.disabled}\n key={`${String(option.value)}-${index}`}\n label={getOptionSearchText(option)}\n render={virtual ? renderVirtualItem : undefined}\n value={option.value}\n className={cx(\n menuStyles.item,\n styles.item,\n isBoldIndicator && styles.itemBoldSelected,\n classNames?.item,\n classNames?.option,\n option.className,\n )}\n style={{\n minHeight: listItemHeight,\n ...option.style,\n }}\n >\n <BaseSelect.ItemText className={itemTextClassName}>\n {optionRender ? optionRender(option, { index }) : option.label}\n </BaseSelect.ItemText>\n {!isBoldIndicator && (\n <BaseSelect.ItemIndicator className={cx(styles.itemIndicator, classNames?.itemIndicator)}>\n <Icon icon={Check} size={'small'} />\n </BaseSelect.ItemIndicator>\n )}\n </BaseSelect.Item>\n );\n}\n\nexport function renderOptions(params: RenderOptionsParams) {\n const { classNames, items } = params;\n let optionIndex = 0;\n\n return items.map((item, index) => {\n if (isGroupOption(item)) {\n return (\n <BaseSelect.Group className={cx(styles.group, classNames?.group)} key={`group-${index}`}>\n <BaseSelect.GroupLabel\n className={cx(menuStyles.groupLabel, styles.groupLabel, classNames?.groupLabel)}\n >\n {item.label}\n </BaseSelect.GroupLabel>\n {item.options.map((option) => renderItem(option, optionIndex++, params))}\n </BaseSelect.Group>\n );\n }\n\n return renderItem(item, optionIndex++, params);\n });\n}\n"],"mappings":";;;;;;;;;;AA8BA,SAAS,WACP,QACA,OACA,QACA;CACA,MAAM,EACJ,YACA,iBACA,mBACA,gBACA,cACA,mBACA,YACE;CAEJ,OACE,qBAACA,OAAW,MAAZ;EACE,UAAU,OAAO;EAEjB,OAAO,oBAAoB,MAAM;EACjC,QAAQ,UAAU,oBAAoB,KAAA;EACtC,OAAO,OAAO;EACd,WAAW,GACTC,OAAW,MACXC,SAAO,MACP,mBAAmBA,SAAO,kBAC1B,YAAY,MACZ,YAAY,QACZ,OAAO,SACT;EACA,OAAO;GACL,WAAW;GACX,GAAG,OAAO;EACZ;EAjBF,UAAA,CAmBE,oBAACF,OAAW,UAAZ;GAAqB,WAAW;GAC7B,UAAA,eAAe,aAAa,QAAQ,EAAE,MAAM,CAAC,IAAI,OAAO;EACtC,CAAA,GACpB,CAAC,mBACA,oBAACA,OAAW,eAAZ;GAA0B,WAAW,GAAGE,SAAO,eAAe,YAAY,aAAa;GACrF,UAAA,oBAAC,MAAD;IAAM,MAAM;IAAO,MAAM;GAAU,CAAA;EACX,CAAA,CAEb;CAzBV,GAAA,GAAG,OAAO,OAAO,KAAK,EAAE,GAAG,OAyBjB;AAErB;AAEA,SAAgB,cAAc,QAA6B;CACzD,MAAM,EAAE,YAAY,UAAU;CAC9B,IAAI,cAAc;CAElB,OAAO,MAAM,KAAK,MAAM,UAAU;EAChC,IAAI,cAAc,IAAI,GACpB,OACE,qBAACF,OAAW,OAAZ;GAAkB,WAAW,GAAGE,SAAO,OAAO,YAAY,KAAK;GAA/D,UAAA,CACE,oBAACF,OAAW,YAAZ;IACE,WAAW,GAAGC,OAAW,YAAYC,SAAO,YAAY,YAAY,UAAU;IAE7E,UAAA,KAAK;GACe,CAAA,GACtB,KAAK,QAAQ,KAAK,WAAW,WAAW,QAAQ,eAAe,MAAM,CAAC,CACvD;EAPqD,GAAA,SAAS,OAO9D;EAItB,OAAO,WAAW,MAAM,eAAe,MAAM;CAC/C,CAAC;AACH"}
1
+ {"version":3,"file":"renderOptions.mjs","names":["BaseSelect","menuStyles","styles"],"sources":["../../../src/base-ui/Select/renderOptions.tsx"],"sourcesContent":["'use client';\n\nimport { Select as BaseSelect } from '@base-ui/react/select';\nimport { cx } from 'antd-style';\nimport { Check } from 'lucide-react';\n\nimport { styles as menuStyles } from '@/base-ui/DropdownMenu/sharedStyle';\nimport Icon from '@/Icon';\n\nimport { getOptionSearchText, isGroupOption } from './helpers';\nimport { styles } from './style';\nimport {\n type SelectClassNames,\n type SelectOption,\n type SelectOptions,\n type SelectProps,\n} from './type';\n\ninterface RenderOptionsParams {\n classNames: SelectClassNames | undefined;\n isBoldIndicator: boolean;\n items: SelectOptions<any>;\n itemTextClassName: string;\n listItemHeight: number | undefined;\n optionRender: SelectProps['optionRender'];\n}\n\nfunction renderItem(\n option: SelectOption<any>,\n index: number,\n params: Omit<RenderOptionsParams, 'items'>,\n) {\n const { classNames, isBoldIndicator, itemTextClassName, listItemHeight, optionRender } = params;\n\n return (\n <BaseSelect.Item\n disabled={option.disabled}\n key={`${String(option.value)}-${index}`}\n label={getOptionSearchText(option)}\n value={option.value}\n className={cx(\n menuStyles.item,\n styles.item,\n isBoldIndicator && styles.itemBoldSelected,\n classNames?.item,\n classNames?.option,\n option.className,\n )}\n style={{\n minHeight: listItemHeight,\n ...option.style,\n }}\n >\n <BaseSelect.ItemText className={itemTextClassName}>\n {optionRender ? optionRender(option, { index }) : option.label}\n </BaseSelect.ItemText>\n {!isBoldIndicator && (\n <BaseSelect.ItemIndicator className={cx(styles.itemIndicator, classNames?.itemIndicator)}>\n <Icon icon={Check} size={'small'} />\n </BaseSelect.ItemIndicator>\n )}\n </BaseSelect.Item>\n );\n}\n\nexport function renderOptions(params: RenderOptionsParams) {\n const { classNames, items } = params;\n let optionIndex = 0;\n\n return items.map((item, index) => {\n if (isGroupOption(item)) {\n return (\n <BaseSelect.Group className={cx(styles.group, classNames?.group)} key={`group-${index}`}>\n <BaseSelect.GroupLabel\n className={cx(menuStyles.groupLabel, styles.groupLabel, classNames?.groupLabel)}\n >\n {item.label}\n </BaseSelect.GroupLabel>\n {item.options.map((option) => renderItem(option, optionIndex++, params))}\n </BaseSelect.Group>\n );\n }\n\n return renderItem(item, optionIndex++, params);\n });\n}\n"],"mappings":";;;;;;;;;;AA2BA,SAAS,WACP,QACA,OACA,QACA;CACA,MAAM,EAAE,YAAY,iBAAiB,mBAAmB,gBAAgB,iBAAiB;CAEzF,OACE,qBAACA,OAAW,MAAZ;EACE,UAAU,OAAO;EAEjB,OAAO,oBAAoB,MAAM;EACjC,OAAO,OAAO;EACd,WAAW,GACTC,OAAW,MACXC,SAAO,MACP,mBAAmBA,SAAO,kBAC1B,YAAY,MACZ,YAAY,QACZ,OAAO,SACT;EACA,OAAO;GACL,WAAW;GACX,GAAG,OAAO;EACZ;EAhBF,UAAA,CAkBE,oBAACF,OAAW,UAAZ;GAAqB,WAAW;GAC7B,UAAA,eAAe,aAAa,QAAQ,EAAE,MAAM,CAAC,IAAI,OAAO;EACtC,CAAA,GACpB,CAAC,mBACA,oBAACA,OAAW,eAAZ;GAA0B,WAAW,GAAGE,SAAO,eAAe,YAAY,aAAa;GACrF,UAAA,oBAAC,MAAD;IAAM,MAAM;IAAO,MAAM;GAAU,CAAA;EACX,CAAA,CAEb;CAxBV,GAAA,GAAG,OAAO,OAAO,KAAK,EAAE,GAAG,OAwBjB;AAErB;AAEA,SAAgB,cAAc,QAA6B;CACzD,MAAM,EAAE,YAAY,UAAU;CAC9B,IAAI,cAAc;CAElB,OAAO,MAAM,KAAK,MAAM,UAAU;EAChC,IAAI,cAAc,IAAI,GACpB,OACE,qBAACF,OAAW,OAAZ;GAAkB,WAAW,GAAGE,SAAO,OAAO,YAAY,KAAK;GAA/D,UAAA,CACE,oBAACF,OAAW,YAAZ;IACE,WAAW,GAAGC,OAAW,YAAYC,SAAO,YAAY,YAAY,UAAU;IAE7E,UAAA,KAAK;GACe,CAAA,GACtB,KAAK,QAAQ,KAAK,WAAW,WAAW,QAAQ,eAAe,MAAM,CAAC,CACvD;EAPqD,GAAA,SAAS,OAO9D;EAItB,OAAO,WAAW,MAAM,eAAe,MAAM;CAC/C,CAAC;AACH"}
@@ -71,7 +71,6 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
71
71
  list: css`
72
72
  overflow-y: auto;
73
73
  flex: 1;
74
-
75
74
  min-height: 0;
76
75
  padding-block: 0;
77
76
  `,
@@ -89,14 +88,13 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
89
88
  var(--lobe-select-popup-max-height, var(--available-height))
90
89
  );
91
90
 
92
- max-height: var(--lobe-select-available-height);
93
-
94
91
  transform-origin: var(--transform-origin);
95
92
 
96
93
  display: flex;
97
94
  flex-direction: column;
98
95
 
99
96
  box-sizing: border-box;
97
+ max-height: var(--lobe-select-available-height);
100
98
 
101
99
  transition:
102
100
  opacity 150ms ${cssVar.motionEaseOut},
@@ -137,7 +135,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
137
135
  align-items: center;
138
136
 
139
137
  min-height: 36px;
140
- margin-inline: -4px;
138
+ margin-inline: calc(-1 * var(--lobe-menu-popup-padding));
141
139
  padding-block: 8px;
142
140
  padding-inline: 12px;
143
141
  border-block-end: 1px solid ${cssVar.colorFillSecondary};