@12-apps/ui 6.24.7 → 6.24.8

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 (125) hide show
  1. package/components-catalog.md +1 -1
  2. package/dist/_internal/components/data-display/CardKit/CardKebab.js +4 -4
  3. package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +4 -4
  4. package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +4 -4
  5. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +18 -18
  6. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +24 -24
  7. package/dist/_internal/components/data-display/DataViews/DeleteViewDialog.js +4 -4
  8. package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +5 -5
  9. package/dist/_internal/components/data-display/DataViews/SaveViewModal.js +4 -4
  10. package/dist/_internal/components/data-display/DataViews/data-views-columns.js +5 -5
  11. package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +5 -5
  12. package/dist/_internal/components/data-display/DataViews/data-views-empty.js +4 -4
  13. package/dist/_internal/components/data-display/DataViews/data-views-export.js +4 -4
  14. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +6 -6
  15. package/dist/_internal/components/data-display/DataViews/data-views-grid-helpers.js +4 -4
  16. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +15 -15
  17. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +5 -5
  18. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +4 -4
  19. package/dist/_internal/components/data-display/DataViews/data-views-select-all-strip.js +4 -4
  20. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +9 -9
  21. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +7 -7
  22. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +8 -8
  23. package/dist/_internal/components/data-display/DataViews/data-views-view-nav.js +4 -4
  24. package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +6 -6
  25. package/dist/_internal/components/feedback/ConfirmAction/ConfirmButton.js +4 -4
  26. package/dist/_internal/components/feedback/index.js +4 -4
  27. package/dist/_internal/components/form/Button/Button.js +3 -3
  28. package/dist/_internal/components/form/Button/Button.metrics.js +3 -1
  29. package/dist/_internal/components/form/Button/Button.styles.js +2 -2
  30. package/dist/_internal/components/form/index.js +3 -3
  31. package/dist/_internal/components/form/total-form/SubmitButton.js +4 -4
  32. package/dist/_internal/components/index.js +5 -5
  33. package/dist/_internal/components/navigation/AppHeader/AppHeader.details.js +4 -4
  34. package/dist/_internal/components/navigation/index.js +4 -4
  35. package/dist/_internal/social-login-button/social-login-button.js +4 -4
  36. package/dist/_internal/user-avatar/user-avatar.js +4 -4
  37. package/dist/{chunk-6JGPPTLX.js → chunk-2GI7ANEL.js} +3 -3
  38. package/dist/{chunk-U2ZDN2AL.js → chunk-2PBGVMM2.js} +2 -2
  39. package/dist/{chunk-ITGG5OKP.js → chunk-5LQ7PKMW.js} +3 -1
  40. package/dist/chunk-5LQ7PKMW.js.map +1 -0
  41. package/dist/{chunk-4T7TXRGM.js → chunk-6ZY5XU4J.js} +3 -3
  42. package/dist/{chunk-CHPZTF34.js → chunk-7KWBGMQC.js} +2 -2
  43. package/dist/{chunk-JT6TERQL.js → chunk-BB2OUERT.js} +2 -2
  44. package/dist/{chunk-XUJG2HFW.js → chunk-BH5BXLGI.js} +2 -2
  45. package/dist/{chunk-NWNSUHEB.js → chunk-CT5K725B.js} +2 -2
  46. package/dist/{chunk-6OORHAE7.js → chunk-E3PUH5IF.js} +3 -3
  47. package/dist/{chunk-H5VEJDEK.js → chunk-FBI6QB3O.js} +6 -6
  48. package/dist/{chunk-ZRPGVHTR.js → chunk-GGI7GM5O.js} +2 -2
  49. package/dist/{chunk-TX5V42AY.js → chunk-HEBQS7QP.js} +3 -3
  50. package/dist/{chunk-BUQ2JUND.js → chunk-JO6BBSGY.js} +2 -2
  51. package/dist/{chunk-4ZV7N5CU.js → chunk-JXPHU3K5.js} +4 -4
  52. package/dist/{chunk-QPLWDSYG.js → chunk-KFWIOFMS.js} +4 -4
  53. package/dist/{chunk-TW3BXVEU.js → chunk-KMXAPYU2.js} +2 -2
  54. package/dist/{chunk-CJBBGMIA.js → chunk-MNXVXW4T.js} +2 -2
  55. package/dist/{chunk-6NSIZ2ZO.js → chunk-NLJV4CPF.js} +2 -2
  56. package/dist/{chunk-BPLFM2GL.js → chunk-NYEA7JAI.js} +3 -3
  57. package/dist/{chunk-O6AZDQJJ.js → chunk-OE2ZVL67.js} +2 -2
  58. package/dist/{chunk-4523RYE7.js → chunk-OG2FP6SE.js} +2 -2
  59. package/dist/{chunk-XKV5ZIBG.js → chunk-OGGPQVIG.js} +2 -2
  60. package/dist/{chunk-SQNW22ZZ.js → chunk-OV4WREMW.js} +3 -3
  61. package/dist/{chunk-6LGWJFQK.js → chunk-PFDM2OIP.js} +2 -2
  62. package/dist/{chunk-YTOYMJPM.js → chunk-SLVQ33AN.js} +15 -5
  63. package/dist/chunk-SLVQ33AN.js.map +1 -0
  64. package/dist/{chunk-5OIH36KX.js → chunk-V4FKHLEB.js} +2 -2
  65. package/dist/{chunk-EMMPNB6D.js → chunk-X4Z62ZQY.js} +2 -2
  66. package/dist/{chunk-OP65D4UR.js → chunk-XR6WBW23.js} +2 -2
  67. package/dist/{chunk-4X4KM4ZB.js → chunk-ZZMZF7PZ.js} +2 -2
  68. package/dist/data-display/CardKit.js +5 -5
  69. package/dist/data-display/DataViews.js +24 -24
  70. package/dist/feedback/ConfirmAction.js +4 -4
  71. package/dist/form/Button.js +3 -3
  72. package/dist/form/total-form.js +4 -4
  73. package/dist/native/chunks/{chunk-ZAQ3AZJM.js → chunk-2R2R35C5.js} +2 -2
  74. package/dist/native/chunks/{chunk-ATS7STZJ.js → chunk-WL5LXVCK.js} +1 -1
  75. package/dist/native/chunks/{chunk-ATS7STZJ.js.map → chunk-WL5LXVCK.js.map} +1 -1
  76. package/dist/native/data-display/EmptyState.js +2 -2
  77. package/dist/native/data-display/ErrorState.js +1 -1
  78. package/dist/native/data-display/FleetMap.js +2 -2
  79. package/dist/native/form/Button.js +1 -1
  80. package/dist/navigation/AppHeader.js +4 -4
  81. package/dist/social-login-button.js +4 -4
  82. package/dist/types/components/form/Button/Button.d.ts +7 -3
  83. package/dist/types/components/form/Button/Button.d.ts.map +1 -1
  84. package/dist/types/components/form/Button/Button.metrics.d.ts +25 -0
  85. package/dist/types/components/form/Button/Button.metrics.d.ts.map +1 -1
  86. package/dist/types/components/form/Button/Button.types.d.ts +37 -4
  87. package/dist/types/components/form/Button/Button.types.d.ts.map +1 -1
  88. package/dist/types-native/components/form/Button/Button.metrics.d.ts +25 -0
  89. package/dist/types-native/components/form/Button/Button.metrics.d.ts.map +1 -1
  90. package/dist/user-avatar.js +4 -4
  91. package/package.json +1 -1
  92. package/src/components/form/Button/Button.md +39 -0
  93. package/src/components/form/Button/Button.metrics.ts +26 -0
  94. package/src/components/form/Button/Button.tsx +77 -4
  95. package/src/components/form/Button/Button.types.ts +47 -5
  96. package/dist/chunk-ITGG5OKP.js.map +0 -1
  97. package/dist/chunk-YTOYMJPM.js.map +0 -1
  98. /package/dist/{chunk-6JGPPTLX.js.map → chunk-2GI7ANEL.js.map} +0 -0
  99. /package/dist/{chunk-U2ZDN2AL.js.map → chunk-2PBGVMM2.js.map} +0 -0
  100. /package/dist/{chunk-4T7TXRGM.js.map → chunk-6ZY5XU4J.js.map} +0 -0
  101. /package/dist/{chunk-CHPZTF34.js.map → chunk-7KWBGMQC.js.map} +0 -0
  102. /package/dist/{chunk-JT6TERQL.js.map → chunk-BB2OUERT.js.map} +0 -0
  103. /package/dist/{chunk-XUJG2HFW.js.map → chunk-BH5BXLGI.js.map} +0 -0
  104. /package/dist/{chunk-NWNSUHEB.js.map → chunk-CT5K725B.js.map} +0 -0
  105. /package/dist/{chunk-6OORHAE7.js.map → chunk-E3PUH5IF.js.map} +0 -0
  106. /package/dist/{chunk-H5VEJDEK.js.map → chunk-FBI6QB3O.js.map} +0 -0
  107. /package/dist/{chunk-ZRPGVHTR.js.map → chunk-GGI7GM5O.js.map} +0 -0
  108. /package/dist/{chunk-TX5V42AY.js.map → chunk-HEBQS7QP.js.map} +0 -0
  109. /package/dist/{chunk-BUQ2JUND.js.map → chunk-JO6BBSGY.js.map} +0 -0
  110. /package/dist/{chunk-4ZV7N5CU.js.map → chunk-JXPHU3K5.js.map} +0 -0
  111. /package/dist/{chunk-QPLWDSYG.js.map → chunk-KFWIOFMS.js.map} +0 -0
  112. /package/dist/{chunk-TW3BXVEU.js.map → chunk-KMXAPYU2.js.map} +0 -0
  113. /package/dist/{chunk-CJBBGMIA.js.map → chunk-MNXVXW4T.js.map} +0 -0
  114. /package/dist/{chunk-6NSIZ2ZO.js.map → chunk-NLJV4CPF.js.map} +0 -0
  115. /package/dist/{chunk-BPLFM2GL.js.map → chunk-NYEA7JAI.js.map} +0 -0
  116. /package/dist/{chunk-O6AZDQJJ.js.map → chunk-OE2ZVL67.js.map} +0 -0
  117. /package/dist/{chunk-4523RYE7.js.map → chunk-OG2FP6SE.js.map} +0 -0
  118. /package/dist/{chunk-XKV5ZIBG.js.map → chunk-OGGPQVIG.js.map} +0 -0
  119. /package/dist/{chunk-SQNW22ZZ.js.map → chunk-OV4WREMW.js.map} +0 -0
  120. /package/dist/{chunk-6LGWJFQK.js.map → chunk-PFDM2OIP.js.map} +0 -0
  121. /package/dist/{chunk-5OIH36KX.js.map → chunk-V4FKHLEB.js.map} +0 -0
  122. /package/dist/{chunk-EMMPNB6D.js.map → chunk-X4Z62ZQY.js.map} +0 -0
  123. /package/dist/{chunk-OP65D4UR.js.map → chunk-XR6WBW23.js.map} +0 -0
  124. /package/dist/{chunk-4X4KM4ZB.js.map → chunk-ZZMZF7PZ.js.map} +0 -0
  125. /package/dist/native/chunks/{chunk-ZAQ3AZJM.js.map → chunk-2R2R35C5.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/form/Button/Button.native.tsx","../../../src/components/form/Button/Button.helpers.ts","../../../src/components/form/Button/Button.metrics.ts"],"sourcesContent":["import * as React from 'react';\nimport {\n ActivityIndicator,\n Animated,\n Easing,\n Platform,\n Pressable,\n StyleSheet,\n View,\n type GestureResponderEvent,\n type PressableStateCallbackType,\n type StyleProp,\n type TextStyle,\n type ViewStyle,\n} from 'react-native';\n\nimport { resolveButtonProps } from './Button.helpers';\nimport {\n BUTTON_FONT_WEIGHT,\n BUTTON_ICON_GAP_UNITS,\n BUTTON_LINE_HEIGHT,\n BUTTON_RADIUS_UNITS,\n BUTTON_SIZES,\n BUTTON_SPINNER_SIZE,\n BUTTON_WASH_ALPHA,\n GLASS_BACKGROUND_ALPHA,\n GLASS_BACKGROUND_ALPHA_PRESSED,\n GLASS_BORDER_ALPHA,\n GLOW_INNER_ALPHA,\n GLOW_RADIUS,\n ICON_ONLY_PADDING,\n PULSE_ALPHA,\n PULSE_DURATION_MS,\n PULSE_SPREAD,\n buttonPalette,\n gradientStops,\n quietInk,\n} from './Button.metrics';\nimport type { ButtonProps, ButtonVariant } from './Button.types.native';\nimport { renderTextChildren } from '../../../platform/text-children';\nimport { childTestId, resolveTestId, withoutTestIdProps } from '../../../platform/test-id';\nimport { useUiTheme } from '../../../provider/use-ui-theme.native';\nimport { alpha } from '../../../tokens/color';\nimport type { ColorValue, SizeValue } from '../../../tokens/vocabulary';\nimport type { UiPaletteColor, UiTheme } from '../../../tokens/theme';\n\n/** MUI's `min-width` for a button that carries a label. */\nconst MIN_WIDTH = 64;\n\ninterface Paint {\n container: ViewStyle;\n pressed: ViewStyle;\n label: TextStyle;\n}\n\n/**\n * What the web's `VARIANT_STYLES` paint, as three React Native styles: at rest,\n * while pressed (the web's `:hover`, which touch has no equivalent of), and the\n * label. Same palette arithmetic, same alphas.\n *\n * `gradient` is the one honest gap: React Native core has no gradient fill, so\n * it paints the gradient's first stop. A host wanting the real thing adds a\n * gradient library; the parity ledger records this.\n */\nfunction paintFor(\n theme: UiTheme,\n variant: ButtonVariant,\n color: ColorValue,\n palette: UiPaletteColor,\n active: boolean,\n): Paint {\n const wash = alpha(palette.main, BUTTON_WASH_ALPHA);\n switch (variant) {\n case 'outline':\n return {\n container: { backgroundColor: 'transparent', borderWidth: 1, borderColor: palette.main },\n pressed: { backgroundColor: wash, borderColor: palette.dark },\n label: { color: palette.main },\n };\n case 'ghost':\n return {\n container: { backgroundColor: 'transparent' },\n pressed: { backgroundColor: wash },\n label: { color: quietInk(theme, palette) },\n };\n case 'text':\n return {\n container: { backgroundColor: active ? wash : 'transparent' },\n pressed: { backgroundColor: wash },\n label: { color: quietInk(theme, palette) },\n };\n case 'glass':\n return {\n container: {\n backgroundColor: alpha(theme.palette.background.paper, GLASS_BACKGROUND_ALPHA),\n borderWidth: 1,\n borderColor: alpha(theme.palette.divider, GLASS_BORDER_ALPHA),\n },\n pressed: { backgroundColor: alpha(theme.palette.background.paper, GLASS_BACKGROUND_ALPHA_PRESSED) },\n label: { color: palette.main },\n };\n case 'gradient': {\n const [from, to] = gradientStops(theme, color, palette);\n return {\n container: { backgroundColor: from },\n pressed: { backgroundColor: to },\n label: { color: '#fff' },\n };\n }\n default:\n return {\n container: { backgroundColor: palette.main },\n pressed: { backgroundColor: palette.dark },\n label: { color: palette.contrastText || '#fff' },\n };\n }\n}\n\n/** MUI's disabled treatment per variant family, so a disabled button reads as one on both sides. */\nfunction disabledPaint(theme: UiTheme, variant: ButtonVariant): Paint {\n const filled = variant === 'solid' || variant === 'gradient' || variant === 'glass';\n return {\n container: filled\n ? { backgroundColor: theme.palette.action.disabledBackground, borderWidth: 0 }\n : variant === 'outline'\n ? { backgroundColor: 'transparent', borderWidth: 1, borderColor: theme.palette.action.disabledBackground }\n : { backgroundColor: 'transparent' },\n pressed: {},\n label: { color: theme.palette.action.disabled },\n };\n}\n\nfunction sizeStyle(theme: UiTheme, size: SizeValue, iconOnly: boolean, hasIcon: boolean): ViewStyle {\n const metrics = BUTTON_SIZES[size];\n if (iconOnly) {\n return { padding: ICON_ONLY_PADDING[size], minWidth: 0 };\n }\n return {\n paddingVertical: metrics.paddingVertical,\n paddingHorizontal: metrics.paddingHorizontal,\n minWidth: MIN_WIDTH,\n gap: hasIcon ? theme.spacing(BUTTON_ICON_GAP_UNITS) : undefined,\n };\n}\n\nfunction glowStyle(palette: UiPaletteColor): ViewStyle {\n return Platform.select<ViewStyle>({\n android: { elevation: 8 },\n default: {\n shadowColor: palette.main,\n shadowOpacity: GLOW_INNER_ALPHA,\n shadowRadius: GLOW_RADIUS,\n shadowOffset: { width: 0, height: 0 },\n },\n });\n}\n\n/** The web's `::after` pulse ring: a looped scale-and-fade behind the button. */\nfunction Pulse({ color, radius, testID }: { color: string; radius: number; testID: string }): React.JSX.Element {\n const progress = React.useRef(new Animated.Value(0)).current;\n\n React.useEffect(() => {\n const loop = Animated.loop(\n Animated.timing(progress, {\n toValue: 1,\n duration: PULSE_DURATION_MS,\n easing: Easing.out(Easing.ease),\n useNativeDriver: Platform.OS !== 'web',\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [progress]);\n\n return (\n <Animated.View\n testID={testID}\n aria-hidden\n style={[\n StyleSheet.absoluteFill,\n {\n pointerEvents: 'none',\n borderRadius: radius,\n backgroundColor: color,\n opacity: progress.interpolate({ inputRange: [0, 0.7, 1], outputRange: [PULSE_ALPHA, 0, 0] }),\n transform: [\n { scale: progress.interpolate({ inputRange: [0, 0.7, 1], outputRange: [1, 1 + PULSE_SPREAD / 40, 1] }) },\n ],\n },\n ]}\n />\n );\n}\n\n\ntype ResolvedProps = ReturnType<typeof resolveButtonProps<ButtonProps>>;\n\ninterface ButtonLook {\n inactive: boolean;\n palette: UiPaletteColor;\n radius: number;\n label: TextStyle;\n container: (state: PressableStateCallbackType) => StyleProp<ViewStyle>;\n}\n\n/**\n * Everything the button paints, decided once per render from the resolved\n * props and the theme. Kept out of the component so the component reads as\n * structure — what renders where — and this reads as arithmetic.\n */\nfunction buttonLook(theme: UiTheme, props: ResolvedProps): ButtonLook {\n const { variant, color, size, loading, icon, children, glow, pulse, active, disabled, style } = props;\n const palette = buttonPalette(theme, color);\n const iconOnly = !loading && icon != null && children == null;\n const inactive = Boolean(disabled) || loading;\n const paint = inactive ? disabledPaint(theme, variant) : paintFor(theme, variant, color, palette, active);\n const radius = theme.spacing(BUTTON_RADIUS_UNITS);\n const metrics = BUTTON_SIZES[size];\n // The web button is `overflow: hidden` (its ripple needs it) unless the pulse\n // ring turns it visible; on native the glow's shadow needs it visible too,\n // because a view's own shadow is clipped by its own overflow there.\n const overflow: ViewStyle['overflow'] = pulse || glow ? 'visible' : 'hidden';\n const sized = sizeStyle(theme, size, iconOnly, icon != null && !loading);\n const glowing = glow && !inactive ? glowStyle(palette) : null;\n\n return {\n inactive,\n palette,\n radius,\n label: {\n fontFamily: theme.typography.fontFamily,\n fontSize: metrics.fontSize,\n lineHeight: metrics.fontSize * BUTTON_LINE_HEIGHT,\n fontWeight: String(BUTTON_FONT_WEIGHT) as TextStyle['fontWeight'],\n textAlign: 'center',\n ...paint.label,\n },\n container: (state) => [\n styles.base,\n { borderRadius: radius, overflow },\n sized,\n paint.container,\n state.pressed && !inactive ? paint.pressed : null,\n glowing,\n style,\n ],\n };\n}\n\n/** The spinner that replaces the label while loading; `role` comes from react-native's ActivityIndicator. */\nfunction Spinner({ color, testID }: { color: string; testID: string }): React.JSX.Element {\n return (\n <ActivityIndicator\n size={Platform.OS === 'ios' ? 'small' : BUTTON_SPINNER_SIZE}\n color={color}\n testID={testID}\n accessibilityLabel=\"loading\"\n />\n );\n}\n\nexport const Button = React.forwardRef<View, ButtonProps>((rawProps, ref) => {\n const resolved = resolveButtonProps(rawProps);\n const { loading, icon, iconPosition, pulse, ripple, children, onClick, onPress, ...others } = resolved;\n const theme = useUiTheme();\n const look = buttonLook(theme, resolved);\n\n // The shared stories pass `'data-testid'` as a plain prop; honour it here and\n // keep all three spellings off the element (react-native-web would drop them).\n const testId = resolveTestId(others, 'button');\n const idFor = (suffix: string) => childTestId(others, suffix, 'button');\n const rest = withoutTestIdProps(others);\n // `buttonLook` consumed these; they are not Pressable props.\n const { variant: _v, color: _c, size: _s, glow: _g, active: _a, disabled: _d, style: _st, ...pressable } = rest;\n\n const handlePress = (event: GestureResponderEvent): void => {\n onClick?.(event);\n onPress?.(event);\n };\n\n const iconNode =\n !loading && icon ? (\n <View style={styles.icon} testID={idFor('icon')}>\n {icon}\n </View>\n ) : null;\n\n return (\n <Pressable\n ref={ref}\n role=\"button\"\n aria-disabled={look.inactive}\n aria-busy={loading}\n disabled={look.inactive}\n onPress={handlePress}\n android_ripple={ripple && !look.inactive ? { color: alpha(look.palette.main, 0.2), borderless: false } : undefined}\n style={look.container}\n testID={testId}\n {...pressable}\n >\n {pulse && !look.inactive ? <Pulse color={look.palette.main} radius={look.radius} testID={idFor('pulse')} /> : null}\n {iconPosition === 'left' ? iconNode : null}\n {loading ? <Spinner color={look.label.color as string} testID={idFor('loading')} /> : renderTextChildren(children, look.label, 1)}\n {iconPosition === 'right' ? iconNode : null}\n </Pressable>\n );\n});\n\nButton.displayName = 'Button';\n\nconst styles = StyleSheet.create({\n base: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n alignSelf: 'flex-start',\n position: 'relative',\n },\n icon: {\n alignItems: 'center',\n justifyContent: 'center',\n },\n});\n","import type { ButtonBaseProps } from './Button.base';\n\ntype ButtonDefaultedKeys =\n | 'variant'\n | 'color'\n | 'size'\n | 'loading'\n | 'iconPosition'\n | 'glow'\n | 'pulse'\n | 'ripple'\n | 'active';\n\n/**\n * Generic over the renderer's own props: the web and the native `Button` pass\n * different handler types through, and both come back out untouched.\n */\ntype ResolvedButtonProps<P extends ButtonBaseProps> = P &\n Required<Pick<ButtonBaseProps, ButtonDefaultedKeys>>;\n\nconst BUTTON_DEFAULTS: Required<Pick<ButtonBaseProps, ButtonDefaultedKeys>> = {\n variant: 'solid',\n color: 'primary',\n size: 'md',\n loading: false,\n iconPosition: 'left',\n glow: false,\n pulse: false,\n ripple: true,\n active: false,\n};\n\n// Strips explicitly-undefined props before the merge, so `size={undefined}` still\n// falls back to the default exactly as a destructuring default would.\nconst definedProps = <P extends ButtonBaseProps>(props: P): Partial<P> =>\n Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<P>;\n\nexport const resolveButtonProps = <P extends ButtonBaseProps>(props: P): ResolvedButtonProps<P> =>\n ({ ...BUTTON_DEFAULTS, ...definedProps(props) }) as ResolvedButtonProps<P>;\n","import { darken, lighten } from '../../../tokens/color';\nimport type { ColorValue, SizeValue } from '../../../tokens/vocabulary';\nimport type { UiPaletteColor, UiTheme } from '../../../tokens/theme';\n\n/**\n * THE NUMBERS BOTH `Button` RENDERERS DRAW WITH.\n *\n * `Button.styles.ts` (web, emotion) and `Button.native.tsx` (React Native)\n * read this one table. The web turns the px into rem and the padding into a\n * shorthand string; native uses the numbers as they are. Neither restates a\n * value, which is what keeps a native `md` button 16px tall of padding and\n * 16px of type exactly like the web one.\n */\nexport interface ButtonSizeMetrics {\n paddingVertical: number;\n paddingHorizontal: number;\n fontSize: number;\n}\n\nexport const BUTTON_SIZES: Record<SizeValue, ButtonSizeMetrics> = {\n xs: { paddingVertical: 2, paddingHorizontal: 8, fontSize: 12 },\n sm: { paddingVertical: 6, paddingHorizontal: 12, fontSize: 14 },\n md: { paddingVertical: 8, paddingHorizontal: 16, fontSize: 16 },\n lg: { paddingVertical: 10, paddingHorizontal: 20, fontSize: 18 },\n xl: { paddingVertical: 12, paddingHorizontal: 24, fontSize: 20 },\n};\n\n/** A button that is only an icon is square: uniform padding, no min-width. */\nexport const ICON_ONLY_PADDING: Record<SizeValue, number> = {\n xs: 2,\n sm: 5,\n md: 7,\n lg: 9,\n xl: 11,\n};\n\nexport const BUTTON_FONT_WEIGHT = 500;\n/** `theme.spacing(1)`. */\nexport const BUTTON_RADIUS_UNITS = 1;\n/** Between the icon and the label: `theme.spacing(0.5)`. */\nexport const BUTTON_ICON_GAP_UNITS = 0.5;\nexport const BUTTON_SPINNER_SIZE = 16;\n/** MUI's `line-height` for button text. */\nexport const BUTTON_LINE_HEIGHT = 1.75;\n\n/** The wash behind an outline, ghost or text button while it is hovered or pressed. */\nexport const BUTTON_WASH_ALPHA = 0.1;\nexport const GLASS_BACKGROUND_ALPHA = 0.1;\nexport const GLASS_BACKGROUND_ALPHA_PRESSED = 0.2;\nexport const GLASS_BORDER_ALPHA = 0.2;\nexport const GLOW_INNER_ALPHA = 0.6;\nexport const GLOW_OUTER_ALPHA = 0.3;\nexport const GLOW_RADIUS = 20;\nexport const PULSE_ALPHA = 0.3;\nexport const PULSE_DURATION_MS = 2000;\nexport const PULSE_SPREAD = 15;\n\n/**\n * `neutral` has no palette slot of its own in MUI, so `Button.styles.ts` has\n * always drawn it from three greys. Same three greys here.\n */\nexport function buttonPalette(theme: UiTheme, color: ColorValue): UiPaletteColor {\n if (color === 'neutral') {\n return {\n main: theme.palette.grey[700],\n dark: theme.palette.grey[800],\n light: theme.palette.grey[500],\n contrastText: '#fff',\n };\n }\n return theme.palette[color];\n}\n\n/**\n * The label colour for `ghost` and `text`: one step darker than `main` in\n * light mode (lighter in dark), because `main` is chosen to sit UNDER white and\n * is not legible AS text on a tinted surface. See the web `quietInk`.\n */\nexport const quietInk = (theme: UiTheme, palette: UiPaletteColor): string =>\n theme.mode === 'dark' ? lighten(palette.main, 0.35) : darken(palette.main, 0.3);\n\n/** Gradients run between two related hues; the named colours pick a specific pair. */\nexport function gradientStops(\n theme: UiTheme,\n color: ColorValue,\n palette: UiPaletteColor,\n): [string, string] {\n switch (color) {\n case 'primary':\n return [theme.palette.primary.main, theme.palette.secondary.main];\n case 'secondary':\n return [theme.palette.secondary.main, theme.palette.primary.main];\n case 'success':\n case 'warning':\n return [theme.palette[color].light, theme.palette[color].dark];\n case 'danger':\n return [theme.palette.danger.light, theme.palette.danger.dark];\n default:\n return [palette.main, palette.dark];\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/form/Button/Button.native.tsx","../../../src/components/form/Button/Button.helpers.ts","../../../src/components/form/Button/Button.metrics.ts"],"sourcesContent":["import * as React from 'react';\nimport {\n ActivityIndicator,\n Animated,\n Easing,\n Platform,\n Pressable,\n StyleSheet,\n View,\n type GestureResponderEvent,\n type PressableStateCallbackType,\n type StyleProp,\n type TextStyle,\n type ViewStyle,\n} from 'react-native';\n\nimport { resolveButtonProps } from './Button.helpers';\nimport {\n BUTTON_FONT_WEIGHT,\n BUTTON_ICON_GAP_UNITS,\n BUTTON_LINE_HEIGHT,\n BUTTON_RADIUS_UNITS,\n BUTTON_SIZES,\n BUTTON_SPINNER_SIZE,\n BUTTON_WASH_ALPHA,\n GLASS_BACKGROUND_ALPHA,\n GLASS_BACKGROUND_ALPHA_PRESSED,\n GLASS_BORDER_ALPHA,\n GLOW_INNER_ALPHA,\n GLOW_RADIUS,\n ICON_ONLY_PADDING,\n PULSE_ALPHA,\n PULSE_DURATION_MS,\n PULSE_SPREAD,\n buttonPalette,\n gradientStops,\n quietInk,\n} from './Button.metrics';\nimport type { ButtonProps, ButtonVariant } from './Button.types.native';\nimport { renderTextChildren } from '../../../platform/text-children';\nimport { childTestId, resolveTestId, withoutTestIdProps } from '../../../platform/test-id';\nimport { useUiTheme } from '../../../provider/use-ui-theme.native';\nimport { alpha } from '../../../tokens/color';\nimport type { ColorValue, SizeValue } from '../../../tokens/vocabulary';\nimport type { UiPaletteColor, UiTheme } from '../../../tokens/theme';\n\n/** MUI's `min-width` for a button that carries a label. */\nconst MIN_WIDTH = 64;\n\ninterface Paint {\n container: ViewStyle;\n pressed: ViewStyle;\n label: TextStyle;\n}\n\n/**\n * What the web's `VARIANT_STYLES` paint, as three React Native styles: at rest,\n * while pressed (the web's `:hover`, which touch has no equivalent of), and the\n * label. Same palette arithmetic, same alphas.\n *\n * `gradient` is the one honest gap: React Native core has no gradient fill, so\n * it paints the gradient's first stop. A host wanting the real thing adds a\n * gradient library; the parity ledger records this.\n */\nfunction paintFor(\n theme: UiTheme,\n variant: ButtonVariant,\n color: ColorValue,\n palette: UiPaletteColor,\n active: boolean,\n): Paint {\n const wash = alpha(palette.main, BUTTON_WASH_ALPHA);\n switch (variant) {\n case 'outline':\n return {\n container: { backgroundColor: 'transparent', borderWidth: 1, borderColor: palette.main },\n pressed: { backgroundColor: wash, borderColor: palette.dark },\n label: { color: palette.main },\n };\n case 'ghost':\n return {\n container: { backgroundColor: 'transparent' },\n pressed: { backgroundColor: wash },\n label: { color: quietInk(theme, palette) },\n };\n case 'text':\n return {\n container: { backgroundColor: active ? wash : 'transparent' },\n pressed: { backgroundColor: wash },\n label: { color: quietInk(theme, palette) },\n };\n case 'glass':\n return {\n container: {\n backgroundColor: alpha(theme.palette.background.paper, GLASS_BACKGROUND_ALPHA),\n borderWidth: 1,\n borderColor: alpha(theme.palette.divider, GLASS_BORDER_ALPHA),\n },\n pressed: { backgroundColor: alpha(theme.palette.background.paper, GLASS_BACKGROUND_ALPHA_PRESSED) },\n label: { color: palette.main },\n };\n case 'gradient': {\n const [from, to] = gradientStops(theme, color, palette);\n return {\n container: { backgroundColor: from },\n pressed: { backgroundColor: to },\n label: { color: '#fff' },\n };\n }\n default:\n return {\n container: { backgroundColor: palette.main },\n pressed: { backgroundColor: palette.dark },\n label: { color: palette.contrastText || '#fff' },\n };\n }\n}\n\n/** MUI's disabled treatment per variant family, so a disabled button reads as one on both sides. */\nfunction disabledPaint(theme: UiTheme, variant: ButtonVariant): Paint {\n const filled = variant === 'solid' || variant === 'gradient' || variant === 'glass';\n return {\n container: filled\n ? { backgroundColor: theme.palette.action.disabledBackground, borderWidth: 0 }\n : variant === 'outline'\n ? { backgroundColor: 'transparent', borderWidth: 1, borderColor: theme.palette.action.disabledBackground }\n : { backgroundColor: 'transparent' },\n pressed: {},\n label: { color: theme.palette.action.disabled },\n };\n}\n\nfunction sizeStyle(theme: UiTheme, size: SizeValue, iconOnly: boolean, hasIcon: boolean): ViewStyle {\n const metrics = BUTTON_SIZES[size];\n if (iconOnly) {\n return { padding: ICON_ONLY_PADDING[size], minWidth: 0 };\n }\n return {\n paddingVertical: metrics.paddingVertical,\n paddingHorizontal: metrics.paddingHorizontal,\n minWidth: MIN_WIDTH,\n gap: hasIcon ? theme.spacing(BUTTON_ICON_GAP_UNITS) : undefined,\n };\n}\n\nfunction glowStyle(palette: UiPaletteColor): ViewStyle {\n return Platform.select<ViewStyle>({\n android: { elevation: 8 },\n default: {\n shadowColor: palette.main,\n shadowOpacity: GLOW_INNER_ALPHA,\n shadowRadius: GLOW_RADIUS,\n shadowOffset: { width: 0, height: 0 },\n },\n });\n}\n\n/** The web's `::after` pulse ring: a looped scale-and-fade behind the button. */\nfunction Pulse({ color, radius, testID }: { color: string; radius: number; testID: string }): React.JSX.Element {\n const progress = React.useRef(new Animated.Value(0)).current;\n\n React.useEffect(() => {\n const loop = Animated.loop(\n Animated.timing(progress, {\n toValue: 1,\n duration: PULSE_DURATION_MS,\n easing: Easing.out(Easing.ease),\n useNativeDriver: Platform.OS !== 'web',\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [progress]);\n\n return (\n <Animated.View\n testID={testID}\n aria-hidden\n style={[\n StyleSheet.absoluteFill,\n {\n pointerEvents: 'none',\n borderRadius: radius,\n backgroundColor: color,\n opacity: progress.interpolate({ inputRange: [0, 0.7, 1], outputRange: [PULSE_ALPHA, 0, 0] }),\n transform: [\n { scale: progress.interpolate({ inputRange: [0, 0.7, 1], outputRange: [1, 1 + PULSE_SPREAD / 40, 1] }) },\n ],\n },\n ]}\n />\n );\n}\n\n\ntype ResolvedProps = ReturnType<typeof resolveButtonProps<ButtonProps>>;\n\ninterface ButtonLook {\n inactive: boolean;\n palette: UiPaletteColor;\n radius: number;\n label: TextStyle;\n container: (state: PressableStateCallbackType) => StyleProp<ViewStyle>;\n}\n\n/**\n * Everything the button paints, decided once per render from the resolved\n * props and the theme. Kept out of the component so the component reads as\n * structure — what renders where — and this reads as arithmetic.\n */\nfunction buttonLook(theme: UiTheme, props: ResolvedProps): ButtonLook {\n const { variant, color, size, loading, icon, children, glow, pulse, active, disabled, style } = props;\n const palette = buttonPalette(theme, color);\n const iconOnly = !loading && icon != null && children == null;\n const inactive = Boolean(disabled) || loading;\n const paint = inactive ? disabledPaint(theme, variant) : paintFor(theme, variant, color, palette, active);\n const radius = theme.spacing(BUTTON_RADIUS_UNITS);\n const metrics = BUTTON_SIZES[size];\n // The web button is `overflow: hidden` (its ripple needs it) unless the pulse\n // ring turns it visible; on native the glow's shadow needs it visible too,\n // because a view's own shadow is clipped by its own overflow there.\n const overflow: ViewStyle['overflow'] = pulse || glow ? 'visible' : 'hidden';\n const sized = sizeStyle(theme, size, iconOnly, icon != null && !loading);\n const glowing = glow && !inactive ? glowStyle(palette) : null;\n\n return {\n inactive,\n palette,\n radius,\n label: {\n fontFamily: theme.typography.fontFamily,\n fontSize: metrics.fontSize,\n lineHeight: metrics.fontSize * BUTTON_LINE_HEIGHT,\n fontWeight: String(BUTTON_FONT_WEIGHT) as TextStyle['fontWeight'],\n textAlign: 'center',\n ...paint.label,\n },\n container: (state) => [\n styles.base,\n { borderRadius: radius, overflow },\n sized,\n paint.container,\n state.pressed && !inactive ? paint.pressed : null,\n glowing,\n style,\n ],\n };\n}\n\n/** The spinner that replaces the label while loading; `role` comes from react-native's ActivityIndicator. */\nfunction Spinner({ color, testID }: { color: string; testID: string }): React.JSX.Element {\n return (\n <ActivityIndicator\n size={Platform.OS === 'ios' ? 'small' : BUTTON_SPINNER_SIZE}\n color={color}\n testID={testID}\n accessibilityLabel=\"loading\"\n />\n );\n}\n\nexport const Button = React.forwardRef<View, ButtonProps>((rawProps, ref) => {\n const resolved = resolveButtonProps(rawProps);\n const { loading, icon, iconPosition, pulse, ripple, children, onClick, onPress, ...others } = resolved;\n const theme = useUiTheme();\n const look = buttonLook(theme, resolved);\n\n // The shared stories pass `'data-testid'` as a plain prop; honour it here and\n // keep all three spellings off the element (react-native-web would drop them).\n const testId = resolveTestId(others, 'button');\n const idFor = (suffix: string) => childTestId(others, suffix, 'button');\n const rest = withoutTestIdProps(others);\n // `buttonLook` consumed these; they are not Pressable props.\n const { variant: _v, color: _c, size: _s, glow: _g, active: _a, disabled: _d, style: _st, ...pressable } = rest;\n\n const handlePress = (event: GestureResponderEvent): void => {\n onClick?.(event);\n onPress?.(event);\n };\n\n const iconNode =\n !loading && icon ? (\n <View style={styles.icon} testID={idFor('icon')}>\n {icon}\n </View>\n ) : null;\n\n return (\n <Pressable\n ref={ref}\n role=\"button\"\n aria-disabled={look.inactive}\n aria-busy={loading}\n disabled={look.inactive}\n onPress={handlePress}\n android_ripple={ripple && !look.inactive ? { color: alpha(look.palette.main, 0.2), borderless: false } : undefined}\n style={look.container}\n testID={testId}\n {...pressable}\n >\n {pulse && !look.inactive ? <Pulse color={look.palette.main} radius={look.radius} testID={idFor('pulse')} /> : null}\n {iconPosition === 'left' ? iconNode : null}\n {loading ? <Spinner color={look.label.color as string} testID={idFor('loading')} /> : renderTextChildren(children, look.label, 1)}\n {iconPosition === 'right' ? iconNode : null}\n </Pressable>\n );\n});\n\nButton.displayName = 'Button';\n\nconst styles = StyleSheet.create({\n base: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n alignSelf: 'flex-start',\n position: 'relative',\n },\n icon: {\n alignItems: 'center',\n justifyContent: 'center',\n },\n});\n","import type { ButtonBaseProps } from './Button.base';\n\ntype ButtonDefaultedKeys =\n | 'variant'\n | 'color'\n | 'size'\n | 'loading'\n | 'iconPosition'\n | 'glow'\n | 'pulse'\n | 'ripple'\n | 'active';\n\n/**\n * Generic over the renderer's own props: the web and the native `Button` pass\n * different handler types through, and both come back out untouched.\n */\ntype ResolvedButtonProps<P extends ButtonBaseProps> = P &\n Required<Pick<ButtonBaseProps, ButtonDefaultedKeys>>;\n\nconst BUTTON_DEFAULTS: Required<Pick<ButtonBaseProps, ButtonDefaultedKeys>> = {\n variant: 'solid',\n color: 'primary',\n size: 'md',\n loading: false,\n iconPosition: 'left',\n glow: false,\n pulse: false,\n ripple: true,\n active: false,\n};\n\n// Strips explicitly-undefined props before the merge, so `size={undefined}` still\n// falls back to the default exactly as a destructuring default would.\nconst definedProps = <P extends ButtonBaseProps>(props: P): Partial<P> =>\n Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<P>;\n\nexport const resolveButtonProps = <P extends ButtonBaseProps>(props: P): ResolvedButtonProps<P> =>\n ({ ...BUTTON_DEFAULTS, ...definedProps(props) }) as ResolvedButtonProps<P>;\n","import { darken, lighten } from '../../../tokens/color';\nimport type { ColorValue, SizeValue } from '../../../tokens/vocabulary';\nimport type { UiPaletteColor, UiTheme } from '../../../tokens/theme';\n\n/**\n * THE NUMBERS BOTH `Button` RENDERERS DRAW WITH.\n *\n * `Button.styles.ts` (web, emotion) and `Button.native.tsx` (React Native)\n * read this one table. The web turns the px into rem and the padding into a\n * shorthand string; native uses the numbers as they are. Neither restates a\n * value, which is what keeps a native `md` button 16px tall of padding and\n * 16px of type exactly like the web one.\n */\nexport interface ButtonSizeMetrics {\n paddingVertical: number;\n paddingHorizontal: number;\n fontSize: number;\n}\n\nexport const BUTTON_SIZES: Record<SizeValue, ButtonSizeMetrics> = {\n xs: { paddingVertical: 2, paddingHorizontal: 8, fontSize: 12 },\n sm: { paddingVertical: 6, paddingHorizontal: 12, fontSize: 14 },\n md: { paddingVertical: 8, paddingHorizontal: 16, fontSize: 16 },\n lg: { paddingVertical: 10, paddingHorizontal: 20, fontSize: 18 },\n xl: { paddingVertical: 12, paddingHorizontal: 24, fontSize: 20 },\n};\n\n/** A button that is only an icon is square: uniform padding, no min-width. */\nexport const ICON_ONLY_PADDING: Record<SizeValue, number> = {\n xs: 2,\n sm: 5,\n md: 7,\n lg: 9,\n xl: 11,\n};\n\n/**\n * The start/end icon slot's font-size, in px — MUI's `medium` value, pinned\n * (12-74).\n *\n * MUI sizes that slot off its OWN `size` prop, writing 18/20/22 onto the first\n * child of `.MuiButton-startIcon`. We never passed a `size`, so every button in\n * every size has always drawn medium's 20px; now that `size` IS forwarded — so\n * the rendered class finally names the size the button actually is — the number\n * would start moving with it.\n *\n * WHAT THAT ACTUALLY REACHES, measured in a browser rather than assumed: this\n * Button renders its own wrapper span around the icon (it carries the child\n * test id), so MUI's rule lands on the WRAPPER and reaches the glyph only when\n * the glyph takes its size by inheritance — `fontSize=\"inherit\"`, an em-sized\n * SVG, a text or emoji glyph. With the pin removed, such a glyph measured 18px\n * at `xs`/`sm` and 22px at `lg`/`xl` against the 20px it has always been. An\n * icon carrying an absolute size of its own does not move at all: a default\n * `SvgIcon` stayed 24×24 across all five.\n *\n * A silent resize of the inherited case is still a design decision arriving as\n * a side effect of a class-name fix, so it is pinned to what shipped before —\n * `Button.tsx` puts it on that same wrapper. Scaling the glyph with the button\n * is a ticket of its own.\n */\nexport const BUTTON_ICON_GLYPH_SIZE = 20;\n\nexport const BUTTON_FONT_WEIGHT = 500;\n/** `theme.spacing(1)`. */\nexport const BUTTON_RADIUS_UNITS = 1;\n/** Between the icon and the label: `theme.spacing(0.5)`. */\nexport const BUTTON_ICON_GAP_UNITS = 0.5;\nexport const BUTTON_SPINNER_SIZE = 16;\n/** MUI's `line-height` for button text. */\nexport const BUTTON_LINE_HEIGHT = 1.75;\n\n/** The wash behind an outline, ghost or text button while it is hovered or pressed. */\nexport const BUTTON_WASH_ALPHA = 0.1;\nexport const GLASS_BACKGROUND_ALPHA = 0.1;\nexport const GLASS_BACKGROUND_ALPHA_PRESSED = 0.2;\nexport const GLASS_BORDER_ALPHA = 0.2;\nexport const GLOW_INNER_ALPHA = 0.6;\nexport const GLOW_OUTER_ALPHA = 0.3;\nexport const GLOW_RADIUS = 20;\nexport const PULSE_ALPHA = 0.3;\nexport const PULSE_DURATION_MS = 2000;\nexport const PULSE_SPREAD = 15;\n\n/**\n * `neutral` has no palette slot of its own in MUI, so `Button.styles.ts` has\n * always drawn it from three greys. Same three greys here.\n */\nexport function buttonPalette(theme: UiTheme, color: ColorValue): UiPaletteColor {\n if (color === 'neutral') {\n return {\n main: theme.palette.grey[700],\n dark: theme.palette.grey[800],\n light: theme.palette.grey[500],\n contrastText: '#fff',\n };\n }\n return theme.palette[color];\n}\n\n/**\n * The label colour for `ghost` and `text`: one step darker than `main` in\n * light mode (lighter in dark), because `main` is chosen to sit UNDER white and\n * is not legible AS text on a tinted surface. See the web `quietInk`.\n */\nexport const quietInk = (theme: UiTheme, palette: UiPaletteColor): string =>\n theme.mode === 'dark' ? lighten(palette.main, 0.35) : darken(palette.main, 0.3);\n\n/** Gradients run between two related hues; the named colours pick a specific pair. */\nexport function gradientStops(\n theme: UiTheme,\n color: ColorValue,\n palette: UiPaletteColor,\n): [string, string] {\n switch (color) {\n case 'primary':\n return [theme.palette.primary.main, theme.palette.secondary.main];\n case 'secondary':\n return [theme.palette.secondary.main, theme.palette.primary.main];\n case 'success':\n case 'warning':\n return [theme.palette[color].light, theme.palette[color].dark];\n case 'danger':\n return [theme.palette.danger.light, theme.palette.danger.dark];\n default:\n return [palette.main, palette.dark];\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  EmptyState
3
- } from "../chunks/chunk-ZAQ3AZJM.js";
4
- import "../chunks/chunk-ATS7STZJ.js";
3
+ } from "../chunks/chunk-2R2R35C5.js";
4
+ import "../chunks/chunk-WL5LXVCK.js";
5
5
  import "../chunks/chunk-DN73KYIZ.js";
6
6
  import "../chunks/chunk-5GJ5OG5R.js";
7
7
  import "../chunks/chunk-QYUD3S6F.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Button
3
- } from "../chunks/chunk-ATS7STZJ.js";
3
+ } from "../chunks/chunk-WL5LXVCK.js";
4
4
  import {
5
5
  webAria
6
6
  } from "../chunks/chunk-DN73KYIZ.js";
@@ -7,8 +7,8 @@ import {
7
7
  } from "../chunks/chunk-MJVSQXOD.js";
8
8
  import {
9
9
  EmptyState
10
- } from "../chunks/chunk-ZAQ3AZJM.js";
11
- import "../chunks/chunk-ATS7STZJ.js";
10
+ } from "../chunks/chunk-2R2R35C5.js";
11
+ import "../chunks/chunk-WL5LXVCK.js";
12
12
  import {
13
13
  webAria,
14
14
  webRole
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Button
3
- } from "../chunks/chunk-ATS7STZJ.js";
3
+ } from "../chunks/chunk-WL5LXVCK.js";
4
4
  import "../chunks/chunk-5GJ5OG5R.js";
