How to convert SVG style to JSX - reactjs

I would like to know is there any inbuilt function or something in react for converting SVG style attribute to JSX.
I have style like this:
'opacity:0.647;fill:#cbcbcb;fill-opacity:1;stroke:#cbcbcb;stroke-width:0.26458335;stroke-opacity:1'
I want to convert it into:
{{"opacity":"0.647","fill":"#cbcbcb","fillOpacity":"1","stroke":"#cbcbcb","strokeWidth":"0.26458335","strokeOpacity":"1"}}
Is there any easy way?

I am not sure there exists a React inbuilt tool for this. You could code this yourself and make your own quick tool to transform the syntax. Othwerise, if you don't want to use external websites, you can have a look at the svg-to-jsx module which can be used within your project or via command line
npm install svg-to-jsx
or svgr (https://github.com/gregberge/svgr) for SVG -> React component directly if you prefer

There's no built-in functionality for this. You may convert your styles string into an object using a simple reducer function, and then pass it as a prop.
const str =
"opacity:0.647;fill:#cbcbcb;fill-opacity:1;stroke:#cbcbcb;stroke-width:0.26458335;stroke-opacity:1";
const styles = str.split(";");
const svgStyles = styles.reduce((obj, item, i) => {
const [key, value] = item.split(":");
const updatedkey = key.replace(/-([a-z])/ig, s => s.slice(-1).toUpperCase());
obj[updatedkey] = value;
return obj;
}, {});
console.log(svgStyles);

There's a vscode extension for this called "html to JSX"
Here's the link to the extension:
https://marketplace.visualstudio.com/items?itemName=riazxrazor.html-to-jsx
Just select all of your svg code and then press Ctrl + Shift + P -> Convert HTML to JSX -> Ctrl + S to save

Related

What would be the optimal way to replace the text in the project code with the t function from i18next?

I was given a task to implement a localization for the whole mobile app on react native with i18next, react localize.
There is a lot of text in many files and so far the only way is to do it manually. Search through the files and then replace the text with the corresponding t reference to the translation file.
Is there actually another way of doing it faster and more convenient?
I made changes in quite many files to the moment. Sometimes thinking if there is a better way to optimize this process.
If by chance your original language isn't English - You can search for characters in that language (using a regex). That will surface all the strings that are user facing (otherwise the code is in English).
Aside from that, I think regex's are your friend. You can search for ".*?" and similar to catch strings.
If you already have a translation file, then you could write a simple script that pulls a translated string, searches for it in project source files, and replaces the occurence with the t() equivalent.
Hope this helps 🙏🏻
Almost all visible text (exceptions are placeholder and accessibilityLabels) would be in <Text> so you can probably override it with a higher-order component to use the existing text value looked up via i18n-next. It's not perfect but it would be a start.
This would do the reverse of what you want (in that it replaces text with i18n keys) https://github.com/trajano/spring-cloud-demo/blob/rework/expo-app/src/lib/native-unstyled/hoc/withI18n.tsx. But I used that along with my hoc template
(note untested)
import {
ComponentType,
forwardRef,
NamedExoticComponent,
PropsWithoutRef,
ReactElement,
Ref,
RefAttributes,
} from "react";
export function withChildrenAsI18n<P extends Q, Q extends TextProps, T>(
Component: ComponentType<Q>,
_options?: O
): NamedExoticComponent<PropsWithoutRef<P> & RefAttributes<T>> {
function useWrapped({children, ...rest}: P, ref: Ref<T>): ReactElement<Q> {
const translatedChildren = t(children);
const componentProps: Q = {...rest, children: translatedChildren } as Q;
return <Component {...componentProps} ref={ref} />;
}
const displayName = Component.displayName ?? Component.name;
useWrapped.displayName = `withChildrenAsI18n(${displayName})`;
return forwardRef(useWrapped);
}
then add something like
import {
Text as RNText,
} from "react-native";
export const Text = withChildrenAsI18n(RNText);
Then do a search and replace the text import with this replacement.

How to include mxFloorplan.js in mxGraph inside React application using Typescript?

So I'm trying to create a simple react application to render a mxGraph that I'm loading from a file. I can load the model, but some shapes aren't rendering correctly. The problem is that they are a specific shape, that are part of the floorplan package, and I can't find a way to include those shapes in my code.
ps.: I'm new to working with mxGraph.
Things I tried
First thing I tried was downloading the mxFloorplan.js file into my application, and import it, like so:
// App.tsx
import './models/mxFloorplan'
const mx = factory({
mxBasePath: './models'
})
let graph: mxGraph
...
Because the docs on extending mxShape show that I should register a new shape: mxCellRenderer.registerShape('customShape', CustomShape); and the mxFloorplan.js file does that.
I then simply added this to the beggining of the file:
// mxFloorplan.js
import Graph, {
mxShape,
mxUtils,
mxCellRenderer,
mxPoint
} from 'mxgraph'
...
But then I get this error:
Then I thought that I needed mxCellRenderer to be linked to my graph instance? So I tried moving one of the shape definitions into App.jsx to test:
// App.jsx
const mx = factory({
mxBasePath: './models'
})
let graph: mxGraph
function mxFloorplanWall(bounds: any, fill: any, stroke: any, strokewidth: any)
{
mx.mxShape.call(this); <-- Error: "Expected 2 args, but got one"
this.bounds = bounds;
this.fill = fill;
this.stroke = stroke;
this.strokewidth = (strokewidth != null) ? strokewidth : 1;
};
/**
* Extends mxShape.
*/
mx.mxUtils.extend(mxFloorplanWall, mxShape); <-- Error: "Property 'extend' does not exist on type mxUtils
// ... more code
mx.mxCellRenderer.registerShape(mxFloorplanWall.prototype.cst.WALL, mxFloorplanWall); <-- Error: mxFloorplanWall type not compatible with expected.
Really don't know how to solve these ones. On my research I only find references to
mxCellRenderer.registerShape('name', CustomShape), so not really sure on the rest.
How it looks
Here is how the diagram looks like (ignore the arrow and labels, please):
Here is what I'm actually rendering (the "black boxes" have shape=shape=mxgraph.floorplan.wallU):
As described in https://jgraph.github.io/mxgraph/docs/js-api/files/shape/mxShape-js.html, you must pass a constructor to mxCellRenderer.registerShape
function CustomShape() { }
CustomShape.prototype = new mxShape();
CustomShape.prototype.constructor = CustomShape;
// To register a custom shape in an existing graph instance,
// one must register the shape under a new name in the graph’s cell renderer
// as follows:
mxCellRenderer.registerShape('customShape', CustomShape);
}
I guess your issues come from a wrong port of drawio code (that use a very old Javscript syntax) and is not related to React at all. It is currently unclear to me what you are exactly have implemented. Here are some hints.
If you use TypeScript, the mxCellRenderer.registerShape signature is enforced by the mxgraph types https://github.com/typed-mxgraph/typed-mxgraph/blob/v0.0.5-0/view/mxCellRenderer.d.ts#L83.
When porting the mxFloorplanWall code to Typescript you should have a constructor like in the following (please avoid any!)
export class mxFloorplanWall extends mxShape { // or extends mx.mxShape depending how you manage mxgraph imports
public constructor(bounds: mxRectangle, fill: string, stroke: string, strokewidth: number) {
super(bounds, fill, stroke, strokewidth);
}
...
}
Calling super directly set the arguments in super class and avoid the errors
// mx.mxUtils.extend(mxFloorplanWall, mxShape); <-- Error: "Property 'extend' does not exist on type mxUtils
// avoid mx.mxShape.call(this); <-- Error: "Expected 2 args, but got one"
Same if you use Javascript, prefer the ES6 class syntax to declare the mxFloorplanWall class.

