Use sass variables into js files create-react-app - javascript

I have some color defined variables into _colors.scss file.
$color-succcess: #706caa;
$color-error: #dc3545;
I would like to also use them into some styled react components react-table into my js file.
I used the following article https://til.hashrocket.com/posts/sxbrscjuqu-share-scss-variables-with-javascript as reference and many others like it but I cannot get it to work.
I export the colors from my scss file:
:export {
colorSuccess: $color-succcess;
colorError: $color-error;
}
and I import them into my js file:
import colors from "../../styles/_colors.scss";
but they are probably not loaded right.
How can I configure the create-react-app generated code to achieve the same thing as the guy in the article does with webpack.

I have faced a similar issue, and it took me a bunch of tries to get the desired result. If you already have node-sass installed, try the following.
First of all, try importing the main scss file without the underscore, i.e. instead of ../../styles/_colors.scss, try ../../styles/index.scss or whatewer your main file is.
Secondly, keep track of the variable names. This code DID NOT work:
:export {
$textBlack: $text-black;
}
while this one works perfectly
:export {
textBlack: $text-black;
}
For some reason it does not like the dollar sign in the variable name, though it is a valid JS variable name. Your case should work fine

Try to reproduce these steps:
1. Enable sass in CRA by installing node-sass.
npm i --save-dev node-sass
2. Create a sass file example.scss.
$hello: 'world';
:export {
my-var: $hello;
}
3. Import the sass into your react component.
import React from 'react';
import Example from './example.scss';
export default () => Example.hello;

If you are using CRA version 4, there is a known issue where this feature will not work unless you define your scss file as <name>.modules.css.
See https://github.com/facebook/create-react-app/issues/10047#issuecomment-724227353 for details.

install the sass in the project if you didn't install that.
yarn add --dev node-sass
create a file and use this rule to name it => filename.module.scss ( for example variables.module.scss )
$color-succcess: #706caa;
$color-error: #dc3545;
:export {
colorSuccess: $color-succcess;
colorError: $color-error;
otherColor: #786539;
}
and import it in the component like below:
import colors from "../../styles/_colors.module.scss";
const TheComponent = () => {
console.log(colors.colorSuccess)
return <h1>The Component</h1>
}
export default TheComponent
// output in console : #706caa

In order to load SCSS files in CRA you need to add node-sass as your dependency to package.json. I've tested it out and after adding it to clean CRA project and importing colors object (using :export, like in the code you provided) works as expected.

Related

NextJS module aliases double declaration needed for import of index

I am setting up my module aliases in a NextJS project and everything runs fine so far.
The issue I have comes when I have a folder utils that includes both, an index.ts but also another someModule.ts.
My imports looked like this before:
import { someHelper } from '../utils'
import { anotherHelper } from '../utils/someModule'
Assuming I am setting the following module alias "#/utils/*": ["utils/*"], I would need to amend the first of the two imports like this:
import { someHelper } from '#/utils/index' // <-- see how I need to add index
unless I am extending the tsconfig with a second module alias like this: "#/utils": ["utils"].
This feels a bit like duplication to me, so I am wondering whether this is needed or do you have another option how to solve this?

Is there a way to automatically import 'cssuseragent' (or any non-exported) package in webpack?

Current cssuseragent package (2.1.31) doesn't export anything. There is only one variable named cssua. I want import/require it into my project with webpack.
I have tried to adding export keyword before cssua variable and it worked. But this is not a good solution. If anybody else upgrade the package in future, she/he won't know that s/he must do this.
In CLI:
npm i cssuseragent
Then I export cssua variable:
//'export' was not exist, I added it
export var cssua = (
//some code here
)(/*some arguments here*/)
Then I can import:
import { cssua } from 'cssuseragent';
Is there any way to say "If you resolve to this file in import/require, get it as 'custom-name' with its all content" to webpack with a loader or plugin? Because changing source code of a 3rd party module is not a good way. Also it may not be as easy as this every time, the module can be huge. And I want a generic way to do this, maybe like adding just the path of module.
I don't know of a webpack plugin that does that, but you can
// customExport.js
import { cssua } from 'cssuseragent';
export default { cssua };
in another file
// other_file,js
import customExport from "customExport.js";

Adding Typescript Type Declarations to Monaco Editor