5
5
  import "../chunks/chunk-AR5O4BEY.js";
6
6
  import "../chunks/chunk-GWGIWQO7.js";
@@ -12,7 +12,7 @@ import {
12
12
  } from "../chunk-H37GIAAM.js";
13
13
  import {
14
14
  AppHeaderDetails
15
- } from "../chunk-BUQ2JUND.js";
15
+ } from "../chunk-JO6BBSGY.js";
16
16
  import {
17
17
  brandGradient,
18
18
  highlightOf,
@@ -29,9 +29,9 @@ import "../chunk-YANLN6HP.js";
29
29
  import "../chunk-5KEMPCW4.js";
30
30
  import "../chunk-VM3HRSAU.js";
31
31
  import "../chunk-GYXUCS37.js";
32
- import "../chunk-YTOYMJPM.js";
33
- import "../chunk-JT6TERQL.js";
34
- import "../chunk-ITGG5OKP.js";
32
+ import "../chunk-SLVQ33AN.js";
33
+ import "../chunk-BB2OUERT.js";
34
+ import "../chunk-5LQ7PKMW.js";
35
35
  import "../chunk-TAMIZE4Q.js";
36
36
  import "../chunk-73BEVJCS.js";
37
37
  import "../chunk-TYJR4GOF.js";
@@ -4,7 +4,7 @@ import {
4
4
  GoogleIcon,
5
5
  SocialLoginButton,
6
6
  SocialLoginContainer
7
- } from "./chunk-4523RYE7.js";
7
+ } from "./chunk-OG2FP6SE.js";
8
8
  import "./chunk-INGPH3YQ.js";
