@moderneinc/neo-styled-components 5.0.0-next.bd2a49 → 5.0.0-next.cd1d8d

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/dist/Alert/Alert.d.ts +15 -1
  2. package/dist/Badge/Badge.d.ts +16 -2
  3. package/dist/Breadcrumbs/Breadcrumbs.d.ts +0 -10
  4. package/dist/CanceledIcon/CanceledIcon.d.ts +11 -0
  5. package/dist/Checkbox/Checkbox.d.ts +5 -4
  6. package/dist/DataGrid/DataGrid.d.ts +1 -1
  7. package/dist/DataGrid/DataGrid.styles.d.ts +3 -0
  8. package/dist/DataGridCell/DataGridCell.d.ts +0 -16
  9. package/dist/DataGridHeaderCell/DataGridHeaderCell.d.ts +0 -37
  10. package/dist/DatePickerListItem/DatePickerListItem.d.ts +2 -22
  11. package/dist/DatePickerMenu/DatePickerMenu.d.ts +2 -22
  12. package/dist/Dot/Dot.d.ts +11 -4
  13. package/dist/FilledStatusIcons/FilledStatusIcons.d.ts +41 -0
  14. package/dist/GeneralAvatar/GeneralAvatar.d.ts +1 -7
  15. package/dist/InputField/InputField.d.ts +12 -1
  16. package/dist/ListItemButton/ListItemButton.d.ts +12 -1
  17. package/dist/MenuItem/MenuItem.d.ts +31 -9
  18. package/dist/NavigationAvatar/NavigationAvatar.d.ts +3 -3
  19. package/dist/NavigationItem/NavigationItem.d.ts +21 -2
  20. package/dist/NeoActionsCell/NeoActionsCell.d.ts +9 -0
  21. package/dist/NeoAvatarCell/NeoAvatarCell.d.ts +25 -0
  22. package/dist/NeoIconCell/NeoIconCell.d.ts +14 -0
  23. package/dist/NeoLogoCell/NeoLogoCell.d.ts +24 -0
  24. package/dist/NeoProgressCell/NeoProgressCell.d.ts +21 -0
  25. package/dist/NeoStatusCell/NeoStatusCell.d.ts +30 -0
  26. package/dist/PageContent/PageContent.d.ts +12 -1
  27. package/dist/RadioButtonWithText/RadioButtonWithText.d.ts +2 -22
  28. package/dist/RipplingDot/RipplingDot.d.ts +12 -0
  29. package/dist/SelectField/SelectField.d.ts +64 -0
  30. package/dist/SideNav/NeoSideNavContext.d.ts +5 -0
  31. package/dist/SideNav/SideNav.d.ts +18 -25
  32. package/dist/TabPanel/TabPanel.d.ts +47 -0
  33. package/dist/Table/Table.d.ts +64 -0
  34. package/dist/Tabs/Tabs.d.ts +1 -1
  35. package/dist/Tag/Tag.d.ts +1 -2
  36. package/dist/ToggleButton/ToggleButton.d.ts +13 -18
  37. package/dist/ToggleButtonGroup/ToggleButtonGroup.d.ts +26 -0
  38. package/dist/ToggleButtonWithText/ToggleButtonWithText.d.ts +2 -22
  39. package/dist/Tooltip/Tooltip.d.ts +8 -5
  40. package/dist/TopNav/TopNav.d.ts +2 -22
  41. package/dist/TourModal/TourModal.d.ts +2 -22
  42. package/dist/TypologyControl/TypologyControl.d.ts +1 -1
  43. package/dist/VibratingDot/VibratingDot.d.ts +12 -0
  44. package/dist/index.d.ts +660 -143
  45. package/dist/index.esm.js +1376 -609
  46. package/dist/index.esm.js.map +1 -1
  47. package/dist/index.js +1400 -604
  48. package/dist/index.js.map +1 -1
  49. package/dist/utils/colorHelpers.d.ts +6 -0
  50. package/package.json +5 -5
  51. package/dist/utils/avatarColors.d.ts +0 -7
package/dist/index.js CHANGED
@@ -38,7 +38,6 @@ var PickersCalendarHeader = require('@mui/x-date-pickers/PickersCalendarHeader')
38
38
  var PickersShortcuts = require('@mui/x-date-pickers/PickersShortcuts');
39
39
  var DateRangePicker = require('@mui/x-date-pickers-pro/DateRangePicker');
40
40
  var DateRangePickerDay = require('@mui/x-date-pickers-pro/DateRangePickerDay');
41
- var Badge = require('@mui/material/Badge');
42
41
  var LinearProgress = require('@mui/material/LinearProgress');
43
42
  var Paper = require('@mui/material/Paper');
44
43
  var Stack = require('@mui/material/Stack');
@@ -54,9 +53,16 @@ var Dialog = require('@mui/material/Dialog');
54
53
  var DialogActions = require('@mui/material/DialogActions');
55
54
  var DialogContent = require('@mui/material/DialogContent');
56
55
  var Fab = require('@mui/material/Fab');
57
- var Fade = require('@mui/material/Fade');
56
+ var Fade$1 = require('@mui/material/Fade');
58
57
  var Radio = require('@mui/material/Radio');
58
+ var material = require('@mui/material');
59
59
  var Skeleton = require('@mui/material/Skeleton');
60
+ var MuiTable = require('@mui/material/Table');
61
+ var TableBody = require('@mui/material/TableBody');
62
+ var TableCell = require('@mui/material/TableCell');
63
+ var TableContainer = require('@mui/material/TableContainer');
64
+ var TableHead = require('@mui/material/TableHead');
65
+ var TableRow = require('@mui/material/TableRow');
60
66
  var MuiTab = require('@mui/material/Tab');
61
67
  var MuiTabs = require('@mui/material/Tabs');
62
68
  var Switch = require('@mui/material/Switch');
@@ -64,8 +70,37 @@ var hooks = require('@mui/x-tree-view/hooks');
64
70
  var TreeItem = require('@mui/x-tree-view/TreeItem');
65
71
  var RichTreeViewPro = require('@mui/x-tree-view-pro/RichTreeViewPro');
66
72
 
