Skip to content

Commit

Permalink
feat: implement SvgWithCss and SvgWithCssUri with Animated support
Browse files Browse the repository at this point in the history
Expose types of SvgCss, SvgWithCss, SvgCssUri & SvgWithCssUri
Move css-select and css-tree to peerDependencies & devDependencies
  • Loading branch information
msand committed Oct 23, 2019
1 parent 7370225 commit 6fb8dd5
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 27 deletions.
42 changes: 31 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,12 @@
"semantic-release": "semantic-release"
},
"peerDependencies": {
"css-select": "^2.0.2",
"css-tree": "^1.0.0-alpha.37",
"react": "*",
"react-native": ">=0.50.0"
},
"dependencies": {
"css-select": "^2.0.2",
"css-tree": "^1.0.0-alpha.36"
},
"dependencies": {},
"devDependencies": {
"@react-native-community/bob": "^0.7.0",
"@react-native-community/eslint-config": "^0.0.5",
Expand All @@ -63,6 +62,8 @@
"@types/react-native": "^0.60.21",
"babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0",
"css-select": "^2.0.2",
"css-tree": "^1.0.0-alpha.37",
"eslint": "^6.5.1",
"eslint-plugin-flowtype": "^4.3.0",
"eslint-plugin-prettier": "^3.1.1",
Expand Down
10 changes: 9 additions & 1 deletion src/ReactNativeSVG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ import Pattern, { RNSVGPattern } from './elements/Pattern';
import Mask, { RNSVGMask } from './elements/Mask';
import Marker, { RNSVGMarker } from './elements/Marker';
import { parse, SvgAst, SvgFromUri, SvgFromXml, SvgUri, SvgXml } from './xml';
import { SvgCss, SvgCssUri, inlineStyles } from './css';
import {
SvgCss,
SvgCssUri,
SvgWithCss,
SvgWithCssUri,
inlineStyles,
} from './css';

export {
Svg,
Expand Down Expand Up @@ -57,6 +63,8 @@ export {
SvgXml,
SvgCss,
SvgCssUri,
SvgWithCss,
SvgWithCssUri,
inlineStyles,
Shape,
RNSVGMarker,
Expand Down
67 changes: 64 additions & 3 deletions src/css.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import React, { useEffect, useMemo, useState } from 'react';
import React, { Component, useEffect, useMemo, useState } from 'react';
import {
camelCase,
err,
fetchText,
JsxAST,
Middleware,
parse,
Styles,
SvgAst,
UriProps,
UriState,
XmlAST,
XmlProps,
XmlState,
} from './xml';
import csstree, {
Atrule,
Expand Down Expand Up @@ -595,7 +598,9 @@ const parseProps = {
* @author strarsis <strarsis@gmail.com>
* @author modified by: msand <msand@abo.fi>
*/
export function inlineStyles(document: XmlAST) {
export const inlineStyles: Middleware = function inlineStyles(
document: XmlAST,
) {
// collect <style/>s
const styleElements = querySelectorAll('style', document);

Expand Down Expand Up @@ -685,7 +690,7 @@ export function inlineStyles(document: XmlAST) {
}

return document;
}
};

export function SvgCss(props: XmlProps) {
const { xml, override } = props;
Expand All @@ -708,3 +713,59 @@ export function SvgCssUri(props: UriProps) {
}, [uri]);
return <SvgCss xml={xml} override={props} />;
}

// Extending Component is required for Animated support.

export class SvgWithCss extends Component<XmlProps, XmlState> {
state = { ast: null };
componentDidMount() {
this.parse(this.props.xml);
}
componentDidUpdate(prevProps: { xml: string | null }) {
const { xml } = this.props;
if (xml !== prevProps.xml) {
this.parse(xml);
}
}
parse(xml: string | null) {
try {
this.setState({ ast: xml ? parse(xml, inlineStyles) : null });
} catch (e) {
console.error(e);
}
}
render() {
const {
props,
state: { ast },
} = this;
return <SvgAst ast={ast} override={props.override || props} />;
}
}

export class SvgWithCssUri extends Component<UriProps, UriState> {
state = { xml: null };
componentDidMount() {
this.fetch(this.props.uri);
}
componentDidUpdate(prevProps: { uri: string | null }) {
const { uri } = this.props;
if (uri !== prevProps.uri) {
this.fetch(uri);
}
}
async fetch(uri: string | null) {
try {
this.setState({ xml: uri ? await fetchText(uri) : null });
} catch (e) {
console.error(e);
}
}
render() {
const {
props,
state: { xml },
} = this;
return <SvgWithCss xml={xml} override={props} />;
}
}
35 changes: 31 additions & 4 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,13 +446,30 @@ export interface MaskProps extends CommonPathProps {
}
export const Mask: React.ComponentClass<MaskProps>;

export type Styles = { [property: string]: string };

export interface AST {
tag: string;
style?: Styles;
styles?: string;
priority?: Map<string, boolean | undefined>;
parent: AST | null;
children: (AST | string)[] | (JSX.Element | string)[];
props: {};
props: {
[prop: string]: Styles | string | undefined;
};
Tag: React.ComponentType;
}

export interface XmlAST extends AST {
children: (XmlAST | string)[];
parent: XmlAST | null;
}

export interface JsxAST extends AST {
children: (JSX.Element | string)[];
}

export interface UriProps extends SvgProps {
uri: string | null;
override?: SvgProps;
Expand All @@ -463,14 +480,16 @@ export interface XmlProps extends SvgProps {
xml: string | null;
override?: SvgProps;
}
export type XmlState = { ast: AST | null };
export type XmlState = { ast: JsxAST | null };

export interface AstProps extends SvgProps {
ast: AST | null;
ast: JsxAST | null;
override?: SvgProps;
}

export function parse(xml: string): AST | null;
export type Middleware = (ast: XmlAST) => XmlAST;

export function parse(source: string, middleware?: Middleware): JsxAST | null;

export const SvgAst: React.FunctionComponent<AstProps>;

Expand All @@ -479,3 +498,11 @@ export const SvgFromXml: React.ComponentClass<XmlProps, XmlState>;

export const SvgUri: React.FunctionComponent<UriProps>;
export const SvgFromUri: React.ComponentClass<UriProps, UriState>;

export const SvgCss: React.FunctionComponent<XmlProps>;
export const SvgWithCss: React.ComponentClass<XmlProps, XmlState>;

export const SvgCssUri: React.FunctionComponent<UriProps>;
export const SvgWithCssUri: React.ComponentClass<UriProps, UriState>;

export const inlineStyles: Middleware;
7 changes: 3 additions & 4 deletions src/xml.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,9 @@ const validNameCharacters = /[a-zA-Z0-9:_-]/;
const whitespace = /[\s\t\r\n]/;
const quotemarks = /['"]/;

export function parse(
source: string,
middleware?: (ast: XmlAST) => XmlAST,
): JsxAST | null {
export type Middleware = (ast: XmlAST) => XmlAST;

export function parse(source: string, middleware?: Middleware): JsxAST | null {
const length = source.length;
let currentElement: XmlAST | null = null;
let state = metadata;
Expand Down

0 comments on commit 6fb8dd5

Please sign in to comment.