@zendir/ui 0.6.0 → 0.6.1

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 (116) hide show
  1. package/CHANGELOG.md +419 -406
  2. package/dist/react/3d/CesiumCaptureSource.js.map +1 -1
  3. package/dist/react/3d/ZenSpace3D.js.map +1 -1
  4. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -1
  5. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -1
  6. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -1
  7. package/dist/react/3d/capturePngAnalysis.js.map +1 -1
  8. package/dist/react/3d/threeLoader.js.map +1 -1
  9. package/dist/react/astro/ClassificationBanner.js.map +1 -1
  10. package/dist/react/astro/GlobalStatusBar.js.map +1 -1
  11. package/dist/react/astro/MissionClock.js.map +1 -1
  12. package/dist/react/astro/MonitoringIcon.js.map +1 -1
  13. package/dist/react/astro/Notification.js.map +1 -1
  14. package/dist/react/astro/Progress.js.map +1 -1
  15. package/dist/react/astro/SimulationControls.js.map +1 -1
  16. package/dist/react/astro/StatusIndicator.js.map +1 -1
  17. package/dist/react/astro/UnifiedTimeline.js.map +1 -1
  18. package/dist/react/cards/AccessCard.js.map +1 -1
  19. package/dist/react/cards/OrbitCard.js.map +1 -1
  20. package/dist/react/cards/SpacecraftCard.js.map +1 -1
  21. package/dist/react/cards/TelemetryCard.js.map +1 -1
  22. package/dist/react/cards/TelemetryStreamCard.js.map +1 -1
  23. package/dist/react/charts/GroundTrackMap.js.map +1 -1
  24. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -1
  25. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -1
  26. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -1
  27. package/dist/react/charts/unified/AstroChart.js.map +1 -1
  28. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -1
  29. package/dist/react/charts/unified/domain.js.map +1 -1
  30. package/dist/react/charts/unified/generators.js.map +1 -1
  31. package/dist/react/charts/unified/presets.js.map +1 -1
  32. package/dist/react/charts/unified/sync.js.map +1 -1
  33. package/dist/react/charts/unified/theme.js.map +1 -1
  34. package/dist/react/charts/unified/useChartStream.js.map +1 -1
  35. package/dist/react/chatgpt/index.js.map +1 -1
  36. package/dist/react/context/CategoryContext.js.map +1 -1
  37. package/dist/react/context/DisplaySettingsContext.js.map +1 -1
  38. package/dist/react/context/SpatialSelectionContext.js.map +1 -1
  39. package/dist/react/core/data/DataTable.js.map +1 -1
  40. package/dist/react/core/data/DataValue.js.map +1 -1
  41. package/dist/react/core/data/propertyConfig.js.map +1 -1
  42. package/dist/react/core/display/AstroIcon.js.map +1 -1
  43. package/dist/react/core/display/Badge.js.map +1 -1
  44. package/dist/react/core/display/CardHeader.js.map +1 -1
  45. package/dist/react/core/display/Container.js.map +1 -1
  46. package/dist/react/core/display/CopyButton.js.map +1 -1
  47. package/dist/react/core/display/GlassCard.js.map +1 -1
  48. package/dist/react/core/display/HeaderIconWithStatus.js.map +1 -1
  49. package/dist/react/core/display/Icon.js.map +1 -1
  50. package/dist/react/core/display/Typography.js.map +1 -1
  51. package/dist/react/core/feedback/ConfirmDialog.js.map +1 -1
  52. package/dist/react/core/feedback/Dialog.js.map +1 -1
  53. package/dist/react/core/feedback/Toast.js.map +1 -1
  54. package/dist/react/core/inputs/Button.js.map +1 -1
  55. package/dist/react/core/inputs/Checkbox.js.map +1 -1
  56. package/dist/react/core/inputs/Input.js.map +1 -1
  57. package/dist/react/core/inputs/LimitsBar.js.map +1 -1
  58. package/dist/react/core/inputs/NumberInput.js.map +1 -1
  59. package/dist/react/core/inputs/PinInput.js.map +1 -1
  60. package/dist/react/core/inputs/Select.js.map +1 -1
  61. package/dist/react/core/inputs/Toggle.js.map +1 -1
  62. package/dist/react/core/layout/Box.js.map +1 -1
  63. package/dist/react/core/layout/Center.js.map +1 -1
  64. package/dist/react/core/layout/Divider.js.map +1 -1
  65. package/dist/react/core/layout/Flex.js.map +1 -1
  66. package/dist/react/core/layout/Grid.js.map +1 -1
  67. package/dist/react/core/layout/Spacer.js.map +1 -1
  68. package/dist/react/core/layout/Stack.js.map +1 -1
  69. package/dist/react/core/layout/responsive.js.map +1 -1
  70. package/dist/react/core/layout/useBreakpoint.js.map +1 -1
  71. package/dist/react/core/navigation/AppBar.js.map +1 -1
  72. package/dist/react/core/navigation/Pagination.js.map +1 -1
  73. package/dist/react/core/navigation/SideNav.js.map +1 -1
  74. package/dist/react/core/navigation/Tabs.js.map +1 -1
  75. package/dist/react/core/overlays/Popover.js.map +1 -1
  76. package/dist/react/core/overlays/SidePanel.js.map +1 -1
  77. package/dist/react/core/overlays/Tooltip.js.map +1 -1
  78. package/dist/react/core/widgets/ActivityPlanner.js.map +1 -1
  79. package/dist/react/core/widgets/Capture.js.map +1 -1
  80. package/dist/react/core/widgets/ChatPanel.js.map +1 -1
  81. package/dist/react/core/widgets/ColorPickerPanel.js.map +1 -1
  82. package/dist/react/core/widgets/CommandBuilder.js.map +1 -1
  83. package/dist/react/core/widgets/ConnectionForm.js.map +1 -1
  84. package/dist/react/core/widgets/FileExplorer.js.map +1 -1
  85. package/dist/react/core/widgets/HexViewer.js.map +1 -1
  86. package/dist/react/core/widgets/ImageFrame.js.map +1 -1
  87. package/dist/react/core/widgets/ImageGallery.js.map +1 -1
  88. package/dist/react/core/widgets/ImagePanel.js.map +1 -1
  89. package/dist/react/core/widgets/LogViewer.js.map +1 -1
  90. package/dist/react/core/widgets/MessageStream.js.map +1 -1
  91. package/dist/react/core/widgets/MissionCalendar.js.map +1 -1
  92. package/dist/react/core/widgets/PacketViewer.js.map +1 -1
  93. package/dist/react/hooks/useCompactMode.js.map +1 -1
  94. package/dist/react/hooks/useSimulationScene.js.map +1 -1
  95. package/dist/react/panels/LayerControlPanel.js.map +1 -1
  96. package/dist/react/panels/ObjectInventoryPanel.js.map +1 -1
  97. package/dist/react/shared/ErrorBoundary.js.map +1 -1
  98. package/dist/react/shared/Skeleton.js.map +1 -1
  99. package/dist/react/theme/ThemeProvider.js +2 -1
  100. package/dist/react/theme/ThemeProvider.js.map +1 -1
  101. package/dist/react/theme/cardAccent.js.map +1 -1
  102. package/dist/react/theme/config.js.map +1 -1
  103. package/dist/react/theme/types.js.map +1 -1
  104. package/dist/react/types.js.map +1 -1
  105. package/dist/react/utils/categoryPalette.js.map +1 -1
  106. package/dist/react/utils/index.js.map +1 -1
  107. package/dist/style.css +216 -216
  108. package/dist/tokens/core.js.map +1 -1
  109. package/dist/tokens/index.js.map +1 -1
  110. package/dist/tokens/palettes/astro.js.map +1 -1
  111. package/dist/tokens/palettes/index.js.map +1 -1
  112. package/dist/tokens/palettes/tailwind.js.map +1 -1
  113. package/dist/tokens/palettes/zendir.js.map +1 -1
  114. package/dist/tokens/themes.js.map +1 -1
  115. package/dist/tokens/tokens.css +533 -533
  116. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AstroIcon.js","names":[],"sources":["../../../../src/react/core/display/AstroIcon.tsx"],"sourcesContent":["/**\n * @zendir/ui - AstroIcon Component\n *\n * Wrapper around official @astrouxds/react RuxIcon component.\n * Provides all 400+ official Astro UXD icons with consistent API.\n *\n * SECURITY: Uses dynamic import with proper error handling.\n * FLEXIBILITY: Works with or without @astrouxds/react installed.\n *\n * @see https://www.astrouxds.com/components/icon-library/\n *\n * @example\n * ```tsx\n * import { AstroIcon } from '@zendir/ui/react';\n *\n * <AstroIcon name=\"satellite\" />\n * <AstroIcon name=\"antenna\" size=\"large\" />\n * <AstroIcon name=\"thermal\" color=\"#ff0000\" />\n * ```\n */\n\nimport React, { memo, useState, useEffect, useRef } from \"react\";\nimport { useTheme } from \"../../theme\";\nimport { Icon, isValidIconName } from \"./Icon\";\n\n/**\n * All official Astro UXD icon names\n * @see https://www.astrouxds.com/components/icon-library/\n */\nexport type AstroIconName =\n // === Astro Space/Mission Icons (Custom by Rocket Communications) ===\n | \"altitude\"\n | \"antenna\"\n | \"antenna-off\"\n | \"antenna-receive\"\n | \"antenna-transmit\"\n | \"equipment\"\n | \"hardware\"\n | \"mission\"\n | \"netcom\"\n | \"payload\"\n | \"processor\"\n | \"processor-alt\"\n | \"propulsion-power\"\n | \"satellite-off\"\n | \"satellite-receive\"\n | \"satellite-transmit\"\n | \"solar\"\n | \"thermal\"\n // === Actions ===\n | \"settings\"\n | \"search\"\n | \"home\"\n | \"info\"\n | \"help\"\n | \"delete\"\n | \"edit\"\n | \"lock\"\n | \"lock-open\"\n | \"visibility\"\n | \"visibility-off\"\n | \"refresh\"\n | \"sync\"\n | \"download\"\n | \"upload\"\n | \"fullscreen\"\n | \"fullscreen-exit\"\n | \"zoom-in\"\n | \"zoom-out\"\n | \"schedule\"\n | \"timeline\"\n | \"today\"\n | \"event\"\n | \"bookmark\"\n | \"favorite\"\n | \"star\"\n | \"check-circle\"\n | \"done\"\n | \"done-all\"\n | \"print\"\n | \"open-in-new\"\n | \"launch\"\n | \"power-settings-new\"\n | \"history\"\n | \"cached\"\n | \"build\"\n | \"code\"\n | \"dns\"\n | \"language\"\n | \"input\"\n | \"label\"\n | \"list\"\n | \"track-changes\"\n | \"verified-user\"\n | \"work\"\n // === Alerts ===\n | \"add-alert\"\n | \"error\"\n | \"error-outline\"\n | \"notification-important\"\n | \"warning\"\n // === AV ===\n | \"play-arrow\"\n | \"pause\"\n | \"stop\"\n | \"skip-next\"\n | \"skip-previous\"\n | \"fast-forward\"\n | \"fast-rewind\"\n | \"replay\"\n | \"loop\"\n | \"shuffle\"\n | \"volume-up\"\n | \"volume-down\"\n | \"volume-off\"\n | \"volume-mute\"\n | \"mic\"\n | \"mic-off\"\n | \"videocam\"\n | \"videocam-off\"\n | \"movie\"\n | \"music-note\"\n | \"equalizer\"\n | \"library-music\"\n | \"queue-music\"\n | \"subscriptions\"\n | \"fiber-new\"\n | \"fiber-manual-record\"\n | \"fiber-smart-record\"\n // === Communication ===\n | \"call\"\n | \"call-end\"\n | \"call-made\"\n | \"call-received\"\n | \"call-missed\"\n | \"call-split\"\n | \"chat\"\n | \"chat-bubble\"\n | \"comment\"\n | \"contacts\"\n | \"dialer-sip\"\n | \"email\"\n | \"forum\"\n | \"import-export\"\n | \"live-help\"\n | \"location-off\"\n | \"location-on\"\n | \"message\"\n | \"phone\"\n | \"phonelink-erase\"\n | \"phonelink-lock\"\n | \"phonelink-ring\"\n | \"portable-wifi-off\"\n | \"present-to-all\"\n | \"ring-volume\"\n | \"screen-share\"\n | \"speaker-phone\"\n | \"stay-primary-landscape\"\n | \"stay-primary-portrait\"\n | \"stop-screen-share\"\n | \"swap-calls\"\n | \"textsms\"\n | \"voicemail\"\n | \"vpn-key\"\n // === Content ===\n | \"add\"\n | \"add-box\"\n | \"add-circle\"\n | \"add-circle-outline\"\n | \"archive\"\n | \"backspace\"\n | \"block\"\n | \"clear\"\n | \"content-copy\"\n | \"content-cut\"\n | \"content-paste\"\n | \"create\"\n | \"drafts\"\n | \"filter-list\"\n | \"flag\"\n | \"forward\"\n | \"gesture\"\n | \"inbox\"\n | \"link\"\n | \"link-off\"\n | \"low-priority\"\n | \"mail\"\n | \"markunread\"\n | \"move-to-inbox\"\n | \"next-week\"\n | \"redo\"\n | \"remove\"\n | \"remove-circle\"\n | \"remove-circle-outline\"\n | \"reply\"\n | \"reply-all\"\n | \"report\"\n | \"save\"\n | \"select-all\"\n | \"send\"\n | \"sort\"\n | \"text-format\"\n | \"unarchive\"\n | \"undo\"\n | \"weekend\"\n // === Device ===\n | \"access-alarm\"\n | \"access-alarms\"\n | \"access-time\"\n | \"add-alarm\"\n | \"airplanemode-active\"\n | \"airplanemode-inactive\"\n | \"battery-20\"\n | \"battery-30\"\n | \"battery-50\"\n | \"battery-60\"\n | \"battery-80\"\n | \"battery-90\"\n | \"battery-alert\"\n | \"battery-charging-20\"\n | \"battery-charging-30\"\n | \"battery-charging-50\"\n | \"battery-charging-60\"\n | \"battery-charging-80\"\n | \"battery-charging-90\"\n | \"battery-charging-full\"\n | \"battery-full\"\n | \"battery-std\"\n | \"battery-unknown\"\n | \"bluetooth\"\n | \"bluetooth-connected\"\n | \"bluetooth-disabled\"\n | \"bluetooth-searching\"\n | \"brightness-auto\"\n | \"brightness-high\"\n | \"brightness-low\"\n | \"brightness-medium\"\n | \"data-usage\"\n | \"developer-mode\"\n | \"devices\"\n | \"dvr\"\n | \"gps-fixed\"\n | \"gps-not-fixed\"\n | \"gps-off\"\n | \"graphic-eq\"\n | \"location-disabled\"\n | \"location-searching\"\n | \"network-cell\"\n | \"network-wifi\"\n | \"nfc\"\n | \"screen-lock-landscape\"\n | \"screen-lock-portrait\"\n | \"screen-lock-rotation\"\n | \"screen-rotation\"\n | \"sd-storage\"\n | \"settings-system-daydream\"\n | \"signal-cellular-0-bar\"\n | \"signal-cellular-1-bar\"\n | \"signal-cellular-2-bar\"\n | \"signal-cellular-3-bar\"\n | \"signal-cellular-4-bar\"\n | \"signal-cellular-connected-no-internet-0-bar\"\n | \"signal-cellular-connected-no-internet-1-bar\"\n | \"signal-cellular-connected-no-internet-2-bar\"\n | \"signal-cellular-connected-no-internet-3-bar\"\n | \"signal-cellular-connected-no-internet-4-bar\"\n | \"signal-cellular-no-sim\"\n | \"signal-cellular-null\"\n | \"signal-cellular-off\"\n | \"signal-wifi-0-bar\"\n | \"signal-wifi-1-bar\"\n | \"signal-wifi-1-bar-lock\"\n | \"signal-wifi-2-bar\"\n | \"signal-wifi-2-bar-lock\"\n | \"signal-wifi-3-bar\"\n | \"signal-wifi-3-bar-lock\"\n | \"signal-wifi-4-bar\"\n | \"signal-wifi-4-bar-lock\"\n | \"signal-wifi-off\"\n | \"storage\"\n | \"usb\"\n | \"wallpaper\"\n | \"widgets\"\n | \"wifi-lock\"\n | \"wifi-tethering\"\n // === Editor ===\n | \"attach-file\"\n | \"attach-money\"\n | \"border-all\"\n | \"border-bottom\"\n | \"border-clear\"\n | \"border-color\"\n | \"border-horizontal\"\n | \"border-inner\"\n | \"border-left\"\n | \"border-outer\"\n | \"border-right\"\n | \"border-style\"\n | \"border-top\"\n | \"border-vertical\"\n | \"bubble-chart\"\n | \"drag-handle\"\n | \"format-align-center\"\n | \"format-align-justify\"\n | \"format-align-left\"\n | \"format-align-right\"\n | \"format-bold\"\n | \"format-clear\"\n | \"format-color-fill\"\n | \"format-color-reset\"\n | \"format-color-text\"\n | \"format-indent-decrease\"\n | \"format-indent-increase\"\n | \"format-italic\"\n | \"format-line-spacing\"\n | \"format-list-bulleted\"\n | \"format-list-numbered\"\n | \"format-paint\"\n | \"format-quote\"\n | \"format-shapes\"\n | \"format-size\"\n | \"format-strikethrough\"\n | \"format-textdirection-l-to-r\"\n | \"format-textdirection-r-to-l\"\n | \"format-underlined\"\n | \"functions\"\n | \"highlight\"\n | \"insert-chart\"\n | \"insert-comment\"\n | \"insert-drive-file\"\n | \"insert-emoticon\"\n | \"insert-invitation\"\n | \"insert-link\"\n | \"insert-photo\"\n | \"linear-scale\"\n | \"merge-type\"\n | \"mode-comment\"\n | \"mode-edit\"\n | \"monetization-on\"\n | \"money-off\"\n | \"multiline-chart\"\n | \"pie-chart\"\n | \"pie-chart-outlined\"\n | \"publish\"\n | \"short-text\"\n | \"show-chart\"\n | \"space-bar\"\n | \"strikethrough-s\"\n | \"table-chart\"\n | \"text-fields\"\n | \"title\"\n | \"vertical-align-bottom\"\n | \"vertical-align-center\"\n | \"vertical-align-top\"\n | \"wrap-text\"\n // === File ===\n | \"attachment\"\n | \"cloud\"\n | \"cloud-circle\"\n | \"cloud-done\"\n | \"cloud-download\"\n | \"cloud-off\"\n | \"cloud-queue\"\n | \"cloud-upload\"\n | \"create-new-folder\"\n | \"file-download\"\n | \"file-upload\"\n | \"folder\"\n | \"folder-open\"\n | \"folder-shared\"\n // === Hardware ===\n | \"cast\"\n | \"cast-connected\"\n | \"computer\"\n | \"desktop-mac\"\n | \"desktop-windows\"\n | \"developer-board\"\n | \"device-hub\"\n | \"devices-other\"\n | \"dock\"\n | \"gamepad\"\n | \"headset\"\n | \"headset-mic\"\n | \"keyboard\"\n | \"keyboard-arrow-down\"\n | \"keyboard-arrow-left\"\n | \"keyboard-arrow-right\"\n | \"keyboard-arrow-up\"\n | \"keyboard-backspace\"\n | \"keyboard-capslock\"\n | \"keyboard-hide\"\n | \"keyboard-return\"\n | \"keyboard-tab\"\n | \"keyboard-voice\"\n | \"laptop\"\n | \"laptop-chromebook\"\n | \"laptop-mac\"\n | \"laptop-windows\"\n | \"memory\"\n | \"mouse\"\n | \"phone-android\"\n | \"phone-iphone\"\n | \"phonelink\"\n | \"phonelink-off\"\n | \"power-input\"\n | \"router\"\n | \"scanner\"\n | \"security\"\n | \"sim-card\"\n | \"smartphone\"\n | \"speaker\"\n | \"speaker-group\"\n | \"tablet\"\n | \"tablet-android\"\n | \"tablet-mac\"\n | \"toys\"\n | \"tv\"\n | \"videogame-asset\"\n | \"watch\"\n // === Image ===\n | \"add-a-photo\"\n | \"add-to-photos\"\n | \"adjust\"\n | \"assistant\"\n | \"assistant-photo\"\n | \"audiotrack\"\n | \"blur-circular\"\n | \"blur-linear\"\n | \"blur-off\"\n | \"blur-on\"\n | \"brightness-1\"\n | \"brightness-2\"\n | \"brightness-3\"\n | \"brightness-4\"\n | \"brightness-5\"\n | \"brightness-6\"\n | \"brightness-7\"\n | \"broken-image\"\n | \"brush\"\n | \"burst-mode\"\n | \"camera\"\n | \"camera-alt\"\n | \"camera-front\"\n | \"camera-rear\"\n | \"camera-roll\"\n | \"center-focus-strong\"\n | \"center-focus-weak\"\n | \"collections\"\n | \"collections-bookmark\"\n | \"color-lens\"\n | \"colorize\"\n | \"compare\"\n | \"control-point\"\n | \"control-point-duplicate\"\n | \"crop\"\n | \"crop-16-9\"\n | \"crop-3-2\"\n | \"crop-5-4\"\n | \"crop-7-5\"\n | \"crop-din\"\n | \"crop-free\"\n | \"crop-landscape\"\n | \"crop-original\"\n | \"crop-portrait\"\n | \"crop-rotate\"\n | \"crop-square\"\n | \"dehaze\"\n | \"details\"\n | \"edit\"\n | \"exposure\"\n | \"exposure-neg-1\"\n | \"exposure-neg-2\"\n | \"exposure-plus-1\"\n | \"exposure-plus-2\"\n | \"exposure-zero\"\n | \"filter\"\n | \"filter-1\"\n | \"filter-2\"\n | \"filter-3\"\n | \"filter-4\"\n | \"filter-5\"\n | \"filter-6\"\n | \"filter-7\"\n | \"filter-8\"\n | \"filter-9\"\n | \"filter-9-plus\"\n | \"filter-b-and-w\"\n | \"filter-center-focus\"\n | \"filter-drama\"\n | \"filter-frames\"\n | \"filter-hdr\"\n | \"filter-none\"\n | \"filter-tilt-shift\"\n | \"filter-vintage\"\n | \"flare\"\n | \"flash-auto\"\n | \"flash-off\"\n | \"flash-on\"\n | \"flip\"\n | \"gradient\"\n | \"grain\"\n | \"grid-off\"\n | \"grid-on\"\n | \"hdr-off\"\n | \"hdr-on\"\n | \"hdr-strong\"\n | \"hdr-weak\"\n | \"healing\"\n | \"image\"\n | \"image-aspect-ratio\"\n | \"iso\"\n | \"landscape\"\n | \"leak-add\"\n | \"leak-remove\"\n | \"lens\"\n | \"linked-camera\"\n | \"looks\"\n | \"looks-3\"\n | \"looks-4\"\n | \"looks-5\"\n | \"looks-6\"\n | \"looks-one\"\n | \"looks-two\"\n | \"loupe\"\n | \"monochrome-photos\"\n | \"movie-creation\"\n | \"movie-filter\"\n | \"music-note\"\n | \"nature\"\n | \"nature-people\"\n | \"navigate-before\"\n | \"navigate-next\"\n | \"palette\"\n | \"panorama\"\n | \"panorama-fish-eye\"\n | \"panorama-horizontal\"\n | \"panorama-vertical\"\n | \"panorama-wide-angle\"\n | \"photo\"\n | \"photo-album\"\n | \"photo-camera\"\n | \"photo-filter\"\n | \"photo-library\"\n | \"photo-size-select-actual\"\n | \"photo-size-select-large\"\n | \"photo-size-select-small\"\n | \"picture-as-pdf\"\n | \"portrait\"\n | \"remove-red-eye\"\n | \"rotate-90-degrees-ccw\"\n | \"rotate-left\"\n | \"rotate-right\"\n | \"slideshow\"\n | \"straighten\"\n | \"style\"\n | \"switch-camera\"\n | \"switch-video\"\n | \"tag-faces\"\n | \"texture\"\n | \"timelapse\"\n | \"timer\"\n | \"timer-10\"\n | \"timer-3\"\n | \"timer-off\"\n | \"tonality\"\n | \"transform\"\n | \"tune\"\n | \"view-comfy\"\n | \"view-compact\"\n | \"vignette\"\n | \"wb-auto\"\n | \"wb-cloudy\"\n | \"wb-incandescent\"\n | \"wb-iridescent\"\n | \"wb-sunny\"\n // === Maps ===\n | \"add-location\"\n | \"beenhere\"\n | \"directions\"\n | \"directions-bike\"\n | \"directions-boat\"\n | \"directions-bus\"\n | \"directions-car\"\n | \"directions-railway\"\n | \"directions-run\"\n | \"directions-subway\"\n | \"directions-transit\"\n | \"directions-walk\"\n | \"edit-location\"\n | \"ev-station\"\n | \"explore\"\n | \"flight\"\n | \"hotel\"\n | \"layers\"\n | \"layers-clear\"\n | \"local-activity\"\n | \"local-airport\"\n | \"local-atm\"\n | \"local-bar\"\n | \"local-cafe\"\n | \"local-car-wash\"\n | \"local-convenience-store\"\n | \"local-dining\"\n | \"local-drink\"\n | \"local-florist\"\n | \"local-gas-station\"\n | \"local-grocery-store\"\n | \"local-hospital\"\n | \"local-hotel\"\n | \"local-laundry-service\"\n | \"local-library\"\n | \"local-mall\"\n | \"local-movies\"\n | \"local-offer\"\n | \"local-parking\"\n | \"local-pharmacy\"\n | \"local-phone\"\n | \"local-pizza\"\n | \"local-play\"\n | \"local-post-office\"\n | \"local-printshop\"\n | \"local-see\"\n | \"local-shipping\"\n | \"local-taxi\"\n | \"map\"\n | \"my-location\"\n | \"navigation\"\n | \"near-me\"\n | \"person-pin\"\n | \"person-pin-circle\"\n | \"pin-drop\"\n | \"place\"\n | \"rate-review\"\n | \"restaurant\"\n | \"restaurant-menu\"\n | \"satellite\"\n | \"store-mall-directory\"\n | \"streetview\"\n | \"subway\"\n | \"terrain\"\n | \"traffic\"\n | \"train\"\n | \"tram\"\n | \"transfer-within-a-station\"\n | \"zoom-out-map\"\n // === Navigation ===\n | \"apps\"\n | \"arrow-back\"\n | \"arrow-downward\"\n | \"arrow-drop-down\"\n | \"arrow-drop-down-circle\"\n | \"arrow-drop-up\"\n | \"arrow-forward\"\n | \"arrow-upward\"\n | \"cancel\"\n | \"check\"\n | \"chevron-left\"\n | \"chevron-right\"\n | \"close\"\n | \"expand-less\"\n | \"expand-more\"\n | \"first-page\"\n | \"fullscreen\"\n | \"fullscreen-exit\"\n | \"last-page\"\n | \"menu\"\n | \"more-horiz\"\n | \"more-vert\"\n | \"refresh\"\n | \"subdirectory-arrow-left\"\n | \"subdirectory-arrow-right\"\n | \"unfold-less\"\n | \"unfold-more\"\n // === Notification ===\n | \"adb\"\n | \"airline-seat-flat\"\n | \"airline-seat-flat-angled\"\n | \"airline-seat-individual-suite\"\n | \"airline-seat-legroom-extra\"\n | \"airline-seat-legroom-normal\"\n | \"airline-seat-legroom-reduced\"\n | \"airline-seat-recline-extra\"\n | \"airline-seat-recline-normal\"\n | \"bluetooth-audio\"\n | \"confirmation-number\"\n | \"disc-full\"\n | \"do-not-disturb\"\n | \"do-not-disturb-alt\"\n | \"do-not-disturb-off\"\n | \"do-not-disturb-on\"\n | \"drive-eta\"\n | \"enhanced-encryption\"\n | \"event-available\"\n | \"event-busy\"\n | \"event-note\"\n | \"folder-special\"\n | \"live-tv\"\n | \"mms\"\n | \"more\"\n | \"network-check\"\n | \"network-locked\"\n | \"no-encryption\"\n | \"ondemand-video\"\n | \"personal-video\"\n | \"phone-bluetooth-speaker\"\n | \"phone-forwarded\"\n | \"phone-in-talk\"\n | \"phone-locked\"\n | \"phone-missed\"\n | \"phone-paused\"\n | \"power\"\n | \"power-off\"\n | \"priority-high\"\n | \"sd-card\"\n | \"sim-card-alert\"\n | \"sms\"\n | \"sms-failed\"\n | \"sync\"\n | \"sync-disabled\"\n | \"sync-problem\"\n | \"system-update\"\n | \"tap-and-play\"\n | \"time-to-leave\"\n | \"vibration\"\n | \"voice-chat\"\n | \"vpn-lock\"\n | \"wc\"\n | \"wifi\"\n | \"wifi-off\"\n // === Places ===\n | \"ac-unit\"\n | \"airport-shuttle\"\n | \"all-inclusive\"\n | \"beach-access\"\n | \"business-center\"\n | \"casino\"\n | \"child-care\"\n | \"child-friendly\"\n | \"fitness-center\"\n | \"free-breakfast\"\n | \"golf-course\"\n | \"hot-tub\"\n | \"kitchen\"\n | \"pool\"\n | \"room-service\"\n | \"rv-hookup\"\n | \"smoke-free\"\n | \"smoking-rooms\"\n | \"spa\"\n // === Social ===\n | \"cake\"\n | \"domain\"\n | \"group\"\n | \"group-add\"\n | \"location-city\"\n | \"mood\"\n | \"mood-bad\"\n | \"notifications\"\n | \"notifications-active\"\n | \"notifications-none\"\n | \"notifications-off\"\n | \"notifications-paused\"\n | \"pages\"\n | \"party-mode\"\n | \"people\"\n | \"people-outline\"\n | \"person\"\n | \"person-add\"\n | \"person-outline\"\n | \"plus-one\"\n | \"poll\"\n | \"public\"\n | \"school\"\n | \"sentiment-dissatisfied\"\n | \"sentiment-neutral\"\n | \"sentiment-satisfied\"\n | \"sentiment-very-dissatisfied\"\n | \"sentiment-very-satisfied\"\n | \"share\"\n | \"whatshot\"\n // === Toggle ===\n | \"check-box\"\n | \"check-box-outline-blank\"\n | \"indeterminate-check-box\"\n | \"radio-button-checked\"\n | \"radio-button-unchecked\"\n | \"star\"\n | \"star-border\"\n | \"star-half\"\n // === Space Operations Aliases (mapped to existing icons) ===\n // Orbit & Trajectory\n | \"orbit\"\n | \"trajectory\"\n | \"orbital\"\n // Ground Operations\n | \"ground-station\"\n | \"ground-control\"\n | \"dish\"\n | \"tracking-station\"\n // Communication\n | \"uplink\"\n | \"downlink\"\n | \"command\"\n | \"telemetry\"\n | \"comms\"\n | \"rf\"\n | \"link\"\n | \"signal\"\n | \"data-link\"\n // Satellite States\n | \"satellite\"\n | \"spacecraft\"\n | \"vehicle\"\n | \"sat\"\n | \"sc\"\n // Power Systems\n | \"power\"\n | \"battery\"\n | \"energy\"\n | \"solar-array\"\n | \"solar-panel\"\n | \"photovoltaic\"\n // Propulsion\n | \"thruster\"\n | \"engine\"\n | \"burn\"\n | \"maneuver\"\n | \"delta-v\"\n | \"rcs\"\n // Thermal\n | \"temperature\"\n | \"heat\"\n | \"cooling\"\n | \"heater\"\n // Attitude & Control\n | \"attitude\"\n | \"pointing\"\n | \"orientation\"\n | \"adcs\"\n | \"gyro\"\n | \"gyroscope\"\n // Navigation\n | \"gps\"\n | \"gnss\"\n | \"position\"\n | \"location\"\n | \"ephemeris\"\n // Status & Health\n | \"health\"\n | \"status\"\n | \"nominal\"\n | \"anomaly\"\n | \"fault\"\n | \"safe-mode\"\n | \"emergency\"\n | \"critical\"\n | \"caution\"\n // Time & Scheduling\n | \"pass\"\n | \"contact\"\n | \"access\"\n | \"window\"\n | \"aos\"\n | \"los\"\n | \"eclipse\"\n | \"sunlight\"\n | \"shadow\"\n // Subsystems\n | \"subsystem\"\n | \"computer\"\n | \"obc\"\n | \"cdh\"\n | \"flight-computer\"\n | \"sensor\"\n | \"instrument\"\n // Launch & Deployment\n | \"launch\"\n | \"rocket\"\n | \"liftoff\"\n | \"deployment\"\n | \"deploy\"\n | \"separation\"\n // Operations\n | \"ops\"\n | \"operations\"\n | \"control\"\n | \"automation\"\n | \"sequence\"\n | \"procedure\"\n // Data & Storage\n | \"storage\"\n | \"memory\"\n | \"recorder\"\n | \"playback\"\n | \"record\"\n // Monitoring\n | \"monitor\"\n | \"dashboard\"\n | \"console\"\n | \"display\"\n // Crew\n | \"astronaut\"\n | \"crew\"\n | \"eva\"\n // Catch-all for any other icon (flexibility)\n | (string & {});\n\nexport type AstroIconSize = \"extra-small\" | \"small\" | \"normal\" | \"large\";\n\nexport interface AstroIconProps {\n /** Icon name from Astro UXD library */\n name: AstroIconName;\n /** Icon size preset or custom pixel value */\n size?: AstroIconSize | number;\n /** Custom color (hex, rgb, or CSS color) */\n color?: string;\n /** Accessibility label (required for screen readers) */\n label?: string;\n /** Additional CSS class */\n className?: string;\n /** Additional inline styles */\n style?: React.CSSProperties;\n /** Click handler */\n onClick?: () => void;\n /** Test ID for testing */\n \"data-testid\"?: string;\n}\n\n// Size mapping for fallback mode\nconst SIZE_MAP: Record<AstroIconSize, number> = {\n \"extra-small\": 16,\n small: 24,\n normal: 32,\n large: 48,\n};\n\n/**\n * Space Operations Icon Aliases\n * Maps common space terminology to existing Astro icons.\n * Provides better developer experience with intuitive naming.\n */\nconst ICON_ALIASES: Record<string, string> = {\n // === Orbit & Trajectory ===\n orbit: \"360\", // Orbital path\n trajectory: \"360\", // Flight path\n orbital: \"360\", // Orbital mechanics\n\n // === Ground Operations ===\n \"ground-station\": \"antenna\", // Ground station\n \"ground-control\": \"antenna\", // Mission control\n dish: \"antenna\", // Antenna dish\n \"tracking-station\": \"antenna\", // Tracking facility\n\n // === Communication ===\n uplink: \"antenna-transmit\", // Command upload\n downlink: \"antenna-receive\", // Data download\n command: \"antenna-transmit\", // Send command\n telemetry: \"antenna-receive\", // Receive telemetry\n comms: \"netcom\", // Communications\n rf: \"antenna\", // Radio frequency\n link: \"netcom\", // Communication link\n signal: \"antenna-transmit\", // Signal transmission\n \"data-link\": \"netcom\", // Data link\n\n // === Satellite States ===\n satellite: \"satellite-transmit\", // Default satellite (active)\n spacecraft: \"satellite-transmit\", // Spacecraft\n vehicle: \"satellite-transmit\", // Space vehicle\n sat: \"satellite-transmit\", // Abbreviation\n sc: \"satellite-transmit\", // Spacecraft abbreviation\n\n // === Power Systems ===\n power: \"propulsion-power\", // Power system\n battery: \"battery-full\", // Battery status\n energy: \"propulsion-power\", // Energy management\n \"solar-array\": \"solar\", // Solar arrays\n \"solar-panel\": \"solar\", // Solar panels\n photovoltaic: \"solar\", // PV system\n\n // === Propulsion ===\n thruster: \"propulsion-power\", // Thruster\n engine: \"propulsion-power\", // Engine\n burn: \"propulsion-power\", // Burn/maneuver\n maneuver: \"propulsion-power\", // Orbital maneuver\n \"delta-v\": \"propulsion-power\", // Delta-V\n rcs: \"propulsion-power\", // Reaction control system\n\n // === Thermal ===\n temperature: \"thermal\", // Temperature\n heat: \"thermal\", // Heat management\n cooling: \"thermal\", // Cooling system\n heater: \"thermal\", // Heater\n\n // === Attitude & Control ===\n attitude: \"explore\", // Attitude control\n pointing: \"explore\", // Pointing direction\n orientation: \"explore\", // Spacecraft orientation\n adcs: \"explore\", // Attitude determination & control\n gyro: \"explore\", // Gyroscope\n gyroscope: \"explore\", // Gyroscope\n\n // === Navigation ===\n gps: \"gps-fixed\", // GPS/GNSS\n gnss: \"gps-fixed\", // Global navigation\n position: \"gps-fixed\", // Position\n location: \"place\", // Location\n ephemeris: \"timeline\", // Ephemeris data\n\n // === Status & Health ===\n health: \"favorite\", // System health\n status: \"info\", // Status indicator\n nominal: \"check-circle\", // Nominal/OK\n anomaly: \"error\", // Anomaly detected\n fault: \"error\", // Fault condition\n \"safe-mode\": \"warning\", // Safe mode\n emergency: \"warning\", // Emergency\n critical: \"error\", // Critical status\n caution: \"warning\", // Caution\n\n // === Time & Scheduling ===\n pass: \"schedule\", // Satellite pass\n contact: \"schedule\", // Ground contact\n access: \"schedule\", // Access window\n window: \"schedule\", // Time window\n aos: \"schedule\", // Acquisition of signal\n los: \"schedule\", // Loss of signal\n eclipse: \"brightness-3\", // Eclipse period\n sunlight: \"wb-sunny\", // In sunlight\n shadow: \"brightness-3\", // In shadow\n\n // === Subsystems ===\n subsystem: \"developer-board\", // Generic subsystem\n computer: \"memory\", // Onboard computer\n obc: \"memory\", // Onboard computer\n cdh: \"memory\", // Command & data handling\n \"flight-computer\": \"memory\", // Flight computer\n sensor: \"settings-input-component\", // Sensor\n instrument: \"settings-input-component\", // Instrument\n\n // === Launch & Deployment ===\n launch: \"flight-takeoff\", // Launch\n rocket: \"flight-takeoff\", // Rocket\n liftoff: \"flight-takeoff\", // Liftoff\n deployment: \"open-in-new\", // Deployment\n deploy: \"open-in-new\", // Deploy\n separation: \"call-split\", // Stage separation\n\n // === Operations ===\n ops: \"build\", // Operations\n operations: \"build\", // Operations\n control: \"tune\", // Control\n automation: \"autorenew\", // Automation\n sequence: \"playlist-play\", // Command sequence\n procedure: \"list\", // Procedure\n\n // === Data & Storage ===\n storage: \"sd-storage\", // Data storage\n memory: \"memory\", // Memory\n recorder: \"fiber-dvr\", // Data recorder\n playback: \"play-arrow\", // Playback\n record: \"fiber-manual-record\", // Recording\n\n // === Monitoring ===\n monitor: \"desktop-mac\", // Monitoring\n dashboard: \"dashboard\", // Dashboard\n console: \"desktop-windows\", // Console\n display: \"tv\", // Display\n\n // === Crew (if applicable) ===\n astronaut: \"person\", // Astronaut\n crew: \"group\", // Crew\n eva: \"directions-walk\", // Extra-vehicular activity\n};\n\n/**\n * Resolve icon alias to actual Astro icon name\n */\nfunction resolveIconAlias(name: string): string {\n return ICON_ALIASES[name] || name;\n}\n\n/**\n * Get all available icon aliases\n */\nexport function getIconAliases(): Record<string, string> {\n return { ...ICON_ALIASES };\n}\n\n/**\n * Check if an icon name is an alias\n */\nexport function isIconAlias(name: string): boolean {\n return name in ICON_ALIASES;\n}\n\n/**\n * All available Astro UXD icon names (official icons, not aliases)\n * This is the comprehensive list from the Astro UXD icon library\n */\nexport const ASTRO_ICON_NAMES: readonly string[] = [\n // === Astro Space/Mission Icons (Custom by Rocket Communications) ===\n \"altitude\",\n \"antenna\",\n \"antenna-off\",\n \"antenna-receive\",\n \"antenna-transmit\",\n \"equipment\",\n \"hardware\",\n \"mission\",\n \"netcom\",\n \"payload\",\n \"processor\",\n \"processor-alt\",\n \"propulsion-power\",\n \"satellite-off\",\n \"satellite-receive\",\n \"satellite-transmit\",\n \"solar\",\n \"thermal\",\n // === Actions ===\n \"settings\",\n \"search\",\n \"home\",\n \"info\",\n \"help\",\n \"delete\",\n \"edit\",\n \"lock\",\n \"lock-open\",\n \"visibility\",\n \"visibility-off\",\n \"refresh\",\n \"sync\",\n \"download\",\n \"upload\",\n \"fullscreen\",\n \"fullscreen-exit\",\n \"zoom-in\",\n \"zoom-out\",\n \"schedule\",\n \"timeline\",\n \"today\",\n \"event\",\n \"bookmark\",\n \"favorite\",\n \"star\",\n \"check-circle\",\n \"done\",\n \"done-all\",\n \"print\",\n \"open-in-new\",\n \"launch\",\n \"power-settings-new\",\n \"history\",\n \"cached\",\n \"build\",\n \"code\",\n \"dns\",\n \"language\",\n \"input\",\n \"label\",\n \"list\",\n \"track-changes\",\n \"verified-user\",\n \"work\",\n // === Alerts ===\n \"add-alert\",\n \"error\",\n \"error-outline\",\n \"notification-important\",\n \"warning\",\n // === AV ===\n \"play-arrow\",\n \"pause\",\n \"stop\",\n \"skip-next\",\n \"skip-previous\",\n \"fast-forward\",\n \"fast-rewind\",\n \"replay\",\n \"loop\",\n \"shuffle\",\n \"volume-up\",\n \"volume-down\",\n \"volume-off\",\n \"volume-mute\",\n \"mic\",\n \"mic-off\",\n \"videocam\",\n \"videocam-off\",\n \"movie\",\n \"music-note\",\n \"equalizer\",\n \"library-music\",\n \"queue-music\",\n // === Communication ===\n \"call\",\n \"call-end\",\n \"chat\",\n \"chat-bubble\",\n \"chat-bubble-outline\",\n \"comment\",\n \"contacts\",\n \"email\",\n \"mail-outline\",\n \"message\",\n \"phone\",\n \"voicemail\",\n \"vpn-key\",\n \"forum\",\n \"live-help\",\n \"location-on\",\n \"location-off\",\n \"business\",\n \"import-contacts\",\n // === Content ===\n \"add\",\n \"remove\",\n \"add-circle\",\n \"add-circle-outline\",\n \"remove-circle\",\n \"remove-circle-outline\",\n \"clear\",\n \"content-copy\",\n \"content-cut\",\n \"content-paste\",\n \"create\",\n \"flag\",\n \"forward\",\n \"reply\",\n \"reply-all\",\n \"save\",\n \"save-alt\",\n \"select-all\",\n \"send\",\n \"undo\",\n \"redo\",\n \"filter-list\",\n \"sort\",\n \"drafts\",\n \"link\",\n \"link-off\",\n // === Device ===\n \"battery-full\",\n \"battery-charging-full\",\n \"battery-alert\",\n \"battery-unknown\",\n \"bluetooth\",\n \"bluetooth-disabled\",\n \"bluetooth-connected\",\n \"bluetooth-searching\",\n \"brightness-1\",\n \"brightness-2\",\n \"brightness-3\",\n \"brightness-4\",\n \"brightness-5\",\n \"brightness-6\",\n \"brightness-7\",\n \"brightness-auto\",\n \"brightness-high\",\n \"brightness-low\",\n \"brightness-medium\",\n \"gps-fixed\",\n \"gps-not-fixed\",\n \"gps-off\",\n \"graphic-eq\",\n \"network-cell\",\n \"network-wifi\",\n \"nfc\",\n \"screen-rotation\",\n \"sd-storage\",\n \"settings-system-daydream\",\n \"signal-cellular-4-bar\",\n \"signal-cellular-connected-no-internet-4-bar\",\n \"signal-cellular-no-sim\",\n \"signal-cellular-null\",\n \"signal-cellular-off\",\n \"signal-wifi-4-bar\",\n \"signal-wifi-4-bar-lock\",\n \"signal-wifi-off\",\n \"storage\",\n \"usb\",\n \"wifi\",\n \"wifi-lock\",\n \"wifi-off\",\n \"wifi-tethering\",\n // === Editor ===\n \"attach-file\",\n \"attach-money\",\n \"border-all\",\n \"border-bottom\",\n \"border-clear\",\n \"border-color\",\n \"border-horizontal\",\n \"border-inner\",\n \"border-left\",\n \"border-outer\",\n \"border-right\",\n \"border-style\",\n \"border-top\",\n \"border-vertical\",\n \"format-align-center\",\n \"format-align-justify\",\n \"format-align-left\",\n \"format-align-right\",\n \"format-bold\",\n \"format-clear\",\n \"format-color-fill\",\n \"format-color-reset\",\n \"format-color-text\",\n \"format-indent-decrease\",\n \"format-indent-increase\",\n \"format-italic\",\n \"format-line-spacing\",\n \"format-list-bulleted\",\n \"format-list-numbered\",\n \"format-paint\",\n \"format-quote\",\n \"format-size\",\n \"format-strikethrough\",\n \"format-textdirection-l-to-r\",\n \"format-textdirection-r-to-l\",\n \"format-underlined\",\n \"functions\",\n \"insert-chart\",\n \"insert-comment\",\n \"insert-drive-file\",\n \"insert-emoticon\",\n \"insert-invitation\",\n \"insert-link\",\n \"insert-photo\",\n \"merge-type\",\n \"mode-comment\",\n \"mode-edit\",\n \"publish\",\n \"short-text\",\n \"space-bar\",\n \"strikethrough-s\",\n \"text-fields\",\n \"title\",\n \"vertical-align-bottom\",\n \"vertical-align-center\",\n \"vertical-align-top\",\n \"wrap-text\",\n // === File ===\n \"attachment\",\n \"cloud\",\n \"cloud-circle\",\n \"cloud-done\",\n \"cloud-download\",\n \"cloud-off\",\n \"cloud-queue\",\n \"cloud-upload\",\n \"create-new-folder\",\n \"file-download\",\n \"file-upload\",\n \"folder\",\n \"folder-open\",\n \"folder-shared\",\n // === Hardware ===\n \"cast\",\n \"cast-connected\",\n \"computer\",\n \"desktop-mac\",\n \"desktop-windows\",\n \"developer-board\",\n \"device-hub\",\n \"devices-other\",\n \"dock\",\n \"gamepad\",\n \"headset\",\n \"headset-mic\",\n \"keyboard\",\n \"keyboard-arrow-down\",\n \"keyboard-arrow-left\",\n \"keyboard-arrow-right\",\n \"keyboard-arrow-up\",\n \"keyboard-backspace\",\n \"keyboard-capslock\",\n \"keyboard-hide\",\n \"keyboard-return\",\n \"keyboard-tab\",\n \"keyboard-voice\",\n \"laptop\",\n \"laptop-chromebook\",\n \"laptop-mac\",\n \"laptop-windows\",\n \"memory\",\n \"mouse\",\n \"phone-android\",\n \"phone-iphone\",\n \"phonelink\",\n \"phonelink-off\",\n \"power-input\",\n \"router\",\n \"scanner\",\n \"security\",\n \"sim-card\",\n \"smartphone\",\n \"speaker\",\n \"speaker-group\",\n \"tablet\",\n \"tablet-android\",\n \"tablet-mac\",\n \"toys\",\n \"tv\",\n \"watch\",\n // === Image ===\n \"add-a-photo\",\n \"add-photo-alternate\",\n \"add-to-photos\",\n \"adjust\",\n \"brightness-1\",\n \"broken-image\",\n \"brush\",\n \"burst-mode\",\n \"camera\",\n \"camera-alt\",\n \"camera-front\",\n \"camera-rear\",\n \"camera-roll\",\n \"center-focus-strong\",\n \"center-focus-weak\",\n \"collections\",\n \"collections-bookmark\",\n \"color-lens\",\n \"colorize\",\n \"compare\",\n \"control-point\",\n \"control-point-duplicate\",\n \"crop\",\n \"crop-16-9\",\n \"crop-3-2\",\n \"crop-5-4\",\n \"crop-7-5\",\n \"crop-din\",\n \"crop-free\",\n \"crop-landscape\",\n \"crop-original\",\n \"crop-portrait\",\n \"crop-rotate\",\n \"crop-square\",\n \"dehaze\",\n \"details\",\n \"edit\",\n \"exposure\",\n \"exposure-neg-1\",\n \"exposure-neg-2\",\n \"exposure-plus-1\",\n \"exposure-plus-2\",\n \"exposure-zero\",\n \"filter\",\n \"filter-1\",\n \"filter-2\",\n \"filter-3\",\n \"filter-4\",\n \"filter-5\",\n \"filter-6\",\n \"filter-7\",\n \"filter-8\",\n \"filter-9\",\n \"filter-9-plus\",\n \"filter-b-and-w\",\n \"filter-center-focus\",\n \"filter-drama\",\n \"filter-frames\",\n \"filter-hdr\",\n \"filter-none\",\n \"filter-tilt-shift\",\n \"filter-vintage\",\n \"flare\",\n \"flash-auto\",\n \"flash-off\",\n \"flash-on\",\n \"flip\",\n \"gradient\",\n \"grain\",\n \"grid-off\",\n \"grid-on\",\n \"hdr-off\",\n \"hdr-on\",\n \"hdr-strong\",\n \"hdr-weak\",\n \"healing\",\n \"image\",\n \"image-aspect-ratio\",\n \"image-search\",\n \"iso\",\n \"landscape\",\n \"leak-add\",\n \"leak-remove\",\n \"lens\",\n \"linked-camera\",\n \"looks\",\n \"looks-3\",\n \"looks-4\",\n \"looks-5\",\n \"looks-6\",\n \"looks-one\",\n \"looks-two\",\n \"loupe\",\n \"monochrome-photos\",\n \"movie-creation\",\n \"movie-filter\",\n \"music-off\",\n \"music-on\",\n \"navigate-before\",\n \"navigate-next\",\n \"nature\",\n \"nature-people\",\n \"palette\",\n \"panorama\",\n \"panorama-fish-eye\",\n \"panorama-horizontal\",\n \"panorama-vertical\",\n \"panorama-wide-angle\",\n \"photo\",\n \"photo-album\",\n \"photo-camera\",\n \"photo-filter\",\n \"photo-library\",\n \"photo-size-select-actual\",\n \"photo-size-select-large\",\n \"photo-size-select-small\",\n \"picture-as-pdf\",\n \"portrait\",\n \"remove-red-eye\",\n \"rotate-90-degrees-ccw\",\n \"rotate-left\",\n \"rotate-right\",\n \"slideshow\",\n \"straighten\",\n \"style\",\n \"switch-camera\",\n \"switch-video\",\n \"tag-faces\",\n \"texture\",\n \"timelapse\",\n \"timer\",\n \"timer-10\",\n \"timer-3\",\n \"timer-off\",\n \"tonality\",\n \"transform\",\n \"tune\",\n \"view-comfy\",\n \"view-compact\",\n \"vignette\",\n \"wb-auto\",\n \"wb-cloudy\",\n \"wb-incandescent\",\n \"wb-iridescent\",\n \"wb-sunny\",\n // === Maps ===\n \"add-location\",\n \"beenhere\",\n \"directions\",\n \"directions-bike\",\n \"directions-boat\",\n \"directions-bus\",\n \"directions-car\",\n \"directions-railway\",\n \"directions-run\",\n \"directions-subway\",\n \"directions-transit\",\n \"directions-walk\",\n \"edit-location\",\n \"ev-station\",\n \"flight\",\n \"hotel\",\n \"layers\",\n \"layers-clear\",\n \"local-activity\",\n \"local-airport\",\n \"local-atm\",\n \"local-bar\",\n \"local-cafe\",\n \"local-car-wash\",\n \"local-convenience-store\",\n \"local-dining\",\n \"local-drink\",\n \"local-florist\",\n \"local-gas-station\",\n \"local-grocery-store\",\n \"local-hospital\",\n \"local-hotel\",\n \"local-laundry-service\",\n \"local-library\",\n \"local-mall\",\n \"local-movies\",\n \"local-offer\",\n \"local-parking\",\n \"local-pharmacy\",\n \"local-phone\",\n \"local-pizza\",\n \"local-play\",\n \"local-post-office\",\n \"local-printshop\",\n \"local-see\",\n \"local-shipping\",\n \"local-taxi\",\n \"map\",\n \"my-location\",\n \"navigation\",\n \"near-me\",\n \"person-pin\",\n \"person-pin-circle\",\n \"pin-drop\",\n \"place\",\n \"rate-review\",\n \"restaurant\",\n \"restaurant-menu\",\n \"satellite\",\n \"store-mall-directory\",\n \"streetview\",\n \"subway\",\n \"terrain\",\n \"traffic\",\n \"train\",\n \"tram\",\n \"transfer-within-a-station\",\n \"zoom-out-map\",\n // === Navigation ===\n \"apps\",\n \"arrow-back\",\n \"arrow-downward\",\n \"arrow-drop-down\",\n \"arrow-drop-down-circle\",\n \"arrow-drop-up\",\n \"arrow-forward\",\n \"arrow-upward\",\n \"cancel\",\n \"check\",\n \"chevron-left\",\n \"chevron-right\",\n \"close\",\n \"expand-less\",\n \"expand-more\",\n \"first-page\",\n \"last-page\",\n \"menu\",\n \"more-horiz\",\n \"more-vert\",\n \"subdirectory-arrow-left\",\n \"subdirectory-arrow-right\",\n \"unfold-less\",\n \"unfold-more\",\n // === Notification ===\n \"adb\",\n \"airline-seat-flat\",\n \"airline-seat-flat-angled\",\n \"airline-seat-individual-suite\",\n \"airline-seat-legroom-extra\",\n \"airline-seat-legroom-normal\",\n \"airline-seat-legroom-reduced\",\n \"airline-seat-recline-extra\",\n \"airline-seat-recline-normal\",\n \"bluetooth-audio\",\n \"confirmation-number\",\n \"disc-full\",\n \"do-not-disturb\",\n \"do-not-disturb-alt\",\n \"do-not-disturb-off\",\n \"do-not-disturb-on\",\n \"drive-eta\",\n \"enhanced-encryption\",\n \"event-available\",\n \"event-busy\",\n \"event-note\",\n \"folder-special\",\n \"live-tv\",\n \"mms\",\n \"more\",\n \"network-check\",\n \"network-locked\",\n \"no-encryption\",\n \"ondemand-video\",\n \"personal-video\",\n \"phone-bluetooth-speaker\",\n \"phone-callback\",\n \"phone-forwarded\",\n \"phone-in-talk\",\n \"phone-locked\",\n \"phone-missed\",\n \"phone-paused\",\n \"power\",\n \"power-off\",\n \"priority-high\",\n \"sd-card\",\n \"sim-card-alert\",\n \"sms\",\n \"sms-failed\",\n \"sync-disabled\",\n \"sync-problem\",\n \"system-update\",\n \"tap-and-play\",\n \"time-to-leave\",\n \"vibration\",\n \"voice-chat\",\n \"vpn-lock\",\n \"wc\",\n \"wifi\",\n \"notifications\",\n \"notifications-active\",\n \"notifications-none\",\n \"notifications-off\",\n \"notifications-paused\",\n // === Places ===\n \"ac-unit\",\n \"airport-shuttle\",\n \"all-inclusive\",\n \"beach-access\",\n \"business-center\",\n \"casino\",\n \"child-care\",\n \"child-friendly\",\n \"fitness-center\",\n \"free-breakfast\",\n \"golf-course\",\n \"hot-tub\",\n \"kitchen\",\n \"meeting-room\",\n \"no-meeting-room\",\n \"pool\",\n \"room-service\",\n \"rv-hookup\",\n \"smoke-free\",\n \"smoking-rooms\",\n \"spa\",\n // === Social ===\n \"cake\",\n \"domain\",\n \"group\",\n \"group-add\",\n \"location-city\",\n \"mood\",\n \"mood-bad\",\n \"notifications\",\n \"pages\",\n \"party-mode\",\n \"people\",\n \"people-outline\",\n \"person\",\n \"person-add\",\n \"person-outline\",\n \"plus-one\",\n \"poll\",\n \"public\",\n \"school\",\n \"sentiment-dissatisfied\",\n \"sentiment-neutral\",\n \"sentiment-satisfied\",\n \"sentiment-very-dissatisfied\",\n \"sentiment-very-satisfied\",\n \"share\",\n \"thumb-down\",\n \"thumb-up\",\n \"whatshot\",\n // === Toggle ===\n \"check-box\",\n \"check-box-outline-blank\",\n \"indeterminate-check-box\",\n \"radio-button-checked\",\n \"radio-button-unchecked\",\n \"star\",\n \"star-border\",\n \"star-half\",\n // === Additional common icons ===\n \"360\",\n \"autorenew\",\n \"call-split\",\n \"explore\",\n \"extension\",\n \"face\",\n \"feedback\",\n \"fiber-dvr\",\n \"fiber-manual-record\",\n \"fiber-new\",\n \"fiber-pin\",\n \"fiber-smart-record\",\n \"get-app\",\n \"grade\",\n \"highlight-off\",\n \"http\",\n \"https\",\n \"important-devices\",\n \"lightbulb\",\n \"lightbulb-outline\",\n \"perm-camera-mic\",\n \"perm-contact-calendar\",\n \"perm-data-setting\",\n \"perm-device-information\",\n \"perm-identity\",\n \"perm-media\",\n \"perm-phone-msg\",\n \"perm-scan-wifi\",\n \"pets\",\n \"playlist-add\",\n \"playlist-add-check\",\n \"playlist-play\",\n \"pregnant-woman\",\n \"query-builder\",\n \"question-answer\",\n \"receipt\",\n \"record-voice-over\",\n \"redeem\",\n \"report-problem\",\n \"restore\",\n \"restore-page\",\n \"room\",\n \"rounded-corner\",\n \"rowing\",\n \"settings-applications\",\n \"settings-backup-restore\",\n \"settings-bluetooth\",\n \"settings-brightness\",\n \"settings-cell\",\n \"settings-ethernet\",\n \"settings-input-antenna\",\n \"settings-input-component\",\n \"settings-input-composite\",\n \"settings-input-hdmi\",\n \"settings-input-svideo\",\n \"settings-overscan\",\n \"settings-phone\",\n \"settings-power\",\n \"settings-remote\",\n \"settings-voice\",\n \"shop\",\n \"shop-two\",\n \"shopping-basket\",\n \"shopping-cart\",\n \"speaker-notes\",\n \"speaker-notes-off\",\n \"spellcheck\",\n \"stars\",\n \"subject\",\n \"supervisor-account\",\n \"swap-horiz\",\n \"swap-vert\",\n \"swap-vertical-circle\",\n \"system-update-alt\",\n \"tab\",\n \"tab-unselected\",\n \"theaters\",\n \"thumb-down\",\n \"thumb-up\",\n \"thumbs-up-down\",\n \"toc\",\n \"toll\",\n \"touch-app\",\n \"translate\",\n \"trending-down\",\n \"trending-flat\",\n \"trending-up\",\n \"turned-in\",\n \"turned-in-not\",\n \"update\",\n \"view-agenda\",\n \"view-array\",\n \"view-carousel\",\n \"view-column\",\n \"view-day\",\n \"view-headline\",\n \"view-list\",\n \"view-module\",\n \"view-quilt\",\n \"view-stream\",\n \"view-week\",\n \"visibility\",\n \"visibility-off\",\n \"watch-later\",\n \"youtube-searched-for\",\n \"aspect-ratio\",\n \"assignment\",\n \"assignment-ind\",\n \"assignment-late\",\n \"assignment-return\",\n \"assignment-returned\",\n \"assignment-turned-in\",\n \"backup\",\n \"book\",\n \"flight-takeoff\",\n \"flight-land\",\n] as const;\n\n/**\n * Get all available Astro icon names\n */\nexport function getAstroIconNames(): readonly string[] {\n return ASTRO_ICON_NAMES;\n}\n\n/**\n * Get all available icon names including aliases\n */\nexport function getAllIconNames(): {\n icons: readonly string[];\n aliases: Record<string, string>;\n} {\n return {\n icons: ASTRO_ICON_NAMES,\n aliases: ICON_ALIASES,\n };\n}\n\n// Global state for RuxIcon loading with subscription pattern\ntype LoadState = \"pending\" | \"loading\" | \"loaded\" | \"failed\";\nlet loadState: LoadState = \"pending\";\nlet RuxIconComponent: React.ComponentType<any> | null = null;\nconst subscribers = new Set<() => void>();\n\nfunction subscribe(callback: () => void) {\n subscribers.add(callback);\n return () => subscribers.delete(callback);\n}\n\nfunction notifySubscribers() {\n subscribers.forEach((cb) => cb());\n}\n\n/**\n * Safely load RuxIcon from @astrouxds/react\n * Returns null if not available\n */\nasync function loadRuxIcon(): Promise<React.ComponentType<any> | null> {\n if (loadState === \"loaded\") {\n return RuxIconComponent;\n }\n\n if (loadState === \"failed\") {\n return null;\n }\n\n if (loadState === \"loading\") {\n // Wait for the existing load to complete\n return new Promise((resolve) => {\n const unsub = subscribe(() => {\n unsub();\n resolve(RuxIconComponent);\n });\n });\n }\n\n loadState = \"loading\";\n\n try {\n // Dynamic import for tree-shaking and optional dependency\n const astroModule = await import(\"@astrouxds/react\");\n RuxIconComponent = astroModule.RuxIcon;\n loadState = \"loaded\";\n notifySubscribers();\n return RuxIconComponent;\n } catch (err) {\n loadState = \"failed\";\n notifySubscribers();\n return null;\n }\n}\n\n/**\n * Fallback icon component when @astrouxds/react is not installed.\n * Uses built-in Icon SVGs when the name matches, otherwise shows a generic placeholder.\n */\nfunction FallbackIcon({\n name,\n size,\n color,\n label,\n className,\n style,\n onClick,\n \"data-testid\": testId,\n}: AstroIconProps) {\n const { tokens } = useTheme();\n const actualSize =\n typeof size === \"number\" ? size : SIZE_MAP[size || \"normal\"];\n\n if (isValidIconName(name)) {\n return (\n <Icon\n name={name}\n size={actualSize}\n color={color}\n className={className}\n aria-label={label || name}\n onClick={onClick}\n style={style}\n />\n );\n }\n\n return (\n <span\n role=\"img\"\n aria-label={label || name}\n className={className}\n data-testid={testId}\n onClick={onClick}\n tabIndex={onClick ? 0 : undefined}\n onKeyDown={onClick ? (e) => e.key === \"Enter\" && onClick() : undefined}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: actualSize,\n height: actualSize,\n fontSize: actualSize * 0.4,\n fontFamily: tokens.typography.fontFamily.mono,\n fontWeight: 700,\n color: color || tokens.colors.status.off,\n backgroundColor: tokens.colors.background.surface,\n border: `1px solid ${tokens.colors.border.default}`,\n borderRadius: 4,\n cursor: onClick ? \"pointer\" : \"default\",\n userSelect: \"none\",\n ...style,\n }}\n title={`Icon: ${name} (install @astrouxds/react for official icons)`}\n >\n <svg\n width={actualSize * 0.6}\n height={actualSize * 0.6}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <rect\n x=\"3\"\n y=\"3\"\n width=\"18\"\n height=\"18\"\n rx=\"2\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <circle cx=\"12\" cy=\"12\" r=\"2\" fill=\"currentColor\" />\n </svg>\n </span>\n );\n}\n\n/**\n * AstroIcon - Official Astro UXD Icons\n *\n * Displays icons from the official Astro UX Design System.\n * Automatically uses @astrouxds/react if installed, otherwise shows fallback.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <AstroIcon name=\"satellite\" />\n *\n * // With size\n * <AstroIcon name=\"antenna\" size=\"large\" />\n * <AstroIcon name=\"thermal\" size={48} />\n *\n * // With color\n * <AstroIcon name=\"warning\" color=\"var(--zendir-status-caution)\" />\n *\n * // With click handler\n * <AstroIcon name=\"settings\" onClick={() => openSettings()} />\n * ```\n */\nexport const AstroIcon = memo(function AstroIcon(props: AstroIconProps) {\n const {\n name,\n size = \"normal\",\n color,\n label,\n className,\n style,\n onClick,\n \"data-testid\": testId,\n } = props;\n\n const [, forceUpdate] = useState(0);\n const [currentState, setCurrentState] = useState(loadState);\n const mountedRef = useRef(true);\n\n // Subscribe to load state changes and trigger loading\n useEffect(() => {\n mountedRef.current = true;\n\n // Subscribe to state changes\n const unsubscribe = subscribe(() => {\n if (mountedRef.current) {\n setCurrentState(loadState);\n forceUpdate((n) => n + 1);\n }\n });\n\n // Trigger load if not yet started\n if (loadState === \"pending\") {\n loadRuxIcon();\n }\n\n return () => {\n mountedRef.current = false;\n unsubscribe();\n };\n }, []);\n\n // If still loading, show a subtle placeholder\n if (currentState === \"pending\" || currentState === \"loading\") {\n const actualSize = typeof size === \"number\" ? size : SIZE_MAP[size];\n return (\n <span\n style={{\n display: \"inline-block\",\n width: actualSize,\n height: actualSize,\n ...style,\n }}\n className={className}\n aria-hidden=\"true\"\n />\n );\n }\n\n // Resolve icon alias to actual Astro icon name\n const resolvedName = resolveIconAlias(name);\n\n // If @astrouxds/react is available, use official RuxIcon\n if (RuxIconComponent) {\n const RuxIcon = RuxIconComponent;\n const pixelSize = typeof size === \"number\" ? size : SIZE_MAP[size];\n\n // Map numeric size to closest Astro size preset for RuxIcon\n // This helps RuxIcon render at approximately the right size before CSS kicks in\n const getClosestAstroSize = (px: number): AstroIconSize => {\n if (px <= 18) return \"extra-small\"; // 16px\n if (px <= 28) return \"small\"; // 24px\n if (px <= 40) return \"normal\"; // 32px\n return \"large\"; // 48px\n };\n const astroSize =\n typeof size === \"number\" ? getClosestAstroSize(size) : size;\n\n // Default to off/grey color if no color specified\n const iconColor = color || \"var(--zendir-status-off, #a4abb6)\";\n\n return (\n <span\n role=\"img\"\n aria-label={label || name}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: pixelSize,\n height: pixelSize,\n minWidth: pixelSize,\n minHeight: pixelSize,\n flexShrink: 0,\n // Don't use overflow:hidden - it clips the icon SVG\n ...style,\n }}\n className={className}\n >\n <RuxIcon\n icon={resolvedName}\n size={astroSize}\n label={label || name}\n data-testid={testId}\n onClick={onClick}\n style={\n {\n // Force the RuxIcon to respect our exact pixel size\n \"--iconDefaultSize\": `${pixelSize}px`,\n \"--iconSize\": `${pixelSize}px`,\n \"--size\": `${pixelSize}px`,\n color: iconColor,\n width: `${pixelSize}px`,\n height: `${pixelSize}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n ...(onClick && { cursor: \"pointer\" }),\n } as React.CSSProperties\n }\n />\n </span>\n );\n }\n\n // Fallback when @astrouxds/react is not installed\n return <FallbackIcon {...props} name={resolvedName} />;\n});\n\n/**\n * Check if @astrouxds/react is available\n * Useful for conditional rendering or feature detection\n */\nexport function isAstroIconsAvailable(): boolean {\n return loadState === \"loaded\" && RuxIconComponent !== null;\n}\n\n/**\n * Preload the Astro icons module\n * Call this early in your app to ensure icons are ready\n */\nexport async function preloadAstroIcons(): Promise<boolean> {\n const component = await loadRuxIcon();\n return component !== null;\n}\n\nexport default AstroIcon;\n"],"mappings":"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"}