67
- const StyledChip$2 = styles.styled(Chip)(({ theme }) => ({
68
- height: 24,
73
+ const STATUS_COLOR_CLASSES = [
74
+ [Chip.chipClasses.colorDefault, neoDesign.semanticColors.status.neutral],
75
+ [Chip.chipClasses.colorError, neoDesign.semanticColors.status.error],
76
+ [Chip.chipClasses.colorWarning, neoDesign.semanticColors.status.warning],
77
+ [Chip.chipClasses.colorSuccess, neoDesign.semanticColors.status.success],
78
+ [Chip.chipClasses.colorInfo, neoDesign.semanticColors.status.info],
79
+ ];
80
+ const outlinedColorOverrides = {
81
+ backgroundColor: 'transparent',
82
+ color: neoDesign.semanticColors.typography.bodySecondary,
83
+ border: `1px solid ${neoDesign.semanticColors.border.secondary}`,
84
+ [`& .${Chip.chipClasses.icon}, & .${Chip.chipClasses.deleteIcon}`]: {
85
+ color: neoDesign.semanticColors.typography.bodySecondary,
86
+ },
87
+ };
88
+ const filledColorRules = Object.fromEntries(STATUS_COLOR_CLASSES.map(([className, palette]) => [
89
+ `&.${className}`,
90
+ {
91
+ backgroundColor: palette.light,
92
+ color: palette.dark,
93
+ border: `1px solid ${palette.transparent}`,
94
+ [`& .${Chip.chipClasses.icon}, & .${Chip.chipClasses.deleteIcon}`]: {
95
+ color: palette.dark,
96
+ },
97
+ },
98
+ ]));
99
+ const outlinedColorRules = Object.fromEntries(STATUS_COLOR_CLASSES.map(([className]) => [`&.${className}`, outlinedColorOverrides]));
100
+ const StyledChip$3 = styles.styled(Chip, {
101
+ shouldForwardProp: prop => prop !== 'badgeSize' && prop !== 'badgeVariant',
102
+ })(({ theme, badgeSize, badgeVariant }) => ({
103
+ height: badgeSize === 'small' ? 20 : 24,
69
104
  paddingTop: neoDesign.spacing.spacing_1_4,
70
105
  paddingBottom: neoDesign.spacing.spacing_1_4,
71
106
  paddingLeft: neoDesign.spacing.spacing_1,
@@ -93,51 +128,7 @@ const StyledChip$2 = styles.styled(Chip)(({ theme }) => ({
93
128
  width: 12,
94
129
  height: 12,
95
130
  },
96
- // Default (Neutral) state
97
- [`&.${Chip.chipClasses.colorDefault}`]: {
98
- backgroundColor: neoDesign.semanticColors.status.neutral.light,
99
- color: neoDesign.semanticColors.status.neutral.dark,
100
- border: `1px solid ${neoDesign.semanticColors.status.neutral.default}80`,
101
- [`& .${Chip.chipClasses.icon}, & .${Chip.chipClasses.deleteIcon}`]: {
102
- color: neoDesign.semanticColors.status.neutral.dark,
103
- },
104
- },
105
- // Error state
106
- [`&.${Chip.chipClasses.colorError}`]: {
107
- backgroundColor: neoDesign.semanticColors.status.error.light,
108
- color: neoDesign.semanticColors.status.error.dark,
109
- border: `1px solid ${neoDesign.semanticColors.status.error.default}80`,
110
- [`& .${Chip.chipClasses.icon}, & .${Chip.chipClasses.deleteIcon}`]: {
111
- color: neoDesign.semanticColors.status.error.dark,
112
- },
113
- },
114
- // Warning state
115
- [`&.${Chip.chipClasses.colorWarning}`]: {
116
- backgroundColor: neoDesign.semanticColors.status.warning.light,
117
- color: neoDesign.semanticColors.status.warning.dark,
118
- border: `1px solid ${neoDesign.semanticColors.status.warning.default}80`,
119
- [`& .${Chip.chipClasses.icon}, & .${Chip.chipClasses.deleteIcon}`]: {
120
- color: neoDesign.semanticColors.status.warning.dark,
121
- },
122
- },
123
- // Success state
124
- [`&.${Chip.chipClasses.colorSuccess}`]: {
125
- backgroundColor: neoDesign.semanticColors.status.success.light,
126
- color: neoDesign.semanticColors.status.success.dark,
127
- border: `1px solid ${neoDesign.semanticColors.status.success.default}80`,
128
- [`& .${Chip.chipClasses.icon}, & .${Chip.chipClasses.deleteIcon}`]: {
129
- color: neoDesign.semanticColors.status.success.dark,
130
- },
131
- },
132
- // Info state
133
- [`&.${Chip.chipClasses.colorInfo}`]: {
134
- backgroundColor: neoDesign.semanticColors.status.info.light,
135
- color: neoDesign.semanticColors.status.info.dark,
136
- border: `1px solid ${neoDesign.semanticColors.status.info.default}80`,
137
- [`& .${Chip.chipClasses.icon}, & .${Chip.chipClasses.deleteIcon}`]: {
138
- color: neoDesign.semanticColors.status.info.dark,
139
- },
140
- },
131
+ ...(badgeVariant === 'outlined' ? outlinedColorRules : filledColorRules),
141
132
  }));
142
133
  /**
143
134
  * NeoBadge - Status badge component based on MUI Chip
@@ -150,23 +141,26 @@ const StyledChip$2 = styles.styled(Chip)(({ theme }) => ({
150
141
  * - TrailingIcon → deleteIcon prop (pass React element)
151
142
  * - Label → label prop
152
143
  */
153
- const NeoBadge = (props) => {
154
- return jsxRuntime.jsx(StyledChip$2, { ...props });
144
+ const NeoBadge = ({ size = 'medium', variant = 'filled', ...props }) => {
145
+ return jsxRuntime.jsx(StyledChip$3, { ...props, badgeSize: size, badgeVariant: variant });
155
146
  };
156
147
  NeoBadge.displayName = 'NeoBadge';
157
148
 
149
+ const djb2Hash = (str) => {
150
+ let hash = 5381;
151
+ for (let i = 0; i < str.length; i++) {
152
+ hash = (hash * 33) ^ str.charCodeAt(i);
153
+ }
154
+ return hash >>> 0;
155
+ };
158
156
  /**
159
- * Shared color palette for avatar components (GeneralAvatar, NavigationAvatar).
160
- * Maps color index (1-7) to background color token pairs.
157
+ * Deterministically derives an HSL background color from a string seed.
158
+ * Produces pastel colors matching the aesthetic of the status.avatar.initials
159
+ * semantic tokens (fixed 80% saturation, 90% lightness; only hue varies).
161
160
  */
162
- const avatarColorPalette = {
163
- 1: { bg: neoDesign.colors.digitalBlue[100] },
164
- 2: { bg: neoDesign.colors.digitalGreen[100] },
165
- 3: { bg: neoDesign.colors.gold[100] },
166
- 4: { bg: neoDesign.colors.red[100] },
167
- 5: { bg: neoDesign.colors.violet[100] },
168
- 6: { bg: neoDesign.colors.tealGreen[100] },
169
- 7: { bg: neoDesign.colors.orange[100] },
161
+ const avatarColorFromSeed = (seed) => {
162
+ const hue = seed ? djb2Hash(seed) % 360 : 235;
163
+ return `hsl(${hue}, 80%, 90%)`;
170
164
  };
171
165
 
172
166
  /**
@@ -181,14 +175,13 @@ const focusRingStyles = {
181
175
  };
182
176
 
183
177
  const sizeConfig$1 = {
184
- small: { width: neoDesign.spacing.spacing_4, height: neoDesign.spacing.spacing_4, fontSize: neoDesign.typography.fontSize.xs },
178
+ small: { width: neoDesign.spacing.spacing_4, height: neoDesign.spacing.spacing_4, fontSize: neoDesign.typography.fontSize.sm },
185
179
  medium: { width: neoDesign.spacing.spacing_5, height: neoDesign.spacing.spacing_5, fontSize: neoDesign.typography.fontSize.sm },
186
180
  };
187
181
  const StyledAvatar = styles.styled(MuiAvatar, {
188
- shouldForwardProp: prop => prop !== 'avatarSize' && prop !== 'colorIndex',
189
- })(({ theme, avatarSize, colorIndex }) => {
182
+ shouldForwardProp: prop => prop !== 'avatarSize' && prop !== 'backgroundColor',
183
+ })(({ theme, avatarSize, backgroundColor }) => {
190
184
  const size = sizeConfig$1[avatarSize];
191
- const palette = avatarColorPalette[colorIndex];
192
185
  return {
193
186
  boxSizing: 'border-box',
194
187
  width: size.width,
@@ -198,7 +191,7 @@ const StyledAvatar = styles.styled(MuiAvatar, {
198
191
  fontWeight: neoDesign.typography.fontWeight.regular,
199
192
  lineHeight: 1,
200
193
  color: neoDesign.semanticColors.typography.body,
201
- backgroundColor: palette ? palette.bg : undefined,
194
+ backgroundColor,
202
195
  border: `1px solid ${neoDesign.semanticColors.border.primary}`,
203
196
  '&:focus-visible': {
204
197
  ...focusRingStyles,
@@ -211,8 +204,9 @@ const StyledAvatar = styles.styled(MuiAvatar, {
211
204
  *
212
205
  * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=9600-185
213
206
  */
214
- const NeoGeneralAvatar = ({ size = 'medium', colorIndex = 0, children, ...props }) => {
215
- return (jsxRuntime.jsx(StyledAvatar, { avatarSize: size, colorIndex: colorIndex, ...props, children: children }));
207
+ const NeoGeneralAvatar = ({ size = 'medium', alt, children, ...props }) => {
208
+ const backgroundColor = avatarColorFromSeed(alt);
209
+ return (jsxRuntime.jsx(StyledAvatar, { avatarSize: size, backgroundColor: backgroundColor, alt: alt, ...props, children: children }));
216
210
  };
217
211
  NeoGeneralAvatar.displayName = 'NeoGeneralAvatar';
218
212
 
@@ -269,22 +263,6 @@ const NeoDataGridCellContent = ({ children, ...props }) => {
269
263
  return jsxRuntime.jsx(CellContentContainer, { ...props, children: children });
270
264
  };
271
265
  NeoDataGridCellContent.displayName = 'NeoDataGridCellContent';
272
- /**
273
- * Utility function to get DataGrid sx styles for consistent cell appearance
274
- *
275
- * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=4212-41631
276
- *
277
- * Apply this to DataGrid's `sx` prop to ensure cells are properly aligned and styled.
278
- *
279
- * @param size - Row size variant (affects row height)
280
- * @returns SxProps for DataGrid
281
- *
282
- * @example
283
- * <DataGrid
284
- * rows={rows}
285
- * columns={columns}
286
- * />
287
- */
288
266
  /**
289
267
  * Row height configuration for DataGrid size variants (from Figma specs)
290
268
  * - compact: 42px
@@ -478,7 +456,7 @@ const NeoActivityIndicatorCell = ({ event = 'commit-job', secondaryEvent, scene
478
456
  NeoActivityIndicatorCell.displayName = 'NeoActivityIndicatorCell';
479
457
 
480
458
  /**
481
- * @license lucide-react v1.7.0 - ISC
459
+ * @license lucide-react v1.16.0 - ISC
482
460
  *
483
461
  * This source code is licensed under the ISC license.
484
462
  * See the LICENSE file in the root directory of this source tree.
@@ -489,7 +467,7 @@ const mergeClasses = (...classes) => classes.filter((className, index, array) =>
489
467
  }).join(" ").trim();
490
468
 
491
469
  /**
492
- * @license lucide-react v1.7.0 - ISC
470
+ * @license lucide-react v1.16.0 - ISC
493
471
  *
494
472
  * This source code is licensed under the ISC license.
495
473
  * See the LICENSE file in the root directory of this source tree.
@@ -498,7 +476,7 @@ const mergeClasses = (...classes) => classes.filter((className, index, array) =>
498
476
  const toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
499
477
 
500
478
  /**
501
- * @license lucide-react v1.7.0 - ISC
479
+ * @license lucide-react v1.16.0 - ISC
502
480
  *
503
481
  * This source code is licensed under the ISC license.
504
482
  * See the LICENSE file in the root directory of this source tree.
@@ -510,7 +488,7 @@ const toCamelCase = (string) => string.replace(
510
488
  );
511
489
 
512
490
  /**
513
- * @license lucide-react v1.7.0 - ISC
491
+ * @license lucide-react v1.16.0 - ISC
514
492
  *
515
493
  * This source code is licensed under the ISC license.
516
494
  * See the LICENSE file in the root directory of this source tree.
@@ -523,7 +501,7 @@ const toPascalCase = (string) => {
523
501
  };
524
502
 
525
503
  /**
526
- * @license lucide-react v1.7.0 - ISC
504
+ * @license lucide-react v1.16.0 - ISC
527
505
  *
528
506
  * This source code is licensed under the ISC license.
529
507
  * See the LICENSE file in the root directory of this source tree.
@@ -542,7 +520,7 @@ var defaultAttributes = {
542
520
  };
543
521
 
544
522
  /**
545
- * @license lucide-react v1.7.0 - ISC
523
+ * @license lucide-react v1.16.0 - ISC
546
524
  *
547
525
  * This source code is licensed under the ISC license.
548
526
  * See the LICENSE file in the root directory of this source tree.
@@ -592,7 +570,7 @@ const Icon = React.forwardRef(
592
570
  );
593
571
 
594
572
  /**
595
- * @license lucide-react v1.7.0 - ISC
573
+ * @license lucide-react v1.16.0 - ISC
596
574
  *
597
575
  * This source code is licensed under the ISC license.
598
576
  * See the LICENSE file in the root directory of this source tree.
@@ -617,42 +595,42 @@ const createLucideIcon = (iconName, iconNode) => {
617
595
  };
618
596
 
619
597
  /**
620
- * @license lucide-react v1.7.0 - ISC
598
+ * @license lucide-react v1.16.0 - ISC
621
599
  *
622
600
  * This source code is licensed under the ISC license.
623
601
  * See the LICENSE file in the root directory of this source tree.
624
602
  */
625
603
 
626
604
 
627
- const __iconNode$k = [
605
+ const __iconNode$p = [
628
606
  ["path", { d: "M12 5v14", key: "s699le" }],
629
607
  ["path", { d: "m19 12-7 7-7-7", key: "1idqje" }]
630
608
  ];
631
- const ArrowDown = createLucideIcon("arrow-down", __iconNode$k);
609
+ const ArrowDown = createLucideIcon("arrow-down", __iconNode$p);
632
610
 
633
611
  /**
634
- * @license lucide-react v1.7.0 - ISC
612
+ * @license lucide-react v1.16.0 - ISC
635
613
  *
636
614
  * This source code is licensed under the ISC license.
637
615
  * See the LICENSE file in the root directory of this source tree.
638
616
  */
639
617
 
640
618
 
641
- const __iconNode$j = [
619
+ const __iconNode$o = [
642
620
  ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
643
621
  ["path", { d: "M12 19V5", key: "x0mq9r" }]
644
622
  ];
645
- const ArrowUp = createLucideIcon("arrow-up", __iconNode$j);
623
+ const ArrowUp = createLucideIcon("arrow-up", __iconNode$o);
646
624
 
647
625
  /**
648
- * @license lucide-react v1.7.0 - ISC
626
+ * @license lucide-react v1.16.0 - ISC
649
627
  *
650
628
  * This source code is licensed under the ISC license.
651
629
  * See the LICENSE file in the root directory of this source tree.
652
630
  */
653
631
 
654
632
 
655
- const __iconNode$i = [
633
+ const __iconNode$n = [
656
634
  [
657
635
  "path",
658
636
  {
@@ -663,17 +641,17 @@ const __iconNode$i = [
663
641
  ["line", { x1: "12", x2: "12", y1: "16", y2: "12", key: "1y1yb1" }],
664
642
  ["line", { x1: "12", x2: "12.01", y1: "8", y2: "8", key: "110wyk" }]
665
643
  ];
666
- const BadgeInfo = createLucideIcon("badge-info", __iconNode$i);
644
+ const BadgeInfo = createLucideIcon("badge-info", __iconNode$n);
667
645
 
668
646
  /**
669
- * @license lucide-react v1.7.0 - ISC
647
+ * @license lucide-react v1.16.0 - ISC
670
648
  *
671
649
  * This source code is licensed under the ISC license.
672
650
  * See the LICENSE file in the root directory of this source tree.
673
651
  */
674
652
 
675
653
 
676
- const __iconNode$h = [
654
+ const __iconNode$m = [
677
655
  ["path", { d: "M8 2v4", key: "1cmpym" }],
678
656
  ["path", { d: "M16 2v4", key: "4m81vk" }],
679
657
  ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
@@ -685,181 +663,252 @@ const __iconNode$h = [
685
663
  ["path", { d: "M12 18h.01", key: "mhygvu" }],
686
664
  ["path", { d: "M16 18h.01", key: "kzsmim" }]
687
665
  ];
688
- const CalendarDays = createLucideIcon("calendar-days", __iconNode$h);
666
+ const CalendarDays = createLucideIcon("calendar-days", __iconNode$m);
689
667
 
690
668
  /**
691
- * @license lucide-react v1.7.0 - ISC
669
+ * @license lucide-react v1.16.0 - ISC
692
670
  *
693
671
  * This source code is licensed under the ISC license.
694
672
  * See the LICENSE file in the root directory of this source tree.
695
673
  */
696
674
 
697
675
 
698
- const __iconNode$g = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
699
- const ChevronDown = createLucideIcon("chevron-down", __iconNode$g);
676
+ const __iconNode$l = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
677
+ const ChevronDown = createLucideIcon("chevron-down", __iconNode$l);
700
678
 
701
679
  /**
702
- * @license lucide-react v1.7.0 - ISC
680
+ * @license lucide-react v1.16.0 - ISC
703
681
  *
704
682
  * This source code is licensed under the ISC license.
705
683
  * See the LICENSE file in the root directory of this source tree.
706
684
  */
707
685
 
708
686
 
709
- const __iconNode$f = [["path", { d: "m15 18-6-6 6-6", key: "1wnfg3" }]];
710
- const ChevronLeft = createLucideIcon("chevron-left", __iconNode$f);
687
+ const __iconNode$k = [["path", { d: "m15 18-6-6 6-6", key: "1wnfg3" }]];
688
+ const ChevronLeft = createLucideIcon("chevron-left", __iconNode$k);
711
689
 
712
690
  /**
713
- * @license lucide-react v1.7.0 - ISC
691
+ * @license lucide-react v1.16.0 - ISC
714
692
  *
715
693
  * This source code is licensed under the ISC license.
716
694
  * See the LICENSE file in the root directory of this source tree.
717
695
  */
718
696
 
719
697
 
720
- const __iconNode$e = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
721
- const ChevronRight = createLucideIcon("chevron-right", __iconNode$e);
698
+ const __iconNode$j = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
699
+ const ChevronRight = createLucideIcon("chevron-right", __iconNode$j);
722
700
 
723
701
  /**
724
- * @license lucide-react v1.7.0 - ISC
702
+ * @license lucide-react v1.16.0 - ISC
725
703
  *
726
704
  * This source code is licensed under the ISC license.
727
705
  * See the LICENSE file in the root directory of this source tree.
728
706
  */
729
707
 
730
708
 
731
- const __iconNode$d = [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]];
732
- const ChevronUp = createLucideIcon("chevron-up", __iconNode$d);
709
+ const __iconNode$i = [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]];
710
+ const ChevronUp = createLucideIcon("chevron-up", __iconNode$i);
733
711
 
734
712
  /**
735
- * @license lucide-react v1.7.0 - ISC
713
+ * @license lucide-react v1.16.0 - ISC
736
714
  *
737
715
  * This source code is licensed under the ISC license.
738
716
  * See the LICENSE file in the root directory of this source tree.
739
717
  */
740
718
 
741
719
 
742
- const __iconNode$c = [
720
+ const __iconNode$h = [
743
721
  ["path", { d: "m7 15 5 5 5-5", key: "1hf1tw" }],
744
722
  ["path", { d: "m7 9 5-5 5 5", key: "sgt6xg" }]
745
723
  ];
746
- const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$c);
724
+ const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$h);
747
725
 
748
726
  /**
749
- * @license lucide-react v1.7.0 - ISC
727
+ * @license lucide-react v1.16.0 - ISC
750
728
  *
751
729
  * This source code is licensed under the ISC license.
752
730
  * See the LICENSE file in the root directory of this source tree.
753
731
  */
754
732
 
755
733
 
756
- const __iconNode$b = [
734
+ const __iconNode$g = [
757
735
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
758
736
  ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
759
737
  ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
760
738
  ];
761
- const CircleAlert = createLucideIcon("circle-alert", __iconNode$b);
739
+ const CircleAlert = createLucideIcon("circle-alert", __iconNode$g);
762
740
 
763
741
  /**
764
- * @license lucide-react v1.7.0 - ISC
742
+ * @license lucide-react v1.16.0 - ISC
765
743
  *
766
744
  * This source code is licensed under the ISC license.
767
745
  * See the LICENSE file in the root directory of this source tree.
768
746
  */
769
747
 
770
748
 
771
- const __iconNode$a = [
749
+ const __iconNode$f = [
772
750
  ["path", { d: "M21.801 10A10 10 0 1 1 17 3.335", key: "yps3ct" }],
773
751
  ["path", { d: "m9 11 3 3L22 4", key: "1pflzl" }]
774
752
  ];
775
- const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$a);
753
+ const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$f);
776
754
 
777
755
  /**
778
- * @license lucide-react v1.7.0 - ISC
756
+ * @license lucide-react v1.16.0 - ISC
779
757
  *
780
758
  * This source code is licensed under the ISC license.
781
759
  * See the LICENSE file in the root directory of this source tree.
782
760
  */
783
761
 
784
762
 
785
- const __iconNode$9 = [
763
+ const __iconNode$e = [
786
764
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
787
765
  ["path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3", key: "1u773s" }],
788
766
  ["path", { d: "M12 17h.01", key: "p32p05" }]
789
767
  ];
790
- const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$9);
768
+ const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$e);
791
769
 
792
770
  /**
793
- * @license lucide-react v1.7.0 - ISC
771
+ * @license lucide-react v1.16.0 - ISC
794
772
  *
795
773
  * This source code is licensed under the ISC license.
796
774
  * See the LICENSE file in the root directory of this source tree.
797
775
  */
798
776
 
799
777
 
800
- const __iconNode$8 = [
778
+ const __iconNode$d = [
801
779
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
802
780
  ["path", { d: "M9 3v18", key: "fh3hqa" }],
803
781
  ["path", { d: "M15 3v18", key: "14nvp0" }]
804
782
  ];
805
- const Columns3 = createLucideIcon("columns-3", __iconNode$8);
783
+ const Columns3 = createLucideIcon("columns-3", __iconNode$d);
806
784
 
807
785
  /**
808
- * @license lucide-react v1.7.0 - ISC
786
+ * @license lucide-react v1.16.0 - ISC
809
787
  *
810
788
  * This source code is licensed under the ISC license.
811
789
  * See the LICENSE file in the root directory of this source tree.
812
790
  */
813
791
 
814
792
 
815
- const __iconNode$7 = [
793
+ const __iconNode$c = [
816
794
  ["path", { d: "M2 5h20", key: "1fs1ex" }],
817
795
  ["path", { d: "M6 12h12", key: "8npq4p" }],
818
796
  ["path", { d: "M9 19h6", key: "456am0" }]
819
797
  ];
820
- const ListFilter = createLucideIcon("list-filter", __iconNode$7);
798
+ const ListFilter = createLucideIcon("list-filter", __iconNode$c);
821
799
 
822
800
  /**
823
- * @license lucide-react v1.7.0 - ISC
801
+ * @license lucide-react v1.16.0 - ISC
824
802
  *
825
803
  * This source code is licensed under the ISC license.
826
804
  * See the LICENSE file in the root directory of this source tree.
827
805
  */
828
806
 
829
807
 
830
- const __iconNode$6 = [["path", { d: "M5 12h14", key: "1ays0h" }]];
831
- const Minus = createLucideIcon("minus", __iconNode$6);
808
+ const __iconNode$b = [["path", { d: "M5 12h14", key: "1ays0h" }]];
809
+ const Minus = createLucideIcon("minus", __iconNode$b);
832
810
 
833
811
  /**
834
- * @license lucide-react v1.7.0 - ISC
812
+ * @license lucide-react v1.16.0 - ISC
835
813
  *
836
814
  * This source code is licensed under the ISC license.
837
815
  * See the LICENSE file in the root directory of this source tree.
838
816
  */
839
817
 
840
818
 
841
- const __iconNode$5 = [
819
+ const __iconNode$a = [
820
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
821
+ ["path", { d: "M9 3v18", key: "fh3hqa" }],
822
+ ["path", { d: "m16 15-3-3 3-3", key: "14y99z" }]
823
+ ];
824
+ const PanelLeftClose = createLucideIcon("panel-left-close", __iconNode$a);
825
+
826
+ /**
827
+ * @license lucide-react v1.16.0 - ISC
828
+ *
829
+ * This source code is licensed under the ISC license.
830
+ * See the LICENSE file in the root directory of this source tree.
831
+ */
832
+
833
+
834
+ const __iconNode$9 = [
835
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
836
+ ["path", { d: "M9 3v18", key: "fh3hqa" }],
837
+ ["path", { d: "m14 9 3 3-3 3", key: "8010ee" }]
838
+ ];
839
+ const PanelLeftOpen = createLucideIcon("panel-left-open", __iconNode$9);
840
+
841
+ /**
842
+ * @license lucide-react v1.16.0 - ISC
843
+ *
844
+ * This source code is licensed under the ISC license.
845
+ * See the LICENSE file in the root directory of this source tree.
846
+ */
847
+
848
+
849
+ const __iconNode$8 = [
842
850
  ["path", { d: "M5 12h14", key: "1ays0h" }],
843
851
  ["path", { d: "M12 5v14", key: "s699le" }]
844
852
  ];
845
- const Plus = createLucideIcon("plus", __iconNode$5);
853
+ const Plus = createLucideIcon("plus", __iconNode$8);
846
854
 
847
855
  /**
848
- * @license lucide-react v1.7.0 - ISC
856
+ * @license lucide-react v1.16.0 - ISC
849
857
  *
850
858
  * This source code is licensed under the ISC license.
851
859
  * See the LICENSE file in the root directory of this source tree.
852
860
  */
853
861
 
854
862
 
855
- const __iconNode$4 = [
863
+ const __iconNode$7 = [
856
864
  ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
857
865
  ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
858
866
  ];
859
- const Search = createLucideIcon("search", __iconNode$4);
867
+ const Search = createLucideIcon("search", __iconNode$7);
868
+
869
+ /**
870
+ * @license lucide-react v1.16.0 - ISC
871
+ *
872
+ * This source code is licensed under the ISC license.
873
+ * See the LICENSE file in the root directory of this source tree.
874
+ */
875
+
876
+
877
+ const __iconNode$6 = [
878
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
879
+ ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
880
+ ];
881
+ const SquareCheck = createLucideIcon("square-check", __iconNode$6);
882
+
883
+ /**
884
+ * @license lucide-react v1.16.0 - ISC
885
+ *
886
+ * This source code is licensed under the ISC license.
887
+ * See the LICENSE file in the root directory of this source tree.
888
+ */
889
+
890
+
891
+ const __iconNode$5 = [
892
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
893
+ ["path", { d: "M8 12h8", key: "1wcyev" }]
894
+ ];
895
+ const SquareMinus = createLucideIcon("square-minus", __iconNode$5);
896
+
897
+ /**
898
+ * @license lucide-react v1.16.0 - ISC
899
+ *
900
+ * This source code is licensed under the ISC license.
901
+ * See the LICENSE file in the root directory of this source tree.
902
+ */
903
+
904
+
905
+ const __iconNode$4 = [
906
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }]
907
+ ];
908
+ const Square = createLucideIcon("square", __iconNode$4);
860
909
 
861
910
  /**
862
- * @license lucide-react v1.7.0 - ISC
911
+ * @license lucide-react v1.16.0 - ISC
863
912
  *
864
913
  * This source code is licensed under the ISC license.
865
914
  * See the LICENSE file in the root directory of this source tree.
@@ -876,7 +925,7 @@ const __iconNode$3 = [
876
925
  const Trash2 = createLucideIcon("trash-2", __iconNode$3);
877
926
 
878
927
  /**
879
- * @license lucide-react v1.7.0 - ISC
928
+ * @license lucide-react v1.16.0 - ISC
880
929
  *
881
930
  * This source code is licensed under the ISC license.
882
931
  * See the LICENSE file in the root directory of this source tree.
@@ -897,7 +946,7 @@ const __iconNode$2 = [
897
946
  const TriangleAlert = createLucideIcon("triangle-alert", __iconNode$2);
898
947
 
899
948
  /**
900
- * @license lucide-react v1.7.0 - ISC
949
+ * @license lucide-react v1.16.0 - ISC
901
950
  *
902
951
  * This source code is licensed under the ISC license.
903
952
  * See the LICENSE file in the root directory of this source tree.
@@ -916,7 +965,7 @@ const __iconNode$1 = [
916
965
  const WifiOff = createLucideIcon("wifi-off", __iconNode$1);
917
966
 
918
967
  /**
919
- * @license lucide-react v1.7.0 - ISC
968
+ * @license lucide-react v1.16.0 - ISC
920
969
  *
921
970
  * This source code is licensed under the ISC license.
922
971
  * See the LICENSE file in the root directory of this source tree.
@@ -939,22 +988,29 @@ const intentColors$2 = {
939
988
  };
940
989
  // biome-ignore lint/suspicious/noExplicitAny: Type cast required to override MUI Alert variant type without global augmentation
941
990
  const StyledAlert$2 = styles.styled(Alert, {
942
- shouldForwardProp: prop => prop !== 'intent' && prop !== 'alertType',
943
- })(({ theme, intent = 'success', alertType = 'outlined' }) => {
991
+ shouldForwardProp: prop => prop !== 'intent' && prop !== 'alertType' && prop !== 'alertSize' && prop !== 'hasChildren',
992
+ })(({ theme, intent = 'success', alertType = 'outlined', alertSize = 'default', hasChildren = false, }) => {
944
993
  const palette = intentColors$2[intent];
945
994
  const isFilled = alertType === 'filled';
995
+ const isCompact = alertSize === 'compact';
946
996
  const iconColor = isFilled ? neoDesign.semanticColors.typography.tooltip : palette.default;
947
- const messageColor = isFilled ? neoDesign.semanticColors.typography.tooltip : neoDesign.semanticColors.typography.body;
997
+ const messageColor = isFilled
998
+ ? neoDesign.semanticColors.typography.tooltip
999
+ : neoDesign.semanticColors.typography.body;
948
1000
  return {
949
- height: neoDesign.spacing.spacing_8,
1001
+ ...(isCompact
1002
+ ? { minHeight: neoDesign.spacing.spacing_5 }
1003
+ : hasChildren
1004
+ ? { minHeight: neoDesign.spacing.spacing_8, height: 'auto' }
1005
+ : { height: neoDesign.spacing.spacing_8 }),
950
1006
  width: '100%',
951
1007
  borderRadius: neoDesign.borderRadius.xS,
952
- alignItems: 'center',
1008
+ alignItems: hasChildren ? 'flex-start' : 'center',
953
1009
  fontFamily: neoDesign.typography.fontFamily.body,
954
1010
  fontSize: theme.typography.pxToRem(neoDesign.typography.fontSize.default),
955
1011
  fontWeight: neoDesign.typography.fontWeight.semiBold,
956
1012
  lineHeight: 1.5,
957
- padding: theme.spacing(0, 2),
1013
+ padding: hasChildren ? theme.spacing(1.5, 2) : theme.spacing(0, 2),
958
1014
  backgroundColor: isFilled ? palette.dark : palette.light,
959
1015
  border: isFilled ? 'none' : `1px solid ${palette.transparent}`,
960
1016
  color: isFilled ? neoDesign.semanticColors.typography.tooltip : neoDesign.semanticColors.typography.body,
@@ -971,7 +1027,7 @@ const StyledAlert$2 = styles.styled(Alert, {
971
1027
  flex: 1,
972
1028
  display: 'flex',
973
1029
  flexDirection: 'column',
974
- justifyContent: 'center',
1030
+ justifyContent: hasChildren ? 'flex-start' : 'center',
975
1031
  '& span:last-child': {
976
1032
  fontSize: theme.typography.pxToRem(neoDesign.typography.fontSize.sm),
977
1033
  fontWeight: neoDesign.typography.fontWeight.medium,
@@ -1009,9 +1065,9 @@ const iconMap = {
1009
1065
  * - Show supporting text → description prop presence
1010
1066
  * - Show Button → action prop presence
1011
1067
  */
1012
- const NeoAlert = ({ intent = 'success', type = 'outlined', title, description, icon, action, ...props }) => {
1068
+ const NeoAlert = ({ intent = 'success', type = 'outlined', size = 'default', title, description, icon, action, children, ...props }) => {
1013
1069
  const defaultIcon = iconMap[intent];
1014
- return (jsxRuntime.jsxs(StyledAlert$2, { ...props, intent: intent, alertType: type, icon: icon ?? defaultIcon, action: action, children: [jsxRuntime.jsx("span", { children: title }), description && jsxRuntime.jsx("span", { children: description })] }));
1070
+ return (jsxRuntime.jsxs(StyledAlert$2, { ...props, intent: intent, alertType: type, alertSize: size, hasChildren: Boolean(children), icon: icon ?? defaultIcon, action: action, children: [jsxRuntime.jsx("span", { children: title }), description && jsxRuntime.jsx("span", { children: description }), children] }));
1015
1071
  };
1016
1072
  NeoAlert.displayName = 'NeoAlert';
1017
1073
 
@@ -1038,38 +1094,43 @@ const StyledAlert$1 = styles.styled(Alert, {
1038
1094
  };
1039
1095
  return {
1040
1096
  width: '100%',
1041
- minHeight: 52,
1042
- paddingTop: neoDesign.spacing.spacing_3_4,
1043
- paddingBottom: neoDesign.spacing.spacing_3_4,
1044
- paddingLeft: neoDesign.spacing.spacing_3,
1045
- paddingRight: neoDesign.spacing.spacing_3,
1046
- gap: neoDesign.spacing.spacing_2,
1097
+ // Include padding in the width so the full-width banner never overflows its
1098
+ // container (don't rely on a global border-box reset being present).
1099
+ boxSizing: 'border-box',
1100
+ // Square corners by default: banners are full-width and typically sit flush
1101
+ // against the top of the viewport, so rounded corners would break the seam.
1102
+ borderRadius: 0,
1103
+ minHeight: 32,
1104
+ paddingTop: neoDesign.spacing.spacing_1_2,
1105
+ paddingBottom: neoDesign.spacing.spacing_1_2,
1106
+ paddingLeft: neoDesign.spacing.spacing_2,
1107
+ paddingRight: neoDesign.spacing.spacing_2,
1108
+ gap: neoDesign.spacing.spacing_1,
1047
1109
  alignItems: 'center',
1048
1110
  justifyContent: messagePosition === 'center' ? 'center' : 'flex-start',
1049
1111
  ...(messagePosition === 'center' && { position: 'relative' }),
1050
- boxShadow: `${neoDesign.shadows.neutral.small.x}px ${neoDesign.shadows.neutral.small.y}px ${neoDesign.shadows.neutral.small.blur}px ${neoDesign.shadows.neutral.small.spread}px ${neoDesign.shadows.neutral.small.shadow}`,
1051
- fontSize: neoDesign.typography.fontSize.default,
1112
+ fontSize: neoDesign.typography.fontSize.sm,
1052
1113
  fontWeight: neoDesign.typography.fontWeight.medium,
1053
1114
  lineHeight: 1.5,
1054
1115
  ...typeStyles,
1055
1116
  [`& .${Alert.alertClasses.icon}`]: {
1056
1117
  padding: 0,
1057
1118
  opacity: 1,
1058
- fontSize: neoDesign.typography.fontSize.h2,
1119
+ fontSize: neoDesign.typography.fontSize.default,
1059
1120
  color: 'inherit',
1060
1121
  },
1061
1122
  [`& .${Alert.alertClasses.message}`]: {
1062
1123
  padding: 0,
1063
1124
  display: 'flex',
1064
1125
  alignItems: 'center',
1065
- gap: neoDesign.spacing.spacing_2,
1126
+ gap: neoDesign.spacing.spacing_1,
1066
1127
  ...(messagePosition === 'left' && { flex: 1 }),
1067
1128
  },
1068
1129
  [`& .${Alert.alertClasses.action}`]: {
1069
1130
  padding: 0,
1070
1131
  ...(messagePosition === 'center' && {
1071
1132
  position: 'absolute',
1072
- right: neoDesign.spacing.spacing_3,
1133
+ right: neoDesign.spacing.spacing_2,
1073
1134
  }),
1074
1135
  },
1075
1136
  };
@@ -1087,6 +1148,8 @@ const LinkText = styles.styled('span')(({ bannerType = 'outlined' }) => ({
1087
1148
  },
1088
1149
  }));
1089
1150
  const StyledIconButton = styles.styled(IconButton)(({ closeIconColor }) => ({
1151
+ minWidth: 24,
1152
+ minHeight: 24,
1090
1153
  padding: 0,
1091
1154
  color: closeIconColor,
1092
1155
  '&:hover': {
@@ -1103,7 +1166,7 @@ const NeoBanner = ({ intent = 'info', type = 'outlined', message, messagePositio
1103
1166
  return null;
1104
1167
  }
1105
1168
  const closeIconColor = type === 'filled' ? neoDesign.semanticColors.surfaces.white : intentColors$1[intent].default;
1106
- return (jsxRuntime.jsx(StyledAlert$1, { ...props, intent: intent, bannerType: type, messagePosition: messagePosition, icon: messagePosition === 'left' ? icon || false : false, action: showClose ? (jsxRuntime.jsx(StyledIconButton, { size: "small", onClick: handleClose, closeIconColor: closeIconColor, children: jsxRuntime.jsx(X, { size: 24 }) })) : undefined, children: messagePosition === 'center' ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [icon, jsxRuntime.jsx("span", { children: message }), linkText && (jsxRuntime.jsx(LinkText, { bannerType: type, onClick: onLinkClick, children: linkText }))] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { children: message }), linkText && (jsxRuntime.jsx(LinkText, { bannerType: type, onClick: onLinkClick, children: linkText }))] })) }));
1169
+ return (jsxRuntime.jsx(StyledAlert$1, { ...props, intent: intent, bannerType: type, messagePosition: messagePosition, icon: messagePosition === 'left' ? icon || false : false, action: showClose ? (jsxRuntime.jsx(StyledIconButton, { size: "small", onClick: handleClose, closeIconColor: closeIconColor, children: jsxRuntime.jsx(X, { size: 16 }) })) : undefined, children: messagePosition === 'center' ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [icon, jsxRuntime.jsx("span", { children: message }), linkText && (jsxRuntime.jsx(LinkText, { bannerType: type, onClick: onLinkClick, children: linkText }))] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { children: message }), linkText && (jsxRuntime.jsx(LinkText, { bannerType: type, onClick: onLinkClick, children: linkText }))] })) }));
1107
1170
  };
1108
1171
  NeoBanner.displayName = 'NeoBanner';
1109
1172
 
@@ -1123,12 +1186,12 @@ const StyledBreadcrumbLink = styles.styled(Link, {
1123
1186
  fontWeight: neoDesign.typography.fontWeight.medium,
1124
1187
  lineHeight: 1,
1125
1188
  textDecoration: 'none',
1126
- color: current ? neoDesign.semanticColors.buttons.primary.default : neoDesign.semanticColors.typography.bodySecondary,
1189
+ color: current ? neoDesign.semanticColors.typography.bodySecondary : neoDesign.semanticColors.typography.link.primary,
1127
1190
  cursor: current ? 'default' : 'pointer',
1128
1191
  borderRadius: neoDesign.borderRadius.xS,
1129
1192
  transition: 'color 0.2s ease-in-out',
1130
1193
  '&:hover': {
1131
- color: current ? neoDesign.semanticColors.buttons.tertiary.hover : neoDesign.semanticColors.icons.hover,
1194
+ color: current ? neoDesign.semanticColors.icons.hover : neoDesign.semanticColors.buttons.tertiary.hover,
1132
1195
  },
1133
1196
  '&:focus-visible': {
1134
1197
  outline: `2px solid ${neoDesign.semanticColors.border.focus}`,
@@ -1511,6 +1574,15 @@ const NeoButtonTabGroup = ({ size = 'medium', exclusive = true, ...props }) => {
1511
1574
  };
1512
1575
  NeoButtonTabGroup.displayName = 'NeoButtonTabGroup';
1513
1576
 
1577
+ /**
1578
+ * NeoCanceledIcon - Outlined circle struck through by a horizontal line.
1579
+ *
1580
+ * Marks a CANCELED state. Color comes entirely from `currentColor` (stroke plus
1581
+ * a 10% fill tint); set it via the `color`/`sx` prop or a parent.
1582
+ */
1583
+ const NeoCanceledIcon = (props) => (jsxRuntime.jsx(SvgIcon, { viewBox: "0 0 24 24", fill: "none", ...props, children: jsxRuntime.jsxs("g", { stroke: "currentColor", strokeWidth: "1.35", children: [jsxRuntime.jsx("path", { fill: "currentColor", fillOpacity: "0.1", d: "M2.55 11.95c0 2.405.918 4.812 2.753 6.647a9.4 9.4 0 0 0 6.647 2.753c2.489 0 4.877-.99 6.646-2.753a9.3 9.3 0 0 0 2.039-3.044 9.4 9.4 0 0 0 .715-3.602m-18.8-.001a9.37 9.37 0 0 1 2.753-6.647A9.4 9.4 0 0 1 11.95 2.55c2.489 0 4.877.99 6.646 2.753a9.3 9.3 0 0 1 2.039 3.045 9.4 9.4 0 0 1 .715 3.603" }), jsxRuntime.jsx("path", { fill: "none", d: "M3 11.825h18" })] }) }));
1584
+ NeoCanceledIcon.displayName = 'NeoCanceledIcon';
1585
+
1514
1586
  // ─── Shared ──────────────────────────────────────────────────────────────────
1515
1587
  const activeShadow = `${neoDesign.shadows.card.x}px ${neoDesign.shadows.card.y}px ${neoDesign.shadows.card.blur}px ${neoDesign.shadows.card.spread}px ${neoDesign.shadows.card.shadow}`;
1516
1588
  // ─── Small card styled components ────────────────────────────────────────────
@@ -1702,20 +1774,6 @@ const NeoCard = (props) => {
1702
1774
  };
1703
1775
  NeoCard.displayName = 'NeoCard';
1704
1776
 
1705
- // Border radius per size (from Figma)
1706
- const borderRadiusConfig = {
1707
- xs: 2,
1708
- small: 3,
1709
- medium: 4,
1710
- };
1711
- // Unchecked: Rounded square outline (20x20 viewBox)
1712
- const UncheckedIcon$1 = ({ size = 'medium' }) => (jsxRuntime.jsx(SvgIcon, { viewBox: "0 0 20 20", children: jsxRuntime.jsx("rect", { x: "1", y: "1", width: "18", height: "18", rx: borderRadiusConfig[size], fill: "none", stroke: "currentColor", strokeWidth: "1.5" }) }));
1713
- // Checked: Filled rounded square with white checkmark
1714
- // Path scaled from Untitled UI 24x24 (M20 6L9 17L4 12) to 20x20
1715
- const CheckedIcon$1 = ({ size = 'medium' }) => (jsxRuntime.jsxs(SvgIcon, { viewBox: "0 0 20 20", children: [jsxRuntime.jsx("rect", { width: "20", height: "20", rx: borderRadiusConfig[size], fill: "currentColor" }), jsxRuntime.jsx("path", { d: "M15 6L8.5 13L5 9.5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" })] }));
1716
- // Indeterminate: Filled rounded square with white minus
1717
- // Path scaled from Untitled UI 24x24 (M5 12H19) to 20x20
1718
- const IndeterminateIcon = ({ size = 'medium' }) => (jsxRuntime.jsxs(SvgIcon, { viewBox: "0 0 20 20", children: [jsxRuntime.jsx("rect", { width: "20", height: "20", rx: borderRadiusConfig[size], fill: "currentColor" }), jsxRuntime.jsx("path", { d: "M5 10H15", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", fill: "none" })] }));
1719
1777
  const CheckboxContainer = styles.styled('label')(({ disabled }) => ({
1720
1778
  display: 'inline-flex',
1721
1779
  alignItems: 'flex-start',
@@ -1748,7 +1806,7 @@ const HelperText$2 = styles.styled('span')(({ theme, size = 'medium' }) => ({
1748
1806
  lineHeight: size === 'xs' ? 1.5 : size === 'small' ? 1.4 : 1.5,
1749
1807
  color: neoDesign.semanticColors.typography.bodySecondary,
1750
1808
  }));
1751
- // Figma-exact border radius for xs checkbox — no matching design token
1809
+ // xs focus-ring radius — no matching design token (box corner comes from the icon)
1752
1810
  const FIGMA_XS_BORDER_RADIUS = 1;
1753
1811
  const StyledCheckbox = styles.styled(Checkbox, {
1754
1812
  shouldForwardProp: prop => prop !== 'size',
@@ -1761,11 +1819,11 @@ const StyledCheckbox = styles.styled(Checkbox, {
1761
1819
  },
1762
1820
  small: {
1763
1821
  size: 16,
1764
- borderRadius: neoDesign.borderRadius.xXS, // From Figma: 2px for small
1822
+ borderRadius: neoDesign.borderRadius.xXS, // focus-ring radius (small)
1765
1823
  },
1766
1824
  medium: {
1767
1825
  size: 20,
1768
- borderRadius: neoDesign.borderRadius.xS, // From Figma: 4px for medium
1826
+ borderRadius: neoDesign.borderRadius.xS, // focus-ring radius (medium)
1769
1827
  },
1770
1828
  };
1771
1829
  const config = sizeConfig[size];
@@ -1777,37 +1835,30 @@ const StyledCheckbox = styles.styled(Checkbox, {
1777
1835
  color: neoDesign.semanticColors.border.primary,
1778
1836
  borderRadius: config.borderRadius,
1779
1837
  flexShrink: 0,
1780
- // Root element
1781
- [`&.${Checkbox.checkboxClasses.root}`]: {
1782
- '&:hover': {
1783
- backgroundColor: 'transparent',
1784
- },
1838
+ // Suppress MUI's grey hover background
1839
+ '&:hover': {
1840
+ backgroundColor: 'transparent',
1785
1841
  },
1786
- // Checkbox icon (unchecked)
1787
- [`& .${Checkbox.checkboxClasses.root}`]: {
1788
- width: config.size,
1789
- height: config.size,
1842
+ // Hover on the unchecked box — subtle blue outline affordance (enabled only)
1843
+ [`&:hover:not(.${Checkbox.checkboxClasses.checked}):not(.${Checkbox.checkboxClasses.indeterminate}):not(.${Checkbox.checkboxClasses.disabled})`]: {
1844
+ color: neoDesign.colors.digitalBlue[300],
1790
1845
  },
1791
- // Checked state
1846
+ // Checked / Indeterminate — primary blue outline + mark
1792
1847
  [`&.${Checkbox.checkboxClasses.checked}`]: {
1793
- color: neoDesign.semanticColors.buttons.primary.default,
1848
+ color: neoDesign.colors.digitalBlue[600],
1794
1849
  },
1795
- // Indeterminate state
1796
1850
  [`&.${Checkbox.checkboxClasses.indeterminate}`]: {
1797
- color: neoDesign.semanticColors.buttons.primary.default,
1851
+ color: neoDesign.colors.digitalBlue[600],
1798
1852
  },
1799
- // Disabled state
1853
+ // Disabled — enabled colors dimmed to 40%. Checked/indeterminate keep
1854
+ // digitalBlue[600] via the rules above; re-assert the unchecked outline
1855
+ // token so it beats MUI's default `.Mui-disabled` color.
1800
1856
  [`&.${Checkbox.checkboxClasses.disabled}`]: {
1801
- color: neoDesign.semanticColors.border.primary,
1857
+ opacity: 0.4,
1802
1858
  cursor: 'not-allowed',
1803
- // When checked and disabled
1804
- [`&.${Checkbox.checkboxClasses.checked}`]: {
1805
- color: neoDesign.semanticColors.border.primary,
1806
- },
1807
- // When indeterminate and disabled
1808
- [`&.${Checkbox.checkboxClasses.indeterminate}`]: {
1809
- color: neoDesign.semanticColors.border.primary,
1810
- },
1859
+ },
1860
+ [`&.${Checkbox.checkboxClasses.disabled}:not(.${Checkbox.checkboxClasses.checked}):not(.${Checkbox.checkboxClasses.indeterminate})`]: {
1861
+ color: neoDesign.semanticColors.border.primary,
1811
1862
  },
1812
1863
  // Focus visible for keyboard navigation
1813
1864
  '&.Mui-focusVisible': {
@@ -1815,11 +1866,10 @@ const StyledCheckbox = styles.styled(Checkbox, {
1815
1866
  outlineOffset: 2,
1816
1867
  borderRadius: config.borderRadius,
1817
1868
  },
1818
- // Custom SVG icons
1869
+ // Size the Lucide icon (color comes from `color` → currentColor → stroke)
1819
1870
  '& svg': {
1820
1871
  width: config.size,
1821
1872
  height: config.size,
1822
- fill: 'currentColor',
1823
1873
  },
1824
1874
  };
1825
1875
  });
@@ -1870,10 +1920,10 @@ const StyledCheckbox = styles.styled(Checkbox, {
1870
1920
  const NeoCheckbox = ({ size = 'medium', label, helperText, disabled, icon, checkedIcon, indeterminateIcon, className, ...props }) => {
1871
1921
  // Add custom class to identify NeoCheckbox instances
1872
1922
  const combinedClassName = className ? `neo-checkbox ${className}` : 'neo-checkbox';
1873
- // Create size-specific icons
1874
- const defaultIcon = icon || jsxRuntime.jsx(UncheckedIcon$1, { size: size });
1875
- const defaultCheckedIcon = checkedIcon || jsxRuntime.jsx(CheckedIcon$1, { size: size });
1876
- const defaultIndeterminateIcon = indeterminateIcon || jsxRuntime.jsx(IndeterminateIcon, { size: size });
1923
+ // Default icons (sized via CSS on the SVG); overridable per instance
1924
+ const defaultIcon = icon || jsxRuntime.jsx(Square, {});
1925
+ const defaultCheckedIcon = checkedIcon || jsxRuntime.jsx(SquareCheck, {});
1926
+ const defaultIndeterminateIcon = indeterminateIcon || jsxRuntime.jsx(SquareMinus, {});
1877
1927
  // If no label, return just the checkbox
1878
1928
  if (!label && !helperText) {
1879
1929
  return (jsxRuntime.jsx(StyledCheckbox, { size: size, disabled: disabled, icon: defaultIcon, checkedIcon: defaultCheckedIcon, indeterminateIcon: defaultIndeterminateIcon, className: combinedClassName, ...props }));
@@ -2185,7 +2235,8 @@ const StyledMenuItem = styles.styled(MenuItem)(({ theme }) => ({
2185
2235
  gap: theme.spacing(2),
2186
2236
  borderRadius: 0,
2187
2237
  color: neoDesign.semanticColors.icons.default,
2188
- fontSize: theme.typography.pxToRem(neoDesign.typography.fontSize.sm),
2238
+ textDecoration: 'none',
2239
+ fontSize: theme.typography.pxToRem(neoDesign.typography.fontSize.default),
2189
2240
  fontWeight: neoDesign.typography.fontWeight.regular,
2190
2241
  lineHeight: `${neoDesign.typography.lineHeight.s}px`,
2191
2242
  transition: theme.transitions.create(['background-color'], {
@@ -2251,7 +2302,7 @@ const Shortcut = styles.styled('span')(({ theme }) => ({
2251
2302
  /**
2252
2303
  * NeoMenuItem - Menu item component based on MUI MenuItem
2253
2304
  *
2254
- * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=4159-8584
2305
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025-26?node-id=4159-8714
2255
2306
  *
2256
2307
  * @example
2257
2308
  * ```tsx
@@ -2266,11 +2317,22 @@ const Shortcut = styles.styled('span')(({ theme }) => ({
2266
2317
  *
2267
2318
  * // Disabled state
2268
2319
  * <NeoMenuItem disabled>Disabled item</NeoMenuItem>
2320
+ *
2321
+ * // As an anchor — middle-click/right-click open in a new tab
2322
+ * <NeoMenuItem href="/api-explorer">API explorer</NeoMenuItem>
2323
+ *
2324
+ * // External link
2325
+ * <NeoMenuItem href="https://docs.example.com" target="_blank" rel="noopener noreferrer">
2326
+ * Documentation
2327
+ * </NeoMenuItem>
2328
+ *
2329
+ * // Client-side routing (Next.js)
2330
+ * <NeoMenuItem component={NextLink} href="/api-explorer">API explorer</NeoMenuItem>
2269
2331
  * ```
2270
2332
  */
2271
- const NeoMenuItem = ({ icon, shortcut, secondaryText, children, ...props }) => {
2272
- return (jsxRuntime.jsx(StyledMenuItem, { ...props, children: jsxRuntime.jsxs(MenuItemContent, { children: [icon && jsxRuntime.jsx(IconWrapper$1, { children: icon }), jsxRuntime.jsxs(LabelContainer$3, { children: [jsxRuntime.jsx(Label$3, { children: children }), secondaryText && jsxRuntime.jsx(SecondaryLabel, { children: secondaryText })] }), shortcut && jsxRuntime.jsx(Shortcut, { children: shortcut })] }) }));
2273
- };
2333
+ function NeoMenuItem({ icon, shortcut, secondaryText, children, ...rest }) {
2334
+ return (jsxRuntime.jsx(StyledMenuItem, { ...rest, children: jsxRuntime.jsxs(MenuItemContent, { children: [icon && jsxRuntime.jsx(IconWrapper$1, { children: icon }), jsxRuntime.jsxs(LabelContainer$3, { children: [jsxRuntime.jsx(Label$3, { children: children }), secondaryText && jsxRuntime.jsx(SecondaryLabel, { children: secondaryText })] }), shortcut && jsxRuntime.jsx(Shortcut, { children: shortcut })] }) }));
2335
+ }
2274
2336
  NeoMenuItem.displayName = 'NeoMenuItem';
2275
2337
 
2276
2338
  /**
@@ -2546,56 +2608,24 @@ function SortedAscendingIcon() {
2546
2608
  function UnsortedIcon() {
2547
2609
  return jsxRuntime.jsx(ChevronsUpDown, { size: 16, color: neoDesign.semanticColors.icons.utility });
2548
2610
  }
2549
- /**
2550
- * Utility function to get DataGrid sx styles for header cells
2551
- *
2552
- * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=4212-41618
2553
- *
2554
- * Figma prop mappings:
2555
- * - `size` → `size`: Figma "condensed" → MUI 'compact', Figma "default" → MUI 'standard', Figma "relaxed" → MUI 'comfortable'
2556
- *
2557
- * Design tokens used:
2558
- * - Background: colors.grey[50] (#f9fafb)
2559
- * - Border: semanticColors.border.primary
2560
- * - Padding: 12px vertical, 24px horizontal
2561
- * - Gap: 12px
2562
- *
2563
- *
2564
- * @param size - Header row size variant (affects header cell height)
2565
- * @returns SxProps for DataGrid header cells
2566
- *
2567
- * @example
2568
- * import { getDataGridHeaderStyles, SortedDescendingIcon, SortedAscendingIcon, UnsortedIcon } from './DataGridHeaderCell'
2569
- *
2570
- * <DataGrid
2571
- * columnHeaderHeight={38} // for compact (Figma: condensed)
2572
- * sx={{
2573
- * ...getDataGridHeaderStyles(),
2574
- * }}
2575
- * slots={{
2576
- * columnSortedDescendingIcon: SortedDescendingIcon,
2577
- * columnSortedAscendingIcon: SortedAscendingIcon,
2578
- * columnUnsortedIcon: UnsortedIcon,
2579
- * }}
2580
- * rows={rows}
2581
- * columns={columns}
2582
- * />
2583
- */
2611
+
2584
2612
  const getDataGridHeaderStyles = () => {
2585
2613
  return {
2586
2614
  // Header cell container styles - from Figma: bg, border, padding
2587
2615
  // Height is set via density-specific selectors in DataGrid.tsx
2588
2616
  [`& .${xDataGrid.gridClasses.columnHeader}`]: {
2589
- backgroundColor: neoDesign.colors.grey[50],
2617
+ backgroundColor: neoDesign.semanticColors.surfaces.dataGrid.header,
2590
2618
  borderBottom: `1px solid ${neoDesign.semanticColors.border.primary}`,
2591
- paddingLeft: `${neoDesign.spacing.spacing_3}px`,
2592
- paddingRight: `${neoDesign.spacing.spacing_3}px`,
2619
+ paddingTop: `${neoDesign.spacing.spacing_1_1_2}px`,
2620
+ paddingBottom: `${neoDesign.spacing.spacing_1_1_2}px`,
2621
+ paddingLeft: `${neoDesign.spacing.spacing_2}px`,
2622
+ paddingRight: `${neoDesign.spacing.spacing_2}px`,
2593
2623
  boxSizing: 'border-box',
2594
2624
  },
2595
2625
  // Style the filler element to match header
2596
2626
  // Height is set via density-specific selectors in DataGrid.tsx
2597
2627
  [`& .${xDataGrid.gridClasses.filler}`]: {
2598
- backgroundColor: neoDesign.colors.grey[50],
2628
+ backgroundColor: neoDesign.semanticColors.surfaces.dataGrid.header,
2599
2629
  borderBottom: `1px solid ${neoDesign.semanticColors.border.primary}`,
2600
2630
  boxSizing: 'border-box',
2601
2631
  },
@@ -2627,12 +2657,19 @@ const getDataGridHeaderStyles = () => {
2627
2657
  },
2628
2658
  },
2629
2659
  },
2660
+ // MUI clips this container when header vertical padding leaves < 16px of content
2661
+ // area (e.g. compact: 38px − 24px padding = 14px). overflow:visible lets the
2662
+ // sort icon render at full 16px without being cropped.
2663
+ [`& .${xDataGrid.gridClasses.columnHeaderTitleContainer}`]: {
2664
+ overflow: 'visible',
2665
+ lineHeight: 1,
2666
+ },
2630
2667
  // Style MUI's sort icon to match Neo design (16x16)
2631
2668
  [`& .${xDataGrid.gridClasses.iconButtonContainer}`]: {
2632
2669
  width: 16,
2633
2670
  height: 16,
2634
2671
  marginLeft: `${neoDesign.spacing.spacing_1_2}px`,
2635
- [`& .${Checkbox.checkboxClasses.root}`]: {
2672
+ '& button': {
2636
2673
  padding: 0,
2637
2674
  width: 16,
2638
2675
  height: 16,
@@ -2645,6 +2682,20 @@ const getDataGridHeaderStyles = () => {
2645
2682
  },
2646
2683
  };
2647
2684
  };
2685
+ const getDataGridRowStyles = () => ({
2686
+ [`& .${xDataGrid.gridClasses.row}`]: {
2687
+ backgroundColor: neoDesign.semanticColors.surfaces.dataGrid.default,
2688
+ },
2689
+ [`& .${xDataGrid.gridClasses.row}:hover`]: {
2690
+ backgroundColor: neoDesign.semanticColors.surfaces.dataGrid.hover,
2691
+ },
2692
+ [`& .${xDataGrid.gridClasses.row}.Mui-selected`]: {
2693
+ backgroundColor: neoDesign.semanticColors.surfaces.dataGrid.selected,
2694
+ },
2695
+ [`& .${xDataGrid.gridClasses.row}.Mui-selected:hover`]: {
2696
+ backgroundColor: neoDesign.semanticColors.surfaces.dataGrid.selectedHover,
2697
+ },
2698
+ });
2648
2699
 
2649
2700
  /**
2650
2701
  * Adapter to use NeoCheckbox in DataGrid's baseCheckbox slot
@@ -2679,7 +2730,7 @@ const DataGridCheckbox = ({ slotProps, ...props }) => (jsxRuntime.jsx(NeoCheckbo
2679
2730
  * - `size` → Row heights (compact: 42px, standard: 48px, comfortable: 56px) and header heights (compact: 38px, standard: 44px, comfortable: 52px)
2680
2731
  *
2681
2732
  * Design tokens used:
2682
- * - Colors: semanticColors.border.primary, semanticColors.background.*
2733
+ * - Colors: semanticColors.border.primary, semanticColors.surfaces.dataGrid.*
2683
2734
  * - Typography: typography.fontFamily.body, typography.fontSize.sm
2684
2735
  * - Spacing: spacing.spacing_*
2685
2736
  *
@@ -2723,19 +2774,22 @@ function NeoDataGrid({ autoHeight = false, toolbar, slots, sx, density = 'standa
2723
2774
  // See: https://github.com/mui/mui-x/issues/20107
2724
2775
  // This must be set to prevent scroll shadow artifacts
2725
2776
  [`& .${xDataGrid.gridClasses.main}`]: {
2726
- backgroundColor: neoDesign.semanticColors.surfaces.white,
2777
+ backgroundColor: neoDesign.semanticColors.surfaces.dataGrid.background,
2727
2778
  },
2728
2779
  // White background for empty/loading overlays
2729
2780
  [`& .${xDataGrid.gridClasses.overlay}`]: {
2730
- backgroundColor: neoDesign.semanticColors.surfaces.white,
2781
+ backgroundColor: neoDesign.semanticColors.surfaces.dataGrid.background,
2731
2782
  },
2732
2783
  ...getDataGridHeaderStyles(),
2784
+ ...getDataGridRowStyles(),
2733
2785
  border: `1px solid ${neoDesign.semanticColors.border.secondary}`,
2734
- // Style row selection checkboxes to match header (16px, proper spacing)
2786
+ // Style row selection checkboxes to match header (16px, proper spacing).
2787
+ // Target `& svg` (not `.MuiSvgIcon-root`) so the rule also matches the
2788
+ // lucide `<svg>` icons NeoCheckbox renders, mirroring the header rule.
2735
2789
  [`& .${xDataGrid.gridClasses.cellCheckbox}`]: {
2736
2790
  [`& .${Checkbox.checkboxClasses.root}`]: {
2737
2791
  padding: `${neoDesign.spacing.spacing_1}px`,
2738
- [`& .${SvgIcon.svgIconClasses.root}`]: {
2792
+ '& svg': {
2739
2793
  width: 16,
2740
2794
  height: 16,
2741
2795
  },
@@ -2784,7 +2838,7 @@ function NeoDataGridColumnsButton() {
2784
2838
  }
2785
2839
  NeoDataGridColumnsButton.displayName = 'NeoDataGridColumnsButton';
2786
2840
 
2787
- const sizeStyles = {
2841
+ const sizeStyles$1 = {
2788
2842
  small: {
2789
2843
  height: 16,
2790
2844
  minWidth: 16,
@@ -2850,16 +2904,18 @@ const filledColorStyles = {
2850
2904
  violet: neoDesign.colors.violet[500],
2851
2905
  beta: neoDesign.colors.digitalBlue[300],
2852
2906
  };
2853
- const StyledChip$1 = styles.styled(Chip)(({ theme, size, variant, color }) => ({
2907
+ const StyledChip$2 = styles.styled(Chip)(({ theme, size, variant, color }) => ({
2854
2908
  padding: 0,
2855
2909
  boxSizing: 'border-box',
2856
2910
  borderRadius: neoDesign.borderRadius.full,
2857
2911
  fontSize: theme.typography.pxToRem(neoDesign.typography.fontSize.xs),
2858
2912
  lineHeight: 1,
2859
2913
  fontWeight: neoDesign.typography.fontWeight.medium,
2860
- ...(size && sizeStyles[size]),
2914
+ overflow: 'visible',
2915
+ ...(size && sizeStyles$1[size]),
2861
2916
  [`& .${Chip.chipClasses.label}`]: {
2862
2917
  padding: 0,
2918
+ overflow: 'visible',
2863
2919
  },
2864
2920
  ...(variant === 'outlined' &&
2865
2921
  color &&
@@ -2884,7 +2940,7 @@ const StyledChip$1 = styles.styled(Chip)(({ theme, size, variant, color }) => ({
2884
2940
  * - TEXT Label → label prop
2885
2941
  */
2886
2942
  function NeoTag({ size = 'small', variant = 'outlined', intent = 'default', ...props }) {
2887
- return jsxRuntime.jsx(StyledChip$1, { size: size, variant: variant, color: intent, ...props });
2943
+ return jsxRuntime.jsx(StyledChip$2, { size: size, variant: variant, color: intent, ...props });
2888
2944
  }
2889
2945
  NeoTag.displayName = 'NeoTag';
2890
2946
 
@@ -2943,7 +2999,7 @@ const LabelContainer$2 = styles.styled('div')({
2943
2999
  alignItems: 'center',
2944
3000
  gap: `${neoDesign.spacing.spacing_1_2}px`,
2945
3001
  });
2946
- const LabelText = styles.styled('p')({
3002
+ const LabelText$1 = styles.styled('p')({
2947
3003
  fontFamily: `${neoDesign.typography.fontFamily.body}, sans-serif`,
2948
3004
  fontSize: neoDesign.typography.fontSize.sm,
2949
3005
  fontWeight: neoDesign.typography.fontWeight.semiBold, // Always semiBold (600)
@@ -2972,7 +3028,7 @@ const IconWrapper = styles.styled('div')({
2972
3028
  },
2973
3029
  });
2974
3030
  function NeoDataGridHeaderLabel({ children, helpTooltip, className, }) {
2975
- return (jsxRuntime.jsxs(LabelContainer$2, { className: className, "data-neo-header-label": true, children: [children && jsxRuntime.jsx(LabelText, { children: children }), helpTooltip && (jsxRuntime.jsx(Tooltip, { title: helpTooltip, placement: "top", children: jsxRuntime.jsx(IconWrapper, { children: jsxRuntime.jsx(CircleQuestionMark, {}) }) }))] }));
3031
+ return (jsxRuntime.jsxs(LabelContainer$2, { className: className, "data-neo-header-label": true, children: [children && jsxRuntime.jsx(LabelText$1, { children: children }), helpTooltip && (jsxRuntime.jsx(Tooltip, { title: helpTooltip, placement: "top", children: jsxRuntime.jsx(IconWrapper, { children: jsxRuntime.jsx(CircleQuestionMark, {}) }) }))] }));
2976
3032
  }
2977
3033
 
2978
3034
  /**
@@ -3510,7 +3566,8 @@ const StyledNavButton = styles.styled(IconButton, {
3510
3566
  */
3511
3567
  const NeoIconButton = ({ size = 'medium', variant = 'tertiary', active = false, loading, children, ...props }) => {
3512
3568
  if (variant === 'nav') {
3513
- return (jsxRuntime.jsx(StyledNavButton, { size: size, active: active, disableRipple: true, ...props, children: children }));
3569
+ const { color, ...navProps } = props;
3570
+ return (jsxRuntime.jsx(StyledNavButton, { size: size, active: active, disableRipple: true, ...navProps, children: children }));
3514
3571
  }
3515
3572
  return (jsxRuntime.jsx(StyledIconOnlyButton, { variant: variant, size: size, loading: loading, ...props, children: children }));
3516
3573
  };
@@ -3763,6 +3820,20 @@ const NeoDatePicker = ({ type = 'single', open, label, value, rangeValue, onChan
3763
3820
  };
3764
3821
  NeoDatePicker.displayName = 'NeoDatePicker';
3765
3822
 
3823
+ /**
3824
+ * NeoDatePickerListItem
3825
+ *
3826
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=4176-8521
3827
+ */
3828
+ const NeoDatePickerListItem = styles.styled('div')({});
3829
+
3830
+ /**
3831
+ * NeoDatePickerMenu
3832
+ *
3833
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=4176-8593
3834
+ */
3835
+ const NeoDatePickerMenu = styles.styled('div')({});
3836
+
3766
3837
  const StyledDivider = styles.styled(Divider)(({ theme }) => ({
3767
3838
  borderColor: neoDesign.semanticColors.border.secondary,
3768
3839
  marginTop: theme.spacing(1),
@@ -3803,26 +3874,34 @@ const sizeMap = {
3803
3874
  medium: 10,
3804
3875
  large: 12,
3805
3876
  };
3806
- const StyledBadge = styles.styled(Badge)(({ ownerState }) => {
3877
+ const StyledDot = styles.styled('span', {
3878
+ shouldForwardProp: prop => prop !== 'ownerState',
3879
+ })(({ ownerState }) => {
3807
3880
  const size = sizeMap[ownerState.size];
3808
- const color = neoDesign.semanticColors.status[ownerState.color].default;
3881
+ const palette = neoDesign.semanticColors.status[ownerState.color];
3809
3882
  return {
3810
- [`& .${Badge.badgeClasses.badge}`]: {
3811
- width: size,
3812
- height: size,
3813
- minWidth: size,
3814
- borderRadius: ownerState.variant === 'solid' ? '50%' : 0,
3815
- padding: 0,
3816
- backgroundColor: ownerState.variant === 'solid' ? color : 'transparent',
3817
- // Remove default badge positioning - make it standalone
3818
- position: 'static',
3819
- transform: 'none',
3820
- overflow: 'visible',
3883
+ display: 'inline-flex',
3884
+ alignItems: 'center',
3885
+ justifyContent: 'center',
3886
+ width: size,
3887
+ height: size,
3888
+ minWidth: size,
3889
+ borderRadius: '50%',
3890
+ flexShrink: 0,
3891
+ boxSizing: 'border-box',
3892
+ backgroundColor: palette.default,
3893
+ color: neoDesign.semanticColors.typography.tooltip,
3894
+ ...(ownerState.variant === 'outline' && {
3895
+ border: `3px solid ${palette.light}`,
3896
+ }),
3897
+ '& > svg': {
3898
+ width: '70%',
3899
+ height: '70%',
3821
3900
  },
3822
3901
  };
3823
3902
  });
3824
3903
  /**
3825
- * NeoDot - Status indicator dot component based on MUI Badge
3904
+ * NeoDot - Status indicator dot.
3826
3905
  *
3827
3906
  * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=4163-3577
3828
3907
  *
@@ -3831,26 +3910,8 @@ const StyledBadge = styles.styled(Badge)(({ ownerState }) => {
3831
3910
  * - outline (False|True) → variant prop (solid|outline)
3832
3911
  * - Color is configurable via color prop (success|error|warning|info|neutral)
3833
3912
  */
3834
- const NeoDot = ({ size = 'medium', variant = 'solid', color = 'neutral', ...props }) => {
3835
- const dotSize = sizeMap[size];
3836
- const mediumColor = neoDesign.semanticColors.status[color].default;
3837
- const lightColor = neoDesign.semanticColors.status[color].light;
3838
- // For outline variant, use SVG for precise control
3839
- const renderDot = () => {
3840
- if (variant === 'outline') {
3841
- // SVG approach: outer circle with light fill, inner circle with medium fill
3842
- // Stroke width of ~3px creates the ring effect
3843
- const strokeWidth = 3;
3844
- const radius = dotSize / 2;
3845
- const innerRadius = radius - strokeWidth;
3846
- return (jsxRuntime.jsxs("svg", { width: dotSize, height: dotSize, viewBox: `0 0 ${dotSize} ${dotSize}`, style: {
3847
- display: 'block',
3848
- borderRadius: '50%',
3849
- }, role: "img", "aria-label": `${color} status indicator`, children: [jsxRuntime.jsx("title", { children: `${color} status indicator` }), jsxRuntime.jsx("circle", { cx: radius, cy: radius, r: radius, fill: lightColor }), jsxRuntime.jsx("circle", { cx: radius, cy: radius, r: innerRadius, fill: mediumColor })] }));
3850
- }
3851
- return jsxRuntime.jsx("span", { style: { display: 'inline-block', width: 0, height: 0 } });
3852
- };
3853
- return (jsxRuntime.jsx(StyledBadge, { ...props, ownerState: { size, variant, color }, variant: "dot", children: renderDot() }));
3913
+ const NeoDot = ({ size = 'medium', variant = 'solid', color = 'neutral', children, ...props }) => {
3914
+ return (jsxRuntime.jsx(StyledDot, { ...props, ownerState: { size, variant, color }, role: "img", "aria-label": props['aria-label'] ?? `${color} status indicator`, children: children }));
3854
3915
  };
3855
3916
  NeoDot.displayName = 'NeoDot';
3856
3917
 
@@ -3932,8 +3993,57 @@ const NeoDownloadToast = ({ title, fileName, progress, showClose = true, showPau
3932
3993
  };
3933
3994
  NeoDownloadToast.displayName = 'NeoDownloadToast';
3934
3995
 
3996
+ const buildFilledIcon = ({ displayName, fillColor, body, knockout }) => {
3997
+ const Component = (props) => (jsxRuntime.jsxs(SvgIcon, { viewBox: "0 0 16 16", ...props, children: [jsxRuntime.jsx("g", { fill: fillColor, children: body }), jsxRuntime.jsx("g", { stroke: "#FFFFFF", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", fill: "none", children: knockout })] }));
3998
+ Component.displayName = displayName;
3999
+ return Component;
4000
+ };
4001
+ const CIRCLE_BODY = (jsxRuntime.jsx("path", { d: "M8.00001 14.6666C11.6819 14.6666 14.6667 11.6818 14.6667 7.99992C14.6667 4.31802 11.6819 1.33325 8.00001 1.33325C4.31811 1.33325 1.33334 4.31802 1.33334 7.99992C1.33334 11.6818 4.31811 14.6666 8.00001 14.6666Z" }));
4002
+ const NeoFilledSuccess = buildFilledIcon({
4003
+ displayName: 'NeoFilledSuccess',
4004
+ fillColor: '#3B8948',
4005
+ body: CIRCLE_BODY,
4006
+ knockout: jsxRuntime.jsx("path", { d: "M6 8.00008L7.33333 9.33341L10 6.66675" }),
4007
+ });
4008
+ const NeoFilledQueued = buildFilledIcon({
4009
+ displayName: 'NeoFilledQueued',
4010
+ fillColor: '#992FB9',
4011
+ body: CIRCLE_BODY,
4012
+ knockout: jsxRuntime.jsx("path", { d: "M8 4V8L10.6667 9.33333" }),
4013
+ });
4014
+ const NeoFilledInfo = buildFilledIcon({
4015
+ displayName: 'NeoFilledInfo',
4016
+ fillColor: '#2F42FF',
4017
+ body: CIRCLE_BODY,
4018
+ knockout: (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M8 10.6667V8" }), jsxRuntime.jsx("path", { d: "M8 5.33325H8.00667" })] })),
4019
+ });
4020
+ const NeoFilledWarning = buildFilledIcon({
4021
+ displayName: 'NeoFilledWarning',
4022
+ fillColor: '#BD9319',
4023
+ body: (jsxRuntime.jsx("path", { d: "M14.4867 12L9.15335 2.66665C9.03706 2.46146 8.86842 2.29078 8.66463 2.17203C8.46084 2.05329 8.22921 1.99072 7.99335 1.99072C7.75749 1.99072 7.52585 2.05329 7.32206 2.17203C7.11828 2.29078 6.94964 2.46146 6.83335 2.66665L1.50001 12C1.38247 12.2036 1.32083 12.4346 1.32135 12.6697C1.32187 12.9047 1.38453 13.1355 1.50298 13.3385C1.62142 13.5416 1.79145 13.7097 1.99581 13.8259C2.20018 13.942 2.43162 14.0021 2.66668 14H13.3333C13.5673 13.9997 13.797 13.938 13.9995 13.8208C14.202 13.7037 14.3702 13.5354 14.487 13.3327C14.6039 13.1301 14.6654 12.9002 14.6653 12.6663C14.6653 12.4324 14.6036 12.2026 14.4867 12Z" })),
4024
+ knockout: (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M8 6V8.66667" }), jsxRuntime.jsx("path", { d: "M8 11.3333H8.00667" })] })),
4025
+ });
4026
+ const NeoFilledError = buildFilledIcon({
4027
+ displayName: 'NeoFilledError',
4028
+ fillColor: '#CB3446',
4029
+ body: (jsxRuntime.jsx("path", { d: "M10.208 1.33325C10.5616 1.33333 10.9007 1.47385 11.1507 1.72392L14.276 4.84925C14.5261 5.09924 14.6666 5.43832 14.6667 5.79192V10.2079C14.6666 10.5615 14.5261 10.9006 14.276 11.1506L11.1507 14.2759C10.9007 14.526 10.5616 14.6665 10.208 14.6666H5.79201C5.43842 14.6665 5.09933 14.526 4.84934 14.2759L1.72401 11.1506C1.47394 10.9006 1.33342 10.5615 1.33334 10.2079V5.79192C1.33342 5.43832 1.47394 5.09924 1.72401 4.84925L4.84934 1.72392C5.09933 1.47385 5.43842 1.33333 5.79201 1.33325H10.208Z" })),
4030
+ knockout: (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M8 5.33325V7.99992" }), jsxRuntime.jsx("path", { d: "M8 10.6667H8.00667" })] })),
4031
+ });
4032
+ const NeoFilledNeutral = buildFilledIcon({
4033
+ displayName: 'NeoFilledNeutral',
4034
+ fillColor: '#6B7280',
4035
+ body: CIRCLE_BODY,
4036
+ knockout: jsxRuntime.jsx("path", { d: "M5.33334 8H10.6667" }),
4037
+ });
4038
+ const NeoFilledCanceled = buildFilledIcon({
4039
+ displayName: 'NeoFilledCanceled',
4040
+ fillColor: '#7B7263',
4041
+ body: CIRCLE_BODY,
4042
+ knockout: (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: "M10 6L6 10" }), jsxRuntime.jsx("path", { d: "M6 6L10 10" })] })),
4043
+ });
4044
+
3935
4045
  const filterChipOnlyProps = ['selected', 'expanded', 'selectedLabel', 'count', 'onClear'];
3936
- const StyledChip = styles.styled(Chip, {
4046
+ const StyledChip$1 = styles.styled(Chip, {
3937
4047
  shouldForwardProp: prop => !filterChipOnlyProps.includes(prop),
3938
4048
  })(({ theme, selected }) => ({
3939
4049
  borderRadius: neoDesign.borderRadius.full,
@@ -4023,7 +4133,7 @@ const CountBadge = styles.styled('span')(({ theme }) => ({
4023
4133
  */
4024
4134
  const NeoFilterChip = ({ label, selected = false, expanded, selectedLabel, count = 0, onClear, onClick, ...props }) => {
4025
4135
  const chipLabel = selected ? (jsxRuntime.jsxs(LabelContent, { children: [jsxRuntime.jsxs(TextStack, { children: [jsxRuntime.jsx(HeaderLabel, { children: label }), jsxRuntime.jsx(SelectedLabel, { children: selectedLabel ?? label })] }), count > 0 && jsxRuntime.jsx(CountBadge, { children: count })] })) : (label);
4026
- return (jsxRuntime.jsx(StyledChip, { label: chipLabel, selected: selected, clickable: true, onClick: onClick, onDelete: selected && onClear ? onClear : undefined, deleteIcon: jsxRuntime.jsx(X, { size: 24 }), "aria-expanded": expanded, ...props }));
4136
+ return (jsxRuntime.jsx(StyledChip$1, { label: chipLabel, selected: selected, clickable: true, onClick: onClick, onDelete: selected && onClear ? onClear : undefined, deleteIcon: jsxRuntime.jsx(X, { size: 24 }), "aria-expanded": expanded, ...props }));
4027
4137
  };
4028
4138
  NeoFilterChip.displayName = 'NeoFilterChip';
4029
4139
 
@@ -4064,6 +4174,7 @@ const StyledFooter = styles.styled(Box, {
4064
4174
  shouldForwardProp: prop => prop !== 'showShadow',
4065
4175
  })(({ theme, showShadow = false }) => ({
4066
4176
  backgroundColor: neoDesign.semanticColors.surfaces.white,
4177
+ borderTop: `1px solid ${neoDesign.semanticColors.border.primary}`,
4067
4178
  display: 'flex',
4068
4179
  alignItems: 'center',
4069
4180
  justifyContent: 'center',
@@ -4389,13 +4500,7 @@ function NeoInfiniteScrollGrid({ onLoadMore, hasNextPage = true, loadMoreAtScrol
4389
4500
  showShadow: isScrolling,
4390
4501
  ...userSlotProps?.footer,
4391
4502
  },
4392
- }, sx: {
4393
- // Add border at bottom of rows section (above footer)
4394
- [`& .${xDataGrid.gridClasses.virtualScrollerContent}`]: {
4395
- borderBottom: `1px solid ${neoDesign.semanticColors.border.primary}`,
4396
- },
4397
- ...userSx,
4398
- }, pagination: false, ...props,
4503
+ }, sx: userSx, pagination: false, ...props,
4399
4504
  // Only show loading overlay when loading AND no rows exist yet
4400
4505
  // This keeps existing rows visible while loading more data (footer shows loading spinner)
4401
4506
  loading: props.loading && !hasRows }));
@@ -4821,87 +4926,127 @@ const NeoListItem = ({ size = 'medium', primaryText, secondaryText, badge, icon,
4821
4926
  };
4822
4927
  NeoListItem.displayName = 'NeoListItem';
4823
4928
 
4824
- /**
4825
- * Styled ListItemButton with Neo design tokens
4826
- * Uses MUI's ListItemButton as base for proper accessibility and interaction
4827
- */
4828
- const StyledListItemButton = styles.styled(ListItemButton)(({ theme }) => ({
4829
- display: 'flex',
4830
- alignItems: 'center',
4831
- gap: neoDesign.spacing.spacing_2,
4832
- borderRadius: neoDesign.borderRadius.m,
4833
- paddingTop: neoDesign.spacing.spacing_1,
4834
- paddingBottom: neoDesign.spacing.spacing_1,
4835
- paddingLeft: neoDesign.spacing.spacing_3_4,
4836
- paddingRight: neoDesign.spacing.spacing_3_4,
4837
- border: `1px solid ${neoDesign.semanticColors.border.primary}`,
4838
- backgroundColor: theme.palette.common.white,
4839
- transition: theme.transitions.create(['border', 'background-color']),
4840
- // Active (selected) state
4841
- [`&.${ListItemButton.listItemButtonClasses.selected}`]: {
4842
- border: `2px solid ${neoDesign.semanticColors.buttons.primary.default}`,
4843
- backgroundColor: theme.palette.common.white,
4844
- '&:hover': {
4845
- backgroundColor: theme.palette.common.white,
4846
- },
4847
- // Icon color in selected state
4848
- [`& .${ListItemIcon.listItemIconClasses.root}`]: {
4849
- color: neoDesign.semanticColors.icons.default,
4929
+ const StyledListItemButton = styles.styled(ListItemButton, {
4930
+ shouldForwardProp: prop => prop !== 'listVariant',
4931
+ })(({ theme, listVariant = 'card' }) => listVariant === 'nav' ? navVariantStyles(theme) : cardVariantStyles(theme));
4932
+ // Nav variant — sidebar list item: no border, compact, subtle highlights.
4933
+ // Renders children inline; no ListItemIcon/ListItemText wrappers required.
4934
+ function navVariantStyles(theme) {
4935
+ return {
4936
+ display: 'flex',
4937
+ alignItems: 'center',
4938
+ gap: neoDesign.spacing.spacing_2,
4939
+ borderRadius: neoDesign.borderRadius.s,
4940
+ paddingTop: neoDesign.spacing.spacing_1,
4941
+ paddingBottom: neoDesign.spacing.spacing_1,
4942
+ paddingLeft: neoDesign.spacing.spacing_2,
4943
+ paddingRight: neoDesign.spacing.spacing_2,
4944
+ border: 'none',
4945
+ color: neoDesign.semanticColors.typography.bodySecondary,
4946
+ backgroundColor: 'transparent',
4947
+ transition: theme.transitions.create(['background-color', 'color']),
4948
+ [`&.${ListItemButton.listItemButtonClasses.selected}`]: {
4949
+ backgroundColor: neoDesign.semanticColors.surfaces.activeHighlight,
4950
+ color: neoDesign.semanticColors.typography.body,
4951
+ '&:hover': {
4952
+ backgroundColor: neoDesign.semanticColors.surfaces.activeHighlight,
4953
+ },
4850
4954
  },
4851
- // Text colors in selected state
4852
- [`& .${ListItemText.listItemTextClasses.primary}`]: {
4853
- color: neoDesign.colors.grey[800],
4955
+ [`&:not(.${ListItemButton.listItemButtonClasses.selected}):not(.${ListItemButton.listItemButtonClasses.disabled})`]: {
4956
+ '&:hover': {
4957
+ backgroundColor: neoDesign.semanticColors.surfaces.listHover,
4958
+ color: neoDesign.semanticColors.typography.body,
4959
+ },
4854
4960
  },
4855
- [`& .${ListItemText.listItemTextClasses.secondary}`]: {
4856
- color: neoDesign.semanticColors.typography.bodySecondary,
4961
+ [`&.${ListItemButton.listItemButtonClasses.focusVisible}`]: {
4962
+ outline: `2px solid ${neoDesign.semanticColors.border.focus}`,
4963
+ outlineOffset: -2,
4857
4964
  },
4858
- },
4859
- // Deselected (default) state
4860
- [`&:not(.${ListItemButton.listItemButtonClasses.selected}):not(.${ListItemButton.listItemButtonClasses.disabled})`]: {
4861
- '&:hover': {
4862
- backgroundColor: neoDesign.colors.grey[50],
4863
- },
4864
- [`& .${ListItemIcon.listItemIconClasses.root}`]: {
4865
- color: neoDesign.semanticColors.icons.disabled,
4866
- },
4867
- [`& .${ListItemText.listItemTextClasses.primary}`]: {
4868
- color: neoDesign.semanticColors.buttons.tertiary.disabled,
4869
- },
4870
- [`& .${ListItemText.listItemTextClasses.secondary}`]: {
4965
+ [`&.${ListItemButton.listItemButtonClasses.disabled}`]: {
4871
4966
  color: neoDesign.semanticColors.typography.button.disabled,
4967
+ opacity: 1,
4872
4968
  },
4873
- },
4874
- // Focus state
4875
- [`&.${ListItemButton.listItemButtonClasses.focusVisible}`]: {
4876
- outline: `2px solid ${neoDesign.semanticColors.buttons.primary.default}`,
4877
- outlineOffset: 2,
4878
- border: `2px solid ${neoDesign.semanticColors.buttons.primary.default}`,
4969
+ };
4970
+ }
4971
+ function cardVariantStyles(theme) {
4972
+ return {
4973
+ display: 'flex',
4974
+ alignItems: 'center',
4975
+ gap: neoDesign.spacing.spacing_2,
4976
+ borderRadius: neoDesign.borderRadius.m,
4977
+ paddingTop: neoDesign.spacing.spacing_1,
4978
+ paddingBottom: neoDesign.spacing.spacing_1,
4979
+ paddingLeft: neoDesign.spacing.spacing_3_4,
4980
+ paddingRight: neoDesign.spacing.spacing_3_4,
4981
+ border: `1px solid ${neoDesign.semanticColors.border.primary}`,
4879
4982
  backgroundColor: theme.palette.common.white,
4880
- [`& .${ListItemIcon.listItemIconClasses.root}`]: {
4881
- color: neoDesign.semanticColors.icons.default,
4882
- },
4883
- [`& .${ListItemText.listItemTextClasses.primary}`]: {
4884
- color: neoDesign.colors.grey[800],
4885
- },
4886
- [`& .${ListItemText.listItemTextClasses.secondary}`]: {
4887
- color: neoDesign.semanticColors.typography.bodySecondary,
4983
+ transition: theme.transitions.create(['border', 'background-color']),
4984
+ // Active (selected) state
4985
+ [`&.${ListItemButton.listItemButtonClasses.selected}`]: {
4986
+ border: `2px solid ${neoDesign.semanticColors.buttons.primary.default}`,
4987
+ backgroundColor: theme.palette.common.white,
4988
+ '&:hover': {
4989
+ backgroundColor: theme.palette.common.white,
4990
+ },
4991
+ // Icon color in selected state
4992
+ [`& .${ListItemIcon.listItemIconClasses.root}`]: {
4993
+ color: neoDesign.semanticColors.icons.default,
4994
+ },
4995
+ // Text colors in selected state
4996
+ [`& .${ListItemText.listItemTextClasses.primary}`]: {
4997
+ color: neoDesign.colors.grey[800],
4998
+ },
4999
+ [`& .${ListItemText.listItemTextClasses.secondary}`]: {
5000
+ color: neoDesign.semanticColors.typography.bodySecondary,
5001
+ },
4888
5002
  },
4889
- },
4890
- // Disabled state
4891
- [`&.${ListItemButton.listItemButtonClasses.disabled}`]: {
4892
- backgroundColor: neoDesign.colors.grey[50],
4893
- opacity: 1, // Override MUI default opacity
4894
- [`& .${ListItemIcon.listItemIconClasses.root}`]: {
4895
- color: neoDesign.semanticColors.icons.disabled,
5003
+ // Deselected (default) state
5004
+ [`&:not(.${ListItemButton.listItemButtonClasses.selected}):not(.${ListItemButton.listItemButtonClasses.disabled})`]: {
5005
+ '&:hover': {
5006
+ backgroundColor: neoDesign.colors.grey[50],
5007
+ },
5008
+ [`& .${ListItemIcon.listItemIconClasses.root}`]: {
5009
+ color: neoDesign.semanticColors.icons.disabled,
5010
+ },
5011
+ [`& .${ListItemText.listItemTextClasses.primary}`]: {
5012
+ color: neoDesign.semanticColors.buttons.tertiary.disabled,
5013
+ },
5014
+ [`& .${ListItemText.listItemTextClasses.secondary}`]: {
5015
+ color: neoDesign.semanticColors.typography.button.disabled,
5016
+ },
4896
5017
  },
4897
- [`& .${ListItemText.listItemTextClasses.primary}`]: {
4898
- color: neoDesign.colors.grey[300],
5018
+ // Focus state
5019
+ [`&.${ListItemButton.listItemButtonClasses.focusVisible}`]: {
5020
+ outline: `2px solid ${neoDesign.semanticColors.buttons.primary.default}`,
5021
+ outlineOffset: 2,
5022
+ border: `2px solid ${neoDesign.semanticColors.buttons.primary.default}`,
5023
+ backgroundColor: theme.palette.common.white,
5024
+ [`& .${ListItemIcon.listItemIconClasses.root}`]: {
5025
+ color: neoDesign.semanticColors.icons.default,
5026
+ },
5027
+ [`& .${ListItemText.listItemTextClasses.primary}`]: {
5028
+ color: neoDesign.colors.grey[800],
5029
+ },
5030
+ [`& .${ListItemText.listItemTextClasses.secondary}`]: {
5031
+ color: neoDesign.semanticColors.typography.bodySecondary,
5032
+ },
4899
5033
  },
4900
- [`& .${ListItemText.listItemTextClasses.secondary}`]: {
4901
- color: neoDesign.colors.grey[300],
5034
+ // Disabled state
5035
+ [`&.${ListItemButton.listItemButtonClasses.disabled}`]: {
5036
+ backgroundColor: neoDesign.colors.grey[50],
5037
+ opacity: 1, // Override MUI default opacity
5038
+ [`& .${ListItemIcon.listItemIconClasses.root}`]: {
5039
+ color: neoDesign.semanticColors.icons.disabled,
5040
+ },
5041
+ [`& .${ListItemText.listItemTextClasses.primary}`]: {
5042
+ color: neoDesign.colors.grey[300],
5043
+ },
5044
+ [`& .${ListItemText.listItemTextClasses.secondary}`]: {
5045
+ color: neoDesign.colors.grey[300],
5046
+ },
4902
5047
  },
4903
- },
4904
- }));
5048
+ };
5049
+ }
4905
5050
  /**
4906
5051
  * NeoListItemButton - Selectable list item with icon and text
4907
5052
  *
@@ -4945,8 +5090,8 @@ const StyledListItemButton = styles.styled(ListItemButton)(({ theme }) => ({
4945
5090
  * - colors.grey[300] (#d1d5db) - Disabled text
4946
5091
  * - colors.grey[50] (#f9fafb) - Disabled background
4947
5092
  */
4948
- const NeoListItemButton = ({ children, selected = false, disabled = false, ...props }) => {
4949
- return (jsxRuntime.jsx(StyledListItemButton, { selected: selected, disabled: disabled, ...props, children: children }));
5093
+ const NeoListItemButton = ({ children, selected = false, disabled = false, variant = 'card', ...props }) => {
5094
+ return (jsxRuntime.jsx(StyledListItemButton, { selected: selected, disabled: disabled, listVariant: variant, ...props, children: children }));
4950
5095
  };
4951
5096
  NeoListItemButton.displayName = 'NeoListItemButton';
4952
5097
 
@@ -4956,7 +5101,6 @@ const StyledMenu = styles.styled(Menu)(({ theme }) => ({
4956
5101
  borderRadius: neoDesign.borderRadius.s,
4957
5102
  border: `1px solid ${neoDesign.semanticColors.border.primary}`,
4958
5103
  boxShadow: `${neoDesign.shadows.dropdown.x}px ${neoDesign.shadows.dropdown.y}px ${neoDesign.shadows.dropdown.blur}px ${neoDesign.shadows.dropdown.spread}px ${neoDesign.shadows.dropdown.shadow}`,
4959
- minWidth: 200,
4960
5104
  marginTop: theme.spacing(1),
4961
5105
  paddingTop: theme.spacing(1),
4962
5106
  paddingBottom: theme.spacing(1),
@@ -5183,9 +5327,8 @@ NeoModalFooter.displayName = 'NeoModalFooter';
5183
5327
  const NavigationAvatarContainer = styles.styled('div')({
5184
5328
  display: 'flex',
5185
5329
  boxSizing: 'border-box',
5186
- width: neoDesign.spacing.spacing_5_1_2,
5187
- height: neoDesign.spacing.spacing_5_1_2,
5188
- padding: neoDesign.spacing.spacing_3_4,
5330
+ padding: neoDesign.spacing.spacing_1_2,
5331
+ aspectRatio: '1 / 1',
5189
5332
  justifyContent: 'center',
5190
5333
  alignItems: 'center',
5191
5334
  borderRadius: '50%',
@@ -5198,16 +5341,103 @@ const NavigationAvatarContainer = styles.styled('div')({
5198
5341
  /**
5199
5342
  * NeoNavigationAvatar - Compact avatar for navigation contexts
5200
5343
  *
5201
- * Wraps NeoGeneralAvatar (size="small") in a 44px container with 6px padding,
5202
- * providing a larger interactive area for navigation UI.
5344
+ * Wraps NeoGeneralAvatar (size="small") in a 40px container,
5345
+ * providing an interactive area for navigation UI.
5203
5346
  *
5204
5347
  * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=11325-102
5205
5348
  */
5206
- const NeoNavigationAvatar = ({ colorIndex = 0, children, ...props }) => {
5207
- return (jsxRuntime.jsx(NavigationAvatarContainer, { children: jsxRuntime.jsx(NeoGeneralAvatar, { size: "small", colorIndex: colorIndex, ...props, children: children }) }));
5349
+ const NeoNavigationAvatar = ({ children, ...props }) => {
5350
+ return (jsxRuntime.jsx(NavigationAvatarContainer, { children: jsxRuntime.jsx(NeoGeneralAvatar, { size: "small", ...props, children: children }) }));
5208
5351
  };
5209
5352
  NeoNavigationAvatar.displayName = 'NeoNavigationAvatar';
5210
5353
 
5354
+ const NeoSideNavContext = React.createContext({
5355
+ collapsed: false,
5356
+ });
5357
+ const useNeoSideNav = () => React.useContext(NeoSideNavContext);
5358
+
5359
+ /**
5360
+ * Variant color configuration
5361
+ */
5362
+ const variantConfig = {
5363
+ light: {
5364
+ backgroundColor: neoDesign.semanticColors.surfaces.tooltip, // #4b5563 - medium gray
5365
+ color: neoDesign.semanticColors.typography.tooltip, // #ffffff - white
5366
+ },
5367
+ dark: {
5368
+ backgroundColor: neoDesign.colors.grey[50], // #f9fafb - very light gray
5369
+ color: neoDesign.colors.grey[800], // #1f2937 - dark gray
5370
+ },
5371
+ brand: {
5372
+ backgroundColor: neoDesign.colors.digitalBlue[800], // #131e7a - dark blue
5373
+ color: neoDesign.semanticColors.typography.tooltip, // #ffffff - white
5374
+ },
5375
+ };
5376
+ /**
5377
+ * Styled MUI Tooltip with Neo design system tokens
5378
+ */
5379
+ const StyledTooltip$1 = styles.styled(Tooltip, {
5380
+ shouldForwardProp: prop => prop !== 'variant' && prop !== 'description',
5381
+ })(({ variant = 'light', description }) => {
5382
+ const hasDescription = Boolean(description);
5383
+ const variantStyles = variantConfig[variant];
5384
+ return {
5385
+ // Style the tooltip content
5386
+ [`& .${Tooltip.tooltipClasses.tooltip}`]: {
5387
+ backgroundColor: variantStyles.backgroundColor,
5388
+ color: variantStyles.color,
5389
+ fontSize: neoDesign.typography.fontSize.xs,
5390
+ fontWeight: neoDesign.typography.fontWeight.medium,
5391
+ lineHeight: hasDescription ? 1.5 : 1,
5392
+ borderRadius: hasDescription ? neoDesign.borderRadius.s : neoDesign.borderRadius.xS,
5393
+ padding: hasDescription ? neoDesign.spacing.spacing_1_1_2 : `0 ${neoDesign.spacing.spacing_1}px`,
5394
+ ...(hasDescription && {
5395
+ maxWidth: 296,
5396
+ }),
5397
+ ...(!hasDescription && {
5398
+ height: neoDesign.spacing.spacing_3_1_4,
5399
+ display: 'flex',
5400
+ alignItems: 'center',
5401
+ justifyContent: 'center',
5402
+ }),
5403
+ boxShadow: `${neoDesign.shadows.neutral.medium.x}px ${neoDesign.shadows.neutral.medium.y}px ${neoDesign.shadows.neutral.medium.blur}px ${neoDesign.shadows.neutral.medium.spread}px ${neoDesign.shadows.neutral.medium.shadow}`,
5404
+ },
5405
+ // Style the arrow
5406
+ [`& .${Tooltip.tooltipClasses.arrow}`]: {
5407
+ color: variantStyles.backgroundColor,
5408
+ },
5409
+ };
5410
+ });
5411
+ /**
5412
+ * NeoTooltip - Tooltip component following Neo design system
5413
+ *
5414
+ * Provides contextual information when users hover over or focus on an element.
5415
+ * Supports three visual variants (light, dark, brand) and optional supporting text.
5416
+ *
5417
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=4091-26557&t=Bo58EpFmg6ILJtmv-11
5418
+ *
5419
+ * Figma Props Mapping:
5420
+ * - Theme (Light mode|Dark mode|Brand color) → variant ('light'|'dark'|'brand')
5421
+ * - Placement → arrow (boolean) + placement (top/bottom/left/right/etc)
5422
+ * - Supporting text (True|False) → description (string|undefined)
5423
+ * - text → title (string, literal content)
5424
+ *
5425
+ * Design Tokens Used:
5426
+ * - Light: surfaces.tooltip (#4b5563), typography.tooltip (#ffffff)
5427
+ * - Dark: grey[50] (#f9fafb), grey[800] (#1f2937)
5428
+ * - Brand: digitalBlue[800] (#131e7a), typography.tooltip (#ffffff)
5429
+ * - Shadow: neutralMedium (0px 8px 15px 0px rgba(31,41,55,0.1))
5430
+ * - Typography: fontSize.xs (12), fontSize.caption (13), fontWeight.medium (500), fontWeight.semiBold (600)
5431
+ */
5432
+ const NeoTooltip = ({ variant = 'light', title, description, children, arrow = false, placement, ...props }) => {
5433
+ // Build the title content
5434
+ // If description is provided, create a structured layout with title + description
5435
+ // Otherwise, just show the title text
5436
+ const titleContent = description ? (jsxRuntime.jsxs(Stack, { gap: 0.5, children: [jsxRuntime.jsx(Typography, { fontSize: neoDesign.typography.fontSize.caption, fontWeight: neoDesign.typography.fontWeight.semiBold, children: title }), jsxRuntime.jsx(Typography, { fontSize: neoDesign.typography.fontSize.xs, fontWeight: neoDesign.typography.fontWeight.medium, sx: { opacity: 0.75 }, children: description })] })) : (title);
5437
+ return (jsxRuntime.jsx(StyledTooltip$1, { variant: variant, description: description, title: titleContent, arrow: arrow, placement: placement, ...props, children: children }));
5438
+ };
5439
+ NeoTooltip.displayName = 'NeoTooltip';
5440
+
5211
5441
  const customProps = ['selected'];
5212
5442
  const StyledRoot = styles.styled(ButtonBase, {
5213
5443
  shouldForwardProp: prop => !customProps.includes(prop),
@@ -5226,41 +5456,34 @@ const StyledRoot = styles.styled(ButtonBase, {
5226
5456
  textDecoration: 'none',
5227
5457
  '&:hover .neo-nav-icon-padding': {
5228
5458
  backgroundColor: neoDesign.semanticColors.buttons.secondary.hoverBackground,
5229
- borderColor: neoDesign.colors.digitalBlue[100],
5459
+ borderColor: neoDesign.semanticColors.buttons.secondary.pressedBackground,
5230
5460
  },
5231
5461
  '&:hover .neo-nav-label': {
5232
5462
  color: neoDesign.semanticColors.buttons.primary.hover,
5233
5463
  },
5464
+ [`& .${Chip.chipClasses.root}`]: {
5465
+ flexShrink: 0,
5466
+ },
5234
5467
  '&:focus-visible': {
5235
- ...focusRingStyles,
5468
+ outline: 'none',
5236
5469
  },
5237
5470
  '&:focus-visible .neo-nav-icon-padding': {
5238
- backgroundColor: neoDesign.semanticColors.buttons.secondary.hoverBackground,
5239
- borderColor: neoDesign.colors.digitalBlue[100],
5240
- },
5241
- '&:focus-visible .neo-nav-label': {
5242
- color: neoDesign.semanticColors.buttons.primary.hover,
5471
+ ...focusRingStyles,
5243
5472
  },
5244
5473
  ...(selected && {
5245
5474
  '& .neo-nav-icon-padding': {
5246
- backgroundColor: neoDesign.colors.digitalBlue[100],
5475
+ backgroundColor: neoDesign.semanticColors.buttons.secondary.pressedBackground,
5247
5476
  },
5248
5477
  '& .neo-nav-label': {
5249
5478
  color: neoDesign.semanticColors.buttons.primary.pressed,
5250
5479
  fontWeight: neoDesign.typography.fontWeight.semiBold,
5251
5480
  },
5252
5481
  '&:hover .neo-nav-icon-padding': {
5253
- backgroundColor: neoDesign.colors.digitalBlue[100],
5482
+ backgroundColor: neoDesign.semanticColors.buttons.secondary.pressedBackground,
5254
5483
  },
5255
5484
  '&:hover .neo-nav-label': {
5256
5485
  color: neoDesign.semanticColors.buttons.primary.pressed,
5257
5486
  },
5258
- '&:focus-visible .neo-nav-icon-padding': {
5259
- backgroundColor: neoDesign.colors.digitalBlue[100],
5260
- },
5261
- '&:focus-visible .neo-nav-label': {
5262
- color: neoDesign.semanticColors.buttons.primary.pressed,
5263
- },
5264
5487
  }),
5265
5488
  }));
5266
5489
  const IconPadding = styles.styled('span')({
@@ -5281,31 +5504,314 @@ const Label$2 = styles.styled('span')(({ theme }) => ({
5281
5504
  width: '100%',
5282
5505
  transition: 'color 150ms',
5283
5506
  }));
5284
- const TagPill = styles.styled('span')(({ theme }) => ({
5285
- display: 'inline-flex',
5286
- alignItems: 'center',
5287
- justifyContent: 'center',
5288
- height: 18,
5289
- paddingLeft: neoDesign.spacing.spacing_3_4, // 6px
5290
- paddingRight: neoDesign.spacing.spacing_3_4, // 6px
5291
- borderRadius: neoDesign.borderRadius.full,
5292
- backgroundColor: neoDesign.colors.digitalBlue[300], // #8D99FF
5293
- color: neoDesign.semanticColors.typography.tooltip, // white
5294
- fontFamily: neoDesign.typography.fontFamily.body,
5295
- fontWeight: neoDesign.typography.fontWeight.medium,
5296
- fontSize: theme.typography.pxToRem(neoDesign.typography.fontSize.xs), // 12px
5297
- lineHeight: 1,
5298
- }));
5299
5507
  /**
5300
5508
  * NeoNavigationItem - Vertical navigation item with icon, label, and optional tag
5301
5509
  *
5302
5510
  * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=8455-6120
5303
5511
  */
5304
- function NeoNavigationItem({ icon, label, selected = false, tag, children, ...props }) {
5305
- return (jsxRuntime.jsxs(StyledRoot, { selected: selected, disableRipple: true, ...props, children: [jsxRuntime.jsx(IconPadding, { className: "neo-nav-icon-padding", children: icon }), label && jsxRuntime.jsx(Label$2, { className: "neo-nav-label", children: label }), tag && jsxRuntime.jsx(TagPill, { children: tag }), children] }));
5512
+ function NeoNavigationItem({ icon, label, selected = false, tag, tooltip, slotProps, children, ...props }) {
5513
+ const { collapsed } = useNeoSideNav();
5514
+ // When collapsed the label is hidden, so fall back to it for the tooltip and
5515
+ // accessible name — otherwise an icon-only button has no name (WCAG 4.1.2).
5516
+ const collapsedTooltip = tooltip ?? label;
5517
+ const item = (jsxRuntime.jsxs(StyledRoot, { selected: selected, "aria-label": collapsed && typeof label === 'string' ? label : undefined, disableRipple: true, ...props, children: [jsxRuntime.jsx(IconPadding, { className: "neo-nav-icon-padding", children: icon }), !collapsed && label && jsxRuntime.jsx(Label$2, { className: "neo-nav-label", children: label }), !collapsed && tag && (jsxRuntime.jsx(NeoTag, { size: "medium", variant: "filled", intent: "beta", label: tag, ...slotProps?.badge })), children] }));
5518
+ if (collapsed && collapsedTooltip) {
5519
+ return (jsxRuntime.jsx(NeoTooltip, { title: collapsedTooltip, placement: "right", arrow: true, children: item }));
5520
+ }
5521
+ return item;
5306
5522
  }
5307
5523
  NeoNavigationItem.displayName = 'NeoNavigationItem';
5308
5524
 
5525
+ const StyledActionsCell = styles.styled(xDataGrid.GridActionsCell)({
5526
+ gap: neoDesign.spacing.spacing_1,
5527
+ paddingLeft: neoDesign.spacing.spacing_1_1_2,
5528
+ paddingRight: neoDesign.spacing.spacing_1_1_2,
5529
+ });
5530
+ function NeoActionsCell(props) {
5531
+ return jsxRuntime.jsx(StyledActionsCell, { ...props });
5532
+ }
5533
+
5534
+ const StyledCell$1 = styles.styled('div', {
5535
+ shouldForwardProp: prop => prop !== 'disabled',
5536
+ })(({ disabled }) => ({
5537
+ display: 'flex',
5538
+ alignItems: 'center',
5539
+ gap: neoDesign.spacing.spacing_1, // 8px between avatar and label
5540
+ width: '100%',
5541
+ height: '100%',
5542
+ paddingLeft: neoDesign.spacing.spacing_1_1_2, // 12px — input-horizontal
5543
+ paddingRight: neoDesign.spacing.spacing_1_1_2,
5544
+ paddingTop: neoDesign.spacing.spacing_1_2, // 4px — input-vertical
5545
+ paddingBottom: neoDesign.spacing.spacing_1_2,
5546
+ backgroundColor: disabled
5547
+ ? neoDesign.semanticColors.surfaces.dataGrid.disabled
5548
+ : neoDesign.semanticColors.surfaces.dataGrid.default,
5549
+ boxSizing: 'border-box',
5550
+ }));
5551
+ const LabelText = styles.styled('span', {
5552
+ shouldForwardProp: prop => prop !== 'disabled',
5553
+ })(({ disabled }) => ({
5554
+ overflow: 'hidden',
5555
+ textOverflow: 'ellipsis',
5556
+ whiteSpace: 'nowrap',
5557
+ fontFamily: neoDesign.typography.fontFamily.body,
5558
+ fontSize: neoDesign.typography.fontSize.xs,
5559
+ fontWeight: neoDesign.typography.fontWeight.regular,
5560
+ lineHeight: 1.5,
5561
+ color: disabled ? neoDesign.semanticColors.typography.bodySecondary : neoDesign.semanticColors.typography.body,
5562
+ }));
5563
+ /**
5564
+ * NeoAvatarCell — DataGrid cell displaying a user avatar with optional label.
5565
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=13425-1725
5566
+ */
5567
+ const NeoAvatarCell = ({ name, src, label, disabled = false, empty = false, }) => {
5568
+ if (empty) {
5569
+ return jsxRuntime.jsx(StyledCell$1, { disabled: disabled });
5570
+ }
5571
+ return (jsxRuntime.jsxs(StyledCell$1, { disabled: disabled, children: [jsxRuntime.jsx(NeoGeneralAvatar, { size: "small", src: src, alt: name, children: !src && name ? name.charAt(0).toUpperCase() : undefined }), label && jsxRuntime.jsx(LabelText, { disabled: disabled, children: label })] }));
5572
+ };
5573
+ NeoAvatarCell.displayName = 'NeoAvatarCell';
5574
+
5575
+ const CellRoot = styles.styled('div', {
5576
+ shouldForwardProp: prop => prop !== 'disabled',
5577
+ })(({ disabled }) => ({
5578
+ display: 'flex',
5579
+ alignItems: 'center',
5580
+ justifyContent: 'center',
5581
+ width: '100%',
5582
+ height: '100%',
5583
+ color: disabled ? neoDesign.semanticColors.icons.disabled : neoDesign.semanticColors.icons.default,
5584
+ }));
5585
+ /**
5586
+ * NeoIconCell — Icon cell for DataGrid. Renders an icon centered in the cell.
5587
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=13272-9345
5588
+ */
5589
+ const NeoIconCell = ({ icon, ariaLabel, disabled = false }) => {
5590
+ if (!icon)
5591
+ return null;
5592
+ return (jsxRuntime.jsx(CellRoot, { disabled: disabled, "aria-label": ariaLabel, children: jsxRuntime.jsx(NeoIconWrapper, { size: 16, children: icon }) }));
5593
+ };
5594
+ NeoIconCell.displayName = 'NeoIconCell';
5595
+
5596
+ const CellWrapper = styles.styled('div', {
5597
+ shouldForwardProp: prop => prop !== 'disabled',
5598
+ })(({ disabled }) => ({
5599
+ display: 'flex',
5600
+ alignItems: 'center',
5601
+ justifyContent: 'flex-start',
5602
+ width: '100%',
5603
+ height: '100%',
5604
+ paddingLeft: neoDesign.spacing.spacing_1,
5605
+ paddingRight: neoDesign.spacing.spacing_1,
5606
+ backgroundColor: disabled
5607
+ ? neoDesign.semanticColors.surfaces.dataGrid.disabled
5608
+ : neoDesign.semanticColors.surfaces.dataGrid.default,
5609
+ '& img': {
5610
+ display: 'block',
5611
+ maxHeight: 32,
5612
+ width: 'auto',
5613
+ maxWidth: '100%',
5614
+ objectFit: 'contain',
5615
+ opacity: disabled ? 0.4 : 1,
5616
+ },
5617
+ }));
5618
+ /**
5619
+ * NeoLogoCell — DataGrid cell displaying a raster or SVG logo image.
5620
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=13278-9558
5621
+ *
5622
+ * Kept separate from NeoIconCell to match Neo's Icon/Logo component split:
5623
+ * - NeoIconCell: MUI SvgIcon components
5624
+ * - NeoLogoCell: raster or SVG image URLs (img tag)
5625
+ */
5626
+ const NeoLogoCell = ({ src, alt = '', disabled = false }) => {
5627
+ if (!src) {
5628
+ return jsxRuntime.jsx(CellWrapper, { disabled: disabled });
5629
+ }
5630
+ return (jsxRuntime.jsx(CellWrapper, { disabled: disabled, children: jsxRuntime.jsx(NeoIconWrapper, { size: 32, children: jsxRuntime.jsx("img", { src: src, alt: alt }) }) }));
5631
+ };
5632
+ NeoLogoCell.displayName = 'NeoLogoCell';
5633
+
5634
+ const StyledLinearProgress = styles.styled(LinearProgress, {
5635
+ shouldForwardProp: prop => prop !== 'labelPosition',
5636
+ })(() => ({
5637
+ height: 8,
5638
+ borderRadius: neoDesign.borderRadius.xS,
5639
+ backgroundColor: neoDesign.colors.grey[200],
5640
+ [`& .${LinearProgress.linearProgressClasses.bar}`]: {
5641
+ borderRadius: neoDesign.borderRadius.xS,
5642
+ backgroundColor: neoDesign.colors.digitalBlue[500],
5643
+ },
5644
+ [`&.${LinearProgress.linearProgressClasses.colorPrimary}`]: {
5645
+ backgroundColor: neoDesign.colors.grey[200],
5646
+ [`& .${LinearProgress.linearProgressClasses.bar}`]: {
5647
+ backgroundColor: neoDesign.colors.digitalBlue[500],
5648
+ },
5649
+ },
5650
+ // Cancelled variant uses warning color
5651
+ '&[data-variant="cancelled"]': {
5652
+ [`& .${LinearProgress.linearProgressClasses.bar}`]: {
5653
+ backgroundColor: neoDesign.semanticColors.status.warning.default,
5654
+ },
5655
+ },
5656
+ }));
5657
+ const ProgressWrapper = styles.styled('div')(({ labelPosition }) => ({
5658
+ display: 'flex',
5659
+ width: '100%',
5660
+ ...(labelPosition === 'right' && {
5661
+ flexDirection: 'row',
5662
+ alignItems: 'center',
5663
+ gap: neoDesign.spacing.spacing_3,
5664
+ }),
5665
+ ...(labelPosition === 'top' && {
5666
+ flexDirection: 'column-reverse',
5667
+ alignItems: 'flex-end',
5668
+ gap: neoDesign.spacing.spacing_2,
5669
+ }),
5670
+ ...(labelPosition === 'bottom' && {
5671
+ flexDirection: 'column',
5672
+ alignItems: 'flex-end',
5673
+ gap: neoDesign.spacing.spacing_2,
5674
+ }),
5675
+ ...(labelPosition === 'none' && {
5676
+ flexDirection: 'row',
5677
+ }),
5678
+ }));
5679
+ const ProgressLabel = styles.styled(Typography)(({ theme }) => ({
5680
+ fontSize: theme.typography.pxToRem(neoDesign.typography.fontSize.sm),
5681
+ fontWeight: neoDesign.typography.fontWeight.medium,
5682
+ color: neoDesign.colors.grey[800],
5683
+ lineHeight: 1.4,
5684
+ whiteSpace: 'nowrap',
5685
+ flexShrink: 0,
5686
+ }));
5687
+ const ProgressBarContainer = styles.styled('div')(({ labelPosition }) => ({
5688
+ flexGrow: labelPosition === 'right' ? 1 : 0,
5689
+ width: labelPosition === 'right' ? 'auto' : '100%',
5690
+ }));
5691
+ /**
5692
+ * NeoProgressbar - Linear progress indicator based on MUI LinearProgress
5693
+ *
5694
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=4120-36679
5695
+ *
5696
+ * Figma Props Mapping:
5697
+ * - progress (0%-100% | Cancelled) → value (0-100) + variant (default|cancelled)
5698
+ * - label (False|Right|Top|Bottom) → labelPosition (none|right|top|bottom)
5699
+ *
5700
+ * Design Decisions (from Issue #75):
5701
+ * - MUI Base Component: LinearProgress (provides accessibility, animations, progress tracking)
5702
+ * - Label Positioning: Single labelPosition prop with values 'none', 'right', 'top', 'bottom'
5703
+ * - Cancelled State: Separate variant prop (variant='cancelled') alongside value prop
5704
+ */
5705
+ const NeoProgressbar = ({ value = 0, labelPosition = 'none', variant = 'default', labelText, ...props }) => {
5706
+ const showLabel = labelPosition !== 'none';
5707
+ const displayLabel = labelText || (variant === 'cancelled' ? 'Canceled' : `${Math.round(value)}%`);
5708
+ return (jsxRuntime.jsxs(ProgressWrapper, { labelPosition: labelPosition, children: [jsxRuntime.jsx(ProgressBarContainer, { labelPosition: labelPosition, children: jsxRuntime.jsx(StyledLinearProgress, { variant: "determinate", value: variant === 'cancelled' ? 100 : value, "data-variant": variant, labelPosition: labelPosition, ...props }) }), showLabel && jsxRuntime.jsx(ProgressLabel, { children: displayLabel })] }));
5709
+ };
5710
+ NeoProgressbar.displayName = 'NeoProgressbar';
5711
+
5712
+ const StyledCell = styles.styled('div', {
5713
+ shouldForwardProp: prop => prop !== 'disabled',
5714
+ })(({ disabled }) => ({
5715
+ display: 'flex',
5716
+ alignItems: 'center',
5717
+ width: '100%',
5718
+ height: '100%',
5719
+ paddingLeft: neoDesign.spacing.spacing_1_1_2, // 12px input-horizontal
5720
+ paddingRight: neoDesign.spacing.spacing_1_1_2,
5721
+ backgroundColor: disabled
5722
+ ? neoDesign.semanticColors.surfaces.dataGrid.disabled
5723
+ : neoDesign.semanticColors.surfaces.dataGrid.default,
5724
+ boxSizing: 'border-box',
5725
+ }));
5726
+ /**
5727
+ * NeoProgressCell — DataGrid cell displaying a linear progress indicator.
5728
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=13425-5378
5729
+ */
5730
+ const NeoProgressCell = ({ value = 0, disabled = false, empty = false, }) => {
5731
+ const clampedValue = Math.min(100, Math.max(0, value));
5732
+ return (jsxRuntime.jsx(StyledCell, { disabled: disabled, children: !empty && jsxRuntime.jsx(NeoProgressbar, { value: clampedValue, labelPosition: "none" }) }));
5733
+ };
5734
+ NeoProgressCell.displayName = 'NeoProgressCell';
5735
+
5736
+ const variantColors = (variant) => ({
5737
+ bg: neoDesign.semanticColors.status[variant].light,
5738
+ fg: neoDesign.semanticColors.status[variant].dark,
5739
+ border: neoDesign.semanticColors.status[variant].transparent,
5740
+ });
5741
+ const StyledChip = styles.styled('div', {
5742
+ shouldForwardProp: prop => prop !== 'disabled' && prop !== 'variant',
5743
+ })(({ disabled, variant }) => {
5744
+ const colors = variantColors(variant);
5745
+ return {
5746
+ display: 'inline-flex',
5747
+ alignItems: 'center',
5748
+ gap: neoDesign.spacing.spacing_3_4,
5749
+ paddingTop: neoDesign.spacing.spacing_1_2,
5750
+ paddingBottom: neoDesign.spacing.spacing_1_2,
5751
+ paddingLeft: neoDesign.spacing.spacing_1_1_2,
5752
+ paddingRight: neoDesign.spacing.spacing_1_1_2,
5753
+ borderRadius: neoDesign.borderRadius.full,
5754
+ border: `1px solid ${disabled ? neoDesign.semanticColors.border.secondary : colors.border}`,
5755
+ backgroundColor: disabled ? neoDesign.semanticColors.surfaces.dataGrid.disabled : colors.bg,
5756
+ color: disabled ? neoDesign.semanticColors.icons.disabled : colors.fg,
5757
+ fontFamily: neoDesign.typography.fontFamily.body,
5758
+ fontSize: neoDesign.typography.fontSize.xs,
5759
+ fontWeight: neoDesign.typography.fontWeight.medium,
5760
+ lineHeight: 1,
5761
+ whiteSpace: 'nowrap',
5762
+ overflow: 'hidden',
5763
+ maxWidth: '100%',
5764
+ '& svg': {
5765
+ flexShrink: 0,
5766
+ width: '1em',
5767
+ height: '1em',
5768
+ fontSize: neoDesign.typography.fontSize.xs,
5769
+ },
5770
+ };
5771
+ });
5772
+ const TooltipErrorPre = styles.styled('pre')({
5773
+ margin: 0,
5774
+ padding: 0,
5775
+ fontFamily: neoDesign.typography.fontFamily.code,
5776
+ fontSize: neoDesign.typography.fontSize.sm,
5777
+ fontWeight: neoDesign.typography.fontWeight.regular,
5778
+ lineHeight: 1.5,
5779
+ color: neoDesign.semanticColors.typography.tooltip,
5780
+ whiteSpace: 'pre-wrap',
5781
+ wordBreak: 'break-all',
5782
+ maxHeight: 200,
5783
+ overflowY: 'auto',
5784
+ });
5785
+ const StyledTooltip = styles.styled(Tooltip)({
5786
+ [`& .${Tooltip.tooltipClasses.tooltip}`]: {
5787
+ backgroundColor: neoDesign.semanticColors.surfaces.tooltip,
5788
+ maxWidth: 400,
5789
+ padding: `${neoDesign.spacing.spacing_1}px ${neoDesign.spacing.spacing_1_1_2}px`,
5790
+ },
5791
+ [`& .${Tooltip.tooltipClasses.arrow}`]: {
5792
+ color: neoDesign.semanticColors.surfaces.tooltip,
5793
+ },
5794
+ });
5795
+ /**
5796
+ * NeoStatusCell — DataGrid cell displaying an icon + label chip with optional error tooltip.
5797
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=13272-8705
5798
+ */
5799
+ const NeoStatusCell = ({ icon, label, details, disabled = false, variant = 'success', empty = false, }) => {
5800
+ if (empty) {
5801
+ return (jsxRuntime.jsx(Box, { component: "span", sx: {
5802
+ color: neoDesign.semanticColors.typography.body,
5803
+ fontSize: neoDesign.typography.fontSize.sm,
5804
+ lineHeight: 1,
5805
+ }, children: '—' }));
5806
+ }
5807
+ const chip = (jsxRuntime.jsxs(StyledChip, { disabled: disabled, variant: variant, children: [icon, label] }));
5808
+ if (details) {
5809
+ return (jsxRuntime.jsx(StyledTooltip, { title: jsxRuntime.jsx(TooltipErrorPre, { children: details }), arrow: true, placement: "bottom-start", children: jsxRuntime.jsx(Box, { component: "span", sx: { display: 'inline-flex' }, children: chip }) }));
5810
+ }
5811
+ return chip;
5812
+ };
5813
+ NeoStatusCell.displayName = 'NeoStatusCell';
5814
+
5309
5815
  /**
5310
5816
  * Sticky header wrapper - sticks to top when scrolling
5311
5817
  */
@@ -5320,10 +5826,9 @@ const StickyHeader = styles.styled(Box)(({ theme }) => ({
5320
5826
  * Page title typography
5321
5827
  */
5322
5828
  const PageTitle = styles.styled(Typography)(() => ({
5323
- fontSize: neoDesign.typography.fontSize.h3,
5324
- fontWeight: neoDesign.typography.fontWeight.medium,
5829
+ ...neoDesign.semanticTypography.titles.pageHeader,
5325
5830
  lineHeight: 1.4,
5326
- color: neoDesign.colors.grey['900'], // #111827 - matches Figma typography/page-header
5831
+ color: neoDesign.colors.grey['900'],
5327
5832
  }));
5328
5833
  /**
5329
5834
  * Subtitle typography
@@ -5387,7 +5892,12 @@ const Subtitle = styles.styled(Typography)(() => ({
5387
5892
  * </NeoPageContent>
5388
5893
  * ```
5389
5894
  */
5390
- function NeoPageContent({ pageTitle, subtitle, breadcrumbs, action, sticky = false, contentMaxWidth = false, centerContent = true, disableGutters = false, isLoading = false, showBackToTop = true, children, sx, ...boxProps }) {
5895
+ function NeoPageContent({ pageTitle, subtitle, breadcrumbs, action, sticky = false, contentMaxWidth: contentMaxWidthProp = false, centerContent = true, disableGutters: disableGuttersProp = false, isLoading = false, showBackToTop = true, layout = 'default', children, sx, ...boxProps }) {
5896
+ // fullBleed forces no max-width, no gutters, and zero bottom padding
5897
+ // so children can fill the viewport edge-to-edge.
5898
+ const isFullBleed = layout === 'fullBleed';
5899
+ const contentMaxWidth = isFullBleed ? false : contentMaxWidthProp;
5900
+ const disableGutters = isFullBleed || disableGuttersProp;
5391
5901
  const [showBackToTopButton, setShowBackToTopButton] = React.useState(false);
5392
5902
  const headerRef = React.useRef(null);
5393
5903
  const containerRef = React.useRef(null);
@@ -5417,7 +5927,7 @@ function NeoPageContent({ pageTitle, subtitle, breadcrumbs, action, sticky = fal
5417
5927
  // Also try to scroll window in case component is in a different context
5418
5928
  window.scrollTo({ top: 0, behavior: 'smooth' });
5419
5929
  };
5420
- const headerContent = (jsxRuntime.jsxs(Stack, { ref: headerRef, sx: { flexShrink: 0, gap: '0.5rem' }, children: [breadcrumbs && breadcrumbs.items.length > 0 && (jsxRuntime.jsx(NeoBreadcrumbs, { children: breadcrumbs.items.map((item, index) => (jsxRuntime.jsx(NeoBreadcrumbLink, { href: item.href, component: item.href && breadcrumbs.linkComponent ? breadcrumbs.linkComponent : undefined, current: index === breadcrumbs.items.length - 1, children: item.label }, item.href ?? index))) })), jsxRuntime.jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "flex-start", sx: { gap: '1rem' }, children: [jsxRuntime.jsxs(Stack, { sx: { gap: '0.5rem', flexGrow: 1 }, children: [jsxRuntime.jsx(PageTitle, { children: pageTitle }), subtitle &&
5930
+ const headerContent = (jsxRuntime.jsxs(Stack, { ref: headerRef, sx: { flexShrink: 0, gap: '0.5rem' }, children: [breadcrumbs && breadcrumbs.items.length > 0 && (jsxRuntime.jsx(NeoBreadcrumbs, { children: breadcrumbs.items.map((item, index) => (jsxRuntime.jsx(NeoBreadcrumbLink, { href: item.href, component: item.href && breadcrumbs.linkComponent ? breadcrumbs.linkComponent : undefined, current: index === breadcrumbs.items.length - 1, children: item.label }, item.href ?? index))) })), jsxRuntime.jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "flex-start", sx: { gap: '1rem' }, children: [jsxRuntime.jsxs(Stack, { sx: { gap: '0.5rem', flexGrow: 1 }, children: [typeof pageTitle === 'string' ? (jsxRuntime.jsx(PageTitle, { component: "h1", children: pageTitle })) : (pageTitle), subtitle &&
5421
5931
  (typeof subtitle === 'string' ? (jsxRuntime.jsx(Subtitle, { variant: "caption", children: subtitle })) : (subtitle))] }), action] })] }));
5422
5932
  const content = isLoading ? (jsxRuntime.jsx(Box, { sx: {
5423
5933
  display: 'flex',
@@ -5439,7 +5949,7 @@ function NeoPageContent({ pageTitle, subtitle, breadcrumbs, action, sticky = fal
5439
5949
  flexDirection: 'column',
5440
5950
  px: disableGutters ? 0 : `${neoDesign.spacing.spacing_2_1_2}px`,
5441
5951
  pt: sticky ? 0 : `${neoDesign.spacing.spacing_2}px`,
5442
- pb: `${neoDesign.spacing.spacing_2_1_2}px`,
5952
+ pb: isFullBleed ? 0 : `${neoDesign.spacing.spacing_2_1_2}px`,
5443
5953
  height: '100%',
5444
5954
  overflow: 'auto',
5445
5955
  }, children: [sticky ? (jsxRuntime.jsx(StickyHeader, { ref: headerRef, sx: {
@@ -5464,7 +5974,7 @@ function NeoPageContent({ pageTitle, subtitle, breadcrumbs, action, sticky = fal
5464
5974
  width: '100%',
5465
5975
  ...(centerContent ? { mx: 'auto' } : { alignSelf: 'flex-start' }),
5466
5976
  }),
5467
- }, children: content })] }) }), showBackToTop && (jsxRuntime.jsx(Fade, { in: showBackToTopButton, children: jsxRuntime.jsx(Box, { sx: {
5977
+ }, children: content })] }) }), showBackToTop && (jsxRuntime.jsx(Fade$1, { in: showBackToTopButton, children: jsxRuntime.jsx(Box, { sx: {
5468
5978
  position: 'fixed',
5469
5979
  bottom: neoDesign.spacing.spacing_2,
5470
5980
  right: neoDesign.spacing.spacing_4,
@@ -5511,99 +6021,21 @@ function NeoPaginatedGrid({ slots, pageSizeOptions, slotProps: userSlotProps, ..
5511
6021
  // Explicitly enable pagination (matching moderne-ui ModerneDataGrid defaults)
5512
6022
  // Set defaults first, then spread props to allow overrides
5513
6023
  , {
5514
- // Explicitly enable pagination (matching moderne-ui ModerneDataGrid defaults)
5515
- // Set defaults first, then spread props to allow overrides
5516
- pagination: true, paginationMode: "client", pageSizeOptions: pageSizeOptions ?? [25, 50, 100], autoHeight: false, ...props,
5517
- // Merge slots after props to ensure footer is set
5518
- slots: mergedSlots, slotProps: {
5519
- basePopper: {
5520
- placement: 'bottom-start',
5521
- },
5522
- footer: {
5523
- variant: 'pagination',
5524
- },
5525
- ...userSlotProps,
5526
- } }));
5527
- }
5528
- NeoPaginatedGrid.displayName = 'NeoPaginatedGrid';
5529
-
5530
- const StyledLinearProgress = styles.styled(LinearProgress, {
5531
- shouldForwardProp: prop => prop !== 'labelPosition',
5532
- })(() => ({
5533
- height: 8,
5534
- borderRadius: neoDesign.borderRadius.xS,
5535
- backgroundColor: neoDesign.colors.grey[200],
5536
- [`& .${LinearProgress.linearProgressClasses.bar}`]: {
5537
- borderRadius: neoDesign.borderRadius.xS,
5538
- backgroundColor: neoDesign.colors.digitalBlue[500],
5539
- },
5540
- [`&.${LinearProgress.linearProgressClasses.colorPrimary}`]: {
5541
- backgroundColor: neoDesign.colors.grey[200],
5542
- [`& .${LinearProgress.linearProgressClasses.bar}`]: {
5543
- backgroundColor: neoDesign.colors.digitalBlue[500],
5544
- },
5545
- },
5546
- // Cancelled variant uses warning color
5547
- '&[data-variant="cancelled"]': {
5548
- [`& .${LinearProgress.linearProgressClasses.bar}`]: {
5549
- backgroundColor: neoDesign.semanticColors.status.warning.default,
5550
- },
5551
- },
5552
- }));
5553
- const ProgressWrapper = styles.styled('div')(({ labelPosition }) => ({
5554
- display: 'flex',
5555
- width: '100%',
5556
- ...(labelPosition === 'right' && {
5557
- flexDirection: 'row',
5558
- alignItems: 'center',
5559
- gap: neoDesign.spacing.spacing_3,
5560
- }),
5561
- ...(labelPosition === 'top' && {
5562
- flexDirection: 'column-reverse',
5563
- alignItems: 'flex-end',
5564
- gap: neoDesign.spacing.spacing_2,
5565
- }),
5566
- ...(labelPosition === 'bottom' && {
5567
- flexDirection: 'column',
5568
- alignItems: 'flex-end',
5569
- gap: neoDesign.spacing.spacing_2,
5570
- }),
5571
- ...(labelPosition === 'none' && {
5572
- flexDirection: 'row',
5573
- }),
5574
- }));
5575
- const ProgressLabel = styles.styled(Typography)(({ theme }) => ({
5576
- fontSize: theme.typography.pxToRem(neoDesign.typography.fontSize.sm),
5577
- fontWeight: neoDesign.typography.fontWeight.medium,
5578
- color: neoDesign.colors.grey[800],
5579
- lineHeight: 1.4,
5580
- whiteSpace: 'nowrap',
5581
- flexShrink: 0,
5582
- }));
5583
- const ProgressBarContainer = styles.styled('div')(({ labelPosition }) => ({
5584
- flexGrow: labelPosition === 'right' ? 1 : 0,
5585
- width: labelPosition === 'right' ? 'auto' : '100%',
5586
- }));
5587
- /**
5588
- * NeoProgressbar - Linear progress indicator based on MUI LinearProgress
5589
- *
5590
- * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=4120-36679
5591
- *
5592
- * Figma Props Mapping:
5593
- * - progress (0%-100% | Cancelled) → value (0-100) + variant (default|cancelled)
5594
- * - label (False|Right|Top|Bottom) → labelPosition (none|right|top|bottom)
5595
- *
5596
- * Design Decisions (from Issue #75):
5597
- * - MUI Base Component: LinearProgress (provides accessibility, animations, progress tracking)
5598
- * - Label Positioning: Single labelPosition prop with values 'none', 'right', 'top', 'bottom'
5599
- * - Cancelled State: Separate variant prop (variant='cancelled') alongside value prop
5600
- */
5601
- const NeoProgressbar = ({ value = 0, labelPosition = 'none', variant = 'default', labelText, ...props }) => {
5602
- const showLabel = labelPosition !== 'none';
5603
- const displayLabel = labelText || (variant === 'cancelled' ? 'Canceled' : `${Math.round(value)}%`);
5604
- return (jsxRuntime.jsxs(ProgressWrapper, { labelPosition: labelPosition, children: [jsxRuntime.jsx(ProgressBarContainer, { labelPosition: labelPosition, children: jsxRuntime.jsx(StyledLinearProgress, { variant: "determinate", value: variant === 'cancelled' ? 100 : value, "data-variant": variant, labelPosition: labelPosition, ...props }) }), showLabel && jsxRuntime.jsx(ProgressLabel, { children: displayLabel })] }));
5605
- };
5606
- NeoProgressbar.displayName = 'NeoProgressbar';
6024
+ // Explicitly enable pagination (matching moderne-ui ModerneDataGrid defaults)
6025
+ // Set defaults first, then spread props to allow overrides
6026
+ pagination: true, paginationMode: "client", pageSizeOptions: pageSizeOptions ?? [25, 50, 100], autoHeight: false, ...props,
6027
+ // Merge slots after props to ensure footer is set
6028
+ slots: mergedSlots, slotProps: {
6029
+ basePopper: {
6030
+ placement: 'bottom-start',
6031
+ },
6032
+ footer: {
6033
+ variant: 'pagination',
6034
+ },
6035
+ ...userSlotProps,
6036
+ } }));
6037
+ }
6038
+ NeoPaginatedGrid.displayName = 'NeoPaginatedGrid';
5607
6039
 
5608
6040
  const StyledTextField = styles.styled(TextField)(({ theme }) => ({
5609
6041
  [`& .${InputBase.inputBaseClasses.root}`]: {
@@ -5847,6 +6279,55 @@ const NeoRadio = ({ size = 'medium', label, helperText, disabled, ...props }) =>
5847
6279
  };
5848
6280
  NeoRadio.displayName = 'NeoRadio';
5849
6281
 
6282
+ /**
6283
+ * NeoRadioButtonWithText
6284
+ *
6285
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=11565-7682
6286
+ */
6287
+ const NeoRadioButtonWithText = styles.styled('div')({});
6288
+
6289
+ // Box-breathing rhythm: appear (inhale) → hold → expand+fade (exhale) → rest.
6290
+ // Max scale is capped so the ring fits within a parent row's line-height.
6291
+ const ripple = material.keyframes `
6292
+ 0% { opacity: 0; transform: scale(0.7); }
6293
+ 20% { opacity: 0.9; transform: scale(0.7); }
6294
+ 35% { opacity: 0.9; transform: scale(0.7); }
6295
+ 80% { opacity: 0; transform: scale(1.7); }
6296
+ 100% { opacity: 0; transform: scale(0.7); }
6297
+ `;
6298
+ /**
6299
+ * NeoRipplingDot - Animated status dot with an expanding ripple ring.
6300
+ *
6301
+ * Indicates an in-progress, indeterminate state (RUNNING / SYNCING / PROCESSING).
6302
+ * Color is inherited from `currentColor`; set it via the `color`/`sx` prop or a
6303
+ * parent. Sized to the lowercase-letter height regardless of parent fontSize.
6304
+ */
6305
+ const NeoRipplingDot = props => (jsxRuntime.jsx(material.Box, { "aria-hidden": "true", ...props, style: {
6306
+ width: neoDesign.spacing.spacing_1,
6307
+ height: neoDesign.spacing.spacing_1,
6308
+ ...props.style,
6309
+ }, sx: {
6310
+ position: 'relative',
6311
+ display: 'inline-block',
6312
+ borderRadius: '50%',
6313
+ backgroundColor: 'currentColor',
6314
+ verticalAlign: 'middle',
6315
+ flexShrink: 0,
6316
+ '&::before': {
6317
+ content: '""',
6318
+ position: 'absolute',
6319
+ inset: '-25%',
6320
+ borderRadius: '50%',
6321
+ border: '1px solid currentColor',
6322
+ animation: `${ripple} 5.6s ease-in-out infinite`,
6323
+ '@media (prefers-reduced-motion: reduce)': {
6324
+ display: 'none',
6325
+ },
6326
+ },
6327
+ ...props.sx,
6328
+ } }));
6329
+ NeoRipplingDot.displayName = 'NeoRipplingDot';
6330
+
5850
6331
  const StyledSearchChip = styles.styled(InputBase)(({ theme }) => ({
5851
6332
  borderRadius: neoDesign.borderRadius.full,
5852
6333
  border: `1px solid ${neoDesign.semanticColors.buttons.secondary.defaultBorder}`,
@@ -5912,6 +6393,126 @@ const NeoSearchChip = ({ onClear, value, ...props }) => {
5912
6393
  };
5913
6394
  NeoSearchChip.displayName = 'NeoSearchChip';
5914
6395
 
6396
+ /**
6397
+ * NeoSelectField — composite of NeoInputField's form chrome (label,
6398
+ * helper text, error state) wrapped around NeoSelect. Mirrors the
6399
+ * MUI `<TextField select>` ergonomics with Neo design tokens, so
6400
+ * consumers don't have to compose the two manually.
6401
+ *
6402
+ * @example
6403
+ * <NeoSelectField
6404
+ * label="Response format"
6405
+ * value={format}
6406
+ * onChange={e => setFormat(e.target.value)}
6407
+ * options={[
6408
+ * { value: 'json', label: 'JSON' },
6409
+ * { value: 'plain', label: 'Plain text' },
6410
+ * ]}
6411
+ * />
6412
+ */
6413
+ const NeoSelectField = ({ size = 'medium', destructive = false, label, required = false, infoIcon, helperText, errorMessage, options, children, disabled, id, ...selectProps }) => {
6414
+ const inputId = id || `neo-select-${Math.random().toString(36).substring(7)}`;
6415
+ const helperTextId = helperText || errorMessage ? `${inputId}-helper-text` : undefined;
6416
+ return (jsxRuntime.jsxs(StyledFormControl, { size: size, error: destructive, disabled: disabled, children: [label && (jsxRuntime.jsxs(StyledInputLabel, { htmlFor: inputId, size: size, infoIcon: !!infoIcon, disabled: disabled, error: destructive, shrink: true, children: [label, required && jsxRuntime.jsx("span", { "aria-hidden": "true", children: "*" }), infoIcon && jsxRuntime.jsx(InfoIconWrapper, { children: infoIcon })] })), jsxRuntime.jsx(NeoSelect, { id: inputId, disabled: disabled, error: destructive, "aria-describedby": helperTextId, ...selectProps, children: children ??
6417
+ options?.map(opt => (jsxRuntime.jsx(NeoMenuItem, { value: opt.value, disabled: opt.disabled, children: opt.label }, String(opt.value)))) }), (helperText || errorMessage) && (jsxRuntime.jsx(StyledFormHelperText, { id: helperTextId, error: destructive, disabled: disabled, sx: { marginTop: `${neoDesign.spacing.spacing_3_4}px` }, children: destructive ? errorMessage : helperText }))] }));
6418
+ };
6419
+ NeoSelectField.displayName = 'NeoSelectField';
6420
+
6421
+ const EXPANDED_WIDTH = 98;
6422
+ const COLLAPSED_WIDTH = 56;
6423
+ // The fade overlay must end on the same color as the rail to blend cleanly.
6424
+ const RAIL_BACKGROUND = neoDesign.colors.grey[100];
6425
+ /**
6426
+ * NeoSideNav
6427
+ *
6428
+ * Collapsible vertical navigation rail with fixed `header`/`footer` slots and a
6429
+ * scrolling content area. Controlled via `collapsed` + `onCollapsedChange`;
6430
+ * broadcasts collapsed state to descendant `NeoNavigationItem`s through context.
6431
+ *
6432
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=4065-3425
6433
+ */
6434
+ const Root = styles.styled('nav', {
6435
+ shouldForwardProp: prop => prop !== 'collapsed',
6436
+ })(({ collapsed, theme }) => ({
6437
+ display: 'flex',
6438
+ flexDirection: 'column',
6439
+ height: '100%',
6440
+ width: collapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH,
6441
+ minWidth: collapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH,
6442
+ backgroundColor: RAIL_BACKGROUND,
6443
+ transition: theme.transitions.create(['width', 'min-width'], {
6444
+ duration: theme.transitions.duration.shorter,
6445
+ }),
6446
+ overflow: 'hidden',
6447
+ }));
6448
+ const Header = styles.styled('div')({
6449
+ flexShrink: 0,
6450
+ display: 'flex',
6451
+ flexDirection: 'column',
6452
+ alignItems: 'center',
6453
+ });
6454
+ const Scroll = styles.styled('div')({
6455
+ flex: 1,
6456
+ minHeight: 0,
6457
+ overflowY: 'auto',
6458
+ overflowX: 'hidden',
6459
+ display: 'flex',
6460
+ flexDirection: 'column',
6461
+ alignItems: 'center',
6462
+ gap: neoDesign.spacing.spacing_1_2,
6463
+ paddingInline: neoDesign.spacing.spacing_1,
6464
+ '&::-webkit-scrollbar': { width: neoDesign.spacing.spacing_1_2 },
6465
+ '&::-webkit-scrollbar-thumb': {
6466
+ backgroundColor: neoDesign.semanticColors.border.primary,
6467
+ borderRadius: neoDesign.borderRadius.xXS,
6468
+ },
6469
+ });
6470
+ const FooterRegion = styles.styled('div')({
6471
+ position: 'relative',
6472
+ flexShrink: 0,
6473
+ display: 'flex',
6474
+ flexDirection: 'column',
6475
+ alignItems: 'center',
6476
+ gap: neoDesign.spacing.spacing_1_2,
6477
+ paddingInline: neoDesign.spacing.spacing_1,
6478
+ paddingBottom: neoDesign.spacing.spacing_1,
6479
+ });
6480
+ // Gradient fade so scrolling items dissolve into the footer instead of butting against it.
6481
+ const Fade = styles.styled('div')({
6482
+ position: 'absolute',
6483
+ top: -neoDesign.spacing.spacing_3,
6484
+ left: 0,
6485
+ right: 0,
6486
+ height: neoDesign.spacing.spacing_3,
6487
+ pointerEvents: 'none',
6488
+ background: `linear-gradient(to bottom, transparent, ${RAIL_BACKGROUND})`,
6489
+ });
6490
+ const Toggle = styles.styled(ButtonBase)(({ theme }) => ({
6491
+ display: 'flex',
6492
+ alignItems: 'center',
6493
+ justifyContent: 'center',
6494
+ flexDirection: 'column',
6495
+ gap: neoDesign.spacing.spacing_1_2,
6496
+ width: '100%',
6497
+ paddingBlock: neoDesign.spacing.spacing_1,
6498
+ borderRadius: neoDesign.borderRadius.s,
6499
+ border: `1px solid ${neoDesign.semanticColors.border.secondary}`,
6500
+ color: neoDesign.semanticColors.typography.bodySecondary,
6501
+ fontFamily: neoDesign.typography.fontFamily.body,
6502
+ fontSize: theme.typography.pxToRem(11),
6503
+ lineHeight: 1,
6504
+ '&:hover': {
6505
+ color: neoDesign.semanticColors.typography.body,
6506
+ borderColor: neoDesign.semanticColors.border.primary,
6507
+ },
6508
+ }));
6509
+ function NeoSideNav({ collapsed, onCollapsedChange, header, footer, children, collapseLabel = 'Less', ...rest }) {
6510
+ const ToggleIcon = collapsed ? PanelLeftOpen : PanelLeftClose;
6511
+ const contextValue = React.useMemo(() => ({ collapsed }), [collapsed]);
6512
+ return (jsxRuntime.jsx(NeoSideNavContext.Provider, { value: contextValue, children: jsxRuntime.jsxs(Root, { collapsed: collapsed, ...rest, children: [header && jsxRuntime.jsx(Header, { children: header }), jsxRuntime.jsx(Scroll, { children: children }), jsxRuntime.jsxs(FooterRegion, { children: [jsxRuntime.jsx(Fade, {}), footer, jsxRuntime.jsxs(Toggle, { "data-testid": "neo-side-nav-toggle", "aria-label": collapsed ? 'Expand navigation' : 'Collapse navigation', disableRipple: true, onClick: () => onCollapsedChange(!collapsed), children: [jsxRuntime.jsx(ToggleIcon, { size: 18 }), !collapsed && jsxRuntime.jsx("span", { children: collapseLabel })] })] })] }) }));
6513
+ }
6514
+ NeoSideNav.displayName = 'NeoSideNav';
6515
+
5915
6516
  const StyledSkeleton = styles.styled(Skeleton, {
5916
6517
  shouldForwardProp: prop => prop !== 'colorTheme' && prop !== 'position',
5917
6518
  })(({ theme, colorTheme = 'light', position = 'start' }) => ({
@@ -5959,6 +6560,111 @@ const NeoSkeleton = ({ colorTheme = 'light', position = 'start', ...props }) =>
5959
6560
  };
5960
6561
  NeoSkeleton.displayName = 'NeoSkeleton';
5961
6562
 
6563
+ const sizePadding = {
6564
+ small: `${neoDesign.spacing.spacing_3_4}px ${neoDesign.spacing.spacing_1_1_2}px`,
6565
+ medium: `${neoDesign.spacing.spacing_1_1_2}px ${neoDesign.spacing.spacing_2}px`,
6566
+ };
6567
+ const sizeFontSize = {
6568
+ small: neoDesign.typography.fontSize.xs,
6569
+ medium: neoDesign.typography.fontSize.sm,
6570
+ };
6571
+ const StyledTable = styles.styled(MuiTable, {
6572
+ shouldForwardProp: prop => prop !== 'tableSize',
6573
+ })(({ theme, tableSize = 'small' }) => ({
6574
+ borderCollapse: 'separate',
6575
+ borderSpacing: 0,
6576
+ [`& .${TableCell.tableCellClasses.head}`]: {
6577
+ backgroundColor: neoDesign.colors.grey[50],
6578
+ color: neoDesign.semanticColors.typography.body,
6579
+ fontFamily: neoDesign.typography.fontFamily.body,
6580
+ fontSize: theme.typography.pxToRem(sizeFontSize[tableSize]),
6581
+ fontWeight: neoDesign.typography.fontWeight.semiBold,
6582
+ lineHeight: 1.4,
6583
+ padding: sizePadding[tableSize],
6584
+ borderBottom: `1px solid ${neoDesign.semanticColors.border.secondary}`,
6585
+ },
6586
+ [`& .${TableCell.tableCellClasses.body}`]: {
6587
+ color: neoDesign.semanticColors.typography.body,
6588
+ fontFamily: neoDesign.typography.fontFamily.body,
6589
+ fontSize: theme.typography.pxToRem(sizeFontSize[tableSize]),
6590
+ fontWeight: neoDesign.typography.fontWeight.regular,
6591
+ lineHeight: 1.4,
6592
+ padding: sizePadding[tableSize],
6593
+ borderBottom: `1px solid ${neoDesign.semanticColors.border.secondary}`,
6594
+ },
6595
+ // Drop the trailing row's bottom border so the container border (if
6596
+ // any) is the visual edge.
6597
+ [`& tbody tr:last-of-type .${TableCell.tableCellClasses.body}`]: {
6598
+ borderBottom: 'none',
6599
+ },
6600
+ }));
6601
+ const StyledContainer = styles.styled('div', {
6602
+ shouldForwardProp: prop => prop !== 'tableVariant',
6603
+ })(({ tableVariant = 'bordered' }) => tableVariant === 'bordered'
6604
+ ? {
6605
+ border: `1px solid ${neoDesign.semanticColors.border.secondary}`,
6606
+ borderRadius: neoDesign.borderRadius.card,
6607
+ overflow: 'hidden',
6608
+ backgroundColor: neoDesign.semanticColors.surfaces.white,
6609
+ }
6610
+ : { backgroundColor: 'transparent' });
6611
+ /**
6612
+ * NeoTable — lightweight read-only table for static data (schema rows,
6613
+ * key/value summaries, response metadata). For interactive grids with
6614
+ * sorting / filtering / pagination, use NeoDataGrid instead.
6615
+ *
6616
+ * @example
6617
+ * <NeoTable
6618
+ * columns={[
6619
+ * { key: 'name', header: 'Property' },
6620
+ * { key: 'type', header: 'Type', align: 'center', width: '120px' },
6621
+ * { key: 'description', header: 'Description' },
6622
+ * ]}
6623
+ * rows={[
6624
+ * { name: 'id', type: 'string', description: 'Resource identifier' },
6625
+ * { name: 'count', type: 'number', description: 'Item count' },
6626
+ * ]}
6627
+ * size="small"
6628
+ * />
6629
+ */
6630
+ const NeoTable = ({ columns, rows, size = 'small', variant = 'bordered', ariaLabel, ...tableProps }) => (jsxRuntime.jsx(StyledContainer, { tableVariant: variant, children: jsxRuntime.jsx(TableContainer, { children: jsxRuntime.jsxs(StyledTable, { tableSize: size, "aria-label": ariaLabel, ...tableProps, children: [jsxRuntime.jsx(TableHead, { children: jsxRuntime.jsx(TableRow, { children: columns.map(col => (jsxRuntime.jsx(TableCell, { align: col.align ?? 'left', style: col.width ? { width: col.width } : undefined, children: col.header }, col.key))) }) }), jsxRuntime.jsx(TableBody, { children: rows.map((row, i) => (jsxRuntime.jsx(TableRow, { children: columns.map(col => (jsxRuntime.jsx(TableCell, { align: col.align ?? 'left', children: row[col.key] ?? '' }, col.key))) }, i))) })] }) }) }));
6631
+ NeoTable.displayName = 'NeoTable';
6632
+
6633
+ const StyledTabPanel = styles.styled(Box, {
6634
+ shouldForwardProp: prop => prop !== 'tabPanelVariant',
6635
+ })(({ tabPanelVariant = 'default' }) => ({
6636
+ backgroundColor: neoDesign.semanticColors.surfaces.white,
6637
+ // default: 16px top padding for content-driven pages.
6638
+ // flush: zero padding so content sits directly against the tab bar's
6639
+ // bottom border (sidebars, panels, builders, canvases).
6640
+ padding: 0,
6641
+ ...(tabPanelVariant === 'flush' ? {} : { paddingTop: neoDesign.spacing.spacing_2 }),
6642
+ }));
6643
+ /**
6644
+ * NeoTabPanel — completes the NeoTabs + NeoTab + NeoTabPanel set.
6645
+ *
6646
+ * Lightweight ARIA-compliant tab panel that renders children when its
6647
+ * `value` matches `currentValue`. No MUI Lab / TabContext dependency.
6648
+ *
6649
+ * @example
6650
+ * const [tab, setTab] = useState('overview')
6651
+ * return (
6652
+ * <>
6653
+ * <NeoTabs value={tab} onChange={(_, v) => setTab(v)}>
6654
+ * <NeoTab value="overview" label="Overview" />
6655
+ * <NeoTab value="details" label="Details" />
6656
+ * </NeoTabs>
6657
+ * <NeoTabPanel value="overview" currentValue={tab}>...</NeoTabPanel>
6658
+ * <NeoTabPanel value="details" currentValue={tab} variant="flush">...</NeoTabPanel>
6659
+ * </>
6660
+ * )
6661
+ */
6662
+ const NeoTabPanel = ({ value, currentValue, variant = 'default', children, ...boxProps }) => {
6663
+ const selected = value === currentValue;
6664
+ return (jsxRuntime.jsx(StyledTabPanel, { role: "tabpanel", hidden: !selected, tabPanelVariant: variant, id: `tabpanel-${value}`, "aria-labelledby": `tab-${value}`, ...boxProps, children: selected ? children : null }));
6665
+ };
6666
+ NeoTabPanel.displayName = 'NeoTabPanel';
6667
+
5962
6668
  /**
5963
6669
  * NeoTabs - Tabs container component based on MUI Tabs
5964
6670
  *
@@ -6338,6 +7044,102 @@ const NeoToggle = ({ size = 'medium', label, helperText, disabled, ...props }) =
6338
7044
  };
6339
7045
  NeoToggle.displayName = 'NeoToggle';
6340
7046
 
7047
+ const sizeStyles = {
7048
+ small: {
7049
+ height: 24,
7050
+ fontSize: neoDesign.typography.fontSize.xs,
7051
+ },
7052
+ medium: {
7053
+ height: 32,
7054
+ fontSize: neoDesign.typography.fontSize.sm,
7055
+ },
7056
+ };
7057
+ const StyledToggleButton$1 = styles.styled(MuiToggleButton, {
7058
+ shouldForwardProp: prop => prop !== 'toggleSize',
7059
+ })(({ theme, toggleSize = 'medium' }) => ({
7060
+ height: sizeStyles[toggleSize].height,
7061
+ padding: `0 ${neoDesign.spacing.spacing_1_1_2}px`,
7062
+ fontFamily: neoDesign.typography.fontFamily.body,
7063
+ fontSize: theme.typography.pxToRem(sizeStyles[toggleSize].fontSize),
7064
+ fontWeight: neoDesign.typography.fontWeight.regular,
7065
+ lineHeight: 1,
7066
+ color: neoDesign.semanticColors.typography.bodySecondary,
7067
+ backgroundColor: 'transparent',
7068
+ border: 'none',
7069
+ textTransform: 'none',
7070
+ transition: theme.transitions.create(['background-color', 'color'], {
7071
+ duration: theme.transitions.duration.short,
7072
+ }),
7073
+ '&:hover': {
7074
+ backgroundColor: neoDesign.colors.grey[100],
7075
+ color: neoDesign.semanticColors.typography.body,
7076
+ },
7077
+ '&.Mui-selected, &.Mui-selected:hover': {
7078
+ backgroundColor: neoDesign.colors.grey[100],
7079
+ color: neoDesign.semanticColors.typography.body,
7080
+ fontWeight: neoDesign.typography.fontWeight.semiBold,
7081
+ },
7082
+ '&.Mui-focusVisible': {
7083
+ outline: `2px solid ${neoDesign.semanticColors.border.focus}`,
7084
+ outlineOffset: -2,
7085
+ },
7086
+ '&.Mui-disabled': {
7087
+ color: neoDesign.semanticColors.typography.button.disabled,
7088
+ cursor: 'default',
7089
+ pointerEvents: 'none',
7090
+ },
7091
+ }));
7092
+ /**
7093
+ * NeoToggleButton — a single button in a segmented control. Use inside
7094
+ * NeoToggleButtonGroup; the group manages selection state and forwards
7095
+ * size to its children. Suitable for inline toolbar mode switches
7096
+ * ("Table" / "Raw"). For page-level tabs, prefer NeoButtonTab.
7097
+ */
7098
+ const NeoToggleButton = ({ children, size = 'medium', ...props }) => (jsxRuntime.jsx(StyledToggleButton$1, { toggleSize: size, ...props, children: children }));
7099
+ NeoToggleButton.displayName = 'NeoToggleButton';
7100
+
7101
+ const StyledToggleButtonGroup$1 = styles.styled(MuiToggleButtonGroup)({
7102
+ borderRadius: neoDesign.borderRadius.button,
7103
+ border: `1px solid ${neoDesign.semanticColors.border.secondary}`,
7104
+ overflow: 'hidden',
7105
+ display: 'inline-flex',
7106
+ // Children fill the pill — first/last get the rounded corners, middles
7107
+ // are square. MUI applies positional classes via ToggleButtonGroup
7108
+ // context; we rely on borderRadius inheritance from the container.
7109
+ [`& .${MuiToggleButton.toggleButtonClasses.root}`]: {
7110
+ borderRadius: 0,
7111
+ },
7112
+ });
7113
+ /**
7114
+ * NeoToggleButtonGroup — pill-shaped segmented control wrapping
7115
+ * MUI ToggleButtonGroup with Neo tokens. Use for inline toolbar mode
7116
+ * switches (e.g. "Table" / "Raw" in a panel header). For page-level
7117
+ * tab navigation, prefer NeoButtonTabGroup.
7118
+ *
7119
+ * @example
7120
+ * <NeoToggleButtonGroup value={mode} exclusive onChange={(_, v) => v && setMode(v)} size="small">
7121
+ * <NeoToggleButton value="table">Table</NeoToggleButton>
7122
+ * <NeoToggleButton value="raw">Raw</NeoToggleButton>
7123
+ * </NeoToggleButtonGroup>
7124
+ */
7125
+ const NeoToggleButtonGroup = ({ size = 'medium', children, ...props }) => {
7126
+ // Forward size to each NeoToggleButton child so consumers don't have to
7127
+ // set it on every button. MUI's group already does this via context for
7128
+ // its own size prop, but our `size` shape doesn't pass through unchanged.
7129
+ const sized = React.Children.map(children, child => React.isValidElement(child) && child.type === NeoToggleButton
7130
+ ? React.cloneElement(child, { size })
7131
+ : child);
7132
+ return jsxRuntime.jsx(StyledToggleButtonGroup$1, { ...props, children: sized });
7133
+ };
7134
+ NeoToggleButtonGroup.displayName = 'NeoToggleButtonGroup';
7135
+
7136
+ /**
7137
+ * NeoToggleButtonWithText
7138
+ *
7139
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=11565-10485
7140
+ */
7141
+ const NeoToggleButtonWithText = styles.styled('div')({});
7142
+
6341
7143
  const StyledToolbar = styles.styled(xDataGrid.Toolbar)(({ theme }) => ({
6342
7144
  backgroundColor: neoDesign.semanticColors.surfaces.white,
6343
7145
  minHeight: 'auto',
@@ -6398,86 +7200,18 @@ const NeoToolbar = ({ children, ...props }) => {
6398
7200
  NeoToolbar.displayName = 'NeoToolbar';
6399
7201
 
6400
7202
  /**
6401
- * Variant color configuration
6402
- */
6403
- const variantConfig = {
6404
- light: {
6405
- backgroundColor: neoDesign.semanticColors.surfaces.tooltip, // #4b5563 - medium gray
6406
- color: neoDesign.semanticColors.typography.tooltip, // #ffffff - white
6407
- },
6408
- dark: {
6409
- backgroundColor: neoDesign.colors.grey[50], // #f9fafb - very light gray
6410
- color: neoDesign.colors.grey[800], // #1f2937 - dark gray
6411
- },
6412
- brand: {
6413
- backgroundColor: neoDesign.colors.digitalBlue[800], // #131e7a - dark blue
6414
- color: neoDesign.semanticColors.typography.tooltip, // #ffffff - white
6415
- },
6416
- };
6417
- /**
6418
- * Styled MUI Tooltip with Neo design system tokens
7203
+ * NeoTopNav
7204
+ *
7205
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=4618-185228
6419
7206
  */
6420
- const StyledTooltip = styles.styled(Tooltip, {
6421
- shouldForwardProp: prop => prop !== 'variant' && prop !== 'description',
6422
- })(({ variant = 'light', description }) => {
6423
- const hasDescription = Boolean(description);
6424
- const variantStyles = variantConfig[variant];
6425
- return {
6426
- // Style the tooltip content
6427
- [`& .${Tooltip.tooltipClasses.tooltip}`]: {
6428
- backgroundColor: variantStyles.backgroundColor,
6429
- color: variantStyles.color,
6430
- fontSize: neoDesign.typography.fontSize.xs,
6431
- fontWeight: neoDesign.typography.fontWeight.medium,
6432
- lineHeight: hasDescription ? 1.5 : 1,
6433
- borderRadius: hasDescription ? neoDesign.borderRadius.s : neoDesign.borderRadius.xS,
6434
- padding: hasDescription ? neoDesign.spacing.spacing_1_1_2 : `0 ${neoDesign.spacing.spacing_1}px`,
6435
- ...(hasDescription && {
6436
- maxWidth: 296,
6437
- }),
6438
- ...(!hasDescription && {
6439
- height: neoDesign.spacing.spacing_3_1_4,
6440
- display: 'flex',
6441
- alignItems: 'center',
6442
- justifyContent: 'center',
6443
- }),
6444
- boxShadow: `${neoDesign.shadows.neutral.medium.x}px ${neoDesign.shadows.neutral.medium.y}px ${neoDesign.shadows.neutral.medium.blur}px ${neoDesign.shadows.neutral.medium.spread}px ${neoDesign.shadows.neutral.medium.shadow}`,
6445
- },
6446
- // Style the arrow
6447
- [`& .${Tooltip.tooltipClasses.arrow}`]: {
6448
- color: variantStyles.backgroundColor,
6449
- },
6450
- };
6451
- });
7207
+ const NeoTopNav = styles.styled('div')({});
7208
+
6452
7209
  /**
6453
- * NeoTooltip - Tooltip component following Neo design system
6454
- *
6455
- * Provides contextual information when users hover over or focus on an element.
6456
- * Supports three visual variants (light, dark, brand) and optional supporting text.
6457
- *
6458
- * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC/Neo---Moderne-Design-system---2025?node-id=4091-26557&t=Bo58EpFmg6ILJtmv-11
6459
- *
6460
- * Figma Props Mapping:
6461
- * - Theme (Light mode|Dark mode|Brand color) → variant ('light'|'dark'|'brand')
6462
- * - Placement → arrow (boolean) + placement (top/bottom/left/right/etc)
6463
- * - Supporting text (True|False) → description (string|undefined)
6464
- * - text → title (string, literal content)
7210
+ * NeoTourModal
6465
7211
  *
6466
- * Design Tokens Used:
6467
- * - Light: surfaces.tooltip (#4b5563), typography.tooltip (#ffffff)
6468
- * - Dark: grey[50] (#f9fafb), grey[800] (#1f2937)
6469
- * - Brand: digitalBlue[800] (#131e7a), typography.tooltip (#ffffff)
6470
- * - Shadow: neutralMedium (0px 8px 15px 0px rgba(31,41,55,0.1))
6471
- * - Typography: fontSize.xs (12), fontWeight.medium (500), fontWeight.semiBold (600)
7212
+ * @figma https://www.figma.com/design/fQTkGSFbYyE7LiHuQJsENC?node-id=12408-1800
6472
7213
  */
6473
- const NeoTooltip = ({ variant = 'light', title, description, children, arrow = false, placement, ...props }) => {
6474
- // Build the title content
6475
- // If description is provided, create a structured layout with title + description
6476
- // Otherwise, just show the title text
6477
- const titleContent = description ? (jsxRuntime.jsxs(Stack, { gap: 0.25, children: [jsxRuntime.jsx(Typography, { fontWeight: neoDesign.typography.fontWeight.semiBold, children: title }), jsxRuntime.jsx(Typography, { fontWeight: neoDesign.typography.fontWeight.medium, children: description })] })) : (title);
6478
- return (jsxRuntime.jsx(StyledTooltip, { variant: variant, description: description, title: titleContent, arrow: arrow, placement: placement, ...props, children: children }));
6479
- };
6480
- NeoTooltip.displayName = 'NeoTooltip';
7214
+ const NeoTourModal = styles.styled('div')({});
6481
7215
 
6482
7216
  /**
6483
7217
  * Custom label component that reads extra slot data from the item model.
@@ -6675,6 +7409,39 @@ const NeoTypologyControl = ({ children, ...props }) => {
6675
7409
  };
6676
7410
  NeoTypologyControl.displayName = 'NeoTypologyControl';
6677
7411
 
7412
+ // Box-breathing rhythm: inhale (grow) → hold → exhale (shadow expand+fade) → rest.
7413
+ const vibrate = material.keyframes `
7414
+ 0% { transform: scale(0.9); box-shadow: 0 0 0 0 transparent; }
7415
+ 25% { transform: scale(1); box-shadow: 0 0 0 0 currentColor; }
7416
+ 50% { transform: scale(1); box-shadow: 0 0 0 0 currentColor; }
7417
+ 75% { transform: scale(0.9); box-shadow: 0 0 0 ${neoDesign.spacing.spacing_3_4}px transparent; }
7418
+ 100% { transform: scale(0.9); box-shadow: 0 0 0 0 transparent; }
7419
+ `;
7420
+ /**
7421
+ * NeoVibratingDot - Animated status dot with a breathing pulse halo.
7422
+ *
7423
+ * Indicates a waiting/pending state (QUEUED / CREATED). Color is inherited from
7424
+ * `currentColor`; set it via the `color`/`sx` prop or a parent. Sized to the
7425
+ * lowercase-letter height regardless of parent fontSize.
7426
+ */
7427
+ const NeoVibratingDot = props => (jsxRuntime.jsx(material.Box, { "aria-hidden": "true", ...props, style: {
7428
+ width: neoDesign.spacing.spacing_1,
7429
+ height: neoDesign.spacing.spacing_1,
7430
+ ...props.style,
7431
+ }, sx: {
7432
+ display: 'inline-block',
7433
+ borderRadius: '50%',
7434
+ backgroundColor: 'currentColor',
7435
+ verticalAlign: 'middle',
7436
+ flexShrink: 0,
7437
+ animation: `${vibrate} 5.6s ease-in-out infinite`,
7438
+ '@media (prefers-reduced-motion: reduce)': {
7439
+ animation: 'none',
7440
+ },
7441
+ ...props.sx,
7442
+ } }));
7443
+ NeoVibratingDot.displayName = 'NeoVibratingDot';
7444
+
6678
7445
  /**
6679
7446
  * @moderneinc/neo-styled-components
6680
7447
  *
@@ -6684,9 +7451,11 @@ NeoTypologyControl.displayName = 'NeoTypologyControl';
6684
7451
  const version = '0.0.0-development';
6685
7452
 
6686
7453
  exports.CIRCLE_RADIUS = CIRCLE_RADIUS;
7454
+ exports.NeoActionsCell = NeoActionsCell;
6687
7455
  exports.NeoActivityHeader = NeoActivityHeader;
6688
7456
  exports.NeoActivityIndicatorCell = NeoActivityIndicatorCell;
6689
7457
  exports.NeoAlert = NeoAlert;
7458
+ exports.NeoAvatarCell = NeoAvatarCell;
6690
7459
  exports.NeoBadge = NeoBadge;
6691
7460
  exports.NeoBanner = NeoBanner;
6692
7461
  exports.NeoBreadcrumbLink = NeoBreadcrumbLink;
@@ -6694,6 +7463,7 @@ exports.NeoBreadcrumbs = NeoBreadcrumbs;
6694
7463
  exports.NeoButton = NeoButton;
6695
7464
  exports.NeoButtonTab = NeoButtonTab;
6696
7465
  exports.NeoButtonTabGroup = NeoButtonTabGroup;
7466
+ exports.NeoCanceledIcon = NeoCanceledIcon;
6697
7467
  exports.NeoCard = NeoCard;
6698
7468
  exports.NeoCheckbox = NeoCheckbox;
6699
7469
  exports.NeoCheckboxWithText = NeoCheckboxWithText;
@@ -6710,6 +7480,8 @@ exports.NeoDataGridFiltersButton = NeoDataGridFiltersButton;
6710
7480
  exports.NeoDataGridHeaderLabel = NeoDataGridHeaderLabel;
6711
7481
  exports.NeoDataGridSelect = NeoSelect;
6712
7482
  exports.NeoDatePicker = NeoDatePicker;
7483
+ exports.NeoDatePickerListItem = NeoDatePickerListItem;
7484
+ exports.NeoDatePickerMenu = NeoDatePickerMenu;
6713
7485
  exports.NeoDivider = NeoDivider;
6714
7486
  exports.NeoDot = NeoDot;
6715
7487
  exports.NeoDownloadToast = NeoDownloadToast;
@@ -6717,16 +7489,25 @@ exports.NeoDropdown = NeoSelect;
6717
7489
  exports.NeoDropdownMenu = NeoMenu;
6718
7490
  exports.NeoDropdownMenuItem = NeoMenuItem;
6719
7491
  exports.NeoDropdownOption = NeoMenuItem;
7492
+ exports.NeoFilledCanceled = NeoFilledCanceled;
7493
+ exports.NeoFilledError = NeoFilledError;
7494
+ exports.NeoFilledInfo = NeoFilledInfo;
7495
+ exports.NeoFilledNeutral = NeoFilledNeutral;
7496
+ exports.NeoFilledQueued = NeoFilledQueued;
7497
+ exports.NeoFilledSuccess = NeoFilledSuccess;
7498
+ exports.NeoFilledWarning = NeoFilledWarning;
6720
7499
  exports.NeoFilterChip = NeoFilterChip;
6721
7500
  exports.NeoFooter = NeoFooter;
6722
7501
  exports.NeoGeneralAvatar = NeoGeneralAvatar;
6723
7502
  exports.NeoIconButton = NeoIconButton;
7503
+ exports.NeoIconCell = NeoIconCell;
6724
7504
  exports.NeoIconWrapper = NeoIconWrapper;
6725
7505
  exports.NeoInfiniteScrollGrid = NeoInfiniteScrollGrid;
6726
7506
  exports.NeoInputField = NeoInputField;
6727
7507
  exports.NeoListItem = NeoListItem;
6728
7508
  exports.NeoListItemButton = NeoListItemButton;
6729
7509
  exports.NeoLoadingSpinner = NeoLoadingSpinner;
7510
+ exports.NeoLogoCell = NeoLogoCell;
6730
7511
  exports.NeoMenu = NeoMenu;
6731
7512
  exports.NeoMenuItem = NeoMenuItem;
6732
7513
  exports.NeoModal = NeoModal;
@@ -6738,32 +7519,47 @@ exports.NeoNavigationAvatar = NeoNavigationAvatar;
6738
7519
  exports.NeoNavigationItem = NeoNavigationItem;
6739
7520
  exports.NeoPageContent = NeoPageContent;
6740
7521
  exports.NeoPaginatedGrid = NeoPaginatedGrid;
7522
+ exports.NeoProgressCell = NeoProgressCell;
6741
7523
  exports.NeoProgressbar = NeoProgressbar;
6742
7524
  exports.NeoQuickFilter = NeoQuickFilter;
6743
7525
  exports.NeoRadio = NeoRadio;
7526
+ exports.NeoRadioButtonWithText = NeoRadioButtonWithText;
7527
+ exports.NeoRipplingDot = NeoRipplingDot;
6744
7528
  exports.NeoSearchChip = NeoSearchChip;
6745
7529
  exports.NeoSelect = NeoSelect;
7530
+ exports.NeoSelectField = NeoSelectField;
6746
7531
  exports.NeoSelectOption = NeoMenuItem;
7532
+ exports.NeoSideNav = NeoSideNav;
6747
7533
  exports.NeoSkeleton = NeoSkeleton;
6748
7534
  exports.NeoStatusBadgeCell = NeoStatusBadgeCell;
7535
+ exports.NeoStatusCell = NeoStatusCell;
6749
7536
  exports.NeoTab = NeoTab;
7537
+ exports.NeoTabPanel = NeoTabPanel;
7538
+ exports.NeoTable = NeoTable;
6750
7539
  exports.NeoTabs = NeoTabs;
6751
7540
  exports.NeoTag = NeoTag;
6752
7541
  exports.NeoToast = NeoToast;
6753
7542
  exports.NeoToastButton = NeoToastButton;
6754
7543
  exports.NeoToggle = NeoToggle;
7544
+ exports.NeoToggleButton = NeoToggleButton;
7545
+ exports.NeoToggleButtonGroup = NeoToggleButtonGroup;
7546
+ exports.NeoToggleButtonWithText = NeoToggleButtonWithText;
6755
7547
  exports.NeoToolbar = NeoToolbar;
6756
7548
  exports.NeoTooltip = NeoTooltip;
7549
+ exports.NeoTopNav = NeoTopNav;
7550
+ exports.NeoTourModal = NeoTourModal;
6757
7551
  exports.NeoTreeItem = NeoTreeItem;
6758
7552
  exports.NeoTreeView = NeoTreeView;
6759
7553
  exports.NeoTypologyButton = StyledToggleButton;
6760
7554
  exports.NeoTypologyControl = NeoTypologyControl;
6761
7555
  exports.NeoUserAvatarCell = NeoUserAvatarCell;
7556
+ exports.NeoVibratingDot = NeoVibratingDot;
6762
7557
  exports.SortedAscendingIcon = SortedAscendingIcon;
6763
7558
  exports.SortedDescendingIcon = SortedDescendingIcon;
6764
7559
  exports.UnsortedIcon = UnsortedIcon;
6765
7560
  exports.focusRingStyles = focusRingStyles;
6766
7561
  exports.getDataGridHeaderStyles = getDataGridHeaderStyles;
7562
+ exports.getDataGridRowStyles = getDataGridRowStyles;
6767
7563
  exports.neoRowHeights = neoRowHeights;
6768
7564
  exports.version = version;
6769
7565
  //# sourceMappingURL=index.js.map