9
9
  import "./chunk-6GP2DOOO.js";
10
10
  import "./chunk-MESRKY67.js";
@@ -20,9 +20,9 @@ import "./chunk-BEBLRL5D.js";
20
20
  import "./chunk-6Q6T3FW5.js";
21
21
  import "./chunk-FKUYRQSP.js";
22
22
  import "./chunk-BA4RHQ3B.js";
23
- import "./chunk-YTOYMJPM.js";
24
- import "./chunk-JT6TERQL.js";
25
- import "./chunk-ITGG5OKP.js";
23
+ import "./chunk-SLVQ33AN.js";
24
+ import "./chunk-BB2OUERT.js";
25
+ import "./chunk-5LQ7PKMW.js";
26
26
  import "./chunk-TAMIZE4Q.js";
27
27
  import "./chunk-73BEVJCS.js";
28
28
  import "./chunk-343TTIHD.js";
@@ -1,4 +1,8 @@
1
- import * as React from 'react';
2
- import type { ButtonProps } from './Button.types';
3
- export declare const Button: React.ForwardRefExoticComponent<Omit<ButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
1
+ import type { ButtonComponent } from './Button.types';
2
+ /**
3
+ * The cast is what publishes the generic — `forwardRef` cannot express
4
+ * "renders as C, and takes C's props" on its own, so MUI's own components do
5
+ * exactly this. `ButtonRoot` above is the implementation and is not exported.
6
+ */
7
+ export declare const Button: ButtonComponent;
4
8
  //# sourceMappingURL=Button.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Button/Button.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA2DlD,eAAO,MAAM,MAAM,oGAkElB,CAAC"}
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Button/Button.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,gBAAgB,CAAC;AAkMnE;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAiB,eAAe,CAAC"}
@@ -17,6 +17,31 @@ export interface ButtonSizeMetrics {
17
17
  export declare const BUTTON_SIZES: Record<SizeValue, ButtonSizeMetrics>;
18
18
  /** A button that is only an icon is square: uniform padding, no min-width. */
19
19
  export declare const ICON_ONLY_PADDING: Record<SizeValue, number>;
20
+ /**
21
+ * The start/end icon slot's font-size, in px — MUI's `medium` value, pinned
22
+ * (12-74).
23
+ *
24
+ * MUI sizes that slot off its OWN `size` prop, writing 18/20/22 onto the first
25
+ * child of `.MuiButton-startIcon`. We never passed a `size`, so every button in
26
+ * every size has always drawn medium's 20px; now that `size` IS forwarded — so
27
+ * the rendered class finally names the size the button actually is — the number
28
+ * would start moving with it.
29
+ *
30
+ * WHAT THAT ACTUALLY REACHES, measured in a browser rather than assumed: this
31
+ * Button renders its own wrapper span around the icon (it carries the child
32
+ * test id), so MUI's rule lands on the WRAPPER and reaches the glyph only when
33
+ * the glyph takes its size by inheritance — `fontSize="inherit"`, an em-sized
34
+ * SVG, a text or emoji glyph. With the pin removed, such a glyph measured 18px
35
+ * at `xs`/`sm` and 22px at `lg`/`xl` against the 20px it has always been. An
36
+ * icon carrying an absolute size of its own does not move at all: a default
37
+ * `SvgIcon` stayed 24×24 across all five.
38
+ *
39
+ * A silent resize of the inherited case is still a design decision arriving as
40
+ * a side effect of a class-name fix, so it is pinned to what shipped before —
41
+ * `Button.tsx` puts it on that same wrapper. Scaling the glyph with the button
42
+ * is a ticket of its own.
43
+ */
44
+ export declare const BUTTON_ICON_GLYPH_SIZE = 20;
20
45
  export declare const BUTTON_FONT_WEIGHT = 500;
21
46
  /** `theme.spacing(1)`. */
22
47
  export declare const BUTTON_RADIUS_UNITS = 1;
@@ -1 +1 @@
1
- {"version":3,"file":"Button.metrics.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Button/Button.metrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAM7D,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAMvD,CAAC;AAEF,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,0BAA0B;AAC1B,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,WAAW,KAAK,CAAC;AAC9B,eAAO,MAAM,WAAW,MAAM,CAAC;AAC/B,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,YAAY,KAAK,CAAC;AAE/B;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,cAAc,CAU/E;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,EAAE,SAAS,cAAc,KAAG,MACc,CAAC;AAElF,sFAAsF;AACtF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,cAAc,GACtB,CAAC,MAAM,EAAE,MAAM,CAAC,CAclB"}
1
+ {"version":3,"file":"Button.metrics.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Button/Button.metrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAM7D,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAMvD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,0BAA0B;AAC1B,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,WAAW,KAAK,CAAC;AAC9B,eAAO,MAAM,WAAW,MAAM,CAAC;AAC/B,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,YAAY,KAAK,CAAC;AAE/B;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,cAAc,CAU/E;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,EAAE,SAAS,cAAc,KAAG,MACc,CAAC;AAElF,sFAAsF;AACtF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,cAAc,GACtB,CAAC,MAAM,EAAE,MAAM,CAAC,CAclB"}
@@ -1,19 +1,52 @@
1
1
  import type { ButtonProps as MuiButtonProps } from '@mui/material/Button/index.js';
2
+ import type { OverridableComponent, OverrideProps } from '@mui/material/OverridableComponent/index.js';
2
3
  import type * as React from 'react';
3
4
  import type { ButtonBaseProps } from './Button.base';
4
5
  export type { ButtonBaseProps, ButtonVariant } from './Button.base';
5
- export interface ButtonProps extends ButtonBaseProps, Omit<MuiButtonProps, 'variant' | 'color' | 'size' | keyof ButtonBaseProps> {
6
+ /**
7
+ * Everything this Button adds, WITHOUT the element it renders as.
8
+ *
9
+ * `component` is deliberately omitted here and reintroduced by the type map
10
+ * below: MUI models "render as something else" with a generic, and taking
11
+ * `component?: React.ElementType` as a plain prop is exactly what threw the
12
+ * target's own props away (12-70).
13
+ */
14
+ export interface ButtonOwnProps extends ButtonBaseProps, Omit<MuiButtonProps, 'variant' | 'color' | 'size' | 'component' | keyof ButtonBaseProps> {
6
15
  /**
7
16
  * Click handler
8
17
  */
9
- onClick?: React.MouseEventHandler<HTMLButtonElement>;
18
+ onClick?: React.MouseEventHandler<HTMLElement>;
10
19
  /**
11
20
  * Focus handler
12
21
  */
13
- onFocus?: React.FocusEventHandler<HTMLButtonElement>;
22
+ onFocus?: React.FocusEventHandler<HTMLElement>;
14
23
  /**
15
24
  * Blur handler
16
25
  */
17
- onBlur?: React.FocusEventHandler<HTMLButtonElement>;
26
+ onBlur?: React.FocusEventHandler<HTMLElement>;
18
27
  }
28
+ /**
29
+ * What `Button` renders as, and what that brings with it.
30
+ *
31
+ * This is the shape MUI's `OverridableComponent` reads. Handing `component` a
32
+ * router `Link` now also hands the call site that Link's OWN props — `to`,
33
+ * `replace`, `state` — typed, which is the whole point of 12-70. Before this,
34
+ * `component` was `React.ElementType` and `to` typechecked nowhere, so a host
35
+ * that wanted a navigation painted as a button had to reach for a type
36
+ * assertion or throw the `href` away.
37
+ */
38
+ export interface ButtonTypeMap<AdditionalProps = object, RootComponent extends React.ElementType = 'button'> {
39
+ props: AdditionalProps & ButtonOwnProps;
40
+ defaultComponent: RootComponent;
41
+ }
42
+ /**
43
+ * The props of a Button rendered as `RootComponent` — `button` by default.
44
+ *
45
+ * Generic WITH defaults, so every existing `ButtonProps` (no arguments) keeps
46
+ * meaning exactly what it meant before this change: the button-rendered case.
47
+ */
48
+ export type ButtonProps<RootComponent extends React.ElementType = 'button', AdditionalProps = object> = OverrideProps<ButtonTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
49
+ component?: React.ElementType;
50
+ };
51
+ export type ButtonComponent = OverridableComponent<ButtonTypeMap>;
19
52
  //# sourceMappingURL=Button.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Button.types.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Button/Button.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,IAAI,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEpE,MAAM,WAAW,WACf,SAAQ,eAAe,EACrB,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,eAAe,CAAC;IAC5E;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAErD;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAErD;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;CACrD"}
1
+ {"version":3,"file":"Button.types.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Button/Button.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,IAAI,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACvG,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEpE;;;;;;;GAOG;AACH,MAAM,WAAW,cACf,SAAQ,eAAe,EACrB,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,eAAe,CAAC;IAC1F;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAE/C;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAE/C;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;CAC/C;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa,CAC5B,eAAe,GAAG,MAAM,EACxB,aAAa,SAAS,KAAK,CAAC,WAAW,GAAG,QAAQ;IAElD,KAAK,EAAE,eAAe,GAAG,cAAc,CAAC;IACxC,gBAAgB,EAAE,aAAa,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CACrB,aAAa,SAAS,KAAK,CAAC,WAAW,GAAG,QAAQ,EAClD,eAAe,GAAG,MAAM,IACtB,aAAa,CAAC,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,EAAE,aAAa,CAAC,GAAG;IAChF,SAAS,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC"}
@@ -17,6 +17,31 @@ export interface ButtonSizeMetrics {
17
17
  export declare const BUTTON_SIZES: Record<SizeValue, ButtonSizeMetrics>;
18
18
  /** A button that is only an icon is square: uniform padding, no min-width. */
19
19
  export declare const ICON_ONLY_PADDING: Record<SizeValue, number>;
20
+ /**
21
+ * The start/end icon slot's font-size, in px — MUI's `medium` value, pinned
22
+ * (12-74).
23
+ *
24
+ * MUI sizes that slot off its OWN `size` prop, writing 18/20/22 onto the first
25
+ * child of `.MuiButton-startIcon`. We never passed a `size`, so every button in
26
+ * every size has always drawn medium's 20px; now that `size` IS forwarded — so
27
+ * the rendered class finally names the size the button actually is — the number
28
+ * would start moving with it.
29
+ *
30
+ * WHAT THAT ACTUALLY REACHES, measured in a browser rather than assumed: this
31
+ * Button renders its own wrapper span around the icon (it carries the child
32
+ * test id), so MUI's rule lands on the WRAPPER and reaches the glyph only when
33
+ * the glyph takes its size by inheritance — `fontSize="inherit"`, an em-sized
34
+ * SVG, a text or emoji glyph. With the pin removed, such a glyph measured 18px
35
+ * at `xs`/`sm` and 22px at `lg`/`xl` against the 20px it has always been. An
36
+ * icon carrying an absolute size of its own does not move at all: a default
37
+ * `SvgIcon` stayed 24×24 across all five.
38
+ *
39
+ * A silent resize of the inherited case is still a design decision arriving as
40
+ * a side effect of a class-name fix, so it is pinned to what shipped before —
41
+ * `Button.tsx` puts it on that same wrapper. Scaling the glyph with the button
42
+ * is a ticket of its own.
43
+ */
44
+ export declare const BUTTON_ICON_GLYPH_SIZE = 20;
20
45
  export declare const BUTTON_FONT_WEIGHT = 500;
21
46
  /** `theme.spacing(1)`. */
22
47
  export declare const BUTTON_RADIUS_UNITS = 1;
@@ -1 +1 @@
1
- {"version":3,"file":"Button.metrics.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Button/Button.metrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAM7D,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAMvD,CAAC;AAEF,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,0BAA0B;AAC1B,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,WAAW,KAAK,CAAC;AAC9B,eAAO,MAAM,WAAW,MAAM,CAAC;AAC/B,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,YAAY,KAAK,CAAC;AAE/B;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,cAAc,CAU/E;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,EAAE,SAAS,cAAc,KAAG,MACc,CAAC;AAElF,sFAAsF;AACtF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,cAAc,GACtB,CAAC,MAAM,EAAE,MAAM,CAAC,CAclB"}
1
+ {"version":3,"file":"Button.metrics.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Button/Button.metrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAM7D,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAMvD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,0BAA0B;AAC1B,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,WAAW,KAAK,CAAC;AAC9B,eAAO,MAAM,WAAW,MAAM,CAAC;AAC/B,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,YAAY,KAAK,CAAC;AAE/B;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,cAAc,CAU/E;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,EAAE,SAAS,cAAc,KAAG,MACc,CAAC;AAElF,sFAAsF;AACtF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,cAAc,GACtB,CAAC,MAAM,EAAE,MAAM,CAAC,CAclB"}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  UserAvatar,
3
3
  UserMenu
4
- } from "./chunk-ZRPGVHTR.js";
4
+ } from "./chunk-GGI7GM5O.js";
5
5
  import "./chunk-UDQSIRAP.js";
