@@ -16,7 +16,7 @@ export interface IconDefinitionBase {
1616
1717/**
1818 * On-disk / nested icon data: `svgPathData` (preferred) or deprecated `svgPath` (at least one is required at
19- * runtime for rendering; if both are set, `svgPathData` takes precedence in { @link resolveSvgPathData} ).
19+ * runtime for rendering; if both are set, `svgPathData` takes precedence when path data is resolved ).
2020 */
2121export interface IconDefinition extends IconDefinitionBase {
2222 svgPathData ?: string | SVGPathObject [ ] ;
@@ -26,12 +26,6 @@ export interface IconDefinition extends IconDefinitionBase {
2626 svgPath ?: string | SVGPathObject [ ] ;
2727}
2828
29- /**
30- * {@link createIconBase } and rendering use this after {@link resolveSvgPathData } — not part of the public
31- * type surface.
32- */
33- type NormalizedIconDefinition = Required < Pick < IconDefinition , 'svgPathData' > > & IconDefinition ;
34-
3529/**
3630 * Nested (current) public API: `{ icon, rhUiIcon?, name? }` as produced by the icon generator and
3731 * `createIconBase` consumers.
@@ -43,24 +37,17 @@ export interface CreateIconBaseProps {
4337}
4438
4539/**
46- * **Flat (legacy) public API** for {@link createIcon} only — not an alias of {@link IconDefinition} so
47- * the legacy shape is obvious at the call site. `createIcon` maps this to { @link CreateIconBaseProps} .
40+ * @deprecated Prefer {@link createIconBase} with a nested {@link IconDefinition} using `svgPathData` instead
41+ * of this flat `createIcon` shape and legacy `svgPath` field .
4842 */
49- export interface CreateIconLegacyProps {
43+ export interface CreateIconProps {
5044 name ?: string ;
5145 width : number ;
5246 height : number ;
5347 xOffset ?: number ;
5448 yOffset ?: number ;
55- svgPathData ?: string | SVGPathObject [ ] ;
56- /**
57- * @deprecated Use {@link CreateIconLegacyProps.svgPathData} instead.
58- */
5949 svgPath ?: string | SVGPathObject [ ] ;
6050 svgClassName ?: string ;
61- /**
62- * Optional second variant for the `set="rh-ui"` / nested-inner-SVG layout, matching {@link createIconBase}.
63- */
6451 rhUiIcon ?: IconDefinition | null ;
6552}
6653
@@ -75,44 +62,19 @@ export interface SVGIconProps extends Omit<React.HTMLProps<SVGElement>, 'ref'> {
7562
7663let currentId = 0 ;
7764
78- /** Returns path data from `svgPathData` or deprecated `svgPath` (prefers `svgPathData` when both exist). */
79- function resolveSvgPathData ( icon : IconDefinition ) : string | SVGPathObject [ ] {
80- if ( 'svgPathData' in icon && icon . svgPathData !== undefined ) {
81- return icon . svgPathData ;
82- }
83- if ( 'svgPath' in icon && icon . svgPath !== undefined ) {
84- return icon . svgPath ;
85- }
86- throw new Error ( '@patternfly/react-icons: IconDefinition must define svgPathData or svgPath' ) ;
87- }
88-
89- /** Produces a single {@link NormalizedIconDefinition} for internal rendering. */
90- function normalizeIconDefinition ( icon : IconDefinition ) : NormalizedIconDefinition {
91- return {
92- name : icon . name ,
93- width : icon . width ,
94- height : icon . height ,
95- svgPathData : resolveSvgPathData ( icon ) ,
96- xOffset : icon . xOffset ,
97- yOffset : icon . yOffset ,
98- svgClassName : icon . svgClassName
99- } ;
100- }
101-
102- /** Renders <path> element(s) from resolved (normalized) path data. */
103- function pathElementsFromResolvedData ( svgPathData : string | SVGPathObject [ ] ) : ReactNode {
104- return Array . isArray ( svgPathData ) ? (
65+ /** Renders the same path markup as the historical `createIcon` implementation. */
66+ function getSvgPaths ( svgPathData : string | SVGPathObject [ ] | undefined ) : ReactNode {
67+ return svgPathData && Array . isArray ( svgPathData ) ? (
10568 svgPathData . map ( ( pathObject , index ) => (
10669 < path className = { pathObject . className } key = { `${ pathObject . path } -${ index } ` } d = { pathObject . path } />
10770 ) )
10871 ) : (
109- < path d = { svgPathData } />
72+ < path d = { svgPathData as string } />
11073 ) ;
11174}
11275
113- /** Renders an inner `<svg>` with viewBox and path(s) for the dual-SVG (CSS swap) layout. */
114- const createSvg = ( icon : NormalizedIconDefinition , iconClassName : string ) => {
115- const { xOffset, yOffset, width, height, svgPathData, svgClassName } = icon ;
76+ const createSvg = ( icon : IconDefinition , iconClassName : string ) => {
77+ const { xOffset, yOffset, width, height, svgPathData, svgClassName } = icon ?? { } ;
11678 const _xOffset = xOffset ?? 0 ;
11779 const _yOffset = yOffset ?? 0 ;
11880 const viewBox = [ _xOffset , _yOffset , width , height ] . join ( ' ' ) ;
@@ -128,62 +90,29 @@ const createSvg = (icon: NormalizedIconDefinition, iconClassName: string) => {
12890
12991 return (
13092 < svg viewBox = { viewBox } className = { classNames . join ( ' ' ) } >
131- { pathElementsFromResolvedData ( svgPathData ) }
93+ { getSvgPaths ( svgPathData ) }
13294 </ svg >
13395 ) ;
13496} ;
13597
13698/**
137- * Preferred factory for **nested** icon config (`icon` and optional `rhUiIcon`). Package-generated icons use this.
138- *
139- * @param name Optional display name for the component; falls back to `icon.name` when not set.
140- * @see {@link createIcon } for the legacy **flat** argument shape.
99+ * Factory for the nested / current icon API. Behavior matches the pre-split `createIcon` on `main` (this name
100+ * replaces the original export). For path mapping from the flat `svgPath` shape, use {@link createIcon} only.
141101 */
142102export function createIconBase ( {
143103 name,
144104 icon,
145105 rhUiIcon = null
146106} : CreateIconBaseProps ) : React . ComponentClass < SVGIconProps > {
147- if ( icon == null ) {
148- const label = name != null ? ` (name: ${ String ( name ) } )` : '' ;
149- throw new Error ( `@patternfly/react-icons: createIconBase requires an \`icon\` definition${ label } .` ) ;
150- }
151- const normalizedIcon = normalizeIconDefinition ( icon ) ;
152- const normalizedRhUiIcon = rhUiIcon != null ? normalizeIconDefinition ( rhUiIcon ) : null ;
153- const displayName = name ?? icon . name ;
154-
155107 return class SVGIcon extends Component < SVGIconProps > {
156- static displayName = displayName ;
108+ static displayName = name ;
157109
158110 id = `icon-title-${ currentId ++ } ` ;
159111
160- private warnedMissingRhUi = false ;
161-
162112 static defaultProps : SVGIconProps = {
163113 noDefaultStyle : false
164114 } ;
165115
166- private warnIfMissingRhUiMapping = ( ) => {
167- if ( this . warnedMissingRhUi ) {
168- return ;
169- }
170- if ( this . props . set === 'rh-ui' && normalizedRhUiIcon === null ) {
171- this . warnedMissingRhUi = true ;
172- // eslint-disable-next-line no-console -- intentional dev-facing warning for invalid set/rh-ui pairing
173- console . warn (
174- `Set "rh-ui" was provided for ${ displayName } , but no rh-ui icon data exists for this icon. The default icon will be rendered.`
175- ) ;
176- }
177- } ;
178-
179- componentDidMount ( ) {
180- this . warnIfMissingRhUiMapping ( ) ;
181- }
182-
183- componentDidUpdate ( ) {
184- this . warnIfMissingRhUiMapping ( ) ;
185- }
186-
187116 /** Renders one root `<svg>`; either a single variant or nested inner SVGs for RH UI swap. */
188117 render ( ) {
189118 const { title, className : propsClassName , set, noDefaultStyle, ...props } = this . props ;
@@ -195,10 +124,16 @@ export function createIconBase({
195124 classNames . push ( propsClassName ) ;
196125 }
197126
198- if ( set !== undefined || normalizedRhUiIcon === null ) {
199- const iconData : NormalizedIconDefinition =
200- set === 'rh-ui' && normalizedRhUiIcon !== null ? normalizedRhUiIcon : normalizedIcon ;
201- const { xOffset, yOffset, width, height, svgPathData, svgClassName } = iconData ;
127+ if ( set === 'rh-ui' && rhUiIcon === null ) {
128+ // eslint-disable-next-line no-console -- same behavior as main branch createIcon
129+ console . warn (
130+ `Set "rh-ui" was provided for ${ name } , but no rh-ui icon data exists for this icon. The default icon will be rendered.`
131+ ) ;
132+ }
133+
134+ if ( ( set === undefined && rhUiIcon === null ) || set !== undefined ) {
135+ const iconData = set !== undefined && set === 'rh-ui' && rhUiIcon !== null ? rhUiIcon : icon ;
136+ const { xOffset, yOffset, width, height, svgPathData, svgClassName } = iconData ?? { } ;
202137 const _xOffset = xOffset ?? 0 ;
203138 const _yOffset = yOffset ?? 0 ;
204139 const viewBox = [ _xOffset , _yOffset , width , height ] . join ( ' ' ) ;
@@ -207,8 +142,6 @@ export function createIconBase({
207142 classNames . push ( svgClassName ) ;
208143 }
209144
210- const svgPaths = pathElementsFromResolvedData ( svgPathData ) ;
211-
212145 return (
213146 < svg
214147 className = { classNames . join ( ' ' ) }
@@ -222,7 +155,7 @@ export function createIconBase({
222155 { ...( props as Omit < React . SVGProps < SVGElement > , 'ref' > ) } // Lie.
223156 >
224157 { hasTitle && < title id = { this . id } > { title } </ title > }
225- { svgPaths }
158+ { getSvgPaths ( svgPathData ) }
226159 </ svg >
227160 ) ;
228161 }
@@ -238,20 +171,20 @@ export function createIconBase({
238171 { ...( props as Omit < React . SVGProps < SVGElement > , 'ref' > ) } // Lie.
239172 >
240173 { hasTitle && < title id = { this . id } > { title } </ title > }
241- { createSvg ( normalizedIcon , 'pf-v6-icon-default' ) }
242- { normalizedRhUiIcon && createSvg ( normalizedRhUiIcon , 'pf-v6-icon-rh-ui' ) }
174+ { icon && createSvg ( icon , 'pf-v6-icon-default' ) }
175+ { rhUiIcon && createSvg ( rhUiIcon , 'pf-v6-icon-rh-ui' ) }
243176 </ svg >
244177 ) ;
245178 }
246179 } ;
247180}
248181
249182/**
250- * Flat **legacy** entry point: turn {@link CreateIconLegacyProps} into a nested
251- * `icon: IconDefinition` with `svgPathData` resolved , then call {@link createIconBase} (all legacy mapping
252- * lives in this function). Prefer {@link createIconBase} for the nested `icon` / `rhUiIcon` shape .
183+ * Flat **legacy** entry point: turn {@link CreateIconProps} (`svgPath` + layout fields) into a nested
184+ * `icon: IconDefinition` with `svgPathData` set from `svgPath` , then call {@link createIconBase}. Use
185+ * {@link createIconBase} directly for nested `icon` objects that already use `svgPathData` .
253186 */
254- export function createIcon ( legacy : CreateIconLegacyProps ) : React . ComponentClass < SVGIconProps > {
187+ export function createIcon ( legacy : CreateIconProps ) : React . ComponentClass < SVGIconProps > {
255188 const { rhUiIcon = null , ...flat } = legacy ;
256189 const icon : IconDefinition = {
257190 name : flat . name ,
@@ -260,8 +193,7 @@ export function createIcon(legacy: CreateIconLegacyProps): React.ComponentClass<
260193 xOffset : flat . xOffset ,
261194 yOffset : flat . yOffset ,
262195 svgClassName : flat . svgClassName ,
263- // Fold deprecated svgPath (and de-dupe vs svgPathData) in one place, then omit svgPath in the object.
264- svgPathData : resolveSvgPathData ( flat as IconDefinition )
196+ svgPathData : flat . svgPath
265197 } ;
266198 return createIconBase ( { name : icon . name , icon, rhUiIcon } ) ;
267199}
0 commit comments