I have a Monaco editor which the user inputs custom javascript code. Within this Monaco Editor they can use Lodash functionality. I want to be able to give them the intellisense / code completion for lodash, by including the type definitions.
I've seen a few answers relating to adding custom declarations, but none that are including a whole 3rd party libraries declarations. Has anybody had experience with this.
This is what I have so far. Then below I create the editor, similar to the example in the documentation.
monaco.languages.typescript.typescriptDefaults.addExtraLib("", "./../../types/lodash/index.d.ts");
I'd like to add the package monaco-editor-auto-typings as an option. Disclaimer: I'm the developer of that package.
It continuously scans code entered in the monaco editor, detects imports and automatically loads the declaration files from UnPkg.
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { AutoTypings, LocalStorageCache } from 'monaco-editor-auto-typings';
const val = `
import React from 'react';
React.useEffect(0); // Type Error!
`;
// Create monaco editor instance
const editor = monaco.editor.create(document.getElementById('root')!, {
model: monaco.editor.createModel(val, 'typescript'),
});
// Initialize auto typing on monaco editor. Imports will now automatically be typed!
const autoTypings = AutoTypings.create(editor, {
sourceCache: new LocalStorageCache(), // Cache loaded sources in localStorage. May be omitted
// Other options...
});
You can explore how it works in the demo.
(Copied from my GH Gist: https://gist.github.com/cdrini/9de507f6ac19da30fd27c5f618783b31 )
Well that was a headache! This is certainly not an elegant solution, but it works. Hopefully someone can use these notes to save themselves a bunch of time.
Known issues:
This does not scale easily to any other library
Requires some internal knowledge of lodash's types library which might break on a lodash update
Add raw-loader and #types/lodash
npm install --save-dev #types/lodash raw-loader
(as of writing, these are at 4.14.162 and 4.0.2, respectively)
Import and register the .d.ts files
Looking at #types/lodash/index.d.ts, copy all the common references and import them. :
import LODASH_index from '!raw-loader!#types/lodash/index.d.ts';
import LODASH_common from '!raw-loader!#types/lodash/common/common.d.ts';
import LODASH_array from '!raw-loader!#types/lodash/common/array.d.ts';
import LODASH_collection from '!raw-loader!#types/lodash/common/collection.d.ts';
import LODASH_date from '!raw-loader!#types/lodash/common/date.d.ts';
import LODASH_function from '!raw-loader!#types/lodash/common/function.d.ts';
import LODASH_lang from '!raw-loader!#types/lodash/common/lang.d.ts';
import LODASH_math from '!raw-loader!#types/lodash/common/math.d.ts';
import LODASH_number from '!raw-loader!#types/lodash/common/number.d.ts';
import LODASH_object from '!raw-loader!#types/lodash/common/object.d.ts';
import LODASH_seq from '!raw-loader!#types/lodash/common/seq.d.ts';
import LODASH_string from '!raw-loader!#types/lodash/common/string.d.ts';
import LODASH_util from '!raw-loader!#types/lodash/common/util.d.ts';
Note: Vetur will complain in VS Code about importing .d.ts files, but won't error.
Then register them into monaco (wherever monaco is in your project):
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_index, '#types/lodash/index.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_common, '#types/lodash/common/common.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_array, '#types/lodash/common/array.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_collection, '#types/lodash/common/collection.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_date, '#types/lodash/common/date.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_function, '#types/lodash/common/function.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_lang, '#types/lodash/common/lang.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_math, '#types/lodash/common/math.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_number, '#types/lodash/common/number.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_object, '#types/lodash/common/object.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_seq, '#types/lodash/common/seq.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_string, '#types/lodash/common/string.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_util, '#types/lodash/common/util.d.ts');
Note:
The file names matter here (somehow); removing the .d.ts extension causes them to break.
References/External Links
The (largely useless) docs: https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.typescript.languageservicedefaults.html#addextralib
GH Issues:
#758: monaco-typescript not picking up configured modules from addExtraLib
#754: Cannot require contents of '.d.ts' files as string in browser for addExtraLib method
StackOverflow Questions:
Adding Typescript Type Declarations to Monaco Editor
Monaco demo using addExtraLib: https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-configure-javascript-defaults
#types/lodash at unpkg, if you want to see the .d.ts files directly: https://unpkg.com/browse/#types/lodash#4.14.162/
GH Search for uses of addExtraLib: https://github.com/search?l=JavaScript&q=addExtraLib&type=Code
Open Questions
What does the filename actually do? Also, what are the protocol prefixes for?
See this as an example and the apis. you should pass the content of the .d.ts file as the first argument
monaco.languages.typescript.typescriptDefaults.addExtraLib(content, "")
check this demo of how pass arguments

How to Embed StencilJS components inside Storybook React App?

I'm trying to integrate Stencil and Storybook inside the same project. I've been following this set up guide and this one however one of the steps is to publish the library of components to NPM and that's not what I want.
I have this repo which I've configured with components library (src folder) and with the reviewer of those components with Storybook, which resides in the storybook folder.
The problem is that when I compile the components using Stencil and copy the dist folder inside the Storybook app and import the component nothing renders. Tweaking the configuration using custom head tags I was able to import it correctly however no styles where applied.
When I open the network panel there is some error when importing the component:
And thus the component is present in the DOM but with visibility set to hidden, which I think it does when there is an error.
This is the component au-button:
import { Component } from '#stencil/core';
#Component({
tag: 'au-button',
styleUrl: 'button.css',
shadow: true
})
export class Button {
render() {
return (
<button class="test">Hello</button>
);
}
}
Here is the story my component:
import React from 'react';
import { storiesOf } from '#storybook/react';
import '../components/components.js'
storiesOf('Button', module)
.add('with text', () => <au-button></au-button>)
These are the scripts inside the Storybook app:
"scripts": {
"storybook": "start-storybook -p 9009",
"build-storybook": "build-storybook",
"copy": "cp -R ./../dist/* components"
},
And the workflow is as follows:
Launch storybook
Make changes in the component
Execute build command
Execute copy command
Also, I would like to automate the developer experience, but after I solve this problem first.
Any ideas of what I could be doing wrong?
Sample for this could be found in the repo
https://github.com/shanmugapriyaEK/stencil-storybook. It autogenerates stories with knobs and notes. Also it has custom theme in it. Hope it helps.
I'm using #storybook/polymer and it's working for me really well.
following your example:
import { Component } from '#stencil/core';
#Component({
tag: 'au-button',
styleUrl: 'button.css',
shadow: true
})
export class Button {
render() {
return (
<button class="test">Hello</button>
);
}
}
the story would be:
import { storiesOf } from '#storybook/polymer';
storiesOf('Button', module)
.add('with text', () => <au-button></au-button>)
the scripts in the package.json:
"scripts": {
"storybook": "start-storybook -p 9001 -c .storybook -s www"
},
the storybook config file:
import { configure, addDecorator } from '#storybook/polymer';
const req = require.context('../src', true, /\.stories\.js$/);
function loadStories() {
req.keys().forEach((filename) => req(filename))
}
configure(loadStories, module);
and storybook preview-head.html you have to add to the body the following:
<body>
<div id="root"></div>
<div id="error-message"></div>
<div id="error-stack"></div>
</body>
I've been following this set up guide and this one however one of the steps is to publish the library of components to NPM and that's not what I want.
My reading of those guides is that they're stating “publish to NPM” as a way to have your files at a known URL, that will work most easily for deployment.
Without doing that, you'll need to figure out a different deployment strategy. How will you get the build products – the dist directory and static files – published so that your HTML will be able to reference it at a known URL? By choosing to diverge from the guidelines, that's the problem you have to address manually instead.
Not an insurmountable problem, but there is no general solution for all. You've chosen (for your own reasons) to reject the solution offered by the how-to guides, which means you accept the mantle of “I know what I want” instead :-)