TypeScript with a variable having two names

I am trying to understand a code written in TypeScript. I myself have a Java background and I find the syntax of the following code hard to understand. The code example is from the first Material UI Select code example:
const [labelWidth, setLabelWidth] = React.useState(0);
React.useEffect(() => {
setLabelWidth(inputLabel.current!.offsetWidth);
}, []);
So what exaclty is done here? What is the name of the variable const [labelWidt, setLabelWidth]? Are these two variables or is this one variable? Like an array? Later in the code it labelWidth has a number that can be used to set the width of some label. Then setLabelWidth is used like a function that takes a param inputLabel.current!.offsetWidth. Where is it defined that this is a function?
Can someone please explain?
It is an ECMAScript 2015 feature that TypeScript has is destructuring. For a complete reference, see the article on the Mozilla Developer Network. Destructing
You can also see typescript documentation here
It is destructuring assignment syntax.
Given
const arr = ['item1', 'item2'];
this
const [a, b] = arr;
is the same as
const a = arr[0];
const b = arr[1];

The code of `for-of` circlation transport by babel not support some browser

I had some es6 codes in my react project like this:
``` javascript
for (const v of [0, 1, 2,]) { /* doSth*/ }
```
and it works well after transport to es5 every where.
however, if I change them like those:
``` javascript
const arr = [0, 1, 2,];
for (const v of arr) { /* doSth*/ }
```
then it throw an error that ReferenceError: Can't find variable: Symbol in iPhone 5c.
I tried both foreach for-in and the pure for circulation, they all works well in that old device.
But, I need do something like async () => { for (...) { await doSthAysnc; } }, and it cannot use foreach.
What's more, for-of was very dangerous, and pure for is very ugly. so if possibly, I prefer to use for-of.
thanks.
#Bergi Well, that's the codes it transpiles to:
javascript
("================================================================"),m=["a","b","c"],e.prev=38,v=c.a.mark(function e(n){return c.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,new Promise(function(e){return setTimeout(function(){return e(n)},1e3)});case 2:case"end":return e.stop()}},e,t)}),y=!0,b=!1,w=void 0,e.prev=43,_=m[Symbol.iterator]();case 45:if(y=(x=_.next()).done){e.next=51;break}return E=x.value,e.delegateYield(v(E),"t2",48);case 48:y=!0,e.next=45;break;case 51:e.next=57;break;case 53:e.prev=53,e.t3=e.catch(43),b=!0,w=e.t3;case 57:e.prev=57,e.prev=58,!y&&_.return&&_.return();case 60:if(e.prev=60,!b){e.next=63;break}throw w;case 63:return e.finish(60);case 64:return e.finish(57);case 65:e.next=69;break;case 67:e.prev=67,e.t4=e.catch(38);case 69:console.log("================================================================"),
Using an array literal directly inside for … of enables an extra transpiler optimisation that causes it not to use iterables. In the default cause, it will try to find the m[Symbol.iterable] method which fails in legacy environments.
In can see three solutions:
Import the babel-polyfill to enable symbols and iterators
Use loose mode which hopefully always uses the array path
Use the transform-for-of-as-array babel plugin instead which always transpiles to array loops

