Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 104 additions & 5 deletions compat/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as _hooks from '../../hooks';
import * as preact1 from 'preact';
import { JSXInternal } from '../../src/jsx';
import * as _Suspense from './suspense';
import { CamelCaseSVGAttributes } from './svg-camel-case';

declare namespace preact {
export interface FunctionComponent<P = {}> {
Expand Down Expand Up @@ -102,9 +103,40 @@ declare namespace preact {
// export default React;
export = React;
export as namespace React;
// Compat JSX namespace with React-compatible camelCase SVG attributes
declare namespace CompatJSX {
export type LibraryManagedAttributes<Component, Props> =
JSXInternal.LibraryManagedAttributes<Component, Props>;

export type IntrinsicAttributes = JSXInternal.IntrinsicAttributes;

export type ElementType<P = any> = JSXInternal.ElementType<P>;

export type Element = JSXInternal.Element;

export type ElementClass = JSXInternal.ElementClass;

export type ElementAttributesProperty = JSXInternal.ElementAttributesProperty;

export type ElementChildrenAttribute = JSXInternal.ElementChildrenAttribute;

// Use compat's IntrinsicSVGElements with camelCase SVG attributes
export interface IntrinsicSVGElements
extends React.CompatIntrinsicSVGElements {}

export type IntrinsicMathMLElements = JSXInternal.IntrinsicMathMLElements;

export type IntrinsicHTMLElements = JSXInternal.IntrinsicHTMLElements;

export interface IntrinsicElements
extends IntrinsicSVGElements,
IntrinsicMathMLElements,
IntrinsicHTMLElements {}
}

Comment thread
rschristian marked this conversation as resolved.
Outdated
declare namespace React {
// Export JSX
export import JSX = JSXInternal;
// Export JSX with React-compatible camelCase SVG attributes
export import JSX = CompatJSX;

// Hooks
export import CreateHandle = _hooks.CreateHandle;
Expand Down Expand Up @@ -175,14 +207,81 @@ declare namespace React {
export import DetailedHTMLProps = preact1.DetailedHTMLProps;
export import CSSProperties = preact1.CSSProperties;

// Compat SVG attributes include React-compatible camelCase properties
// that are not available in core Preact
export interface SVGProps<T extends EventTarget>
extends preact1.SVGAttributes<T>,
preact1.ClassAttributes<T> {}
preact1.ClassAttributes<T>,
CamelCaseSVGAttributes {}

interface SVGAttributes<T extends EventTarget = SVGElement>
extends preact1.SVGAttributes<T> {}
extends preact1.SVGAttributes<T>,
CamelCaseSVGAttributes {}

// Compat IntrinsicSVGElements uses SVGAttributes with camelCase properties
interface CompatIntrinsicSVGElements {
Comment thread
rschristian marked this conversation as resolved.
Outdated
svg: SVGAttributes<SVGSVGElement>;
animate: SVGAttributes<SVGAnimateElement>;
circle: SVGAttributes<SVGCircleElement>;
animateMotion: SVGAttributes<SVGAnimateMotionElement>;
animateTransform: SVGAttributes<SVGAnimateTransformElement>;
clipPath: SVGAttributes<SVGClipPathElement>;
defs: SVGAttributes<SVGDefsElement>;
desc: SVGAttributes<SVGDescElement>;
ellipse: SVGAttributes<SVGEllipseElement>;
feBlend: SVGAttributes<SVGFEBlendElement>;
feColorMatrix: SVGAttributes<SVGFEColorMatrixElement>;
feComponentTransfer: SVGAttributes<SVGFEComponentTransferElement>;
feComposite: SVGAttributes<SVGFECompositeElement>;
feConvolveMatrix: SVGAttributes<SVGFEConvolveMatrixElement>;
feDiffuseLighting: SVGAttributes<SVGFEDiffuseLightingElement>;
feDisplacementMap: SVGAttributes<SVGFEDisplacementMapElement>;
feDistantLight: SVGAttributes<SVGFEDistantLightElement>;
feDropShadow: SVGAttributes<SVGFEDropShadowElement>;
feFlood: SVGAttributes<SVGFEFloodElement>;
feFuncA: SVGAttributes<SVGFEFuncAElement>;
feFuncB: SVGAttributes<SVGFEFuncBElement>;
feFuncG: SVGAttributes<SVGFEFuncGElement>;
feFuncR: SVGAttributes<SVGFEFuncRElement>;
feGaussianBlur: SVGAttributes<SVGFEGaussianBlurElement>;
feImage: SVGAttributes<SVGFEImageElement>;
feMerge: SVGAttributes<SVGFEMergeElement>;
feMergeNode: SVGAttributes<SVGFEMergeNodeElement>;
feMorphology: SVGAttributes<SVGFEMorphologyElement>;
feOffset: SVGAttributes<SVGFEOffsetElement>;
fePointLight: SVGAttributes<SVGFEPointLightElement>;
feSpecularLighting: SVGAttributes<SVGFESpecularLightingElement>;
feSpotLight: SVGAttributes<SVGFESpotLightElement>;
feTile: SVGAttributes<SVGFETileElement>;
feTurbulence: SVGAttributes<SVGFETurbulenceElement>;
filter: SVGAttributes<SVGFilterElement>;
foreignObject: SVGAttributes<SVGForeignObjectElement>;
g: SVGAttributes<SVGGElement>;
image: SVGAttributes<SVGImageElement>;
line: SVGAttributes<SVGLineElement>;
linearGradient: SVGAttributes<SVGLinearGradientElement>;
marker: SVGAttributes<SVGMarkerElement>;
mask: SVGAttributes<SVGMaskElement>;
metadata: SVGAttributes<SVGMetadataElement>;
mpath: SVGAttributes<SVGMPathElement>;
path: SVGAttributes<SVGPathElement>;
pattern: SVGAttributes<SVGPatternElement>;
polygon: SVGAttributes<SVGPolygonElement>;
polyline: SVGAttributes<SVGPolylineElement>;
radialGradient: SVGAttributes<SVGRadialGradientElement>;
rect: SVGAttributes<SVGRectElement>;
set: SVGAttributes<SVGSetElement>;
stop: SVGAttributes<SVGStopElement>;
switch: SVGAttributes<SVGSwitchElement>;
symbol: SVGAttributes<SVGSymbolElement>;
text: SVGAttributes<SVGTextElement>;
textPath: SVGAttributes<SVGTextPathElement>;
tspan: SVGAttributes<SVGTSpanElement>;
use: SVGAttributes<SVGUseElement>;
view: SVGAttributes<SVGViewElement>;
}

interface ReactSVG extends JSXInternal.IntrinsicSVGElements {}
interface ReactSVG extends CompatIntrinsicSVGElements {}

export import AriaAttributes = preact1.AriaAttributes;

Expand Down
124 changes: 124 additions & 0 deletions compat/src/svg-camel-case.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { Signalish } from '../../src/dom';

/**
* React-compatible camelCase SVG attributes.
* These are only supported when using preact/compat, which converts
* camelCase attribute names to their kebab-case equivalents at runtime.
*
* Core Preact does not support these - use the kebab-case versions instead
* (e.g., 'stroke-width' instead of 'strokeWidth').
*/
export interface CamelCaseSVGAttributes {
Comment thread
rschristian marked this conversation as resolved.
Outdated
alignmentBaseline?: Signalish<
| 'auto'
| 'baseline'
| 'before-edge'
| 'text-before-edge'
| 'middle'
| 'central'
| 'after-edge'
| 'text-after-edge'
| 'ideographic'
| 'alphabetic'
| 'hanging'
| 'mathematical'
| 'inherit'
| undefined
>;
allowReorder?: Signalish<'no' | 'yes' | undefined>;
/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/arabic-form */
arabicForm?: Signalish<
'initial' | 'medial' | 'terminal' | 'isolated' | undefined
>;
baselineShift?: Signalish<number | string | undefined>;
capHeight?: Signalish<number | string | undefined>;
clipPath?: Signalish<string | undefined>;
clipRule?: Signalish<number | string | undefined>;
colorInterpolation?: Signalish<number | string | undefined>;
colorInterpolationFilters?: Signalish<
'auto' | 'sRGB' | 'linearRGB' | 'inherit' | undefined
>;
colorProfile?: Signalish<number | string | undefined>;
colorRendering?: Signalish<number | string | undefined>;
contentScriptType?: Signalish<number | string | undefined>;
contentStyleType?: Signalish<number | string | undefined>;
dominantBaseline?: Signalish<number | string | undefined>;
enableBackground?: Signalish<number | string | undefined>;
fillOpacity?: Signalish<number | string | undefined>;
fillRule?: Signalish<'nonzero' | 'evenodd' | 'inherit' | undefined>;
floodColor?: Signalish<number | string | undefined>;
floodOpacity?: Signalish<number | string | undefined>;
fontFamily?: Signalish<string | undefined>;
fontSize?: Signalish<number | string | undefined>;
fontSizeAdjust?: Signalish<number | string | undefined>;
fontStretch?: Signalish<number | string | undefined>;
fontStyle?: Signalish<number | string | undefined>;
fontVariant?: Signalish<number | string | undefined>;
fontWeight?: Signalish<number | string | undefined>;
glyphName?: Signalish<number | string | undefined>;
glyphOrientationHorizontal?: Signalish<number | string | undefined>;
glyphOrientationVertical?: Signalish<number | string | undefined>;
horizAdvX?: Signalish<number | string | undefined>;
horizOriginX?: Signalish<number | string | undefined>;
hrefLang?: Signalish<string | undefined>;
imageRendering?: Signalish<number | string | undefined>;
letterSpacing?: Signalish<number | string | undefined>;
lightingColor?: Signalish<number | string | undefined>;
markerEnd?: Signalish<string | undefined>;
markerMid?: Signalish<string | undefined>;
markerStart?: Signalish<string | undefined>;
overlinePosition?: Signalish<number | string | undefined>;
overlineThickness?: Signalish<number | string | undefined>;
paintOrder?: Signalish<number | string | undefined>;
panose1?: Signalish<number | string | undefined>;
pointerEvents?: Signalish<number | string | undefined>;
renderingIntent?: Signalish<number | string | undefined>;
repeatCount?: Signalish<number | string | undefined>;
repeatDur?: Signalish<number | string | undefined>;
shapeRendering?: Signalish<number | string | undefined>;
stopColor?: Signalish<string | undefined>;
stopOpacity?: Signalish<number | string | undefined>;
strikethroughPosition?: Signalish<number | string | undefined>;
strikethroughThickness?: Signalish<number | string | undefined>;
strokeDasharray?: Signalish<string | number | undefined>;
strokeDashoffset?: Signalish<string | number | undefined>;
strokeLinecap?: Signalish<
'butt' | 'round' | 'square' | 'inherit' | undefined
>;
strokeLinejoin?: Signalish<
'miter' | 'round' | 'bevel' | 'inherit' | undefined
>;
strokeMiterlimit?: Signalish<string | number | undefined>;
strokeOpacity?: Signalish<number | string | undefined>;
strokeWidth?: Signalish<number | string | undefined>;
textAnchor?: Signalish<string | undefined>;
textDecoration?: Signalish<number | string | undefined>;
textRendering?: Signalish<number | string | undefined>;
transformOrigin?: Signalish<string | undefined>;
underlinePosition?: Signalish<number | string | undefined>;
underlineThickness?: Signalish<number | string | undefined>;
unicodeBidi?: Signalish<number | string | undefined>;
unicodeRange?: Signalish<number | string | undefined>;
unitsPerEm?: Signalish<number | string | undefined>;
vAlphabetic?: Signalish<number | string | undefined>;
vectorEffect?: Signalish<number | string | undefined>;
vertAdvY?: Signalish<number | string | undefined>;
vertOriginX?: Signalish<number | string | undefined>;
vertOriginY?: Signalish<number | string | undefined>;
vHanging?: Signalish<number | string | undefined>;
vIdeographic?: Signalish<number | string | undefined>;
vMathematical?: Signalish<number | string | undefined>;
wordSpacing?: Signalish<number | string | undefined>;
writingMode?: Signalish<number | string | undefined>;
xHeight?: Signalish<number | string | undefined>;
xlinkActuate?: Signalish<string | undefined>;
xlinkArcrole?: Signalish<string | undefined>;
xlinkHref?: Signalish<string | undefined>;
xlinkRole?: Signalish<string | undefined>;
xlinkShow?: Signalish<string | undefined>;
xlinkTitle?: Signalish<string | undefined>;
xlinkType?: Signalish<string | undefined>;
xmlBase?: Signalish<string | undefined>;
xmlLang?: Signalish<string | undefined>;
xmlSpace?: Signalish<string | undefined>;
}
22 changes: 22 additions & 0 deletions compat/test/ts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,25 @@ React.render(
<SimpleComponentWithContextAsProvider />,
document.createElement('div')
);

// SVG camelCase attributes should be available in preact/compat
// These are React-compatible and converted to kebab-case at runtime
const svgCasingTest = (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<circle fill="blue" strokeWidth="2" cx="24" cy="24" r="20" />
</svg>
);

// Standard kebab-case SVG attributes should also work
const svgKebabCaseTest = (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<circle fill="blue" stroke-width="2" cx="24" cy="24" r="20" />
</svg>
);

// More camelCase SVG attributes that should work in compat
const fillOpacityTest = <rect fillOpacity="0.5" />;
const stopColorTest = <stop stopColor="red" />;
const fontFamilyTest = <text fontFamily="Arial" />;
const strokeDasharrayTest = <path strokeDasharray="5,5" />;
const textAnchorTest = <text textAnchor="middle" />;
Comment thread
rschristian marked this conversation as resolved.
Outdated
Loading