6
6
  import "./chunk-JUHUKZGU.js";
7
7
  import "./chunk-NA7MIEG6.js";
@@ -15,9 +15,9 @@ import "./chunk-BEBLRL5D.js";
15
15
  import "./chunk-6Q6T3FW5.js";
16
16
  import "./chunk-FKUYRQSP.js";
17
17
  import "./chunk-BA4RHQ3B.js";
18
- import "./chunk-YTOYMJPM.js";
19
- import "./chunk-JT6TERQL.js";
20
- import "./chunk-ITGG5OKP.js";
18
+ import "./chunk-SLVQ33AN.js";
19
+ import "./chunk-BB2OUERT.js";
20
+ import "./chunk-5LQ7PKMW.js";
21
21
  import "./chunk-TAMIZE4Q.js";
22
22
  import "./chunk-73BEVJCS.js";
23
23
  import "./chunk-343TTIHD.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.24.7",
3
+ "version": "6.24.8",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -12,6 +12,8 @@ The Button component is a versatile and highly customizable interactive element
12
12
  - **Special Effects**: glow, pulse animations
13
13
  - **Loading States**: Built-in loading spinner
14
14
  - **Icon Support**: Leading icons with automatic loading state handling
15
+ - **Renders As Anything**: `component` swaps the element, carrying that
16
+ component's own props through the types (a router link, an `<a>`, a label)
15
17
  - **Accessibility**: Full ARIA support, keyboard navigation