Writing a file client side using Angularjs

Can we write an xlsx file on client side using angular js .If it is possible then please provide me the solution.
You could use a library like angular-xlsx or js-xlsx to help you with this process.
You can export data from AngularJS to XLS, XLSX and CSV formats with Alasql library.
For example we want to write a data which we saved in test variable in an XLSX file through click a button. To do this just use following steps:
1- Include following files in your page:
<script src="http://alasql.org/console/alasql.min.js"></script>
<script src="http://alasql.org/console/xlsx.core.min.js"></script>
2- So Then make a function in controller to save the test variable as a xlsx file:
$scope.test = [{a:2,b:8,c:9},{a:0,b:14,c:12},{a:24,b:35,c:76}];
$scope.saveAsXlsx = function () {
alasql('SELECT * INTO XLSX("output.xlsx",{headers:true}) FROM ?',[$scope.test]);
}
So We save the data which we had in variable test into a file which we named it output.xlsx here.
3- The last part is the easiest part. Run the function on click on a button:
<button ng-click="saveAsXlsx()" >Save as XLSX</button>
Above solution is a js library which can be used with jQuery, js and angularJS. If you are looking for something just made for angular then in addition of this solution, you can use ng-csv library. If you want to just have a spreadsheet you can use ng-csv library too. It is very easy but you can't get XLSX, you will get the spreadsheet file with CSV format.
you can create your excel file.
install npm install excel4node
and then use the basic code
// Require library
var xl = require('excel4node');
// Create a new instance of a Workbook class
var wb = new xl.Workbook();
// Add Worksheets to the workbook
var ws = wb.addWorksheet('Sheet 1');
var ws2 = wb.addWorksheet('Sheet 2');
// Create a reusable style
var style = wb.createStyle({
font: {
color: '#FF0800',
size: 12
},
numberFormat: '$#,##0.00; ($#,##0.00); -'
});
// Set value of cell A1 to 100 as a number type styled with paramaters of style
ws.cell(1,1).number(100).style(style);
// Set value of cell B1 to 300 as a number type styled with paramaters of style
ws.cell(1,2).number(200).style(style);
// Set value of cell C1 to a formula styled with paramaters of style
ws.cell(1,3).formula('A1 + B1').style(style);
// Set value of cell A2 to 'string' styled with paramaters of style
ws.cell(2,1).string('string').style(style);
// Set value of cell A3 to true as a boolean type styled with paramaters of style but with an adjustment to the font size.
ws.cell(3,1).bool(true).style(style).style({font: {size: 14}});
wb.write('Excel.xlsx');
here i have added ref link :https://www.npmjs.com/package/excel4node

Resources