@moderneinc/neo-styled-components 2.0.3 → 2.1.0-next.1c3b0f

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.
package/dist/index.js CHANGED
@@ -501,7 +501,7 @@ const NeoActivityIndicatorCell = ({ event = 'commit-job', secondaryEvent, scene
501
501
  NeoActivityIndicatorCell.displayName = 'NeoActivityIndicatorCell';
502
502
 
503
503
  /**
504
- * @license lucide-react v0.552.0 - ISC
504
+ * @license lucide-react v0.562.0 - ISC
505
505
  *
506
506
  * This source code is licensed under the ISC license.
507
507
  * See the LICENSE file in the root directory of this source tree.
@@ -528,7 +528,7 @@ const hasA11yProp = (props) => {
528
528
  };
529
529
 
530
530
  /**
531
- * @license lucide-react v0.552.0 - ISC
531
+ * @license lucide-react v0.562.0 - ISC
532
532
  *
533
533
  * This source code is licensed under the ISC license.
534
534
  * See the LICENSE file in the root directory of this source tree.
@@ -547,7 +547,7 @@ var defaultAttributes = {
547
547
  };
548
548
 
549
549
  /**
550
- * @license lucide-react v0.552.0 - ISC
550
+ * @license lucide-react v0.562.0 - ISC
551
551
  *
552
552
  * This source code is licensed under the ISC license.
553
553
  * See the LICENSE file in the root directory of this source tree.
@@ -585,7 +585,7 @@ const Icon = react.forwardRef(
585
585
  );
586
586
 
587
587
  /**
588
- * @license lucide-react v0.552.0 - ISC
588
+ * @license lucide-react v0.562.0 - ISC
589
589
  *
590
590
  * This source code is licensed under the ISC license.
591
591
  * See the LICENSE file in the root directory of this source tree.
@@ -610,7 +610,7 @@ const createLucideIcon = (iconName, iconNode) => {
610
610
  };
611
611
 
612
612
  /**
613
- * @license lucide-react v0.552.0 - ISC
613
+ * @license lucide-react v0.562.0 - ISC
614
614
  *
615
615
  * This source code is licensed under the ISC license.
616
616
  * See the LICENSE file in the root directory of this source tree.
@@ -624,7 +624,7 @@ const __iconNode$h = [
624
624
  const ArrowDown = createLucideIcon("arrow-down", __iconNode$h);
625
625
 
626
626
  /**
627
- * @license lucide-react v0.552.0 - ISC
627
+ * @license lucide-react v0.562.0 - ISC
628
628
  *
629
629
  * This source code is licensed under the ISC license.
630
630
  * See the LICENSE file in the root directory of this source tree.
@@ -638,7 +638,7 @@ const __iconNode$g = [
638
638
  const ArrowUp = createLucideIcon("arrow-up", __iconNode$g);
639
639
 
640
640
  /**
641
- * @license lucide-react v0.552.0 - ISC
641
+ * @license lucide-react v0.562.0 - ISC
642
642
  *
643
643
  * This source code is licensed under the ISC license.
644
644
  * See the LICENSE file in the root directory of this source tree.
@@ -660,7 +660,7 @@ const __iconNode$f = [
660
660
  const CalendarDays = createLucideIcon("calendar-days", __iconNode$f);
661
661
 
662
662
  /**
663
- * @license lucide-react v0.552.0 - ISC
663
+ * @license lucide-react v0.562.0 - ISC
664
664
  *
665
665
  * This source code is licensed under the ISC license.
666
666
  * See the LICENSE file in the root directory of this source tree.
@@ -671,7 +671,7 @@ const __iconNode$e = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
671
671
  const ChevronDown = createLucideIcon("chevron-down", __iconNode$e);
672
672
 
673
673
  /**
674
- * @license lucide-react v0.552.0 - ISC
674
+ * @license lucide-react v0.562.0 - ISC
675
675
  *
676
676
  * This source code is licensed under the ISC license.
677
677
  * See the LICENSE file in the root directory of this source tree.
@@ -682,7 +682,7 @@ const __iconNode$d = [["path", { d: "m15 18-6-6 6-6", key: "1wnfg3" }]];
682
682
  const ChevronLeft = createLucideIcon("chevron-left", __iconNode$d);
683
683
 
684
684
  /**
685
- * @license lucide-react v0.552.0 - ISC
685
+ * @license lucide-react v0.562.0 - ISC
686
686
  *
687
687
  * This source code is licensed under the ISC license.
688
688
  * See the LICENSE file in the root directory of this source tree.
@@ -693,7 +693,7 @@ const __iconNode$c = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
693
693
  const ChevronRight = createLucideIcon("chevron-right", __iconNode$c);
694
694
 
695
695
  /**
696
- * @license lucide-react v0.552.0 - ISC
696
+ * @license lucide-react v0.562.0 - ISC
697
697
  *
698
698
  * This source code is licensed under the ISC license.
699
699
  * See the LICENSE file in the root directory of this source tree.
@@ -704,7 +704,7 @@ const __iconNode$b = [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]];
704
704
  const ChevronUp = createLucideIcon("chevron-up", __iconNode$b);
705
705
 
706
706
  /**
707
- * @license lucide-react v0.552.0 - ISC
707
+ * @license lucide-react v0.562.0 - ISC
708
708
  *
709
709
  * This source code is licensed under the ISC license.
710
710
  * See the LICENSE file in the root directory of this source tree.
@@ -718,7 +718,7 @@ const __iconNode$a = [
718
718
  const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$a);
719
719
 
720
720
  /**
721
- * @license lucide-react v0.552.0 - ISC
721
+ * @license lucide-react v0.562.0 - ISC
722
722
  *
723
723
  * This source code is licensed under the ISC license.
724
724
  * See the LICENSE file in the root directory of this source tree.
@@ -733,7 +733,7 @@ const __iconNode$9 = [
733
733
  const CircleAlert = createLucideIcon("circle-alert", __iconNode$9);
734
734
 
735
735
  /**
736
- * @license lucide-react v0.552.0 - ISC
736
+ * @license lucide-react v0.562.0 - ISC
737
737
  *
738
738
  * This source code is licensed under the ISC license.
739
739
  * See the LICENSE file in the root directory of this source tree.
@@ -747,7 +747,7 @@ const __iconNode$8 = [
747
747
  const CircleCheck = createLucideIcon("circle-check", __iconNode$8);
748
748
 
749
749
  /**
750
- * @license lucide-react v0.552.0 - ISC
750
+ * @license lucide-react v0.562.0 - ISC
751
751
  *
752
752
  * This source code is licensed under the ISC license.
753
753
  * See the LICENSE file in the root directory of this source tree.
@@ -762,7 +762,7 @@ const __iconNode$7 = [
762
762
  const CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode$7);
763
763
 
764
764
  /**
765
- * @license lucide-react v0.552.0 - ISC
765
+ * @license lucide-react v0.562.0 - ISC
766
766
  *
767
767
  * This source code is licensed under the ISC license.
768
768
  * See the LICENSE file in the root directory of this source tree.
@@ -777,7 +777,7 @@ const __iconNode$6 = [
777
777
  const Columns3 = createLucideIcon("columns-3", __iconNode$6);
778
778
 
779
779
  /**
780
- * @license lucide-react v0.552.0 - ISC
780
+ * @license lucide-react v0.562.0 - ISC
781
781
  *
782
782
  * This source code is licensed under the ISC license.
783
783
  * See the LICENSE file in the root directory of this source tree.
@@ -792,7 +792,7 @@ const __iconNode$5 = [
792
792
  const ListFilter = createLucideIcon("list-filter", __iconNode$5);
793
793
 
794
794
  /**
795
- * @license lucide-react v0.552.0 - ISC
795
+ * @license lucide-react v0.562.0 - ISC
796
796
  *
797
797
  * This source code is licensed under the ISC license.
798
798
  * See the LICENSE file in the root directory of this source tree.
@@ -806,7 +806,7 @@ const __iconNode$4 = [
806
806
  const Plus = createLucideIcon("plus", __iconNode$4);
807
807
 
808
808
  /**
809
- * @license lucide-react v0.552.0 - ISC
809
+ * @license lucide-react v0.562.0 - ISC
810
810
  *
811
811
  * This source code is licensed under the ISC license.
812
812
  * See the LICENSE file in the root directory of this source tree.
@@ -820,7 +820,7 @@ const __iconNode$3 = [
820
820
  const Search = createLucideIcon("search", __iconNode$3);
821
821
 
822
822
  /**
823
- * @license lucide-react v0.552.0 - ISC
823
+ * @license lucide-react v0.562.0 - ISC
824
824
  *
825
825
  * This source code is licensed under the ISC license.
826
826
  * See the LICENSE file in the root directory of this source tree.
@@ -837,7 +837,7 @@ const __iconNode$2 = [
837
837
  const Trash2 = createLucideIcon("trash-2", __iconNode$2);
838
838
 
839
839
  /**
840
- * @license lucide-react v0.552.0 - ISC
840
+ * @license lucide-react v0.562.0 - ISC
841
841
  *
842
842
  * This source code is licensed under the ISC license.
843
843
  * See the LICENSE file in the root directory of this source tree.
@@ -856,7 +856,7 @@ const __iconNode$1 = [
856
856
  const WifiOff = createLucideIcon("wifi-off", __iconNode$1);
857
857
 
858
858
  /**
859
- * @license lucide-react v0.552.0 - ISC
859
+ * @license lucide-react v0.562.0 - ISC
860
860
  *
861
861
  * This source code is licensed under the ISC license.
862
862
  * See the LICENSE file in the root directory of this source tree.
@@ -1036,8 +1036,8 @@ const StyledBreadcrumbLink = styles.styled(Link, {
1036
1036
  * </NeoBreadcrumbs>
1037
1037
  * ```
1038
1038
  */
1039
- function NeoBreadcrumbLink({ current = false, children, ...props }) {
1040
- return (jsxRuntime.jsx(StyledBreadcrumbLink, { current: current, "aria-current": current ? 'page' : undefined, underline: "none", ...props, children: children }));
1039
+ function NeoBreadcrumbLink({ current = false, children, component, ...props }) {
1040
+ return (jsxRuntime.jsx(StyledBreadcrumbLink, { ...(component && { component }), current: current, "aria-current": current ? 'page' : undefined, underline: "none", ...props, children: children }));
1041
1041
  }
1042
1042
  /**
1043
1043
  * NeoBreadcrumbs - Navigation breadcrumb component
@@ -3984,11 +3984,11 @@ NeoInputField.displayName = 'NeoInputField';
3984
3984
  // Size configuration for consistent styling
3985
3985
  const sizeConfig = {
3986
3986
  small: {
3987
- height: 36,
3988
- paddingTop: neoDesign.spacing.spacing_1,
3989
- paddingRight: neoDesign.spacing.spacing_1_1_4,
3990
- paddingBottom: neoDesign.spacing.spacing_1,
3991
- paddingLeft: neoDesign.spacing.spacing_1_1_4,
3987
+ height: neoDesign.spacing.spacing_3_1_2,
3988
+ paddingTop: 1,
3989
+ paddingRight: neoDesign.spacing.spacing_3_4,
3990
+ paddingBottom: 1,
3991
+ paddingLeft: neoDesign.spacing.spacing_3_4,
3992
3992
  gap: neoDesign.spacing.spacing_1,
3993
3993
  iconSize: neoDesign.typography.fontSize.h4,
3994
3994
  fontSize: neoDesign.typography.fontSize.sm,
@@ -3996,10 +3996,10 @@ const sizeConfig = {
3996
3996
  },
3997
3997
  medium: {
3998
3998
  height: neoDesign.spacing.spacing_5,
3999
- paddingTop: neoDesign.spacing.spacing_1,
4000
- paddingRight: neoDesign.spacing.spacing_1_1_4,
4001
- paddingBottom: neoDesign.spacing.spacing_1,
4002
- paddingLeft: neoDesign.spacing.spacing_1,
3999
+ paddingTop: 1,
4000
+ paddingRight: neoDesign.spacing.spacing_3_4,
4001
+ paddingBottom: 1,
4002
+ paddingLeft: neoDesign.spacing.spacing_3_4,
4003
4003
  gap: neoDesign.spacing.spacing_1,
4004
4004
  iconSize: neoDesign.typography.fontSize.h4,
4005
4005
  fontSize: neoDesign.typography.fontSize.default,
@@ -4007,10 +4007,10 @@ const sizeConfig = {
4007
4007
  },
4008
4008
  large: {
4009
4009
  height: neoDesign.spacing.spacing_6,
4010
- paddingTop: neoDesign.spacing.spacing_1,
4011
- paddingRight: neoDesign.spacing.spacing_1_1_4,
4012
- paddingBottom: neoDesign.spacing.spacing_1,
4013
- paddingLeft: neoDesign.spacing.spacing_1_1_4,
4010
+ paddingTop: 1,
4011
+ paddingRight: neoDesign.spacing.spacing_3_4,
4012
+ paddingBottom: 1,
4013
+ paddingLeft: neoDesign.spacing.spacing_3_4,
4014
4014
  gap: neoDesign.spacing.spacing_1_1_2,
4015
4015
  iconSize: neoDesign.typography.fontSize.h2,
4016
4016
  fontSize: neoDesign.typography.fontSize.default,
@@ -4019,10 +4019,10 @@ const sizeConfig = {
4019
4019
  },
4020
4020
  xlarge: {
4021
4021
  height: neoDesign.spacing.spacing_8,
4022
- paddingTop: neoDesign.spacing.spacing_1,
4023
- paddingRight: neoDesign.spacing.spacing_1_1_4,
4024
- paddingBottom: neoDesign.spacing.spacing_1,
4025
- paddingLeft: neoDesign.spacing.spacing_1_1_4,
4022
+ paddingTop: 1,
4023
+ paddingRight: neoDesign.spacing.spacing_3_4,
4024
+ paddingBottom: 1,
4025
+ paddingLeft: neoDesign.spacing.spacing_3_4,
4026
4026
  gap: neoDesign.spacing.spacing_2,
4027
4027
  iconSize: neoDesign.typography.fontSize.h2,
4028
4028
  fontSize: neoDesign.typography.fontSize.default,
@@ -4031,16 +4031,16 @@ const sizeConfig = {
4031
4031
  },
4032
4032
  xxlarge: {
4033
4033
  height: neoDesign.spacing.spacing_10,
4034
- paddingTop: neoDesign.spacing.spacing_1,
4035
- paddingRight: neoDesign.spacing.spacing_1_1_2,
4036
- paddingBottom: neoDesign.spacing.spacing_1,
4037
- paddingLeft: neoDesign.spacing.spacing_1_1_2,
4034
+ paddingTop: 1,
4035
+ paddingRight: neoDesign.spacing.spacing_3_4,
4036
+ paddingBottom: 1,
4037
+ paddingLeft: neoDesign.spacing.spacing_3_4,
4038
4038
  gap: neoDesign.spacing.spacing_2,
4039
4039
  iconSize: neoDesign.spacing.spacing_5,
4040
4040
  fontSize: neoDesign.typography.fontSize.h5,
4041
4041
  secondaryFontSize: neoDesign.typography.fontSize.sm,
4042
4042
  badgeFontSize: neoDesign.typography.fontSize.xs,
4043
- lineHeight: 1,
4043
+ lineHeight: 1.5,
4044
4044
  },
4045
4045
  };
4046
4046
  const StyledListItemButton$1 = styles.styled(ListItemButton, {
@@ -4049,12 +4049,14 @@ const StyledListItemButton$1 = styles.styled(ListItemButton, {
4049
4049
  prop !== 'secondaryText' &&
4050
4050
  prop !== 'badge' &&
4051
4051
  prop !== 'icon' &&
4052
- prop !== 'isLink',
4053
- })(({ theme, size = 'medium', isLink }) => {
4052
+ prop !== 'isLink' &&
4053
+ prop !== 'hasSecondaryText' &&
4054
+ prop !== 'trailingElement',
4055
+ })(({ theme, size = 'medium', isLink, hasSecondaryText }) => {
4054
4056
  const config = sizeConfig[size];
4055
4057
  return {
4056
4058
  minHeight: config.height,
4057
- height: config.height,
4059
+ height: hasSecondaryText ? 'auto' : config.height,
4058
4060
  paddingTop: config.paddingTop,
4059
4061
  paddingRight: config.paddingRight,
4060
4062
  paddingBottom: config.paddingBottom,
@@ -4062,6 +4064,8 @@ const StyledListItemButton$1 = styles.styled(ListItemButton, {
4062
4064
  borderRadius: neoDesign.spacing.spacing_3_4, // 6px
4063
4065
  backgroundColor: neoDesign.semanticColors.input.background,
4064
4066
  gap: config.gap,
4067
+ // Icon is always centered vertically per Figma design
4068
+ alignItems: 'center',
4065
4069
  transition: theme.transitions.create(['background-color'], {
4066
4070
  duration: theme.transitions.duration.short,
4067
4071
  }),
@@ -4076,17 +4080,32 @@ const StyledListItemButton$1 = styles.styled(ListItemButton, {
4076
4080
  }),
4077
4081
  },
4078
4082
  // Primary text styling
4083
+ // Font weight varies by size per Figma:
4084
+ // - Default: small/medium use 400, large/xlarge/xxlarge use 500
4085
+ // - Link: xxlarge uses 600, others use their default weight
4079
4086
  '& .list-item-primary': {
4080
4087
  fontSize: theme.typography.pxToRem(config.fontSize),
4081
4088
  lineHeight: config.lineHeight,
4082
- fontWeight: neoDesign.typography.fontWeight.medium,
4089
+ fontWeight: isLink && size === 'xxlarge'
4090
+ ? neoDesign.typography.fontWeight.semiBold
4091
+ : size === 'small' || size === 'medium'
4092
+ ? neoDesign.typography.fontWeight.regular
4093
+ : neoDesign.typography.fontWeight.medium,
4083
4094
  color: isLink
4084
4095
  ? neoDesign.semanticColors.typography.link.primary
4085
4096
  : neoDesign.semanticColors.typography.navigation.default,
4086
4097
  overflow: 'hidden',
4087
4098
  textOverflow: 'ellipsis',
4088
4099
  whiteSpace: 'nowrap',
4100
+ ...(isLink && size === 'xxlarge' && { textDecoration: 'none' }),
4089
4101
  },
4102
+ // Link hover styling (underline on hover for xxlarge)
4103
+ ...(isLink &&
4104
+ size === 'xxlarge' && {
4105
+ '&:hover .list-item-primary': {
4106
+ textDecoration: 'underline',
4107
+ },
4108
+ }),
4090
4109
  // Badge styling (for xxlarge link variant)
4091
4110
  '& .list-item-badge': {
4092
4111
  fontSize: theme.typography.pxToRem(size === 'xxlarge' ? config.badgeFontSize || 12 : 12),
@@ -4094,24 +4113,34 @@ const StyledListItemButton$1 = styles.styled(ListItemButton, {
4094
4113
  fontWeight: neoDesign.typography.fontWeight.regular,
4095
4114
  color: neoDesign.semanticColors.typography.bodySecondary,
4096
4115
  },
4097
- // Secondary text styling
4116
+ // Secondary text styling - wraps with word break
4098
4117
  '& .list-item-secondary': {
4099
4118
  fontSize: theme.typography.pxToRem('secondaryFontSize' in config ? config.secondaryFontSize : config.fontSize),
4100
4119
  lineHeight: size === 'large' ? 1.5 : 1.4,
4101
4120
  fontWeight: neoDesign.typography.fontWeight.regular,
4102
4121
  color: neoDesign.semanticColors.typography.bodySecondary,
4103
- overflow: 'hidden',
4104
- textOverflow: 'ellipsis',
4105
- whiteSpace: 'nowrap',
4122
+ wordBreak: 'break-word',
4123
+ whiteSpace: 'normal',
4106
4124
  ...(size === 'large' && {
4107
4125
  marginBottom: -2,
4108
4126
  }),
4109
4127
  },
4128
+ // Trailing element styling (e.g., chevron icon)
4129
+ '& .list-item-trailing': {
4130
+ display: 'flex',
4131
+ alignItems: 'center',
4132
+ flexShrink: 0,
4133
+ marginLeft: neoDesign.spacing.spacing_1,
4134
+ color: neoDesign.semanticColors.icons.default,
4135
+ },
4110
4136
  // Hover state
4111
4137
  '&:hover': {
4112
4138
  backgroundColor: neoDesign.semanticColors.input.background,
4113
4139
  },
4114
4140
  // Selected/Active state
4141
+ // Font weights per Figma:
4142
+ // - Primary: small/medium/xxlarge use 500, large/xlarge use 600
4143
+ // - Secondary: large/xlarge use 500, xxlarge uses 400
4115
4144
  [`&.${ListItemButton.listItemButtonClasses.selected}`]: {
4116
4145
  backgroundColor: neoDesign.semanticColors.buttons.secondary.hoverBackground,
4117
4146
  '&:hover': {
@@ -4121,11 +4150,15 @@ const StyledListItemButton$1 = styles.styled(ListItemButton, {
4121
4150
  color: neoDesign.semanticColors.icons.pressed,
4122
4151
  },
4123
4152
  '& .list-item-primary': {
4124
- fontWeight: neoDesign.typography.fontWeight.semiBold,
4153
+ fontWeight: size === 'large' || size === 'xlarge'
4154
+ ? neoDesign.typography.fontWeight.semiBold
4155
+ : neoDesign.typography.fontWeight.medium,
4125
4156
  color: neoDesign.semanticColors.typography.navigation.default,
4126
4157
  },
4127
4158
  '& .list-item-secondary': {
4128
- fontWeight: neoDesign.typography.fontWeight.medium,
4159
+ fontWeight: size === 'large' || size === 'xlarge'
4160
+ ? neoDesign.typography.fontWeight.medium
4161
+ : neoDesign.typography.fontWeight.regular,
4129
4162
  },
4130
4163
  },
4131
4164
  // Disabled state
@@ -4144,17 +4177,10 @@ const StyledListItemButton$1 = styles.styled(ListItemButton, {
4144
4177
  '& .list-item-badge': {
4145
4178
  color: neoDesign.semanticColors.buttons.tertiary.disabled,
4146
4179
  },
4147
- },
4148
- // Link-specific styling (underline on hover for xxlarge)
4149
- ...(isLink &&
4150
- size === 'xxlarge' && {
4151
- '& .list-item-primary': {
4152
- textDecoration: 'none',
4153
- },
4154
- '&:hover .list-item-primary': {
4155
- textDecoration: 'underline',
4180
+ '& .list-item-trailing': {
4181
+ color: neoDesign.semanticColors.icons.disabled,
4156
4182
  },
4157
- }),
4183
+ },
4158
4184
  };
4159
4185
  });
4160
4186
  /**
@@ -4171,6 +4197,7 @@ const StyledListItemButton$1 = styles.styled(ListItemButton, {
4171
4197
  * - state (default|active|disabled|link) → selected, disabled, isLink props
4172
4198
  * - showIcon → icon prop (pass ReactNode)
4173
4199
  * - showSupportingText → secondaryText prop (pass ReactNode)
4200
+ * - showChevron → trailingElement prop (pass ReactNode, e.g., ChevronRight icon)
4174
4201
  * - Placeholder → primaryText prop
4175
4202
  * - Recipe name → secondaryText prop
4176
4203
  * - (# recipes) → badge prop
@@ -4187,17 +4214,17 @@ const StyledListItemButton$1 = styles.styled(ListItemButton, {
4187
4214
  * - semanticColors.surface.input.disabled-background (disabled background)
4188
4215
  * - semanticColors.buttons.tertiary.disabled (disabled text color)
4189
4216
  */
4190
- const NeoListItem = ({ size = 'medium', primaryText, secondaryText, badge, icon, isLink = false, component, ...props }) => {
4217
+ const NeoListItem = ({ size = 'medium', primaryText, secondaryText, badge, icon, isLink = false, trailingElement, component, ...props }) => {
4191
4218
  // Determine if secondary text should be shown based on size
4192
4219
  const showSecondaryText = secondaryText && (size === 'large' || size === 'xlarge' || size === 'xxlarge');
4193
4220
  // Determine if badge should be shown (only for xxlarge)
4194
4221
  const showBadge = badge && size === 'xxlarge';
4195
4222
  // Prepare primary text with badge if needed
4196
4223
  const primaryContent = showBadge ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [primaryText, ' ', jsxRuntime.jsx(Typography, { component: "span", className: "list-item-badge", children: badge })] })) : (primaryText);
4197
- return (jsxRuntime.jsxs(StyledListItemButton$1, { size: size, isLink: isLink, ...(component && { component }), ...props, children: [icon && jsxRuntime.jsx(ListItemIcon, { children: icon }), jsxRuntime.jsx(ListItemText, { primary: primaryContent, secondary: showSecondaryText ? secondaryText : undefined, slotProps: {
4224
+ return (jsxRuntime.jsxs(StyledListItemButton$1, { size: size, isLink: isLink, hasSecondaryText: !!showSecondaryText, ...(component && { component }), ...props, children: [icon && jsxRuntime.jsx(ListItemIcon, { children: icon }), jsxRuntime.jsx(ListItemText, { primary: primaryContent, secondary: showSecondaryText ? secondaryText : undefined, sx: { minWidth: 0, flex: 1 }, slotProps: {
4198
4225
  primary: { className: 'list-item-primary' },
4199
4226
  secondary: { className: 'list-item-secondary' },
4200
- } })] }));
4227
+ } }), trailingElement && jsxRuntime.jsx(Box, { className: "list-item-trailing", children: trailingElement })] }));
4201
4228
  };
4202
4229
  NeoListItem.displayName = 'NeoListItem';
4203
4230
 
@@ -4313,6 +4340,15 @@ const NeoListItemButton = ({ children, selected = false, disabled = false, ...pr
4313
4340
  };
4314
4341
  NeoListItemButton.displayName = 'NeoListItemButton';
4315
4342
 
4343
+ /**
4344
+ * Focus ring box-shadow using Neo design tokens
4345
+ * Combines focusWhite1 (inner white ring) and focusBlue2 (outer blue ring)
4346
+ */
4347
+ const focusRingShadow = `${neoDesign.shadows.focusWhite1.x}px ${neoDesign.shadows.focusWhite1.y}px ${neoDesign.shadows.focusWhite1.blur}px ${neoDesign.shadows.focusWhite1.spread}px ${neoDesign.shadows.focusWhite1.shadow}, ${neoDesign.shadows.focusBlue2.x}px ${neoDesign.shadows.focusBlue2.y}px ${neoDesign.shadows.focusBlue2.blur}px ${neoDesign.shadows.focusBlue2.spread}px ${neoDesign.shadows.focusBlue2.shadow}`;
4348
+ /**
4349
+ * Card box-shadow using Neo design tokens for hover and selected states
4350
+ */
4351
+ 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}`;
4316
4352
  /**
4317
4353
  * Styled Card component with Neo design tokens
4318
4354
  */
@@ -4328,16 +4364,17 @@ const StyledCard = styles.styled(MuiCard, {
4328
4364
  backgroundColor: neoDesign.semanticColors.surfaces.card,
4329
4365
  border: `1px solid ${selected ? neoDesign.semanticColors.border.tabActive : neoDesign.semanticColors.border.card}`,
4330
4366
  borderRadius: theme.typography.pxToRem(4),
4331
- boxShadow: 'none',
4332
- transition: theme.transitions.create(['border-color']),
4367
+ boxShadow: selected ? activeShadow : 'none',
4368
+ transition: theme.transitions.create(['border-color', 'background-color', 'box-shadow']),
4333
4369
  cursor: 'pointer',
4334
4370
  '&:hover': {
4335
- borderColor: selected ? neoDesign.semanticColors.border.tabActive : neoDesign.semanticColors.border.card,
4371
+ borderColor: neoDesign.semanticColors.border.tabActive,
4372
+ boxShadow: activeShadow,
4336
4373
  },
4337
4374
  '&:focus-visible': {
4338
- outline: `2px solid ${neoDesign.semanticColors.border.tabActive}`,
4339
- outlineOffset: '2px',
4340
4375
  borderColor: neoDesign.semanticColors.border.tabActive,
4376
+ boxShadow: focusRingShadow,
4377
+ outline: 'none',
4341
4378
  },
4342
4379
  ...(disabled && {
4343
4380
  opacity: 0.5,
@@ -4403,6 +4440,11 @@ const Description = styles.styled('p')(({ theme }) => ({
4403
4440
  lineHeight: 1.5,
4404
4441
  color: neoDesign.colors.grey[800],
4405
4442
  width: '100%',
4443
+ display: '-webkit-box',
4444
+ WebkitLineClamp: 2,
4445
+ WebkitBoxOrient: 'vertical',
4446
+ overflow: 'hidden',
4447
+ textOverflow: 'ellipsis',
4406
4448
  }));
4407
4449
  /**
4408
4450
  * NeoMarketplaceCard - Selectable card component for marketplace items
@@ -4432,9 +4474,12 @@ const Description = styles.styled('p')(({ theme }) => ({
4432
4474
  * - Property 1="Default" → Base state (no props)
4433
4475
  *
4434
4476
  * Design Tokens Used:
4435
- * - semanticColors.surfaces.card (#FFFFFF) - Card background
4477
+ * - semanticColors.surfaces.card (#FFFFFF) - Default card background
4478
+ * - semanticColors.status.info.light (#f2f3ff) - Active/focused card background
4436
4479
  * - semanticColors.border.card (#d1d5db) - Default border
4437
4480
  * - semanticColors.border.tabActive (#2f42ff) - Active/focused border
4481
+ * - shadows.focusWhite1 - Inner white focus ring (2px spread)
4482
+ * - shadows.focusBlue2 - Outer blue focus ring (4px spread)
4438
4483
  * - colors.grey[800] (#1F2937) - Text color
4439
4484
  * - typography.fontSize.xxs (10px) - Recipe count
4440
4485
  * - typography.fontSize.xs (12px) - Description
@@ -4771,7 +4816,7 @@ const Subtitle = styles.styled(Typography)(() => ({
4771
4816
  * </NeoPageContent>
4772
4817
  * ```
4773
4818
  */
4774
- function NeoPageContent({ pageTitle, subtitle, action, sticky = false, contentMaxWidth = false, disableGutters = false, isLoading = false, showBackToTop = true, children, sx, ...boxProps }) {
4819
+ function NeoPageContent({ pageTitle, subtitle, breadcrumbs, action, sticky = false, contentMaxWidth = false, centerContent = true, disableGutters = false, isLoading = false, showBackToTop = true, children, sx, ...boxProps }) {
4775
4820
  const [showBackToTopButton, setShowBackToTopButton] = react.useState(false);
4776
4821
  const headerRef = react.useRef(null);
4777
4822
  const containerRef = react.useRef(null);
@@ -4801,8 +4846,8 @@ function NeoPageContent({ pageTitle, subtitle, action, sticky = false, contentMa
4801
4846
  // Also try to scroll window in case component is in a different context
4802
4847
  window.scrollTo({ top: 0, behavior: 'smooth' });
4803
4848
  };
4804
- const headerContent = (jsxRuntime.jsxs(Stack, { ref: headerRef, direction: "row", justifyContent: "space-between", alignItems: "flex-start", sx: { flexShrink: 0, gap: neoDesign.spacing.spacing_2 }, children: [jsxRuntime.jsxs(Stack, { sx: { gap: neoDesign.spacing.spacing_1, flexGrow: 1 }, children: [jsxRuntime.jsx(PageTitle, { children: pageTitle }), subtitle &&
4805
- (typeof subtitle === 'string' ? (jsxRuntime.jsx(Subtitle, { variant: "caption", children: subtitle })) : (subtitle))] }), action] }));
4849
+ 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 &&
4850
+ (typeof subtitle === 'string' ? (jsxRuntime.jsx(Subtitle, { variant: "caption", children: subtitle })) : (subtitle))] }), action] })] }));
4806
4851
  const content = isLoading ? (jsxRuntime.jsx(Box, { sx: {
4807
4852
  display: 'flex',
4808
4853
  alignItems: 'center',
@@ -4826,15 +4871,27 @@ function NeoPageContent({ pageTitle, subtitle, action, sticky = false, contentMa
4826
4871
  pb: `${neoDesign.spacing.spacing_2_1_2}px`,
4827
4872
  height: '100%',
4828
4873
  overflow: 'auto',
4829
- }, children: [sticky ? (jsxRuntime.jsx(StickyHeader, { ref: headerRef, sx: { pt: `${neoDesign.spacing.spacing_2}px` }, children: headerContent })) : (jsxRuntime.jsx(Box, { ref: headerRef, sx: { mb: `${neoDesign.spacing.spacing_1}px` }, children: headerContent })), jsxRuntime.jsx(Box, { sx: {
4874
+ }, children: [sticky ? (jsxRuntime.jsx(StickyHeader, { ref: headerRef, sx: {
4875
+ pt: `${neoDesign.spacing.spacing_2}px`,
4876
+ ...(contentMaxWidth !== false && {
4877
+ maxWidth: theme => theme.breakpoints.values[contentMaxWidth],
4878
+ width: '100%',
4879
+ }),
4880
+ }, children: headerContent })) : (jsxRuntime.jsx(Box, { ref: headerRef, sx: {
4881
+ mb: `${neoDesign.spacing.spacing_1}px`,
4882
+ ...(contentMaxWidth !== false && {
4883
+ maxWidth: theme => theme.breakpoints.values[contentMaxWidth],
4884
+ width: '100%',
4885
+ }),
4886
+ }, children: headerContent })), jsxRuntime.jsx(Box, { sx: {
4830
4887
  flexGrow: 1,
4831
4888
  minHeight: 0,
4832
4889
  display: 'flex',
4833
4890
  flexDirection: 'column',
4834
4891
  ...(contentMaxWidth !== false && {
4835
4892
  maxWidth: theme => theme.breakpoints.values[contentMaxWidth],
4836
- mx: 'auto',
4837
4893
  width: '100%',
4894
+ ...(centerContent ? { mx: 'auto' } : { alignSelf: 'flex-start' }),
4838
4895
  }),
4839
4896
  }, children: content })] }) }), showBackToTop && (jsxRuntime.jsx(Fade, { in: showBackToTopButton, children: jsxRuntime.jsx(Box, { sx: {
4840
4897
  position: 'fixed',
@@ -5664,10 +5721,10 @@ const NeoToastButton = ({ primary, variant = 'default', children, ...props }) =>
5664
5721
  NeoToast.displayName = 'NeoToast';
5665
5722
  NeoToastButton.displayName = 'NeoToastButton';
5666
5723
 
5667
- const ToggleContainer = styles.styled('label')(({ disabled }) => ({
5724
+ const ToggleContainer = styles.styled('label')(({ disabled, size = 'medium' }) => ({
5668
5725
  display: 'inline-flex',
5669
5726
  alignItems: 'flex-start',
5670
- gap: 12,
5727
+ gap: size === 'small' ? 8 : 12,
5671
5728
  cursor: disabled ? 'not-allowed' : 'pointer',
5672
5729
  userSelect: 'none',
5673
5730
  }));
@@ -5819,7 +5876,7 @@ const NeoToggle = ({ size = 'medium', label, helperText, disabled, ...props }) =
5819
5876
  return jsxRuntime.jsx(StyledSwitch, { size: size, disabled: disabled, ...props });
5820
5877
  }
5821
5878
  // With label, wrap in container for proper layout
5822
- return (jsxRuntime.jsxs(ToggleContainer, { disabled: disabled, children: [jsxRuntime.jsx(StyledSwitch, { size: size, disabled: disabled, ...props }), jsxRuntime.jsxs(LabelContainer, { children: [label && jsxRuntime.jsx(Label, { size: size, children: label }), helperText && jsxRuntime.jsx(HelperText, { size: size, children: helperText })] })] }));
5879
+ return (jsxRuntime.jsxs(ToggleContainer, { disabled: disabled, size: size, children: [jsxRuntime.jsx(StyledSwitch, { size: size, disabled: disabled, ...props }), jsxRuntime.jsxs(LabelContainer, { children: [label && jsxRuntime.jsx(Label, { size: size, children: label }), helperText && jsxRuntime.jsx(HelperText, { size: size, children: helperText })] })] }));
5823
5880
  };
5824
5881
  NeoToggle.displayName = 'NeoToggle';
5825
5882