Import ace code editor into webpack, es6, typescript project

I'm trying to build a web component that will host the ace editor. The trouble is that I don't find enough information on how to import the module and set the types. The code bellow was working just fine using simple <script> tags and global vars.
So far this is what I have:
npm install ace-code-editor --save
npm install #types/ace --save-dev
code-editor.cmp.ts
// Error: [ts] File '.../node_modules/#types/ace/index.d.ts' is not a module.
import * as ace from 'ace';
export class CodeEditorCmp extends HTMLElement {
// DOM
private editor: AceAjax; // How do I import the type. What type to use?
constructor() {
super();
}
connectedCallback() {
this.initCodeEditor();
}
initCodeEditor(){
this.editor = ace.edit("editor-vsc");
// How do I import the editor themes?
this.editor.setTheme("ace/theme/xcode");
// How do I import the editor modes?
var JavaScriptMode = ace.require("ace/mode/html").Mode;
this.editor.session.setMode(new JavaScriptMode());
this.editor.getSession().setTabSize(4);
this.editor.getSession().setUseSoftTabs(true);
this.editor.getSession().setUseWrapMode(true);
this.editor.setAutoScrollEditorIntoView(true);
// Update document
this.editor.getSession().on('change', this.onEditorChange);
}
onEditorChange(){
}
}
require('./code-editor.cmp.scss');
window.customElements.define('editor-vsc', CodeEditorCmp);
For those who don't want to use the brace module, I saw that my issue was that I was importing the wrong version of ace. Once installed, make sure to import from src-noconflict. The noconflict version uses ace.require which seems to play a lot more nicely than the other iterations that use require.
I would suggest that you do the following:
npm install ace-builds --save
npm install #types/ace --save-dev
Afterwards in your file just import the noconflict like below:
import * as ace from 'ace-builds/src-noconflict/ace';
This will result in a variable ace being defined. You will then be able to reference methods and properties of ace as normal, such as ace.edit()
You can get more information about the different versions of ace check out the git page.
After a lot of digging I managed to find brace module. It's a browserify wrapper for ace. Fortunately it works straight away with webpack. No need to use separate types, they come prepackaged.
import * as ace from 'brace';
import 'brace/mode/javascript';
import 'brace/theme/monokai';
export class CodeEditorCmp extends HTMLElement {
private editor: ace.Editor;
initCodeEditor(){
this.editor = ace.edit('javascript-editor');
this.editor.getSession().setMode('ace/mode/javascript');
this.editor.setTheme('ace/theme/monokai');
//...
}
//...
}

Categories