Cant import CSS from MDCTextField to style MDCTextField child elements in LitElement based WebComponent - lit-element

How do you import CSS into a ES6 module?
I receive the following error in browser console;
Failed to load module script: The server responded with a
non-JavaScript MIME type of "text/css". Strict MIME type checking is
enforced for module scripts per HTML spec.
Module below:
import { LitElement, html, css } from "lit-element";
import { MDCTextField } from "#material/textfield";
import style from "#material/textfield/dist/mdc.textfield.css";
export class MyWC extends LitElement {
static get styles() { return style; } //was using return css'...'
render() {
return html`
<label class="mdc-text-field mdc-text-field--textarea">
<textarea class="mdc-text-field__input" aria-labelledby="my-label-id" rows="8" cols="40" maxlength="140"></textarea>
...blah blah blah...
</label>
`;
}
#material/textfield & lit-element installed via npm OK. I'm using es-dev-server on linux.
ps - I want to use MDC web components but keep things as simple as possible.
Any help appreciated - Thanks.

The HTML spec currently only allows to import javascript modules. This is enforced by checking that the MIME type of the imported file is a javascript one, hence the error you're getting. The fact that in some environments (especially with bundlers/transpilers) importing other resource types is possible may give the wrong impression that it is case also in the browser.
To use this kind of import
import style from "#material/textfield/dist/mdc.textfield.css";
you would need some tool capable of transforming it into a CSSResult. A typical scenario is using bundlers like Rollup or Webpack with dedicated plugins/loaders (ie rollup-plugin-lit-css or lit-css-loader).

Related

Can you instantiate another `BrowserRouter` inside a `BrowserRouter` based App?

Background: I am trying to use sweetalert2-react-content to let me put a react <Link> inside a Sweetalert2 footer.
Generally speaking sweetalert2-react-content is supposed to let you place react JSX into its fields, like this:
MySwal.fire({
text: "Fire fire",
footer: <div>Call the firebrigade</div>
});
... and indeed that sort of thing does work.
However, putting a <Link> there does not work: it renders empty.
In this issue resolution message the the advice is "wrap your element in BrowserRouter like this:
MySwal.fire({
html: (
<BrowserRouter>
...
</BrowserRouter>
),
})
Is this "legitimate"? What does it "mean" to have a BrowserRouter inside an app that is routed using BrowserRouter already?
No, it is an invariant violation to nest a router within another router. I think your situation is not a case of invalid nesting, but more to do with where sweetalert is rendering the React JSX. From what I recall of sweetalert it renders content outside the ReactTree.
You can certainly render more than one router, so long as they are not nested, but then the issue is that you've separate routing contexts that each individually handle routing/navigation, and navigating within one routing context doesn't update the others.
I suspect you could use a single custom history reference and pass these to the routers you need, so they all reference the same history context internally.
react-router-dom#6 exports a HistoryRouter for this purpose.
Example:
import { createBrowserHistory } from "history";
const history = createBrowserHistory({ window });
export default history;
...
import * as React from "react";
import * as ReactDOM from "react-dom";
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import history from "../path/to/history";
ReactDOM.render(
<HistoryRouter history={history}>
{/* The rest of your app goes here */}
</HistoryRouter>,
root
);
...
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import history from "../path/to/history";
MySwal.fire({
html: (
<HistoryRouter history={history}>
...
</HistoryRouter>
),
})
Note about unstable_HistoryRouter:
This API is currently prefixed as unstable_ because you may
unintentionally add two versions of the history library to your app,
the one you have added to your package.json and whatever version React
Router uses internally. If it is allowed by your tooling, it's
recommended to not add history as a direct dependency and instead rely
on the nested dependency from the react-router package. Once we have a
mechanism to detect mis-matched versions, this API will remove its
unstable_ prefix.
No, this is wrong and will usually throw an error.
What you would like to do is to render it like this:
<UNSAFE_LocationContext.Provider value={null as any}>
<BrowserRouter>
...
</BrowserRouter>
</UNSAFE_LocationContext.Provider>

Why cannot render HTML with ReactJS

I have seen online plenty of examples and tests using React and typescript where they issue something like this:
import * as ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello world!!</h1>, //or any other valid html snippet
document.getElementById('root') as HTMLElement
);
However, when I try to reproduce those multiple examples in my machine, I get, first a highlight error from VS code, and then when I try to bundle I get this error:
TS2686: 'React' refers to a UMD global, but the current file is a
module. Consider adding an import instead.
If instead of putting the HTML as argument of the function I write a my SimpleComponent.render(), the bundle will be produced without errors.
What is wrong with that code snippet?
Try to add import * as React from 'react'. <h1> is React component (React.createClass('h1') after transpile JSX to JavaScript), but you have imported only ReactDOM.