16
18
  - **Responsive Design**: Adapts to different screen sizes
17
19
 
@@ -37,6 +39,14 @@ import { Button } from '@procurement/ui';
37
39
  <Button variant="gradient" glow pulse>
38
40
  Special Button
39
41
  </Button>
42
+
43
+ // As a navigation, painted as a button
44
+ <Button component={Link} to="/orders/42">
45
+ Track my order
46
+ </Button>
47
+
48
+ // Or a plain anchor, when there is no router in the tree
49
+ <Button href="/orders/42">Track my order</Button>
40
50
  ```
41
51
 
42
52
  ## Props
@@ -60,6 +70,35 @@ import { Button } from '@procurement/ui';
60
70
  | `onBlur` | `(event: FocusEvent) => void` | - | Blur event handler |
61
71
  | `children` | `ReactNode` | - | Button content |
62
72
  | `className` | `string` | - | Additional CSS classes |
73
+ | `component` | `ElementType` | `'button'` | Render as this element/component instead |
74
+ | `href` | `string` | - | Renders an `<a>` (MUI's own behaviour) |
75
+
76
+ ## Rendering as something else
77
+
78
+ `component` swaps the element the button renders as, and the button's props are
79
+ typed against it — so the target's own props are checked at the call site rather
80
+ than silently dropped:
81
+
82
+ ```tsx
83
+ import { Link } from 'react-router-dom';
84
+
85
+ <Button component={Link} to="/orders/42" variant="solid" size="lg">
86
+ Track my order
87
+ </Button>;
88
+ ```
89
+
90
+ Three things are worth knowing:
91
+
92
+ - **`to` is typed.** `Button` is an `OverridableComponent`, so the generic
93
+ carries the target's props through. Misspell `to` and it fails to compile.
94
+ - **The paint does not change.** Measured against the same button rendered as a
95
+ `<button>`: identical box, background, padding, radius and type; hover still
96
+ darkens; the class still names the size.
97
+ - **`href` alone is enough** when there is no router involved — MUI renders an
98
+ `<a>` for it without a `component`.
99
+
100
+ The event handlers are typed on `HTMLElement` rather than `HTMLButtonElement`
101
+ for this reason: the element under the pointer is not always a button.
63
102
 
64
103
  ## Variants
65
104
 
@@ -34,6 +34,32 @@ export const ICON_ONLY_PADDING: Record<SizeValue, number> = {
34
34
  xl: 11,
35
35
  };
36
36
 
37
+ /**
38
+ * The start/end icon slot's font-size, in px — MUI's `medium` value, pinned
39
+ * (12-74).
40
+ *
41
+ * MUI sizes that slot off its OWN `size` prop, writing 18/20/22 onto the first
42
+ * child of `.MuiButton-startIcon`. We never passed a `size`, so every button in
43
+ * every size has always drawn medium's 20px; now that `size` IS forwarded — so
44
+ * the rendered class finally names the size the button actually is — the number
45
+ * would start moving with it.
46
+ *
47
+ * WHAT THAT ACTUALLY REACHES, measured in a browser rather than assumed: this
48
+ * Button renders its own wrapper span around the icon (it carries the child
49
+ * test id), so MUI's rule lands on the WRAPPER and reaches the glyph only when
50
+ * the glyph takes its size by inheritance — `fontSize="inherit"`, an em-sized
51
+ * SVG, a text or emoji glyph. With the pin removed, such a glyph measured 18px
52
+ * at `xs`/`sm` and 22px at `lg`/`xl` against the 20px it has always been. An
53
+ * icon carrying an absolute size of its own does not move at all: a default
54
+ * `SvgIcon` stayed 24×24 across all five.
55
+ *
56
+ * A silent resize of the inherited case is still a design decision arriving as
57
+ * a side effect of a class-name fix, so it is pinned to what shipped before —
58
+ * `Button.tsx` puts it on that same wrapper. Scaling the glyph with the button
59
+ * is a ticket of its own.
60
+ */
61
+ export const BUTTON_ICON_GLYPH_SIZE = 20;
62
+
37
63
  export const BUTTON_FONT_WEIGHT = 500;
38
64
  /** `theme.spacing(1)`. */
39
65
  export const BUTTON_RADIUS_UNITS = 1;
@@ -4,6 +4,7 @@ import { styled } from '@mui/material/styles/index.js';
4
4
  import * as React from 'react';
5
5
 
6
6
  import { resolveButtonProps } from './Button.helpers';
7
+ import { BUTTON_ICON_GLYPH_SIZE } from './Button.metrics';
7
8
  import { childTestId, resolveTestId, withoutTestIdProps } from '../../../platform/test-id';
8
9
  import {
9
10
  buttonEmphasisStyles,
@@ -12,7 +13,7 @@ import {
12
13
  iconAlignmentStyles,
13
14
  buttonSize,
14
15
  } from './Button.styles';
15
- import type { ButtonProps } from './Button.types';
16
+ import type { ButtonComponent, ButtonProps } from './Button.types';
16
17
 
17
18
  const StyledButton = styled(MuiButton, {
18
19
  shouldForwardProp: (prop) =>
@@ -49,12 +50,53 @@ const muiVariantFor = (variant?: string): 'outlined' | 'text' | 'contained' => {
49
50
 
50
51
  type MuiButtonColor = 'inherit' | 'primary' | 'secondary' | 'success' | 'warning' | 'info' | 'error';
51
52
 
53
+ /**
54
+ * Our five sizes collapse onto MUI's three, so the rendered class NAMES the
55
+ * size the button actually is (12-74).
56
+ *
57
+ * It was never forwarded, so every button — `xs` through `xl` — carried
58
+ * `MuiButton-sizeMedium`. The pixels were right (they come from `buttonSize`'s
59
+ * `sx`, which still decides them) but the DOM said "medium" about a large
60
+ * button: a test could never assert the size, and devtools lied to whoever
61
+ * opened them.
62
+ *
63
+ * MUI's own size styles are padding, font-size and the icon glyph. The first
64
+ * two are overridden by that same `sx`; the third is pinned by
65
+ * `BUTTON_ICON_GLYPH_SIZE`, so forwarding this moves nothing on screen.
66
+ */
67
+ const muiSizeFor = (size: NonNullable<ButtonProps['size']>): 'small' | 'medium' | 'large' => {
68
+ if (size === 'xs' || size === 'sm') return 'small';
69
+ return size === 'md' ? 'medium' : 'large';
70
+ };
71
+
52
72
  /** `danger` and `neutral` are ours; the rest are MUI's own names already. */
53
73
  const muiColorFor = (color: NonNullable<ButtonProps['color']>): MuiButtonColor => {
54
74
  if (color === 'danger') return 'error';
55
75
  return color === 'neutral' ? 'inherit' : color;
56
76
  };
57
77
 
78
+ /**
79
+ * The icon slot's font-size, pinned on the wrapper this component already owns
80
+ * (12-74).
81
+ *
82
+ * MUI writes 18/20/22 there off its own `size`, and that prop is now forwarded,
83
+ * so a glyph that takes its size by INHERITANCE would start moving with the
84
+ * button — measured at 18px on `xs` and 22px on `lg` against the 20px every
85
+ * size has always drawn. See {@link BUTTON_ICON_GLYPH_SIZE} for what that does
86
+ * and does not reach.
87
+ *
88
+ * Written as an inline style rather than a selector in `sx` because MUI's own
89
+ * rule sits on the start/end-icon span itself. Beating it from the root means
90
+ * winning a specificity contest at a distance — true in a browser, but not
91
+ * something a test can hold, since jsdom resolves `getComputedStyle` by
92
+ * document order and never by specificity. Inline wins both, and it sits on the
93
+ * one element we already render for this glyph.
94
+ *
95
+ * A number, not `px()`: React writes `font-size: 20px`, which is exactly the
96
+ * declaration MUI was emitting before.
97
+ */
98
+ const ICON_GLYPH_STYLE = { fontSize: BUTTON_ICON_GLYPH_SIZE } as const;
99
+
58
100
  /**
59
101
  * An icon and nothing else — the shape that should render square.
60
102
  *
@@ -71,7 +113,26 @@ function isIconOnly({
71
113
  return !loading && icon != null && children == null;
72
114
  }
73
115
 
74
- export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
116
+ /**
117
+ * The design system's button.
118
+ *
119
+ * Typed as an `OverridableComponent` (12-70) rather than a plain `forwardRef`,
120
+ * which is how MUI models a component that can render as something else. The
121
+ * practical difference is one line at a call site:
122
+ *
123
+ * ```tsx
124
+ * <Button component={Link} to="/account/compras/42">Acompanhar pedido</Button>
125
+ * ```
126
+ *
127
+ * `to` is typed here because the generic carries the target component's own
128
+ * props through. A plain `component?: React.ElementType` — what this was —
129
+ * accepts the component and throws its props away, so `to` typechecked
130
+ * nowhere even though it arrived intact at runtime. A host wanting a router
131
+ * navigation painted as a button had to choose between a type assertion and
132
+ * losing the `href`; both were shipped, and both are the reason this ticket
133
+ * exists.
134
+ */
135
+ const ButtonRoot = React.forwardRef<HTMLButtonElement, ButtonProps>(
75
136
  (rawProps, ref) => {
76
137
  const {
77
138
  variant,
@@ -99,7 +160,11 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
99
160
 
100
161
  // Wrap icon with testId if provided
101
162
  const iconWithTestId =
102
- !loading && icon ? <span data-testid={testId('icon')}>{icon}</span> : undefined;
163
+ !loading && icon ? (
164
+ <span data-testid={testId('icon')} style={ICON_GLYPH_STYLE}>
165
+ {icon}
166
+ </span>
167
+ ) : undefined;
103
168
 
104
169
  // Only an icon, so the button is a square rather than a 64px slab.
105
170
  const iconOnly = isIconOnly({ loading, icon, children });
@@ -112,6 +177,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
112
177
  ref={ref}
113
178
  variant={muiVariantFor(variant)}
114
179
  color={muiColorFor(color)}
180
+ size={muiSizeFor(size)}
115
181
  customVariant={variant}
116
182
  customColor={color}
117
183
  glow={glow}
@@ -139,4 +205,11 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
139
205
  },
140
206
  );
141
207
 
142
- Button.displayName = 'Button';
208
+ ButtonRoot.displayName = 'Button';
209
+
210
+ /**
211
+ * The cast is what publishes the generic — `forwardRef` cannot express
212
+ * "renders as C, and takes C's props" on its own, so MUI's own components do
213
+ * exactly this. `ButtonRoot` above is the implementation and is not exported.
214
+ */
215
+ export const Button = ButtonRoot as ButtonComponent;