1
+ {"version":3,"file":"AstroIcon.js","names":[],"sources":["../../../../src/react/core/display/AstroIcon.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - AstroIcon Component\r\n *\r\n * Wrapper around official @astrouxds/react RuxIcon component.\r\n * Provides all 400+ official Astro UXD icons with consistent API.\r\n *\r\n * SECURITY: Uses dynamic import with proper error handling.\r\n * FLEXIBILITY: Works with or without @astrouxds/react installed.\r\n *\r\n * @see https://www.astrouxds.com/components/icon-library/\r\n *\r\n * @example\r\n * ```tsx\r\n * import { AstroIcon } from '@zendir/ui/react';\r\n *\r\n * <AstroIcon name=\"satellite\" />\r\n * <AstroIcon name=\"antenna\" size=\"large\" />\r\n * <AstroIcon name=\"thermal\" color=\"#ff0000\" />\r\n * ```\r\n */\r\n\r\nimport React, { memo, useState, useEffect, useRef } from \"react\";\r\nimport { useTheme } from \"../../theme\";\r\nimport { Icon, isValidIconName } from \"./Icon\";\r\n\r\n/**\r\n * All official Astro UXD icon names\r\n * @see https://www.astrouxds.com/components/icon-library/\r\n */\r\nexport type AstroIconName =\r\n // === Astro Space/Mission Icons (Custom by Rocket Communications) ===\r\n | \"altitude\"\r\n | \"antenna\"\r\n | \"antenna-off\"\r\n | \"antenna-receive\"\r\n | \"antenna-transmit\"\r\n | \"equipment\"\r\n | \"hardware\"\r\n | \"mission\"\r\n | \"netcom\"\r\n | \"payload\"\r\n | \"processor\"\r\n | \"processor-alt\"\r\n | \"propulsion-power\"\r\n | \"satellite-off\"\r\n | \"satellite-receive\"\r\n | \"satellite-transmit\"\r\n | \"solar\"\r\n | \"thermal\"\r\n // === Actions ===\r\n | \"settings\"\r\n | \"search\"\r\n | \"home\"\r\n | \"info\"\r\n | \"help\"\r\n | \"delete\"\r\n | \"edit\"\r\n | \"lock\"\r\n | \"lock-open\"\r\n | \"visibility\"\r\n | \"visibility-off\"\r\n | \"refresh\"\r\n | \"sync\"\r\n | \"download\"\r\n | \"upload\"\r\n | \"fullscreen\"\r\n | \"fullscreen-exit\"\r\n | \"zoom-in\"\r\n | \"zoom-out\"\r\n | \"schedule\"\r\n | \"timeline\"\r\n | \"today\"\r\n | \"event\"\r\n | \"bookmark\"\r\n | \"favorite\"\r\n | \"star\"\r\n | \"check-circle\"\r\n | \"done\"\r\n | \"done-all\"\r\n | \"print\"\r\n | \"open-in-new\"\r\n | \"launch\"\r\n | \"power-settings-new\"\r\n | \"history\"\r\n | \"cached\"\r\n | \"build\"\r\n | \"code\"\r\n | \"dns\"\r\n | \"language\"\r\n | \"input\"\r\n | \"label\"\r\n | \"list\"\r\n | \"track-changes\"\r\n | \"verified-user\"\r\n | \"work\"\r\n // === Alerts ===\r\n | \"add-alert\"\r\n | \"error\"\r\n | \"error-outline\"\r\n | \"notification-important\"\r\n | \"warning\"\r\n // === AV ===\r\n | \"play-arrow\"\r\n | \"pause\"\r\n | \"stop\"\r\n | \"skip-next\"\r\n | \"skip-previous\"\r\n | \"fast-forward\"\r\n | \"fast-rewind\"\r\n | \"replay\"\r\n | \"loop\"\r\n | \"shuffle\"\r\n | \"volume-up\"\r\n | \"volume-down\"\r\n | \"volume-off\"\r\n | \"volume-mute\"\r\n | \"mic\"\r\n | \"mic-off\"\r\n | \"videocam\"\r\n | \"videocam-off\"\r\n | \"movie\"\r\n | \"music-note\"\r\n | \"equalizer\"\r\n | \"library-music\"\r\n | \"queue-music\"\r\n | \"subscriptions\"\r\n | \"fiber-new\"\r\n | \"fiber-manual-record\"\r\n | \"fiber-smart-record\"\r\n // === Communication ===\r\n | \"call\"\r\n | \"call-end\"\r\n | \"call-made\"\r\n | \"call-received\"\r\n | \"call-missed\"\r\n | \"call-split\"\r\n | \"chat\"\r\n | \"chat-bubble\"\r\n | \"comment\"\r\n | \"contacts\"\r\n | \"dialer-sip\"\r\n | \"email\"\r\n | \"forum\"\r\n | \"import-export\"\r\n | \"live-help\"\r\n | \"location-off\"\r\n | \"location-on\"\r\n | \"message\"\r\n | \"phone\"\r\n | \"phonelink-erase\"\r\n | \"phonelink-lock\"\r\n | \"phonelink-ring\"\r\n | \"portable-wifi-off\"\r\n | \"present-to-all\"\r\n | \"ring-volume\"\r\n | \"screen-share\"\r\n | \"speaker-phone\"\r\n | \"stay-primary-landscape\"\r\n | \"stay-primary-portrait\"\r\n | \"stop-screen-share\"\r\n | \"swap-calls\"\r\n | \"textsms\"\r\n | \"voicemail\"\r\n | \"vpn-key\"\r\n // === Content ===\r\n | \"add\"\r\n | \"add-box\"\r\n | \"add-circle\"\r\n | \"add-circle-outline\"\r\n | \"archive\"\r\n | \"backspace\"\r\n | \"block\"\r\n | \"clear\"\r\n | \"content-copy\"\r\n | \"content-cut\"\r\n | \"content-paste\"\r\n | \"create\"\r\n | \"drafts\"\r\n | \"filter-list\"\r\n | \"flag\"\r\n | \"forward\"\r\n | \"gesture\"\r\n | \"inbox\"\r\n | \"link\"\r\n | \"link-off\"\r\n | \"low-priority\"\r\n | \"mail\"\r\n | \"markunread\"\r\n | \"move-to-inbox\"\r\n | \"next-week\"\r\n | \"redo\"\r\n | \"remove\"\r\n | \"remove-circle\"\r\n | \"remove-circle-outline\"\r\n | \"reply\"\r\n | \"reply-all\"\r\n | \"report\"\r\n | \"save\"\r\n | \"select-all\"\r\n | \"send\"\r\n | \"sort\"\r\n | \"text-format\"\r\n | \"unarchive\"\r\n | \"undo\"\r\n | \"weekend\"\r\n // === Device ===\r\n | \"access-alarm\"\r\n | \"access-alarms\"\r\n | \"access-time\"\r\n | \"add-alarm\"\r\n | \"airplanemode-active\"\r\n | \"airplanemode-inactive\"\r\n | \"battery-20\"\r\n | \"battery-30\"\r\n | \"battery-50\"\r\n | \"battery-60\"\r\n | \"battery-80\"\r\n | \"battery-90\"\r\n | \"battery-alert\"\r\n | \"battery-charging-20\"\r\n | \"battery-charging-30\"\r\n | \"battery-charging-50\"\r\n | \"battery-charging-60\"\r\n | \"battery-charging-80\"\r\n | \"battery-charging-90\"\r\n | \"battery-charging-full\"\r\n | \"battery-full\"\r\n | \"battery-std\"\r\n | \"battery-unknown\"\r\n | \"bluetooth\"\r\n | \"bluetooth-connected\"\r\n | \"bluetooth-disabled\"\r\n | \"bluetooth-searching\"\r\n | \"brightness-auto\"\r\n | \"brightness-high\"\r\n | \"brightness-low\"\r\n | \"brightness-medium\"\r\n | \"data-usage\"\r\n | \"developer-mode\"\r\n | \"devices\"\r\n | \"dvr\"\r\n | \"gps-fixed\"\r\n | \"gps-not-fixed\"\r\n | \"gps-off\"\r\n | \"graphic-eq\"\r\n | \"location-disabled\"\r\n | \"location-searching\"\r\n | \"network-cell\"\r\n | \"network-wifi\"\r\n | \"nfc\"\r\n | \"screen-lock-landscape\"\r\n | \"screen-lock-portrait\"\r\n | \"screen-lock-rotation\"\r\n | \"screen-rotation\"\r\n | \"sd-storage\"\r\n | \"settings-system-daydream\"\r\n | \"signal-cellular-0-bar\"\r\n | \"signal-cellular-1-bar\"\r\n | \"signal-cellular-2-bar\"\r\n | \"signal-cellular-3-bar\"\r\n | \"signal-cellular-4-bar\"\r\n | \"signal-cellular-connected-no-internet-0-bar\"\r\n | \"signal-cellular-connected-no-internet-1-bar\"\r\n | \"signal-cellular-connected-no-internet-2-bar\"\r\n | \"signal-cellular-connected-no-internet-3-bar\"\r\n | \"signal-cellular-connected-no-internet-4-bar\"\r\n | \"signal-cellular-no-sim\"\r\n | \"signal-cellular-null\"\r\n | \"signal-cellular-off\"\r\n | \"signal-wifi-0-bar\"\r\n | \"signal-wifi-1-bar\"\r\n | \"signal-wifi-1-bar-lock\"\r\n | \"signal-wifi-2-bar\"\r\n | \"signal-wifi-2-bar-lock\"\r\n | \"signal-wifi-3-bar\"\r\n | \"signal-wifi-3-bar-lock\"\r\n | \"signal-wifi-4-bar\"\r\n | \"signal-wifi-4-bar-lock\"\r\n | \"signal-wifi-off\"\r\n | \"storage\"\r\n | \"usb\"\r\n | \"wallpaper\"\r\n | \"widgets\"\r\n | \"wifi-lock\"\r\n | \"wifi-tethering\"\r\n // === Editor ===\r\n | \"attach-file\"\r\n | \"attach-money\"\r\n | \"border-all\"\r\n | \"border-bottom\"\r\n | \"border-clear\"\r\n | \"border-color\"\r\n | \"border-horizontal\"\r\n | \"border-inner\"\r\n | \"border-left\"\r\n | \"border-outer\"\r\n | \"border-right\"\r\n | \"border-style\"\r\n | \"border-top\"\r\n | \"border-vertical\"\r\n | \"bubble-chart\"\r\n | \"drag-handle\"\r\n | \"format-align-center\"\r\n | \"format-align-justify\"\r\n | \"format-align-left\"\r\n | \"format-align-right\"\r\n | \"format-bold\"\r\n | \"format-clear\"\r\n | \"format-color-fill\"\r\n | \"format-color-reset\"\r\n | \"format-color-text\"\r\n | \"format-indent-decrease\"\r\n | \"format-indent-increase\"\r\n | \"format-italic\"\r\n | \"format-line-spacing\"\r\n | \"format-list-bulleted\"\r\n | \"format-list-numbered\"\r\n | \"format-paint\"\r\n | \"format-quote\"\r\n | \"format-shapes\"\r\n | \"format-size\"\r\n | \"format-strikethrough\"\r\n | \"format-textdirection-l-to-r\"\r\n | \"format-textdirection-r-to-l\"\r\n | \"format-underlined\"\r\n | \"functions\"\r\n | \"highlight\"\r\n | \"insert-chart\"\r\n | \"insert-comment\"\r\n | \"insert-drive-file\"\r\n | \"insert-emoticon\"\r\n | \"insert-invitation\"\r\n | \"insert-link\"\r\n | \"insert-photo\"\r\n | \"linear-scale\"\r\n | \"merge-type\"\r\n | \"mode-comment\"\r\n | \"mode-edit\"\r\n | \"monetization-on\"\r\n | \"money-off\"\r\n | \"multiline-chart\"\r\n | \"pie-chart\"\r\n | \"pie-chart-outlined\"\r\n | \"publish\"\r\n | \"short-text\"\r\n | \"show-chart\"\r\n | \"space-bar\"\r\n | \"strikethrough-s\"\r\n | \"table-chart\"\r\n | \"text-fields\"\r\n | \"title\"\r\n | \"vertical-align-bottom\"\r\n | \"vertical-align-center\"\r\n | \"vertical-align-top\"\r\n | \"wrap-text\"\r\n // === File ===\r\n | \"attachment\"\r\n | \"cloud\"\r\n | \"cloud-circle\"\r\n | \"cloud-done\"\r\n | \"cloud-download\"\r\n | \"cloud-off\"\r\n | \"cloud-queue\"\r\n | \"cloud-upload\"\r\n | \"create-new-folder\"\r\n | \"file-download\"\r\n | \"file-upload\"\r\n | \"folder\"\r\n | \"folder-open\"\r\n | \"folder-shared\"\r\n // === Hardware ===\r\n | \"cast\"\r\n | \"cast-connected\"\r\n | \"computer\"\r\n | \"desktop-mac\"\r\n | \"desktop-windows\"\r\n | \"developer-board\"\r\n | \"device-hub\"\r\n | \"devices-other\"\r\n | \"dock\"\r\n | \"gamepad\"\r\n | \"headset\"\r\n | \"headset-mic\"\r\n | \"keyboard\"\r\n | \"keyboard-arrow-down\"\r\n | \"keyboard-arrow-left\"\r\n | \"keyboard-arrow-right\"\r\n | \"keyboard-arrow-up\"\r\n | \"keyboard-backspace\"\r\n | \"keyboard-capslock\"\r\n | \"keyboard-hide\"\r\n | \"keyboard-return\"\r\n | \"keyboard-tab\"\r\n | \"keyboard-voice\"\r\n | \"laptop\"\r\n | \"laptop-chromebook\"\r\n | \"laptop-mac\"\r\n | \"laptop-windows\"\r\n | \"memory\"\r\n | \"mouse\"\r\n | \"phone-android\"\r\n | \"phone-iphone\"\r\n | \"phonelink\"\r\n | \"phonelink-off\"\r\n | \"power-input\"\r\n | \"router\"\r\n | \"scanner\"\r\n | \"security\"\r\n | \"sim-card\"\r\n | \"smartphone\"\r\n | \"speaker\"\r\n | \"speaker-group\"\r\n | \"tablet\"\r\n | \"tablet-android\"\r\n | \"tablet-mac\"\r\n | \"toys\"\r\n | \"tv\"\r\n | \"videogame-asset\"\r\n | \"watch\"\r\n // === Image ===\r\n | \"add-a-photo\"\r\n | \"add-to-photos\"\r\n | \"adjust\"\r\n | \"assistant\"\r\n | \"assistant-photo\"\r\n | \"audiotrack\"\r\n | \"blur-circular\"\r\n | \"blur-linear\"\r\n | \"blur-off\"\r\n | \"blur-on\"\r\n | \"brightness-1\"\r\n | \"brightness-2\"\r\n | \"brightness-3\"\r\n | \"brightness-4\"\r\n | \"brightness-5\"\r\n | \"brightness-6\"\r\n | \"brightness-7\"\r\n | \"broken-image\"\r\n | \"brush\"\r\n | \"burst-mode\"\r\n | \"camera\"\r\n | \"camera-alt\"\r\n | \"camera-front\"\r\n | \"camera-rear\"\r\n | \"camera-roll\"\r\n | \"center-focus-strong\"\r\n | \"center-focus-weak\"\r\n | \"collections\"\r\n | \"collections-bookmark\"\r\n | \"color-lens\"\r\n | \"colorize\"\r\n | \"compare\"\r\n | \"control-point\"\r\n | \"control-point-duplicate\"\r\n | \"crop\"\r\n | \"crop-16-9\"\r\n | \"crop-3-2\"\r\n | \"crop-5-4\"\r\n | \"crop-7-5\"\r\n | \"crop-din\"\r\n | \"crop-free\"\r\n | \"crop-landscape\"\r\n | \"crop-original\"\r\n | \"crop-portrait\"\r\n | \"crop-rotate\"\r\n | \"crop-square\"\r\n | \"dehaze\"\r\n | \"details\"\r\n | \"edit\"\r\n | \"exposure\"\r\n | \"exposure-neg-1\"\r\n | \"exposure-neg-2\"\r\n | \"exposure-plus-1\"\r\n | \"exposure-plus-2\"\r\n | \"exposure-zero\"\r\n | \"filter\"\r\n | \"filter-1\"\r\n | \"filter-2\"\r\n | \"filter-3\"\r\n | \"filter-4\"\r\n | \"filter-5\"\r\n | \"filter-6\"\r\n | \"filter-7\"\r\n | \"filter-8\"\r\n | \"filter-9\"\r\n | \"filter-9-plus\"\r\n | \"filter-b-and-w\"\r\n | \"filter-center-focus\"\r\n | \"filter-drama\"\r\n | \"filter-frames\"\r\n | \"filter-hdr\"\r\n | \"filter-none\"\r\n | \"filter-tilt-shift\"\r\n | \"filter-vintage\"\r\n | \"flare\"\r\n | \"flash-auto\"\r\n | \"flash-off\"\r\n | \"flash-on\"\r\n | \"flip\"\r\n | \"gradient\"\r\n | \"grain\"\r\n | \"grid-off\"\r\n | \"grid-on\"\r\n | \"hdr-off\"\r\n | \"hdr-on\"\r\n | \"hdr-strong\"\r\n | \"hdr-weak\"\r\n | \"healing\"\r\n | \"image\"\r\n | \"image-aspect-ratio\"\r\n | \"iso\"\r\n | \"landscape\"\r\n | \"leak-add\"\r\n | \"leak-remove\"\r\n | \"lens\"\r\n | \"linked-camera\"\r\n | \"looks\"\r\n | \"looks-3\"\r\n | \"looks-4\"\r\n | \"looks-5\"\r\n | \"looks-6\"\r\n | \"looks-one\"\r\n | \"looks-two\"\r\n | \"loupe\"\r\n | \"monochrome-photos\"\r\n | \"movie-creation\"\r\n | \"movie-filter\"\r\n | \"music-note\"\r\n | \"nature\"\r\n | \"nature-people\"\r\n | \"navigate-before\"\r\n | \"navigate-next\"\r\n | \"palette\"\r\n | \"panorama\"\r\n | \"panorama-fish-eye\"\r\n | \"panorama-horizontal\"\r\n | \"panorama-vertical\"\r\n | \"panorama-wide-angle\"\r\n | \"photo\"\r\n | \"photo-album\"\r\n | \"photo-camera\"\r\n | \"photo-filter\"\r\n | \"photo-library\"\r\n | \"photo-size-select-actual\"\r\n | \"photo-size-select-large\"\r\n | \"photo-size-select-small\"\r\n | \"picture-as-pdf\"\r\n | \"portrait\"\r\n | \"remove-red-eye\"\r\n | \"rotate-90-degrees-ccw\"\r\n | \"rotate-left\"\r\n | \"rotate-right\"\r\n | \"slideshow\"\r\n | \"straighten\"\r\n | \"style\"\r\n | \"switch-camera\"\r\n | \"switch-video\"\r\n | \"tag-faces\"\r\n | \"texture\"\r\n | \"timelapse\"\r\n | \"timer\"\r\n | \"timer-10\"\r\n | \"timer-3\"\r\n | \"timer-off\"\r\n | \"tonality\"\r\n | \"transform\"\r\n | \"tune\"\r\n | \"view-comfy\"\r\n | \"view-compact\"\r\n | \"vignette\"\r\n | \"wb-auto\"\r\n | \"wb-cloudy\"\r\n | \"wb-incandescent\"\r\n | \"wb-iridescent\"\r\n | \"wb-sunny\"\r\n // === Maps ===\r\n | \"add-location\"\r\n | \"beenhere\"\r\n | \"directions\"\r\n | \"directions-bike\"\r\n | \"directions-boat\"\r\n | \"directions-bus\"\r\n | \"directions-car\"\r\n | \"directions-railway\"\r\n | \"directions-run\"\r\n | \"directions-subway\"\r\n | \"directions-transit\"\r\n | \"directions-walk\"\r\n | \"edit-location\"\r\n | \"ev-station\"\r\n | \"explore\"\r\n | \"flight\"\r\n | \"hotel\"\r\n | \"layers\"\r\n | \"layers-clear\"\r\n | \"local-activity\"\r\n | \"local-airport\"\r\n | \"local-atm\"\r\n | \"local-bar\"\r\n | \"local-cafe\"\r\n | \"local-car-wash\"\r\n | \"local-convenience-store\"\r\n | \"local-dining\"\r\n | \"local-drink\"\r\n | \"local-florist\"\r\n | \"local-gas-station\"\r\n | \"local-grocery-store\"\r\n | \"local-hospital\"\r\n | \"local-hotel\"\r\n | \"local-laundry-service\"\r\n | \"local-library\"\r\n | \"local-mall\"\r\n | \"local-movies\"\r\n | \"local-offer\"\r\n | \"local-parking\"\r\n | \"local-pharmacy\"\r\n | \"local-phone\"\r\n | \"local-pizza\"\r\n | \"local-play\"\r\n | \"local-post-office\"\r\n | \"local-printshop\"\r\n | \"local-see\"\r\n | \"local-shipping\"\r\n | \"local-taxi\"\r\n | \"map\"\r\n | \"my-location\"\r\n | \"navigation\"\r\n | \"near-me\"\r\n | \"person-pin\"\r\n | \"person-pin-circle\"\r\n | \"pin-drop\"\r\n | \"place\"\r\n | \"rate-review\"\r\n | \"restaurant\"\r\n | \"restaurant-menu\"\r\n | \"satellite\"\r\n | \"store-mall-directory\"\r\n | \"streetview\"\r\n | \"subway\"\r\n | \"terrain\"\r\n | \"traffic\"\r\n | \"train\"\r\n | \"tram\"\r\n | \"transfer-within-a-station\"\r\n | \"zoom-out-map\"\r\n // === Navigation ===\r\n | \"apps\"\r\n | \"arrow-back\"\r\n | \"arrow-downward\"\r\n | \"arrow-drop-down\"\r\n | \"arrow-drop-down-circle\"\r\n | \"arrow-drop-up\"\r\n | \"arrow-forward\"\r\n | \"arrow-upward\"\r\n | \"cancel\"\r\n | \"check\"\r\n | \"chevron-left\"\r\n | \"chevron-right\"\r\n | \"close\"\r\n | \"expand-less\"\r\n | \"expand-more\"\r\n | \"first-page\"\r\n | \"fullscreen\"\r\n | \"fullscreen-exit\"\r\n | \"last-page\"\r\n | \"menu\"\r\n | \"more-horiz\"\r\n | \"more-vert\"\r\n | \"refresh\"\r\n | \"subdirectory-arrow-left\"\r\n | \"subdirectory-arrow-right\"\r\n | \"unfold-less\"\r\n | \"unfold-more\"\r\n // === Notification ===\r\n | \"adb\"\r\n | \"airline-seat-flat\"\r\n | \"airline-seat-flat-angled\"\r\n | \"airline-seat-individual-suite\"\r\n | \"airline-seat-legroom-extra\"\r\n | \"airline-seat-legroom-normal\"\r\n | \"airline-seat-legroom-reduced\"\r\n | \"airline-seat-recline-extra\"\r\n | \"airline-seat-recline-normal\"\r\n | \"bluetooth-audio\"\r\n | \"confirmation-number\"\r\n | \"disc-full\"\r\n | \"do-not-disturb\"\r\n | \"do-not-disturb-alt\"\r\n | \"do-not-disturb-off\"\r\n | \"do-not-disturb-on\"\r\n | \"drive-eta\"\r\n | \"enhanced-encryption\"\r\n | \"event-available\"\r\n | \"event-busy\"\r\n | \"event-note\"\r\n | \"folder-special\"\r\n | \"live-tv\"\r\n | \"mms\"\r\n | \"more\"\r\n | \"network-check\"\r\n | \"network-locked\"\r\n | \"no-encryption\"\r\n | \"ondemand-video\"\r\n | \"personal-video\"\r\n | \"phone-bluetooth-speaker\"\r\n | \"phone-forwarded\"\r\n | \"phone-in-talk\"\r\n | \"phone-locked\"\r\n | \"phone-missed\"\r\n | \"phone-paused\"\r\n | \"power\"\r\n | \"power-off\"\r\n | \"priority-high\"\r\n | \"sd-card\"\r\n | \"sim-card-alert\"\r\n | \"sms\"\r\n | \"sms-failed\"\r\n | \"sync\"\r\n | \"sync-disabled\"\r\n | \"sync-problem\"\r\n | \"system-update\"\r\n | \"tap-and-play\"\r\n | \"time-to-leave\"\r\n | \"vibration\"\r\n | \"voice-chat\"\r\n | \"vpn-lock\"\r\n | \"wc\"\r\n | \"wifi\"\r\n | \"wifi-off\"\r\n // === Places ===\r\n | \"ac-unit\"\r\n | \"airport-shuttle\"\r\n | \"all-inclusive\"\r\n | \"beach-access\"\r\n | \"business-center\"\r\n | \"casino\"\r\n | \"child-care\"\r\n | \"child-friendly\"\r\n | \"fitness-center\"\r\n | \"free-breakfast\"\r\n | \"golf-course\"\r\n | \"hot-tub\"\r\n | \"kitchen\"\r\n | \"pool\"\r\n | \"room-service\"\r\n | \"rv-hookup\"\r\n | \"smoke-free\"\r\n | \"smoking-rooms\"\r\n | \"spa\"\r\n // === Social ===\r\n | \"cake\"\r\n | \"domain\"\r\n | \"group\"\r\n | \"group-add\"\r\n | \"location-city\"\r\n | \"mood\"\r\n | \"mood-bad\"\r\n | \"notifications\"\r\n | \"notifications-active\"\r\n | \"notifications-none\"\r\n | \"notifications-off\"\r\n | \"notifications-paused\"\r\n | \"pages\"\r\n | \"party-mode\"\r\n | \"people\"\r\n | \"people-outline\"\r\n | \"person\"\r\n | \"person-add\"\r\n | \"person-outline\"\r\n | \"plus-one\"\r\n | \"poll\"\r\n | \"public\"\r\n | \"school\"\r\n | \"sentiment-dissatisfied\"\r\n | \"sentiment-neutral\"\r\n | \"sentiment-satisfied\"\r\n | \"sentiment-very-dissatisfied\"\r\n | \"sentiment-very-satisfied\"\r\n | \"share\"\r\n | \"whatshot\"\r\n // === Toggle ===\r\n | \"check-box\"\r\n | \"check-box-outline-blank\"\r\n | \"indeterminate-check-box\"\r\n | \"radio-button-checked\"\r\n | \"radio-button-unchecked\"\r\n | \"star\"\r\n | \"star-border\"\r\n | \"star-half\"\r\n // === Space Operations Aliases (mapped to existing icons) ===\r\n // Orbit & Trajectory\r\n | \"orbit\"\r\n | \"trajectory\"\r\n | \"orbital\"\r\n // Ground Operations\r\n | \"ground-station\"\r\n | \"ground-control\"\r\n | \"dish\"\r\n | \"tracking-station\"\r\n // Communication\r\n | \"uplink\"\r\n | \"downlink\"\r\n | \"command\"\r\n | \"telemetry\"\r\n | \"comms\"\r\n | \"rf\"\r\n | \"link\"\r\n | \"signal\"\r\n | \"data-link\"\r\n // Satellite States\r\n | \"satellite\"\r\n | \"spacecraft\"\r\n | \"vehicle\"\r\n | \"sat\"\r\n | \"sc\"\r\n // Power Systems\r\n | \"power\"\r\n | \"battery\"\r\n | \"energy\"\r\n | \"solar-array\"\r\n | \"solar-panel\"\r\n | \"photovoltaic\"\r\n // Propulsion\r\n | \"thruster\"\r\n | \"engine\"\r\n | \"burn\"\r\n | \"maneuver\"\r\n | \"delta-v\"\r\n | \"rcs\"\r\n // Thermal\r\n | \"temperature\"\r\n | \"heat\"\r\n | \"cooling\"\r\n | \"heater\"\r\n // Attitude & Control\r\n | \"attitude\"\r\n | \"pointing\"\r\n | \"orientation\"\r\n | \"adcs\"\r\n | \"gyro\"\r\n | \"gyroscope\"\r\n // Navigation\r\n | \"gps\"\r\n | \"gnss\"\r\n | \"position\"\r\n | \"location\"\r\n | \"ephemeris\"\r\n // Status & Health\r\n | \"health\"\r\n | \"status\"\r\n | \"nominal\"\r\n | \"anomaly\"\r\n | \"fault\"\r\n | \"safe-mode\"\r\n | \"emergency\"\r\n | \"critical\"\r\n | \"caution\"\r\n // Time & Scheduling\r\n | \"pass\"\r\n | \"contact\"\r\n | \"access\"\r\n | \"window\"\r\n | \"aos\"\r\n | \"los\"\r\n | \"eclipse\"\r\n | \"sunlight\"\r\n | \"shadow\"\r\n // Subsystems\r\n | \"subsystem\"\r\n | \"computer\"\r\n | \"obc\"\r\n | \"cdh\"\r\n | \"flight-computer\"\r\n | \"sensor\"\r\n | \"instrument\"\r\n // Launch & Deployment\r\n | \"launch\"\r\n | \"rocket\"\r\n | \"liftoff\"\r\n | \"deployment\"\r\n | \"deploy\"\r\n | \"separation\"\r\n // Operations\r\n | \"ops\"\r\n | \"operations\"\r\n | \"control\"\r\n | \"automation\"\r\n | \"sequence\"\r\n | \"procedure\"\r\n // Data & Storage\r\n | \"storage\"\r\n | \"memory\"\r\n | \"recorder\"\r\n | \"playback\"\r\n | \"record\"\r\n // Monitoring\r\n | \"monitor\"\r\n | \"dashboard\"\r\n | \"console\"\r\n | \"display\"\r\n // Crew\r\n | \"astronaut\"\r\n | \"crew\"\r\n | \"eva\"\r\n // Catch-all for any other icon (flexibility)\r\n | (string & {});\r\n\r\nexport type AstroIconSize = \"extra-small\" | \"small\" | \"normal\" | \"large\";\r\n\r\nexport interface AstroIconProps {\r\n /** Icon name from Astro UXD library */\r\n name: AstroIconName;\r\n /** Icon size preset or custom pixel value */\r\n size?: AstroIconSize | number;\r\n /** Custom color (hex, rgb, or CSS color) */\r\n color?: string;\r\n /** Accessibility label (required for screen readers) */\r\n label?: string;\r\n /** Additional CSS class */\r\n className?: string;\r\n /** Additional inline styles */\r\n style?: React.CSSProperties;\r\n /** Click handler */\r\n onClick?: () => void;\r\n /** Test ID for testing */\r\n \"data-testid\"?: string;\r\n}\r\n\r\n// Size mapping for fallback mode\r\nconst SIZE_MAP: Record<AstroIconSize, number> = {\r\n \"extra-small\": 16,\r\n small: 24,\r\n normal: 32,\r\n large: 48,\r\n};\r\n\r\n/**\r\n * Space Operations Icon Aliases\r\n * Maps common space terminology to existing Astro icons.\r\n * Provides better developer experience with intuitive naming.\r\n */\r\nconst ICON_ALIASES: Record<string, string> = {\r\n // === Orbit & Trajectory ===\r\n orbit: \"360\", // Orbital path\r\n trajectory: \"360\", // Flight path\r\n orbital: \"360\", // Orbital mechanics\r\n\r\n // === Ground Operations ===\r\n \"ground-station\": \"antenna\", // Ground station\r\n \"ground-control\": \"antenna\", // Mission control\r\n dish: \"antenna\", // Antenna dish\r\n \"tracking-station\": \"antenna\", // Tracking facility\r\n\r\n // === Communication ===\r\n uplink: \"antenna-transmit\", // Command upload\r\n downlink: \"antenna-receive\", // Data download\r\n command: \"antenna-transmit\", // Send command\r\n telemetry: \"antenna-receive\", // Receive telemetry\r\n comms: \"netcom\", // Communications\r\n rf: \"antenna\", // Radio frequency\r\n link: \"netcom\", // Communication link\r\n signal: \"antenna-transmit\", // Signal transmission\r\n \"data-link\": \"netcom\", // Data link\r\n\r\n // === Satellite States ===\r\n satellite: \"satellite-transmit\", // Default satellite (active)\r\n spacecraft: \"satellite-transmit\", // Spacecraft\r\n vehicle: \"satellite-transmit\", // Space vehicle\r\n sat: \"satellite-transmit\", // Abbreviation\r\n sc: \"satellite-transmit\", // Spacecraft abbreviation\r\n\r\n // === Power Systems ===\r\n power: \"propulsion-power\", // Power system\r\n battery: \"battery-full\", // Battery status\r\n energy: \"propulsion-power\", // Energy management\r\n \"solar-array\": \"solar\", // Solar arrays\r\n \"solar-panel\": \"solar\", // Solar panels\r\n photovoltaic: \"solar\", // PV system\r\n\r\n // === Propulsion ===\r\n thruster: \"propulsion-power\", // Thruster\r\n engine: \"propulsion-power\", // Engine\r\n burn: \"propulsion-power\", // Burn/maneuver\r\n maneuver: \"propulsion-power\", // Orbital maneuver\r\n \"delta-v\": \"propulsion-power\", // Delta-V\r\n rcs: \"propulsion-power\", // Reaction control system\r\n\r\n // === Thermal ===\r\n temperature: \"thermal\", // Temperature\r\n heat: \"thermal\", // Heat management\r\n cooling: \"thermal\", // Cooling system\r\n heater: \"thermal\", // Heater\r\n\r\n // === Attitude & Control ===\r\n attitude: \"explore\", // Attitude control\r\n pointing: \"explore\", // Pointing direction\r\n orientation: \"explore\", // Spacecraft orientation\r\n adcs: \"explore\", // Attitude determination & control\r\n gyro: \"explore\", // Gyroscope\r\n gyroscope: \"explore\", // Gyroscope\r\n\r\n // === Navigation ===\r\n gps: \"gps-fixed\", // GPS/GNSS\r\n gnss: \"gps-fixed\", // Global navigation\r\n position: \"gps-fixed\", // Position\r\n location: \"place\", // Location\r\n ephemeris: \"timeline\", // Ephemeris data\r\n\r\n // === Status & Health ===\r\n health: \"favorite\", // System health\r\n status: \"info\", // Status indicator\r\n nominal: \"check-circle\", // Nominal/OK\r\n anomaly: \"error\", // Anomaly detected\r\n fault: \"error\", // Fault condition\r\n \"safe-mode\": \"warning\", // Safe mode\r\n emergency: \"warning\", // Emergency\r\n critical: \"error\", // Critical status\r\n caution: \"warning\", // Caution\r\n\r\n // === Time & Scheduling ===\r\n pass: \"schedule\", // Satellite pass\r\n contact: \"schedule\", // Ground contact\r\n access: \"schedule\", // Access window\r\n window: \"schedule\", // Time window\r\n aos: \"schedule\", // Acquisition of signal\r\n los: \"schedule\", // Loss of signal\r\n eclipse: \"brightness-3\", // Eclipse period\r\n sunlight: \"wb-sunny\", // In sunlight\r\n shadow: \"brightness-3\", // In shadow\r\n\r\n // === Subsystems ===\r\n subsystem: \"developer-board\", // Generic subsystem\r\n computer: \"memory\", // Onboard computer\r\n obc: \"memory\", // Onboard computer\r\n cdh: \"memory\", // Command & data handling\r\n \"flight-computer\": \"memory\", // Flight computer\r\n sensor: \"settings-input-component\", // Sensor\r\n instrument: \"settings-input-component\", // Instrument\r\n\r\n // === Launch & Deployment ===\r\n launch: \"flight-takeoff\", // Launch\r\n rocket: \"flight-takeoff\", // Rocket\r\n liftoff: \"flight-takeoff\", // Liftoff\r\n deployment: \"open-in-new\", // Deployment\r\n deploy: \"open-in-new\", // Deploy\r\n separation: \"call-split\", // Stage separation\r\n\r\n // === Operations ===\r\n ops: \"build\", // Operations\r\n operations: \"build\", // Operations\r\n control: \"tune\", // Control\r\n automation: \"autorenew\", // Automation\r\n sequence: \"playlist-play\", // Command sequence\r\n procedure: \"list\", // Procedure\r\n\r\n // === Data & Storage ===\r\n storage: \"sd-storage\", // Data storage\r\n memory: \"memory\", // Memory\r\n recorder: \"fiber-dvr\", // Data recorder\r\n playback: \"play-arrow\", // Playback\r\n record: \"fiber-manual-record\", // Recording\r\n\r\n // === Monitoring ===\r\n monitor: \"desktop-mac\", // Monitoring\r\n dashboard: \"dashboard\", // Dashboard\r\n console: \"desktop-windows\", // Console\r\n display: \"tv\", // Display\r\n\r\n // === Crew (if applicable) ===\r\n astronaut: \"person\", // Astronaut\r\n crew: \"group\", // Crew\r\n eva: \"directions-walk\", // Extra-vehicular activity\r\n};\r\n\r\n/**\r\n * Resolve icon alias to actual Astro icon name\r\n */\r\nfunction resolveIconAlias(name: string): string {\r\n return ICON_ALIASES[name] || name;\r\n}\r\n\r\n/**\r\n * Get all available icon aliases\r\n */\r\nexport function getIconAliases(): Record<string, string> {\r\n return { ...ICON_ALIASES };\r\n}\r\n\r\n/**\r\n * Check if an icon name is an alias\r\n */\r\nexport function isIconAlias(name: string): boolean {\r\n return name in ICON_ALIASES;\r\n}\r\n\r\n/**\r\n * All available Astro UXD icon names (official icons, not aliases)\r\n * This is the comprehensive list from the Astro UXD icon library\r\n */\r\nexport const ASTRO_ICON_NAMES: readonly string[] = [\r\n // === Astro Space/Mission Icons (Custom by Rocket Communications) ===\r\n \"altitude\",\r\n \"antenna\",\r\n \"antenna-off\",\r\n \"antenna-receive\",\r\n \"antenna-transmit\",\r\n \"equipment\",\r\n \"hardware\",\r\n \"mission\",\r\n \"netcom\",\r\n \"payload\",\r\n \"processor\",\r\n \"processor-alt\",\r\n \"propulsion-power\",\r\n \"satellite-off\",\r\n \"satellite-receive\",\r\n \"satellite-transmit\",\r\n \"solar\",\r\n \"thermal\",\r\n // === Actions ===\r\n \"settings\",\r\n \"search\",\r\n \"home\",\r\n \"info\",\r\n \"help\",\r\n \"delete\",\r\n \"edit\",\r\n \"lock\",\r\n \"lock-open\",\r\n \"visibility\",\r\n \"visibility-off\",\r\n \"refresh\",\r\n \"sync\",\r\n \"download\",\r\n \"upload\",\r\n \"fullscreen\",\r\n \"fullscreen-exit\",\r\n \"zoom-in\",\r\n \"zoom-out\",\r\n \"schedule\",\r\n \"timeline\",\r\n \"today\",\r\n \"event\",\r\n \"bookmark\",\r\n \"favorite\",\r\n \"star\",\r\n \"check-circle\",\r\n \"done\",\r\n \"done-all\",\r\n \"print\",\r\n \"open-in-new\",\r\n \"launch\",\r\n \"power-settings-new\",\r\n \"history\",\r\n \"cached\",\r\n \"build\",\r\n \"code\",\r\n \"dns\",\r\n \"language\",\r\n \"input\",\r\n \"label\",\r\n \"list\",\r\n \"track-changes\",\r\n \"verified-user\",\r\n \"work\",\r\n // === Alerts ===\r\n \"add-alert\",\r\n \"error\",\r\n \"error-outline\",\r\n \"notification-important\",\r\n \"warning\",\r\n // === AV ===\r\n \"play-arrow\",\r\n \"pause\",\r\n \"stop\",\r\n \"skip-next\",\r\n \"skip-previous\",\r\n \"fast-forward\",\r\n \"fast-rewind\",\r\n \"replay\",\r\n \"loop\",\r\n \"shuffle\",\r\n \"volume-up\",\r\n \"volume-down\",\r\n \"volume-off\",\r\n \"volume-mute\",\r\n \"mic\",\r\n \"mic-off\",\r\n \"videocam\",\r\n \"videocam-off\",\r\n \"movie\",\r\n \"music-note\",\r\n \"equalizer\",\r\n \"library-music\",\r\n \"queue-music\",\r\n // === Communication ===\r\n \"call\",\r\n \"call-end\",\r\n \"chat\",\r\n \"chat-bubble\",\r\n \"chat-bubble-outline\",\r\n \"comment\",\r\n \"contacts\",\r\n \"email\",\r\n \"mail-outline\",\r\n \"message\",\r\n \"phone\",\r\n \"voicemail\",\r\n \"vpn-key\",\r\n \"forum\",\r\n \"live-help\",\r\n \"location-on\",\r\n \"location-off\",\r\n \"business\",\r\n \"import-contacts\",\r\n // === Content ===\r\n \"add\",\r\n \"remove\",\r\n \"add-circle\",\r\n \"add-circle-outline\",\r\n \"remove-circle\",\r\n \"remove-circle-outline\",\r\n \"clear\",\r\n \"content-copy\",\r\n \"content-cut\",\r\n \"content-paste\",\r\n \"create\",\r\n \"flag\",\r\n \"forward\",\r\n \"reply\",\r\n \"reply-all\",\r\n \"save\",\r\n \"save-alt\",\r\n \"select-all\",\r\n \"send\",\r\n \"undo\",\r\n \"redo\",\r\n \"filter-list\",\r\n \"sort\",\r\n \"drafts\",\r\n \"link\",\r\n \"link-off\",\r\n // === Device ===\r\n \"battery-full\",\r\n \"battery-charging-full\",\r\n \"battery-alert\",\r\n \"battery-unknown\",\r\n \"bluetooth\",\r\n \"bluetooth-disabled\",\r\n \"bluetooth-connected\",\r\n \"bluetooth-searching\",\r\n \"brightness-1\",\r\n \"brightness-2\",\r\n \"brightness-3\",\r\n \"brightness-4\",\r\n \"brightness-5\",\r\n \"brightness-6\",\r\n \"brightness-7\",\r\n \"brightness-auto\",\r\n \"brightness-high\",\r\n \"brightness-low\",\r\n \"brightness-medium\",\r\n \"gps-fixed\",\r\n \"gps-not-fixed\",\r\n \"gps-off\",\r\n \"graphic-eq\",\r\n \"network-cell\",\r\n \"network-wifi\",\r\n \"nfc\",\r\n \"screen-rotation\",\r\n \"sd-storage\",\r\n \"settings-system-daydream\",\r\n \"signal-cellular-4-bar\",\r\n \"signal-cellular-connected-no-internet-4-bar\",\r\n \"signal-cellular-no-sim\",\r\n \"signal-cellular-null\",\r\n \"signal-cellular-off\",\r\n \"signal-wifi-4-bar\",\r\n \"signal-wifi-4-bar-lock\",\r\n \"signal-wifi-off\",\r\n \"storage\",\r\n \"usb\",\r\n \"wifi\",\r\n \"wifi-lock\",\r\n \"wifi-off\",\r\n \"wifi-tethering\",\r\n // === Editor ===\r\n \"attach-file\",\r\n \"attach-money\",\r\n \"border-all\",\r\n \"border-bottom\",\r\n \"border-clear\",\r\n \"border-color\",\r\n \"border-horizontal\",\r\n \"border-inner\",\r\n \"border-left\",\r\n \"border-outer\",\r\n \"border-right\",\r\n \"border-style\",\r\n \"border-top\",\r\n \"border-vertical\",\r\n \"format-align-center\",\r\n \"format-align-justify\",\r\n \"format-align-left\",\r\n \"format-align-right\",\r\n \"format-bold\",\r\n \"format-clear\",\r\n \"format-color-fill\",\r\n \"format-color-reset\",\r\n \"format-color-text\",\r\n \"format-indent-decrease\",\r\n \"format-indent-increase\",\r\n \"format-italic\",\r\n \"format-line-spacing\",\r\n \"format-list-bulleted\",\r\n \"format-list-numbered\",\r\n \"format-paint\",\r\n \"format-quote\",\r\n \"format-size\",\r\n \"format-strikethrough\",\r\n \"format-textdirection-l-to-r\",\r\n \"format-textdirection-r-to-l\",\r\n \"format-underlined\",\r\n \"functions\",\r\n \"insert-chart\",\r\n \"insert-comment\",\r\n \"insert-drive-file\",\r\n \"insert-emoticon\",\r\n \"insert-invitation\",\r\n \"insert-link\",\r\n \"insert-photo\",\r\n \"merge-type\",\r\n \"mode-comment\",\r\n \"mode-edit\",\r\n \"publish\",\r\n \"short-text\",\r\n \"space-bar\",\r\n \"strikethrough-s\",\r\n \"text-fields\",\r\n \"title\",\r\n \"vertical-align-bottom\",\r\n \"vertical-align-center\",\r\n \"vertical-align-top\",\r\n \"wrap-text\",\r\n // === File ===\r\n \"attachment\",\r\n \"cloud\",\r\n \"cloud-circle\",\r\n \"cloud-done\",\r\n \"cloud-download\",\r\n \"cloud-off\",\r\n \"cloud-queue\",\r\n \"cloud-upload\",\r\n \"create-new-folder\",\r\n \"file-download\",\r\n \"file-upload\",\r\n \"folder\",\r\n \"folder-open\",\r\n \"folder-shared\",\r\n // === Hardware ===\r\n \"cast\",\r\n \"cast-connected\",\r\n \"computer\",\r\n \"desktop-mac\",\r\n \"desktop-windows\",\r\n \"developer-board\",\r\n \"device-hub\",\r\n \"devices-other\",\r\n \"dock\",\r\n \"gamepad\",\r\n \"headset\",\r\n \"headset-mic\",\r\n \"keyboard\",\r\n \"keyboard-arrow-down\",\r\n \"keyboard-arrow-left\",\r\n \"keyboard-arrow-right\",\r\n \"keyboard-arrow-up\",\r\n \"keyboard-backspace\",\r\n \"keyboard-capslock\",\r\n \"keyboard-hide\",\r\n \"keyboard-return\",\r\n \"keyboard-tab\",\r\n \"keyboard-voice\",\r\n \"laptop\",\r\n \"laptop-chromebook\",\r\n \"laptop-mac\",\r\n \"laptop-windows\",\r\n \"memory\",\r\n \"mouse\",\r\n \"phone-android\",\r\n \"phone-iphone\",\r\n \"phonelink\",\r\n \"phonelink-off\",\r\n \"power-input\",\r\n \"router\",\r\n \"scanner\",\r\n \"security\",\r\n \"sim-card\",\r\n \"smartphone\",\r\n \"speaker\",\r\n \"speaker-group\",\r\n \"tablet\",\r\n \"tablet-android\",\r\n \"tablet-mac\",\r\n \"toys\",\r\n \"tv\",\r\n \"watch\",\r\n // === Image ===\r\n \"add-a-photo\",\r\n \"add-photo-alternate\",\r\n \"add-to-photos\",\r\n \"adjust\",\r\n \"brightness-1\",\r\n \"broken-image\",\r\n \"brush\",\r\n \"burst-mode\",\r\n \"camera\",\r\n \"camera-alt\",\r\n \"camera-front\",\r\n \"camera-rear\",\r\n \"camera-roll\",\r\n \"center-focus-strong\",\r\n \"center-focus-weak\",\r\n \"collections\",\r\n \"collections-bookmark\",\r\n \"color-lens\",\r\n \"colorize\",\r\n \"compare\",\r\n \"control-point\",\r\n \"control-point-duplicate\",\r\n \"crop\",\r\n \"crop-16-9\",\r\n \"crop-3-2\",\r\n \"crop-5-4\",\r\n \"crop-7-5\",\r\n \"crop-din\",\r\n \"crop-free\",\r\n \"crop-landscape\",\r\n \"crop-original\",\r\n \"crop-portrait\",\r\n \"crop-rotate\",\r\n \"crop-square\",\r\n \"dehaze\",\r\n \"details\",\r\n \"edit\",\r\n \"exposure\",\r\n \"exposure-neg-1\",\r\n \"exposure-neg-2\",\r\n \"exposure-plus-1\",\r\n \"exposure-plus-2\",\r\n \"exposure-zero\",\r\n \"filter\",\r\n \"filter-1\",\r\n \"filter-2\",\r\n \"filter-3\",\r\n \"filter-4\",\r\n \"filter-5\",\r\n \"filter-6\",\r\n \"filter-7\",\r\n \"filter-8\",\r\n \"filter-9\",\r\n \"filter-9-plus\",\r\n \"filter-b-and-w\",\r\n \"filter-center-focus\",\r\n \"filter-drama\",\r\n \"filter-frames\",\r\n \"filter-hdr\",\r\n \"filter-none\",\r\n \"filter-tilt-shift\",\r\n \"filter-vintage\",\r\n \"flare\",\r\n \"flash-auto\",\r\n \"flash-off\",\r\n \"flash-on\",\r\n \"flip\",\r\n \"gradient\",\r\n \"grain\",\r\n \"grid-off\",\r\n \"grid-on\",\r\n \"hdr-off\",\r\n \"hdr-on\",\r\n \"hdr-strong\",\r\n \"hdr-weak\",\r\n \"healing\",\r\n \"image\",\r\n \"image-aspect-ratio\",\r\n \"image-search\",\r\n \"iso\",\r\n \"landscape\",\r\n \"leak-add\",\r\n \"leak-remove\",\r\n \"lens\",\r\n \"linked-camera\",\r\n \"looks\",\r\n \"looks-3\",\r\n \"looks-4\",\r\n \"looks-5\",\r\n \"looks-6\",\r\n \"looks-one\",\r\n \"looks-two\",\r\n \"loupe\",\r\n \"monochrome-photos\",\r\n \"movie-creation\",\r\n \"movie-filter\",\r\n \"music-off\",\r\n \"music-on\",\r\n \"navigate-before\",\r\n \"navigate-next\",\r\n \"nature\",\r\n \"nature-people\",\r\n \"palette\",\r\n \"panorama\",\r\n \"panorama-fish-eye\",\r\n \"panorama-horizontal\",\r\n \"panorama-vertical\",\r\n \"panorama-wide-angle\",\r\n \"photo\",\r\n \"photo-album\",\r\n \"photo-camera\",\r\n \"photo-filter\",\r\n \"photo-library\",\r\n \"photo-size-select-actual\",\r\n \"photo-size-select-large\",\r\n \"photo-size-select-small\",\r\n \"picture-as-pdf\",\r\n \"portrait\",\r\n \"remove-red-eye\",\r\n \"rotate-90-degrees-ccw\",\r\n \"rotate-left\",\r\n \"rotate-right\",\r\n \"slideshow\",\r\n \"straighten\",\r\n \"style\",\r\n \"switch-camera\",\r\n \"switch-video\",\r\n \"tag-faces\",\r\n \"texture\",\r\n \"timelapse\",\r\n \"timer\",\r\n \"timer-10\",\r\n \"timer-3\",\r\n \"timer-off\",\r\n \"tonality\",\r\n \"transform\",\r\n \"tune\",\r\n \"view-comfy\",\r\n \"view-compact\",\r\n \"vignette\",\r\n \"wb-auto\",\r\n \"wb-cloudy\",\r\n \"wb-incandescent\",\r\n \"wb-iridescent\",\r\n \"wb-sunny\",\r\n // === Maps ===\r\n \"add-location\",\r\n \"beenhere\",\r\n \"directions\",\r\n \"directions-bike\",\r\n \"directions-boat\",\r\n \"directions-bus\",\r\n \"directions-car\",\r\n \"directions-railway\",\r\n \"directions-run\",\r\n \"directions-subway\",\r\n \"directions-transit\",\r\n \"directions-walk\",\r\n \"edit-location\",\r\n \"ev-station\",\r\n \"flight\",\r\n \"hotel\",\r\n \"layers\",\r\n \"layers-clear\",\r\n \"local-activity\",\r\n \"local-airport\",\r\n \"local-atm\",\r\n \"local-bar\",\r\n \"local-cafe\",\r\n \"local-car-wash\",\r\n \"local-convenience-store\",\r\n \"local-dining\",\r\n \"local-drink\",\r\n \"local-florist\",\r\n \"local-gas-station\",\r\n \"local-grocery-store\",\r\n \"local-hospital\",\r\n \"local-hotel\",\r\n \"local-laundry-service\",\r\n \"local-library\",\r\n \"local-mall\",\r\n \"local-movies\",\r\n \"local-offer\",\r\n \"local-parking\",\r\n \"local-pharmacy\",\r\n \"local-phone\",\r\n \"local-pizza\",\r\n \"local-play\",\r\n \"local-post-office\",\r\n \"local-printshop\",\r\n \"local-see\",\r\n \"local-shipping\",\r\n \"local-taxi\",\r\n \"map\",\r\n \"my-location\",\r\n \"navigation\",\r\n \"near-me\",\r\n \"person-pin\",\r\n \"person-pin-circle\",\r\n \"pin-drop\",\r\n \"place\",\r\n \"rate-review\",\r\n \"restaurant\",\r\n \"restaurant-menu\",\r\n \"satellite\",\r\n \"store-mall-directory\",\r\n \"streetview\",\r\n \"subway\",\r\n \"terrain\",\r\n \"traffic\",\r\n \"train\",\r\n \"tram\",\r\n \"transfer-within-a-station\",\r\n \"zoom-out-map\",\r\n // === Navigation ===\r\n \"apps\",\r\n \"arrow-back\",\r\n \"arrow-downward\",\r\n \"arrow-drop-down\",\r\n \"arrow-drop-down-circle\",\r\n \"arrow-drop-up\",\r\n \"arrow-forward\",\r\n \"arrow-upward\",\r\n \"cancel\",\r\n \"check\",\r\n \"chevron-left\",\r\n \"chevron-right\",\r\n \"close\",\r\n \"expand-less\",\r\n \"expand-more\",\r\n \"first-page\",\r\n \"last-page\",\r\n \"menu\",\r\n \"more-horiz\",\r\n \"more-vert\",\r\n \"subdirectory-arrow-left\",\r\n \"subdirectory-arrow-right\",\r\n \"unfold-less\",\r\n \"unfold-more\",\r\n // === Notification ===\r\n \"adb\",\r\n \"airline-seat-flat\",\r\n \"airline-seat-flat-angled\",\r\n \"airline-seat-individual-suite\",\r\n \"airline-seat-legroom-extra\",\r\n \"airline-seat-legroom-normal\",\r\n \"airline-seat-legroom-reduced\",\r\n \"airline-seat-recline-extra\",\r\n \"airline-seat-recline-normal\",\r\n \"bluetooth-audio\",\r\n \"confirmation-number\",\r\n \"disc-full\",\r\n \"do-not-disturb\",\r\n \"do-not-disturb-alt\",\r\n \"do-not-disturb-off\",\r\n \"do-not-disturb-on\",\r\n \"drive-eta\",\r\n \"enhanced-encryption\",\r\n \"event-available\",\r\n \"event-busy\",\r\n \"event-note\",\r\n \"folder-special\",\r\n \"live-tv\",\r\n \"mms\",\r\n \"more\",\r\n \"network-check\",\r\n \"network-locked\",\r\n \"no-encryption\",\r\n \"ondemand-video\",\r\n \"personal-video\",\r\n \"phone-bluetooth-speaker\",\r\n \"phone-callback\",\r\n \"phone-forwarded\",\r\n \"phone-in-talk\",\r\n \"phone-locked\",\r\n \"phone-missed\",\r\n \"phone-paused\",\r\n \"power\",\r\n \"power-off\",\r\n \"priority-high\",\r\n \"sd-card\",\r\n \"sim-card-alert\",\r\n \"sms\",\r\n \"sms-failed\",\r\n \"sync-disabled\",\r\n \"sync-problem\",\r\n \"system-update\",\r\n \"tap-and-play\",\r\n \"time-to-leave\",\r\n \"vibration\",\r\n \"voice-chat\",\r\n \"vpn-lock\",\r\n \"wc\",\r\n \"wifi\",\r\n \"notifications\",\r\n \"notifications-active\",\r\n \"notifications-none\",\r\n \"notifications-off\",\r\n \"notifications-paused\",\r\n // === Places ===\r\n \"ac-unit\",\r\n \"airport-shuttle\",\r\n \"all-inclusive\",\r\n \"beach-access\",\r\n \"business-center\",\r\n \"casino\",\r\n \"child-care\",\r\n \"child-friendly\",\r\n \"fitness-center\",\r\n \"free-breakfast\",\r\n \"golf-course\",\r\n \"hot-tub\",\r\n \"kitchen\",\r\n \"meeting-room\",\r\n \"no-meeting-room\",\r\n \"pool\",\r\n \"room-service\",\r\n \"rv-hookup\",\r\n \"smoke-free\",\r\n \"smoking-rooms\",\r\n \"spa\",\r\n // === Social ===\r\n \"cake\",\r\n \"domain\",\r\n \"group\",\r\n \"group-add\",\r\n \"location-city\",\r\n \"mood\",\r\n \"mood-bad\",\r\n \"notifications\",\r\n \"pages\",\r\n \"party-mode\",\r\n \"people\",\r\n \"people-outline\",\r\n \"person\",\r\n \"person-add\",\r\n \"person-outline\",\r\n \"plus-one\",\r\n \"poll\",\r\n \"public\",\r\n \"school\",\r\n \"sentiment-dissatisfied\",\r\n \"sentiment-neutral\",\r\n \"sentiment-satisfied\",\r\n \"sentiment-very-dissatisfied\",\r\n \"sentiment-very-satisfied\",\r\n \"share\",\r\n \"thumb-down\",\r\n \"thumb-up\",\r\n \"whatshot\",\r\n // === Toggle ===\r\n \"check-box\",\r\n \"check-box-outline-blank\",\r\n \"indeterminate-check-box\",\r\n \"radio-button-checked\",\r\n \"radio-button-unchecked\",\r\n \"star\",\r\n \"star-border\",\r\n \"star-half\",\r\n // === Additional common icons ===\r\n \"360\",\r\n \"autorenew\",\r\n \"call-split\",\r\n \"explore\",\r\n \"extension\",\r\n \"face\",\r\n \"feedback\",\r\n \"fiber-dvr\",\r\n \"fiber-manual-record\",\r\n \"fiber-new\",\r\n \"fiber-pin\",\r\n \"fiber-smart-record\",\r\n \"get-app\",\r\n \"grade\",\r\n \"highlight-off\",\r\n \"http\",\r\n \"https\",\r\n \"important-devices\",\r\n \"lightbulb\",\r\n \"lightbulb-outline\",\r\n \"perm-camera-mic\",\r\n \"perm-contact-calendar\",\r\n \"perm-data-setting\",\r\n \"perm-device-information\",\r\n \"perm-identity\",\r\n \"perm-media\",\r\n \"perm-phone-msg\",\r\n \"perm-scan-wifi\",\r\n \"pets\",\r\n \"playlist-add\",\r\n \"playlist-add-check\",\r\n \"playlist-play\",\r\n \"pregnant-woman\",\r\n \"query-builder\",\r\n \"question-answer\",\r\n \"receipt\",\r\n \"record-voice-over\",\r\n \"redeem\",\r\n \"report-problem\",\r\n \"restore\",\r\n \"restore-page\",\r\n \"room\",\r\n \"rounded-corner\",\r\n \"rowing\",\r\n \"settings-applications\",\r\n \"settings-backup-restore\",\r\n \"settings-bluetooth\",\r\n \"settings-brightness\",\r\n \"settings-cell\",\r\n \"settings-ethernet\",\r\n \"settings-input-antenna\",\r\n \"settings-input-component\",\r\n \"settings-input-composite\",\r\n \"settings-input-hdmi\",\r\n \"settings-input-svideo\",\r\n \"settings-overscan\",\r\n \"settings-phone\",\r\n \"settings-power\",\r\n \"settings-remote\",\r\n \"settings-voice\",\r\n \"shop\",\r\n \"shop-two\",\r\n \"shopping-basket\",\r\n \"shopping-cart\",\r\n \"speaker-notes\",\r\n \"speaker-notes-off\",\r\n \"spellcheck\",\r\n \"stars\",\r\n \"subject\",\r\n \"supervisor-account\",\r\n \"swap-horiz\",\r\n \"swap-vert\",\r\n \"swap-vertical-circle\",\r\n \"system-update-alt\",\r\n \"tab\",\r\n \"tab-unselected\",\r\n \"theaters\",\r\n \"thumb-down\",\r\n \"thumb-up\",\r\n \"thumbs-up-down\",\r\n \"toc\",\r\n \"toll\",\r\n \"touch-app\",\r\n \"translate\",\r\n \"trending-down\",\r\n \"trending-flat\",\r\n \"trending-up\",\r\n \"turned-in\",\r\n \"turned-in-not\",\r\n \"update\",\r\n \"view-agenda\",\r\n \"view-array\",\r\n \"view-carousel\",\r\n \"view-column\",\r\n \"view-day\",\r\n \"view-headline\",\r\n \"view-list\",\r\n \"view-module\",\r\n \"view-quilt\",\r\n \"view-stream\",\r\n \"view-week\",\r\n \"visibility\",\r\n \"visibility-off\",\r\n \"watch-later\",\r\n \"youtube-searched-for\",\r\n \"aspect-ratio\",\r\n \"assignment\",\r\n \"assignment-ind\",\r\n \"assignment-late\",\r\n \"assignment-return\",\r\n \"assignment-returned\",\r\n \"assignment-turned-in\",\r\n \"backup\",\r\n \"book\",\r\n \"flight-takeoff\",\r\n \"flight-land\",\r\n] as const;\r\n\r\n/**\r\n * Get all available Astro icon names\r\n */\r\nexport function getAstroIconNames(): readonly string[] {\r\n return ASTRO_ICON_NAMES;\r\n}\r\n\r\n/**\r\n * Get all available icon names including aliases\r\n */\r\nexport function getAllIconNames(): {\r\n icons: readonly string[];\r\n aliases: Record<string, string>;\r\n} {\r\n return {\r\n icons: ASTRO_ICON_NAMES,\r\n aliases: ICON_ALIASES,\r\n };\r\n}\r\n\r\n// Global state for RuxIcon loading with subscription pattern\r\ntype LoadState = \"pending\" | \"loading\" | \"loaded\" | \"failed\";\r\nlet loadState: LoadState = \"pending\";\r\nlet RuxIconComponent: React.ComponentType<any> | null = null;\r\nconst subscribers = new Set<() => void>();\r\n\r\nfunction subscribe(callback: () => void) {\r\n subscribers.add(callback);\r\n return () => subscribers.delete(callback);\r\n}\r\n\r\nfunction notifySubscribers() {\r\n subscribers.forEach((cb) => cb());\r\n}\r\n\r\n/**\r\n * Safely load RuxIcon from @astrouxds/react\r\n * Returns null if not available\r\n */\r\nasync function loadRuxIcon(): Promise<React.ComponentType<any> | null> {\r\n if (loadState === \"loaded\") {\r\n return RuxIconComponent;\r\n }\r\n\r\n if (loadState === \"failed\") {\r\n return null;\r\n }\r\n\r\n if (loadState === \"loading\") {\r\n // Wait for the existing load to complete\r\n return new Promise((resolve) => {\r\n const unsub = subscribe(() => {\r\n unsub();\r\n resolve(RuxIconComponent);\r\n });\r\n });\r\n }\r\n\r\n loadState = \"loading\";\r\n\r\n try {\r\n // Dynamic import for tree-shaking and optional dependency\r\n const astroModule = await import(\"@astrouxds/react\");\r\n RuxIconComponent = astroModule.RuxIcon;\r\n loadState = \"loaded\";\r\n notifySubscribers();\r\n return RuxIconComponent;\r\n } catch (err) {\r\n loadState = \"failed\";\r\n notifySubscribers();\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fallback icon component when @astrouxds/react is not installed.\r\n * Uses built-in Icon SVGs when the name matches, otherwise shows a generic placeholder.\r\n */\r\nfunction FallbackIcon({\r\n name,\r\n size,\r\n color,\r\n label,\r\n className,\r\n style,\r\n onClick,\r\n \"data-testid\": testId,\r\n}: AstroIconProps) {\r\n const { tokens } = useTheme();\r\n const actualSize =\r\n typeof size === \"number\" ? size : SIZE_MAP[size || \"normal\"];\r\n\r\n if (isValidIconName(name)) {\r\n return (\r\n <Icon\r\n name={name}\r\n size={actualSize}\r\n color={color}\r\n className={className}\r\n aria-label={label || name}\r\n onClick={onClick}\r\n style={style}\r\n />\r\n );\r\n }\r\n\r\n return (\r\n <span\r\n role=\"img\"\r\n aria-label={label || name}\r\n className={className}\r\n data-testid={testId}\r\n onClick={onClick}\r\n tabIndex={onClick ? 0 : undefined}\r\n onKeyDown={onClick ? (e) => e.key === \"Enter\" && onClick() : undefined}\r\n style={{\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n width: actualSize,\r\n height: actualSize,\r\n fontSize: actualSize * 0.4,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontWeight: 700,\r\n color: color || tokens.colors.status.off,\r\n backgroundColor: tokens.colors.background.surface,\r\n border: `1px solid ${tokens.colors.border.default}`,\r\n borderRadius: 4,\r\n cursor: onClick ? \"pointer\" : \"default\",\r\n userSelect: \"none\",\r\n ...style,\r\n }}\r\n title={`Icon: ${name} (install @astrouxds/react for official icons)`}\r\n >\r\n <svg\r\n width={actualSize * 0.6}\r\n height={actualSize * 0.6}\r\n viewBox=\"0 0 24 24\"\r\n fill=\"currentColor\"\r\n >\r\n <rect\r\n x=\"3\"\r\n y=\"3\"\r\n width=\"18\"\r\n height=\"18\"\r\n rx=\"2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.5\"\r\n />\r\n <circle cx=\"12\" cy=\"12\" r=\"2\" fill=\"currentColor\" />\r\n </svg>\r\n </span>\r\n );\r\n}\r\n\r\n/**\r\n * AstroIcon - Official Astro UXD Icons\r\n *\r\n * Displays icons from the official Astro UX Design System.\r\n * Automatically uses @astrouxds/react if installed, otherwise shows fallback.\r\n *\r\n * @example\r\n * ```tsx\r\n * // Basic usage\r\n * <AstroIcon name=\"satellite\" />\r\n *\r\n * // With size\r\n * <AstroIcon name=\"antenna\" size=\"large\" />\r\n * <AstroIcon name=\"thermal\" size={48} />\r\n *\r\n * // With color\r\n * <AstroIcon name=\"warning\" color=\"var(--zendir-status-caution)\" />\r\n *\r\n * // With click handler\r\n * <AstroIcon name=\"settings\" onClick={() => openSettings()} />\r\n * ```\r\n */\r\nexport const AstroIcon = memo(function AstroIcon(props: AstroIconProps) {\r\n const {\r\n name,\r\n size = \"normal\",\r\n color,\r\n label,\r\n className,\r\n style,\r\n onClick,\r\n \"data-testid\": testId,\r\n } = props;\r\n\r\n const [, forceUpdate] = useState(0);\r\n const [currentState, setCurrentState] = useState(loadState);\r\n const mountedRef = useRef(true);\r\n\r\n // Subscribe to load state changes and trigger loading\r\n useEffect(() => {\r\n mountedRef.current = true;\r\n\r\n // Subscribe to state changes\r\n const unsubscribe = subscribe(() => {\r\n if (mountedRef.current) {\r\n setCurrentState(loadState);\r\n forceUpdate((n) => n + 1);\r\n }\r\n });\r\n\r\n // Trigger load if not yet started\r\n if (loadState === \"pending\") {\r\n loadRuxIcon();\r\n }\r\n\r\n return () => {\r\n mountedRef.current = false;\r\n unsubscribe();\r\n };\r\n }, []);\r\n\r\n // If still loading, show a subtle placeholder\r\n if (currentState === \"pending\" || currentState === \"loading\") {\r\n const actualSize = typeof size === \"number\" ? size : SIZE_MAP[size];\r\n return (\r\n <span\r\n style={{\r\n display: \"inline-block\",\r\n width: actualSize,\r\n height: actualSize,\r\n ...style,\r\n }}\r\n className={className}\r\n aria-hidden=\"true\"\r\n />\r\n );\r\n }\r\n\r\n // Resolve icon alias to actual Astro icon name\r\n const resolvedName = resolveIconAlias(name);\r\n\r\n // If @astrouxds/react is available, use official RuxIcon\r\n if (RuxIconComponent) {\r\n const RuxIcon = RuxIconComponent;\r\n const pixelSize = typeof size === \"number\" ? size : SIZE_MAP[size];\r\n\r\n // Map numeric size to closest Astro size preset for RuxIcon\r\n // This helps RuxIcon render at approximately the right size before CSS kicks in\r\n const getClosestAstroSize = (px: number): AstroIconSize => {\r\n if (px <= 18) return \"extra-small\"; // 16px\r\n if (px <= 28) return \"small\"; // 24px\r\n if (px <= 40) return \"normal\"; // 32px\r\n return \"large\"; // 48px\r\n };\r\n const astroSize =\r\n typeof size === \"number\" ? getClosestAstroSize(size) : size;\r\n\r\n // Default to off/grey color if no color specified\r\n const iconColor = color || \"var(--zendir-status-off, #a4abb6)\";\r\n\r\n return (\r\n <span\r\n role=\"img\"\r\n aria-label={label || name}\r\n style={{\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n width: pixelSize,\r\n height: pixelSize,\r\n minWidth: pixelSize,\r\n minHeight: pixelSize,\r\n flexShrink: 0,\r\n // Don't use overflow:hidden - it clips the icon SVG\r\n ...style,\r\n }}\r\n className={className}\r\n >\r\n <RuxIcon\r\n icon={resolvedName}\r\n size={astroSize}\r\n label={label || name}\r\n data-testid={testId}\r\n onClick={onClick}\r\n style={\r\n {\r\n // Force the RuxIcon to respect our exact pixel size\r\n \"--iconDefaultSize\": `${pixelSize}px`,\r\n \"--iconSize\": `${pixelSize}px`,\r\n \"--size\": `${pixelSize}px`,\r\n color: iconColor,\r\n width: `${pixelSize}px`,\r\n height: `${pixelSize}px`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n ...(onClick && { cursor: \"pointer\" }),\r\n } as React.CSSProperties\r\n }\r\n />\r\n </span>\r\n );\r\n }\r\n\r\n // Fallback when @astrouxds/react is not installed\r\n return <FallbackIcon {...props} name={resolvedName} />;\r\n});\r\n\r\n/**\r\n * Check if @astrouxds/react is available\r\n * Useful for conditional rendering or feature detection\r\n */\r\nexport function isAstroIconsAvailable(): boolean {\r\n return loadState === \"loaded\" && RuxIconComponent !== null;\r\n}\r\n\r\n/**\r\n * Preload the Astro icons module\r\n * Call this early in your app to ensure icons are ready\r\n */\r\nexport async function preloadAstroIcons(): Promise<boolean> {\r\n const component = await loadRuxIcon();\r\n return component !== null;\r\n}\r\n\r\nexport default AstroIcon;\r\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.js","names":[],"sources":["../../../../src/react/core/display/Badge.tsx"],"sourcesContent":["/**\n * @zendir/ui - Badge/Tag Component\n *\n * Badge and tag following Astro UX Design System.\n *\n * @example\n * ```tsx\n * <Badge>Default</Badge>\n * <Badge status=\"normal\">Active</Badge>\n * <Badge variant=\"outline\" status=\"caution\">Warning</Badge>\n * <Badge icon={<Icon name=\"satellite\" size={12} />}>Satellite</Badge>\n * ```\n */\n\nimport React, { memo } from \"react\";\nimport { useTheme } from \"../../theme\";\nimport { classNames, type StatusLevel } from \"../../utils\";\n\nexport type BadgeVariant = \"filled\" | \"outline\" | \"subtle\";\nexport type BadgeSize = \"small\" | \"medium\";\n\nexport interface BadgeProps {\n /** Visual variant */\n variant?: BadgeVariant;\n /** Size */\n size?: BadgeSize;\n /** Status-based coloring */\n status?: StatusLevel;\n /** Custom color */\n color?: string;\n /** Icon before text */\n icon?: React.ReactNode;\n /** Removable (shows X button) */\n onRemove?: () => void;\n /** Children */\n children: React.ReactNode;\n /** Custom className */\n className?: string;\n /** Click handler */\n onClick?: () => void;\n}\n\nexport const Badge = memo(function Badge({\n variant = \"filled\",\n size = \"small\",\n status,\n color,\n icon,\n onRemove,\n children,\n className = \"\",\n onClick,\n}: BadgeProps): React.ReactElement {\n const { tokens } = useTheme();\n\n // Determine base color\n const baseColor =\n color ??\n (status ? tokens.colors.status[status] : tokens.colors.accent.primary);\n\n // WCAG AA: choose black or white text based on background luminance\n // Uses relative luminance formula (WCAG 2.1 SC 1.4.3)\n const getContrastText = (bg: string): string => {\n const hex = bg.replace(\"#\", \"\");\n if (hex.length < 6) return \"#ffffff\";\n const r = parseInt(hex.slice(0, 2), 16) / 255;\n const g = parseInt(hex.slice(2, 4), 16) / 255;\n const b = parseInt(hex.slice(4, 6), 16) / 255;\n const toLinear = (c: number) =>\n c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n const L =\n 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);\n // If luminance > 0.179, background is bright → use dark text\n return L > 0.179 ? \"#000000\" : \"#ffffff\";\n };\n\n const sizeConfig = {\n small: {\n padding: `2px ${tokens.spacing.xs}`,\n fontSize: tokens.typography.fontSize.xs,\n height: \"20px\",\n },\n medium: {\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\n fontSize: tokens.typography.fontSize.sm,\n height: \"26px\",\n },\n };\n const config = sizeConfig[size];\n\n const variantStyles: Record<BadgeVariant, React.CSSProperties> = {\n filled: {\n backgroundColor: baseColor,\n color: getContrastText(baseColor), // WCAG AA: auto dark/light text based on bg luminance\n border: \"none\",\n },\n outline: {\n backgroundColor: \"transparent\",\n color: baseColor,\n border: `1px solid ${baseColor}`,\n },\n subtle: {\n backgroundColor: `${baseColor}20`,\n color: baseColor,\n border: \"none\",\n },\n };\n\n const isInteractive = !!onClick;\n\n return (\n <span\n className={classNames(\n \"zendir-badge\",\n `zendir-badge--${variant}`,\n className,\n )}\n onClick={onClick}\n role={isInteractive ? \"button\" : undefined}\n tabIndex={isInteractive ? 0 : undefined}\n onKeyDown={\n onClick\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick();\n }\n }\n : undefined\n }\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: tokens.spacing.xs,\n padding: config.padding,\n height: config.height,\n fontSize: config.fontSize,\n fontWeight: tokens.typography.fontWeight.medium,\n fontFamily: tokens.typography.fontFamily.primary,\n borderRadius: tokens.borderRadius.full,\n cursor: isInteractive ? \"pointer\" : \"default\",\n transition: `all ${tokens.animation.fast}`,\n whiteSpace: \"nowrap\",\n ...variantStyles[variant],\n }}\n >\n {icon}\n {children}\n {onRemove && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n aria-label=\"Remove\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n /* Visual size stays 14px; touch target expanded to 24px via padding (WCAG 2.5.8) */\n padding: \"5px\",\n marginLeft: tokens.spacing.xxs,\n width: \"24px\",\n height: \"24px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n borderRadius: \"50%\",\n cursor: \"pointer\",\n color: \"inherit\",\n opacity: 0.7,\n transition: `opacity ${tokens.animation.fast}`,\n boxSizing: \"border-box\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = \"1\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = \"0.7\";\n }}\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\" />\n </svg>\n </button>\n )}\n </span>\n );\n});\n\nexport default Badge;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Badge.js","names":[],"sources":["../../../../src/react/core/display/Badge.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - Badge/Tag Component\r\n *\r\n * Badge and tag following Astro UX Design System.\r\n *\r\n * @example\r\n * ```tsx\r\n * <Badge>Default</Badge>\r\n * <Badge status=\"normal\">Active</Badge>\r\n * <Badge variant=\"outline\" status=\"caution\">Warning</Badge>\r\n * <Badge icon={<Icon name=\"satellite\" size={12} />}>Satellite</Badge>\r\n * ```\r\n */\r\n\r\nimport React, { memo } from \"react\";\r\nimport { useTheme } from \"../../theme\";\r\nimport { classNames, type StatusLevel } from \"../../utils\";\r\n\r\nexport type BadgeVariant = \"filled\" | \"outline\" | \"subtle\";\r\nexport type BadgeSize = \"small\" | \"medium\";\r\n\r\nexport interface BadgeProps {\r\n /** Visual variant */\r\n variant?: BadgeVariant;\r\n /** Size */\r\n size?: BadgeSize;\r\n /** Status-based coloring */\r\n status?: StatusLevel;\r\n /** Custom color */\r\n color?: string;\r\n /** Icon before text */\r\n icon?: React.ReactNode;\r\n /** Removable (shows X button) */\r\n onRemove?: () => void;\r\n /** Children */\r\n children: React.ReactNode;\r\n /** Custom className */\r\n className?: string;\r\n /** Click handler */\r\n onClick?: () => void;\r\n}\r\n\r\nexport const Badge = memo(function Badge({\r\n variant = \"filled\",\r\n size = \"small\",\r\n status,\r\n color,\r\n icon,\r\n onRemove,\r\n children,\r\n className = \"\",\r\n onClick,\r\n}: BadgeProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n\r\n // Determine base color\r\n const baseColor =\r\n color ??\r\n (status ? tokens.colors.status[status] : tokens.colors.accent.primary);\r\n\r\n // WCAG AA: choose black or white text based on background luminance\r\n // Uses relative luminance formula (WCAG 2.1 SC 1.4.3)\r\n const getContrastText = (bg: string): string => {\r\n const hex = bg.replace(\"#\", \"\");\r\n if (hex.length < 6) return \"#ffffff\";\r\n const r = parseInt(hex.slice(0, 2), 16) / 255;\r\n const g = parseInt(hex.slice(2, 4), 16) / 255;\r\n const b = parseInt(hex.slice(4, 6), 16) / 255;\r\n const toLinear = (c: number) =>\r\n c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\r\n const L =\r\n 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);\r\n // If luminance > 0.179, background is bright → use dark text\r\n return L > 0.179 ? \"#000000\" : \"#ffffff\";\r\n };\r\n\r\n const sizeConfig = {\r\n small: {\r\n padding: `2px ${tokens.spacing.xs}`,\r\n fontSize: tokens.typography.fontSize.xs,\r\n height: \"20px\",\r\n },\r\n medium: {\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n height: \"26px\",\r\n },\r\n };\r\n const config = sizeConfig[size];\r\n\r\n const variantStyles: Record<BadgeVariant, React.CSSProperties> = {\r\n filled: {\r\n backgroundColor: baseColor,\r\n color: getContrastText(baseColor), // WCAG AA: auto dark/light text based on bg luminance\r\n border: \"none\",\r\n },\r\n outline: {\r\n backgroundColor: \"transparent\",\r\n color: baseColor,\r\n border: `1px solid ${baseColor}`,\r\n },\r\n subtle: {\r\n backgroundColor: `${baseColor}20`,\r\n color: baseColor,\r\n border: \"none\",\r\n },\r\n };\r\n\r\n const isInteractive = !!onClick;\r\n\r\n return (\r\n <span\r\n className={classNames(\r\n \"zendir-badge\",\r\n `zendir-badge--${variant}`,\r\n className,\r\n )}\r\n onClick={onClick}\r\n role={isInteractive ? \"button\" : undefined}\r\n tabIndex={isInteractive ? 0 : undefined}\r\n onKeyDown={\r\n onClick\r\n ? (e) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n onClick();\r\n }\r\n }\r\n : undefined\r\n }\r\n style={{\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.xs,\r\n padding: config.padding,\r\n height: config.height,\r\n fontSize: config.fontSize,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n borderRadius: tokens.borderRadius.full,\r\n cursor: isInteractive ? \"pointer\" : \"default\",\r\n transition: `all ${tokens.animation.fast}`,\r\n whiteSpace: \"nowrap\",\r\n ...variantStyles[variant],\r\n }}\r\n >\r\n {icon}\r\n {children}\r\n {onRemove && (\r\n <button\r\n type=\"button\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onRemove();\r\n }}\r\n aria-label=\"Remove\"\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n /* Visual size stays 14px; touch target expanded to 24px via padding (WCAG 2.5.8) */\r\n padding: \"5px\",\r\n marginLeft: tokens.spacing.xxs,\r\n width: \"24px\",\r\n height: \"24px\",\r\n backgroundColor: \"transparent\",\r\n border: \"none\",\r\n borderRadius: \"50%\",\r\n cursor: \"pointer\",\r\n color: \"inherit\",\r\n opacity: 0.7,\r\n transition: `opacity ${tokens.animation.fast}`,\r\n boxSizing: \"border-box\",\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.opacity = \"1\";\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.opacity = \"0.7\";\r\n }}\r\n >\r\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\" />\r\n </svg>\r\n </button>\r\n )}\r\n </span>\r\n );\r\n});\r\n\r\nexport default Badge;\r\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CardHeader.js","names":[],"sources":["../../../../src/react/core/display/CardHeader.tsx"],"sourcesContent":["/**\n * @zendir/ui - CardHeader Component\n *\n * Unified card header component for consistent styling across all cards.\n * Uses HeaderIconWithStatus for status-aware icon display.\n *\n * Features:\n * - Consistent header styling across all theme variants (Regular, Bold, Minimal)\n * - Integrated HeaderIconWithStatus for status indicator\n * - Theme-aware accent colors and styling\n * - Optional badge/tag display\n * - Optional subtitle\n * - Accessibility compliant\n *\n * @example\n * ```tsx\n * <CardHeader\n * icon=\"satellite-transmit\"\n * title=\"ISS\"\n * subtitle=\"SC-001\"\n * status=\"normal\"\n * badge=\"LEO\"\n * badgeColor=\"#3E3CFF\"\n * />\n * ```\n */\n\nimport React, { memo, useMemo } from \"react\";\nimport { useTheme } from \"../../theme\";\nimport { HeaderIconWithStatus } from \"./HeaderIconWithStatus\";\nimport { AstroIcon, type AstroIconName } from \"./AstroIcon\";\nimport { Icon } from \"./Icon\";\nimport { type StatusLevel, getStatusColor, safeAccentText } from \"../../utils\";\n\n// =============================================================================\n// StatusBadge - Compact status indicator for accent lines\n// =============================================================================\n\ninterface StatusBadgeProps {\n status: StatusLevel;\n size?: \"bold\" | \"minimal\";\n}\n\nfunction StatusBadge({\n status,\n size = \"bold\",\n}: StatusBadgeProps): React.ReactElement {\n const { tokens } = useTheme();\n const color = tokens.colors.status[status];\n const label = status.charAt(0).toUpperCase() + status.slice(1);\n const isBold = size === \"bold\";\n\n // Render status shape\n const renderShape = () => {\n const s = isBold ? 6 : 5;\n switch (status) {\n case \"critical\":\n return (\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\n <polygon points=\"6,11 1,2 11,2\" fill={color} />\n </svg>\n );\n case \"serious\":\n return (\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\n <polygon points=\"6,1 11,6 6,11 1,6\" fill={color} />\n </svg>\n );\n case \"caution\":\n return (\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\n <rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" fill={color} />\n </svg>\n );\n case \"standby\":\n return (\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\n <circle\n cx=\"6\"\n cy=\"6\"\n r=\"3.5\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n />\n </svg>\n );\n case \"off\":\n return (\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\n <circle cx=\"6\" cy=\"6\" r=\"3\" fill={color} />\n </svg>\n );\n case \"normal\":\n default:\n return (\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\n <circle cx=\"6\" cy=\"6\" r=\"5\" fill={color} />\n </svg>\n );\n }\n };\n\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: isBold ? \"6px\" : \"4px\",\n padding: isBold ? \"3px 10px\" : \"2px 8px\",\n borderRadius: \"12px\",\n fontSize: isBold ? \"0.6875rem\" : \"0.625rem\", // 11px / 10px in rem (AstroUXDS compliant)\n fontWeight: 500, // AstroUXDS: medium weight\n backgroundColor: `${color}20`,\n color: color,\n flexShrink: 0,\n textTransform: \"uppercase\",\n letterSpacing: \"0.3px\",\n }}\n >\n {renderShape()}\n {label}\n </span>\n );\n}\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CardHeaderProps {\n /** Icon name (AstroIcon) */\n icon: AstroIconName | string;\n /** Main title text */\n title: string;\n /** Optional subtitle text */\n subtitle?: string;\n /** Status level - determines icon color and status indicator */\n status?: StatusLevel;\n /** Badge text (e.g., orbit type, category) */\n badge?: string;\n /** Badge background color */\n badgeColor?: string;\n /** Show pin indicator */\n isPinned?: boolean;\n /** Icon size override */\n iconSize?: number;\n /** Custom icon color (overrides status-based coloring) */\n iconColor?: string;\n /** Hide status indicator (show plain icon) */\n hideStatusIndicator?: boolean;\n /** Additional className */\n className?: string;\n /** Additional styles */\n style?: React.CSSProperties;\n /** Slot for additional content on the right side */\n rightSlot?: React.ReactNode;\n}\n\n// =============================================================================\n// CardHeader Component\n// =============================================================================\n\nexport const CardHeader = memo(function CardHeader({\n icon,\n title,\n subtitle,\n status = \"off\",\n badge,\n badgeColor,\n isPinned,\n iconSize,\n iconColor,\n hideStatusIndicator = false,\n className,\n style,\n rightSlot,\n}: CardHeaderProps) {\n const { tokens, theme } = useTheme();\n\n // Theme detection\n const _isTransparentTheme =\n theme === \"transparent\" ||\n theme === \"transparent-bold\" ||\n theme === \"transparent-minimal\";\n const isBoldVariant = theme === \"transparent-bold\";\n const isMinimalVariant = theme === \"transparent-minimal\";\n const _useGlassMode = isBoldVariant || isMinimalVariant;\n\n // Glass accent colors — use safeAccentText for text to meet WCAG AA 4.5:1\n const glassAccentColor = useMemo(\n () => safeAccentText(tokens.colors.accent.primary),\n [tokens.colors.accent.primary],\n );\n const glassAccentRaw = tokens.colors.accent.primary; // raw color for non-text usage (gradients, glows)\n const glassAccentMuted = `${glassAccentRaw}66`;\n\n // Status color (for icon when showing status)\n const statusColor =\n iconColor ??\n (status ? getStatusColor(status) : tokens.colors.text.secondary);\n\n // Single card heading system (tokens.layout.card.heading)\n const headingConfig = tokens.layout?.card?.heading ?? {\n iconSize: 20,\n iconSizeCompact: 16,\n titleFontSize: \"1.125rem\",\n titleFontWeight: 500,\n gap: 8,\n };\n const defaultIconSize = isMinimalVariant\n ? headingConfig.iconSizeCompact\n : headingConfig.iconSize;\n const finalIconSize = iconSize ?? defaultIconSize;\n const titleFontSize = headingConfig.titleFontSize;\n const titleFontWeight = headingConfig.titleFontWeight;\n const iconTitleGap = headingConfig.gap;\n\n // Badge color (use safe accent text if not provided) — ensures 4.5:1 contrast\n const safeBadgeColor = useMemo(\n () =>\n badgeColor\n ? safeAccentText(badgeColor)\n : safeAccentText(tokens.colors.accent.primary),\n [badgeColor, tokens.colors.accent.primary],\n );\n const finalBadgeColor = safeBadgeColor;\n\n // ═══════════════════════════════════════════════════════════════════════════\n // BOLD VARIANT\n // ═══════════════════════════════════════════════════════════════════════════\n if (isBoldVariant) {\n return (\n <header\n className={className}\n style={{\n position: \"relative\",\n zIndex: 1,\n marginBottom: tokens.spacing.sm,\n ...style,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n }}\n >\n <div\n style={{ display: \"flex\", alignItems: \"center\", gap: iconTitleGap }}\n >\n {/* Icon with status badge — only when icon is provided */}\n {icon &&\n (hideStatusIndicator ? (\n <AstroIcon\n name={icon as AstroIconName}\n size={finalIconSize}\n color={statusColor}\n />\n ) : (\n <HeaderIconWithStatus\n icon={icon as AstroIconName}\n size={finalIconSize}\n status={status}\n />\n ))}\n\n {/* Title with accent color — card heading system */}\n <h3\n style={{\n margin: 0,\n fontSize: titleFontSize,\n fontWeight: titleFontWeight,\n color: glassAccentColor,\n letterSpacing: \"0.5px\",\n textShadow: `0 0 20px ${glassAccentMuted}`,\n }}\n >\n {title}\n </h3>\n\n {/* Pin indicator */}\n {isPinned && (\n <Icon\n name=\"lock\"\n size={12}\n color={tokens.colors.accent.primary}\n />\n )}\n </div>\n\n {/* Right side: Badge + rightSlot */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n }}\n >\n {badge && (\n <span\n style={{\n backgroundColor: `${finalBadgeColor}20`,\n color: finalBadgeColor,\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\n borderRadius: tokens.borderRadius.sm,\n flexShrink: 0,\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n }}\n >\n {badge}\n </span>\n )}\n {rightSlot}\n </div>\n </div>\n\n {/* Subtitle if provided */}\n {subtitle && (\n <span\n style={{\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n marginLeft: finalIconSize + parseInt(tokens.spacing.sm),\n }}\n >\n {subtitle}\n </span>\n )}\n\n {/* Accent line with optional status badge */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n marginTop: tokens.spacing.sm,\n marginBottom: tokens.spacing.xs,\n }}\n >\n <div\n style={{\n flex: 1,\n height: \"2px\",\n background: `linear-gradient(90deg, ${glassAccentRaw} 0%, ${glassAccentMuted} 70%, ${glassAccentMuted}20 100%)`,\n boxShadow: `0 0 8px ${glassAccentMuted}`,\n }}\n />\n {/* Status badge at end of line if status is set and not 'off' */}\n {status && status !== \"off\" && !hideStatusIndicator && (\n <StatusBadge status={status} size=\"bold\" />\n )}\n </div>\n </header>\n );\n }\n\n // ═══════════════════════════════════════════════════════════════════════════\n // MINIMAL VARIANT\n // ═══════════════════════════════════════════════════════════════════════════\n if (isMinimalVariant) {\n return (\n <header\n className={className}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n marginBottom: tokens.spacing.sm,\n position: \"relative\",\n zIndex: 1,\n ...style,\n }}\n >\n {/* Icon with status badge — only when icon is provided */}\n {icon &&\n (hideStatusIndicator ? (\n <AstroIcon\n name={icon as AstroIconName}\n size={finalIconSize}\n color={statusColor}\n style={{ marginRight: tokens.spacing.sm }}\n />\n ) : (\n <HeaderIconWithStatus\n icon={icon as AstroIconName}\n size={finalIconSize}\n status={status}\n style={{ marginRight: tokens.spacing.sm }}\n />\n ))}\n\n {/* Title with accent color — card heading system */}\n <h3\n style={{\n margin: 0,\n fontSize: titleFontSize,\n fontWeight: titleFontWeight,\n color: glassAccentColor,\n textShadow: `0 0 16px ${glassAccentMuted}`,\n letterSpacing: \"0.02em\",\n whiteSpace: \"nowrap\",\n marginRight: \"12px\",\n }}\n >\n {title}\n </h3>\n\n {/* Pin indicator */}\n {isPinned && (\n <Icon\n name=\"lock\"\n size={10}\n color={tokens.colors.accent.primary}\n style={{ marginRight: \"8px\" }}\n />\n )}\n\n {/* Accent line with optional status badge */}\n <div\n style={{\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n minWidth: 40,\n }}\n >\n <div\n style={{\n flex: 1,\n height: \"1px\",\n background: `linear-gradient(90deg, ${glassAccentRaw} 0%, ${glassAccentMuted} 70%, ${glassAccentMuted}20 100%)`,\n }}\n />\n {/* Status badge at end of line if status is set and not 'off' */}\n {status && status !== \"off\" && !hideStatusIndicator && !badge && (\n <StatusBadge status={status} size=\"minimal\" />\n )}\n </div>\n\n {/* Badge (takes precedence over status badge in minimal view for space) */}\n {badge && (\n <span\n style={{\n backgroundColor: `${finalBadgeColor}20`,\n color: finalBadgeColor,\n padding: \"2px 6px\",\n borderRadius: tokens.borderRadius.sm,\n flexShrink: 0,\n fontSize: tokens.typography.fontSize.xxs, // 0.625rem / 10px (AstroUXDS compact)\n fontWeight: tokens.typography.fontWeight.medium,\n marginLeft: \"8px\",\n }}\n >\n {badge}\n </span>\n )}\n\n {rightSlot}\n </header>\n );\n }\n\n // ═══════════════════════════════════════════════════════════════════════════\n // REGULAR THEMES (Dark, Light, Simple Glass)\n // ═══════════════════════════════════════════════════════════════════════════\n return (\n <header\n className={className}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: tokens.spacing.md,\n ...style,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: iconTitleGap }}>\n {/* Icon with status badge — only when icon is provided */}\n {icon &&\n (hideStatusIndicator ? (\n <AstroIcon\n name={icon as AstroIconName}\n size={finalIconSize}\n color={statusColor}\n />\n ) : (\n <HeaderIconWithStatus\n icon={icon as AstroIconName}\n size={finalIconSize}\n status={status}\n />\n ))}\n\n <div style={{ minWidth: 0 }}>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <h3\n style={{\n margin: 0,\n fontSize: titleFontSize,\n fontWeight: titleFontWeight,\n lineHeight: 1.2,\n color: tokens.colors.text.primary,\n }}\n >\n {title}\n </h3>\n\n {/* Pin indicator */}\n {isPinned && (\n <Icon\n name=\"lock\"\n size={12}\n color={tokens.colors.accent.primary}\n />\n )}\n </div>\n\n {subtitle && (\n <span\n style={{\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n }}\n >\n {subtitle}\n </span>\n )}\n </div>\n </div>\n\n {/* Right side: Status badge + Badge + rightSlot */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n }}\n >\n {/* Status badge - consistent with Container styling */}\n {status && status !== \"off\" && !hideStatusIndicator && !rightSlot && (\n <StatusBadge status={status} size=\"bold\" />\n )}\n {badge && (\n <span\n style={{\n backgroundColor: `${finalBadgeColor}20`,\n color: finalBadgeColor,\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\n borderRadius: tokens.borderRadius.sm,\n flexShrink: 0,\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n }}\n >\n {badge}\n </span>\n )}\n {rightSlot}\n </div>\n </header>\n );\n});\n\nexport default CardHeader;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CardHeader.js","names":[],"sources":["../../../../src/react/core/display/CardHeader.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - CardHeader Component\r\n *\r\n * Unified card header component for consistent styling across all cards.\r\n * Uses HeaderIconWithStatus for status-aware icon display.\r\n *\r\n * Features:\r\n * - Consistent header styling across all theme variants (Regular, Bold, Minimal)\r\n * - Integrated HeaderIconWithStatus for status indicator\r\n * - Theme-aware accent colors and styling\r\n * - Optional badge/tag display\r\n * - Optional subtitle\r\n * - Accessibility compliant\r\n *\r\n * @example\r\n * ```tsx\r\n * <CardHeader\r\n * icon=\"satellite-transmit\"\r\n * title=\"ISS\"\r\n * subtitle=\"SC-001\"\r\n * status=\"normal\"\r\n * badge=\"LEO\"\r\n * badgeColor=\"#3E3CFF\"\r\n * />\r\n * ```\r\n */\r\n\r\nimport React, { memo, useMemo } from \"react\";\r\nimport { useTheme } from \"../../theme\";\r\nimport { HeaderIconWithStatus } from \"./HeaderIconWithStatus\";\r\nimport { AstroIcon, type AstroIconName } from \"./AstroIcon\";\r\nimport { Icon } from \"./Icon\";\r\nimport { type StatusLevel, getStatusColor, safeAccentText } from \"../../utils\";\r\n\r\n// =============================================================================\r\n// StatusBadge - Compact status indicator for accent lines\r\n// =============================================================================\r\n\r\ninterface StatusBadgeProps {\r\n status: StatusLevel;\r\n size?: \"bold\" | \"minimal\";\r\n}\r\n\r\nfunction StatusBadge({\r\n status,\r\n size = \"bold\",\r\n}: StatusBadgeProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const color = tokens.colors.status[status];\r\n const label = status.charAt(0).toUpperCase() + status.slice(1);\r\n const isBold = size === \"bold\";\r\n\r\n // Render status shape\r\n const renderShape = () => {\r\n const s = isBold ? 6 : 5;\r\n switch (status) {\r\n case \"critical\":\r\n return (\r\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\r\n <polygon points=\"6,11 1,2 11,2\" fill={color} />\r\n </svg>\r\n );\r\n case \"serious\":\r\n return (\r\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\r\n <polygon points=\"6,1 11,6 6,11 1,6\" fill={color} />\r\n </svg>\r\n );\r\n case \"caution\":\r\n return (\r\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\r\n <rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" fill={color} />\r\n </svg>\r\n );\r\n case \"standby\":\r\n return (\r\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3.5\"\r\n fill=\"none\"\r\n stroke={color}\r\n strokeWidth=\"2\"\r\n />\r\n </svg>\r\n );\r\n case \"off\":\r\n return (\r\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\r\n <circle cx=\"6\" cy=\"6\" r=\"3\" fill={color} />\r\n </svg>\r\n );\r\n case \"normal\":\r\n default:\r\n return (\r\n <svg viewBox=\"0 0 12 12\" width={s} height={s}>\r\n <circle cx=\"6\" cy=\"6\" r=\"5\" fill={color} />\r\n </svg>\r\n );\r\n }\r\n };\r\n\r\n return (\r\n <span\r\n style={{\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n gap: isBold ? \"6px\" : \"4px\",\r\n padding: isBold ? \"3px 10px\" : \"2px 8px\",\r\n borderRadius: \"12px\",\r\n fontSize: isBold ? \"0.6875rem\" : \"0.625rem\", // 11px / 10px in rem (AstroUXDS compliant)\r\n fontWeight: 500, // AstroUXDS: medium weight\r\n backgroundColor: `${color}20`,\r\n color: color,\r\n flexShrink: 0,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.3px\",\r\n }}\r\n >\r\n {renderShape()}\r\n {label}\r\n </span>\r\n );\r\n}\r\n\r\n// =============================================================================\r\n// Types\r\n// =============================================================================\r\n\r\nexport interface CardHeaderProps {\r\n /** Icon name (AstroIcon) */\r\n icon: AstroIconName | string;\r\n /** Main title text */\r\n title: string;\r\n /** Optional subtitle text */\r\n subtitle?: string;\r\n /** Status level - determines icon color and status indicator */\r\n status?: StatusLevel;\r\n /** Badge text (e.g., orbit type, category) */\r\n badge?: string;\r\n /** Badge background color */\r\n badgeColor?: string;\r\n /** Show pin indicator */\r\n isPinned?: boolean;\r\n /** Icon size override */\r\n iconSize?: number;\r\n /** Custom icon color (overrides status-based coloring) */\r\n iconColor?: string;\r\n /** Hide status indicator (show plain icon) */\r\n hideStatusIndicator?: boolean;\r\n /** Additional className */\r\n className?: string;\r\n /** Additional styles */\r\n style?: React.CSSProperties;\r\n /** Slot for additional content on the right side */\r\n rightSlot?: React.ReactNode;\r\n}\r\n\r\n// =============================================================================\r\n// CardHeader Component\r\n// =============================================================================\r\n\r\nexport const CardHeader = memo(function CardHeader({\r\n icon,\r\n title,\r\n subtitle,\r\n status = \"off\",\r\n badge,\r\n badgeColor,\r\n isPinned,\r\n iconSize,\r\n iconColor,\r\n hideStatusIndicator = false,\r\n className,\r\n style,\r\n rightSlot,\r\n}: CardHeaderProps) {\r\n const { tokens, theme } = useTheme();\r\n\r\n // Theme detection\r\n const _isTransparentTheme =\r\n theme === \"transparent\" ||\r\n theme === \"transparent-bold\" ||\r\n theme === \"transparent-minimal\";\r\n const isBoldVariant = theme === \"transparent-bold\";\r\n const isMinimalVariant = theme === \"transparent-minimal\";\r\n const _useGlassMode = isBoldVariant || isMinimalVariant;\r\n\r\n // Glass accent colors — use safeAccentText for text to meet WCAG AA 4.5:1\r\n const glassAccentColor = useMemo(\r\n () => safeAccentText(tokens.colors.accent.primary),\r\n [tokens.colors.accent.primary],\r\n );\r\n const glassAccentRaw = tokens.colors.accent.primary; // raw color for non-text usage (gradients, glows)\r\n const glassAccentMuted = `${glassAccentRaw}66`;\r\n\r\n // Status color (for icon when showing status)\r\n const statusColor =\r\n iconColor ??\r\n (status ? getStatusColor(status) : tokens.colors.text.secondary);\r\n\r\n // Single card heading system (tokens.layout.card.heading)\r\n const headingConfig = tokens.layout?.card?.heading ?? {\r\n iconSize: 20,\r\n iconSizeCompact: 16,\r\n titleFontSize: \"1.125rem\",\r\n titleFontWeight: 500,\r\n gap: 8,\r\n };\r\n const defaultIconSize = isMinimalVariant\r\n ? headingConfig.iconSizeCompact\r\n : headingConfig.iconSize;\r\n const finalIconSize = iconSize ?? defaultIconSize;\r\n const titleFontSize = headingConfig.titleFontSize;\r\n const titleFontWeight = headingConfig.titleFontWeight;\r\n const iconTitleGap = headingConfig.gap;\r\n\r\n // Badge color (use safe accent text if not provided) — ensures 4.5:1 contrast\r\n const safeBadgeColor = useMemo(\r\n () =>\r\n badgeColor\r\n ? safeAccentText(badgeColor)\r\n : safeAccentText(tokens.colors.accent.primary),\r\n [badgeColor, tokens.colors.accent.primary],\r\n );\r\n const finalBadgeColor = safeBadgeColor;\r\n\r\n // ═══════════════════════════════════════════════════════════════════════════\r\n // BOLD VARIANT\r\n // ═══════════════════════════════════════════════════════════════════════════\r\n if (isBoldVariant) {\r\n return (\r\n <header\r\n className={className}\r\n style={{\r\n position: \"relative\",\r\n zIndex: 1,\r\n marginBottom: tokens.spacing.sm,\r\n ...style,\r\n }}\r\n >\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"space-between\",\r\n }}\r\n >\r\n <div\r\n style={{ display: \"flex\", alignItems: \"center\", gap: iconTitleGap }}\r\n >\r\n {/* Icon with status badge — only when icon is provided */}\r\n {icon &&\r\n (hideStatusIndicator ? (\r\n <AstroIcon\r\n name={icon as AstroIconName}\r\n size={finalIconSize}\r\n color={statusColor}\r\n />\r\n ) : (\r\n <HeaderIconWithStatus\r\n icon={icon as AstroIconName}\r\n size={finalIconSize}\r\n status={status}\r\n />\r\n ))}\r\n\r\n {/* Title with accent color — card heading system */}\r\n <h3\r\n style={{\r\n margin: 0,\r\n fontSize: titleFontSize,\r\n fontWeight: titleFontWeight,\r\n color: glassAccentColor,\r\n letterSpacing: \"0.5px\",\r\n textShadow: `0 0 20px ${glassAccentMuted}`,\r\n }}\r\n >\r\n {title}\r\n </h3>\r\n\r\n {/* Pin indicator */}\r\n {isPinned && (\r\n <Icon\r\n name=\"lock\"\r\n size={12}\r\n color={tokens.colors.accent.primary}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Right side: Badge + rightSlot */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n }}\r\n >\r\n {badge && (\r\n <span\r\n style={{\r\n backgroundColor: `${finalBadgeColor}20`,\r\n color: finalBadgeColor,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n borderRadius: tokens.borderRadius.sm,\r\n flexShrink: 0,\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n {badge}\r\n </span>\r\n )}\r\n {rightSlot}\r\n </div>\r\n </div>\r\n\r\n {/* Subtitle if provided */}\r\n {subtitle && (\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n marginLeft: finalIconSize + parseInt(tokens.spacing.sm),\r\n }}\r\n >\r\n {subtitle}\r\n </span>\r\n )}\r\n\r\n {/* Accent line with optional status badge */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n marginTop: tokens.spacing.sm,\r\n marginBottom: tokens.spacing.xs,\r\n }}\r\n >\r\n <div\r\n style={{\r\n flex: 1,\r\n height: \"2px\",\r\n background: `linear-gradient(90deg, ${glassAccentRaw} 0%, ${glassAccentMuted} 70%, ${glassAccentMuted}20 100%)`,\r\n boxShadow: `0 0 8px ${glassAccentMuted}`,\r\n }}\r\n />\r\n {/* Status badge at end of line if status is set and not 'off' */}\r\n {status && status !== \"off\" && !hideStatusIndicator && (\r\n <StatusBadge status={status} size=\"bold\" />\r\n )}\r\n </div>\r\n </header>\r\n );\r\n }\r\n\r\n // ═══════════════════════════════════════════════════════════════════════════\r\n // MINIMAL VARIANT\r\n // ═══════════════════════════════════════════════════════════════════════════\r\n if (isMinimalVariant) {\r\n return (\r\n <header\r\n className={className}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n marginBottom: tokens.spacing.sm,\r\n position: \"relative\",\r\n zIndex: 1,\r\n ...style,\r\n }}\r\n >\r\n {/* Icon with status badge — only when icon is provided */}\r\n {icon &&\r\n (hideStatusIndicator ? (\r\n <AstroIcon\r\n name={icon as AstroIconName}\r\n size={finalIconSize}\r\n color={statusColor}\r\n style={{ marginRight: tokens.spacing.sm }}\r\n />\r\n ) : (\r\n <HeaderIconWithStatus\r\n icon={icon as AstroIconName}\r\n size={finalIconSize}\r\n status={status}\r\n style={{ marginRight: tokens.spacing.sm }}\r\n />\r\n ))}\r\n\r\n {/* Title with accent color — card heading system */}\r\n <h3\r\n style={{\r\n margin: 0,\r\n fontSize: titleFontSize,\r\n fontWeight: titleFontWeight,\r\n color: glassAccentColor,\r\n textShadow: `0 0 16px ${glassAccentMuted}`,\r\n letterSpacing: \"0.02em\",\r\n whiteSpace: \"nowrap\",\r\n marginRight: \"12px\",\r\n }}\r\n >\r\n {title}\r\n </h3>\r\n\r\n {/* Pin indicator */}\r\n {isPinned && (\r\n <Icon\r\n name=\"lock\"\r\n size={10}\r\n color={tokens.colors.accent.primary}\r\n style={{ marginRight: \"8px\" }}\r\n />\r\n )}\r\n\r\n {/* Accent line with optional status badge */}\r\n <div\r\n style={{\r\n flex: 1,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n minWidth: 40,\r\n }}\r\n >\r\n <div\r\n style={{\r\n flex: 1,\r\n height: \"1px\",\r\n background: `linear-gradient(90deg, ${glassAccentRaw} 0%, ${glassAccentMuted} 70%, ${glassAccentMuted}20 100%)`,\r\n }}\r\n />\r\n {/* Status badge at end of line if status is set and not 'off' */}\r\n {status && status !== \"off\" && !hideStatusIndicator && !badge && (\r\n <StatusBadge status={status} size=\"minimal\" />\r\n )}\r\n </div>\r\n\r\n {/* Badge (takes precedence over status badge in minimal view for space) */}\r\n {badge && (\r\n <span\r\n style={{\r\n backgroundColor: `${finalBadgeColor}20`,\r\n color: finalBadgeColor,\r\n padding: \"2px 6px\",\r\n borderRadius: tokens.borderRadius.sm,\r\n flexShrink: 0,\r\n fontSize: tokens.typography.fontSize.xxs, // 0.625rem / 10px (AstroUXDS compact)\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n marginLeft: \"8px\",\r\n }}\r\n >\r\n {badge}\r\n </span>\r\n )}\r\n\r\n {rightSlot}\r\n </header>\r\n );\r\n }\r\n\r\n // ═══════════════════════════════════════════════════════════════════════════\r\n // REGULAR THEMES (Dark, Light, Simple Glass)\r\n // ═══════════════════════════════════════════════════════════════════════════\r\n return (\r\n <header\r\n className={className}\r\n style={{\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n marginBottom: tokens.spacing.md,\r\n ...style,\r\n }}\r\n >\r\n <div style={{ display: \"flex\", alignItems: \"center\", gap: iconTitleGap }}>\r\n {/* Icon with status badge — only when icon is provided */}\r\n {icon &&\r\n (hideStatusIndicator ? (\r\n <AstroIcon\r\n name={icon as AstroIconName}\r\n size={finalIconSize}\r\n color={statusColor}\r\n />\r\n ) : (\r\n <HeaderIconWithStatus\r\n icon={icon as AstroIconName}\r\n size={finalIconSize}\r\n status={status}\r\n />\r\n ))}\r\n\r\n <div style={{ minWidth: 0 }}>\r\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\r\n <h3\r\n style={{\r\n margin: 0,\r\n fontSize: titleFontSize,\r\n fontWeight: titleFontWeight,\r\n lineHeight: 1.2,\r\n color: tokens.colors.text.primary,\r\n }}\r\n >\r\n {title}\r\n </h3>\r\n\r\n {/* Pin indicator */}\r\n {isPinned && (\r\n <Icon\r\n name=\"lock\"\r\n size={12}\r\n color={tokens.colors.accent.primary}\r\n />\r\n )}\r\n </div>\r\n\r\n {subtitle && (\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n }}\r\n >\r\n {subtitle}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Right side: Status badge + Badge + rightSlot */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n }}\r\n >\r\n {/* Status badge - consistent with Container styling */}\r\n {status && status !== \"off\" && !hideStatusIndicator && !rightSlot && (\r\n <StatusBadge status={status} size=\"bold\" />\r\n )}\r\n {badge && (\r\n <span\r\n style={{\r\n backgroundColor: `${finalBadgeColor}20`,\r\n color: finalBadgeColor,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n borderRadius: tokens.borderRadius.sm,\r\n flexShrink: 0,\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n {badge}\r\n </span>\r\n )}\r\n {rightSlot}\r\n </div>\r\n </header>\r\n );\r\n});\r\n\r\nexport default CardHeader;\r\n"],"mappings":"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"}