Using TypeScript Declaration For External JavaScript Library

I'm not sure if this extreme edge case or something but I cannot seem to find straight forward documentation on how to do this (or I'm just really not understanding what is available):
I am developing an ionic application and as part of that I need to use the ALKMaps JavaScript library (which is similar to Google Maps API). To do so, I created a local npm module and within that I created a alkmaps.d.ts file as recommended by https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#objects-with-properties). However, I cannot seem to figure out how to properly import it into my angular code. The same document suggests that using <reference path=''> tags is not good but that is the only thing that seems to satisfy the tsc compiler.
My declaration file, alkmaps.d.ts, looks like (inside excluded for brevity):
declare namespace ALKMaps {
export class Map { ... }
...
}
And I was trying to import it into a file like:
import { ALKMaps } from 'alkmaps'; // Error: File '.../alkmaps.d.ts' is not a module
I also tried the following but got the same error.
import ALKMaps = require('alkmaps');
Using the reference tag seems to work within this module but then the project that utilizes this module still throws the "is not a module" error (that might warrant a separate question)
From https://github.com/Microsoft/TypeScript/issues/11420 I found the idea of using export = ALKMaps or export as namespace ALKMaps but adding those to my declaration file resulted in different errors instead.
Can anyone please explain in a straightforward way how to use declaration files representing external JS libraries in a typescript node module?
This is how I was able to get alkMaps into my Angular 2 app
Insert the script into the index.html file.
Declare an ALKMaps variable in the component that you are adding the map
imports .....
declare let ALKMaps : any;
#Component({
selector: 'show-map',
templateUrl: 'show-map.component.html'
})
export class ShowMapComponent implements Oninit{
map : any;
constructor() {
}
ngOnInit() {
ALKMaps.APIKey = "apiKey";
this.map = new ALKMaps.Map("map", {displayProjection: new ALKMaps.Projection("EPSG:4326")});
}
}
This will get the map to display and you can put different layers on the map, however the map does not display correctly. #Mike, if you were able to get further than this, will you please comment?
EDIT: The tiles on the image were elongated and not connected. After inspecting the css the main.css, after building, set a global property on the img element to:
img {
max-width:100%
}
The tiles for the map are originally set to 256% for the width. To correct the element, I changed the property for img in the style sheet.
show-map {
img {
max-width: 256%
}
}

Chessboardjs NPM package, not showing images

I am trying to use https://www.npmjs.com/package/chessboardjs package with meteor 1.13. I wrote simple react component to render the board, but it doesn't render images for some reason. The compoent code:
import React from 'react'
import ChessBoard from 'chessboardjs'
export default class GamePage extends React.Component {
render() {
return (
<div>
<div id="chessboard" style={{"width": "400px"}}></div>
</div>
)
}
componentDidMount() {
var board = ChessBoard('chessboard');
}
}
I see that .css from that package is not being used, so maybe I have to import it as well somehow?
So the assets for chessboard.js are stored somewhere in static, right? There's a question out there about Flask which might have your answer,
Integrate chessbord.js with Flask
The idea is to modify the chessboard.js library, where it src the images for the board.
Remember to clear your cache if it's not working, as the browser will hold onto to the unedited library.

Invoke the text plugin from requirejs mapping

I'm writing a web app using TypeScript, Backbone, and Mustache. I want to use Requirejs for dependency loading.
I'm also using the Web Essentials visual studio plugin for TypeScript with the AMD compilation option turned on. For those that are not familiar with this, it will wrap your type script file in an AMD module if you import external modules.
For example:
In type script I import the following modules in type definition files.
export import Backbone = module("Backbone");
import mainTemplate = module("MainTemplate");
The output is something like:
define(["require", "exports", "Backbone", "MainTemplate"], function(require, exports, __Backbone__, __mainTemplate__) {
//...code goes here ...
});
For the template, I've declared the following in a type definition file:
declare module "MainTemplate" { }
In order to support requirejs plugins, you need to declare your module as:
declare module "text!MainTemplate.html" { }
I'd like to keep the module name free of plugins and file extensions. This would leave me with some flexibility in the future.
I have the following mapping in require.
require.config({
map: {
"MyModule": {
"MainTemplate": "text!MainTemplate.html"
}
}
}
This successfully invokes the text plugin however, the plugin loads the wrong url. Sifting through the source code for the text plugin, I found that the following code is the culprit.
load: function (name, req, onLoad, config) {
...
url = req.toUrl(nonStripName),
//returns "scripts/**text!**MainTemplate.html**.html**"
...
}
If I name the module, 'MainTemplate.html' it works fine but I'd like to keep the extension out of the module name.
I've modified the text plugin with a simple regex replacement to strip out the plugin reference and the duplicate extension.
Is there a better way to handle this?
Ran into similar issue. Solved finally. See TypeScript: compiling removes unreferenced imports
/// <amd-dependency path="text!templates/application.htm" />
var applicationTemplate = require('text!templates/application.htm');
For Typescript 1.0 this works for me.
First I created a .d.ts file which stores all module declarations for each text template.
//workaround for typescript's lack of support for requirejs text template notation
//remember that a reference to the import variable has to be found in the class, otherwise typescript ignores the import
declare module "text!views/details/details.html" {
var text: string;
export = text;
}
declare module "text!views/layout/layout.html" {
var text: string;
export = text;
}
declare module "text!views/home/home.html" {
var text: string;
export = text;
}
then to refer to the text template I add these lines on top of the class/module.
/// <reference path="../texttemplate.d.ts"/>
import detailsTemplate = require('text!views/details/details.html');
The reference line is not actually needed, since the .d.ts file is picked up globally. But I added it as a reminder of the workaround. It also makes it easy to ctrl+click to go the d.ts. file.
There is a slightly nicer way to do this (I'm using typescript 2.0)
Referenced here: https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html
This code expects that your requirejs configuration and plugins are set up correctly:
/// <amd-dependency path="text!./about.html" name="template"/>
declare let template: string;
This helped me a lot to migrate lagacy code to typescript.
Since TypeScript 0.9.0 I think you need to do the following:
/// <amd-dependency path="text!templates/application.htm" />
declare var require:(moduleId:string) => any;
var applicationTemplate:string = require("text!templates/application.htm");
Check out more at http://www.codebelt.com/typescript/typescript-amd-with-requirejs-tutorial/
We are using Backbone and require.js for our TypeScript applications.
We don't use the
import backbone = module("Backbone")
syntax, but rather use a
/// <reference path="../../modules/Backbone.d.ts" />
reference, and then a BootStrapper.
This way, the 'text!htmlfile.html' syntax works perfectly with require.js.
I've put together a blog on using require.js with TypeScript and AMD:
http://blorkfish.wordpress.com/2012/10/23/typescript-organizing-your-code-with-amd-modules-and-require-js/

Resources