draft-js-plugins / draft-js-plugins

React Plugin Architecture for Draft.js including Slack-Like Emojis, FB-Like Mentions and Stickers
https://www.draft-js-plugins.com/
MIT License
4.09k stars 1.06k forks source link

Styles are not applied on Webpack5 #1833

Closed nimahkh closed 3 years ago

nimahkh commented 3 years ago

Hello guys, I am using Draftjs mention plugin and I am getting the result below Screenshot from 2021-02-24 00-04-16

This is my webpack5 code:

    module: {
      rules: [
        {
          test: /\.css$/,
          use: ['style-loader', 'css-loader'],
        },
      ],
    },

And this is my code

import React, { ReactElement, useRef, useState } from 'react';
import { EditorState } from 'draft-js';
import Editor from '@draft-js-plugins/editor';
import createMentionPlugin, {
  defaultSuggestionsFilter,
} from '@draft-js-plugins/mention';
import editorStyles from './editorStyles.css';
import mentions from './Mention';
import '@draft-js-plugins/mention/lib/plugin.css';

const mentionPlugin = createMentionPlugin();
const { MentionSuggestions } = mentionPlugin;
const plugins = [mentionPlugin];

const SimpleMentionEditor = (): ReactElement => {
  const [editorState, setEditorState] = useState(EditorState.createEmpty());
  const editor = useRef<Editor>();

  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState('');

  const onChange = (value): void => {
    setEditorState(value);
  };

  const focus = (): void => {
    editor.current.focus();
  };

  const onOpenChange = (newOpen): void => {
    setOpen(newOpen);
  };

  const onSearchChange = ({ value }): void => {
    setSearch(value);
  };

  const onAddMention = (): void => {
    // get the mention object selected
  };

  return (
    <div className={editorStyles.editor} onClick={focus}>
      <Editor
        editorState={editorState}
        onChange={onChange}
        plugins={plugins}
        ref={(element) => {
          editor.current = element;
        }}
      />
      <MentionSuggestions
        open={open}
        suggestions={defaultSuggestionsFilter(search, mentions)}
        onOpenChange={onOpenChange}
        onSearchChange={onSearchChange}
        onAddMention={onAddMention}
      />
    </div>
  );
};

export default SimpleMentionEditor;
Naspo88 commented 3 years ago

As written here: https://draftjs.slack.com/archives/C0U9WS9PZ/p1614095907005700 I have the same issue but wit Webpack version 4.29.6.

{
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
},
{
  test: /\.css$/,
  use: ['style-loader', 'css-loader'],
}

Both of the version above doesn't import plugin.css styles from @draft-js-plugin/emoji and @draft-js-plugins/linkify but it imports the style correctly for the library draft-js-mention-plugin and draft-js

Please let me know if I can help :)

sibelius commented 3 years ago

is this dev or production mode?

is the css in the page?

can you create a small repro?

Naspo88 commented 3 years ago

Hi, it should be production, considering if I lunch it locally it works correctly. The CSS is definitely on the page with the mentions CSS and draft-js CSS, so I would expect that getting them correctly I should be able to get the emoji and linkify ones.

I will try to get a small repo to reproduce it. For now, I try to share what I can share from my file (for company policy I can't do more than this).

webpack rule

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
...
{
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              fallback: 'style-loader',
              modules: true,
              namedExport: true,
              camelCase: true,
              importLoaders: 1,
              localIdentName: '[name]__[local]___[hash:base64:5]',
            },
          },
          'css-loader',
        ],
 },

RichTextArea.tsx imports

import React, { useState } from 'react';
import createEmojiPlugin, { defaultTheme } from '@draft-js-plugins/emoji';
import createLinkifyPlugin from '@draft-js-plugins/linkify';
import createListPlugin from 'draft-js-list-plugin';
import createMentionPlugin from 'draft-js-mention-plugin';
import 'draft-js/dist/Draft.css';
import 'draft-js-mention-plugin/lib/plugin.css';
import '@draft-js-plugins/emoji/lib/plugin.css';
import '@draft-js-plugins/linkify/lib/plugin.css';
import Editor from '@draft-js-plugins/editor';
import { defaultSuggestionsFilter } from 'draft-js-mention-plugin';
sibelius commented 3 years ago

do you have happypack?

happypack was causing issues for us

Naspo88 commented 3 years ago

No, I don't use happypack :)

sibelius commented 3 years ago

can you share your whole webpack config?

Naspo88 commented 3 years ago
const TypescriptPlugingForStyledComponent = require('typescript-plugin-styled-components').default;
const path = require('path');
const TsConfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(t|j)sx?$/,
        exclude: /node_modules/,
        loader: 'ts-loader',
        options: {
          transpileOnly: true,
          getCustomTransformers: () => {
            return {
              before: [TypescriptPlugingForStyledComponent()],
            };
          },
        },
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              fallback: 'style-loader',
              modules: true,
              namedExport: true,
              camelCase: true,
              importLoaders: 1,
              localIdentName: '[name]__[local]___[hash:base64:5]',
            },
          },
          'css-loader',
        ],
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        exclude: [
          /node_modules/,
          path.resolve(__dirname, '../src/url'),
          path.resolve(__dirname, '../src/url2'),
        ],
        use: [
          {
            loader: 'url-loader',
          },
        ],
      },
      {
        test: /\.jpe?g$|\.png$|\.svg$/,
        include: [path.resolve(__dirname, '../src/url')],
        use: {
          loader: 'file-loader',
          options: {
            name: 'img/sd/[name].[ext]?[hash]',
          },
        },
      },
      {
        test: /\.(gif)$/i,
        include: [path.resolve(__dirname, '../src/url')],
        use: {
          loader: 'file-loader',
          options: {
            name: 'img/[name].[ext]',
          },
        },
      },
      {
        test: /\.(woff|woff2)$/i,
        use: {
          loader: 'file-loader',
          options: {
            name: 'fonts/[name].[ext]',
          },
        },
      },
    ],
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx', '.css', '.png', '.gif', '.svg', '.d.ts', '.woff', '.woff2'],
    modules: [path.join(__dirname, '../src'), 'node_modules'],
    plugins: [
      new TsConfigPathsPlugin({
        configFile: path.resolve(__dirname, '../tsconfig.json'),
      }),
    ],
    alias: { 'my-library': path.resolve(__dirname, '../src/index.ts') },
  },
  plugins: [new MiniCssExtractPlugin()],
  devServer: {
    allowedHosts: ['host.docker.internal'],
  },
};

Here you are I removed just company based info

sibelius commented 3 years ago

using a simpler rule like this

module: { rules: [ { test: /.css$/, use: ['style-loader', 'css-loader'], }, ], },

works?

Naspo88 commented 3 years ago

I tried before contacting you. It didn't work either :)

nimahkh commented 3 years ago

Hi, it should be production, considering if I lunch it locally it works correctly. The CSS is definitely on the page with the mentions CSS and draft-js CSS, so I would expect that getting them correctly I should be able to get the emoji and linkify ones.

I will try to get a small repo to reproduce it. For now, I try to share what I can share from my file (for company policy I can't do more than this).

webpack rule

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
...
{
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              fallback: 'style-loader',
              modules: true,
              namedExport: true,
              camelCase: true,
              importLoaders: 1,
              localIdentName: '[name]__[local]___[hash:base64:5]',
            },
          },
          'css-loader',
        ],
 },

RichTextArea.tsx imports

import React, { useState } from 'react';
import createEmojiPlugin, { defaultTheme } from '@draft-js-plugins/emoji';
import createLinkifyPlugin from '@draft-js-plugins/linkify';
import createListPlugin from 'draft-js-list-plugin';
import createMentionPlugin from 'draft-js-mention-plugin';
import 'draft-js/dist/Draft.css';
import 'draft-js-mention-plugin/lib/plugin.css';
import '@draft-js-plugins/emoji/lib/plugin.css';
import '@draft-js-plugins/linkify/lib/plugin.css';
import Editor from '@draft-js-plugins/editor';
import { defaultSuggestionsFilter } from 'draft-js-mention-plugin';

I tested all of the solutions above, but not working.

const HtmlWebPackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const Dotenv = require('dotenv-webpack');
const deps = require('./package.json').dependencies;
const PORTS = require('../../PORTS');
const PORT = process.env.PORT || PORTS.home;
const BASE_URL = process.env.BASE_URL || '';

module.exports = (_, argv) => {
  const isDev = argv.mode === 'development';

  return {
    output: {
      publicPath: isDev ? `http://localhost:${PORT}/` : `${BASE_URL}/profile/`,
    },
    resolve: {
      extensions: ['.tsx', '.ts', '.jsx', '.js', '.json', '.css'],
    },
    devServer: {
      port: PORT,
      historyApiFallback: true,
    },
    module: {
      rules: [
        {
          test: /bootstrap\.tsx$/,
          loader: 'bundle-loader',
          options: {
            lazy: true,
          },
        },
        {
          test: /\.m?js/,
          type: 'javascript/auto',
          resolve: {
            fullySpecified: false,
          },
        },
        {
          test: /\.(ts|tsx|js|jsx)$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              sourceMap: isDev,
            },
          },
        },
        {
          test: /\.svg$/,
          use: [
            {
              loader: 'svg-url-loader',
              options: {
                limit: 10000,
              },
            },
          ],
        },
        {
          test: /\.(png|jpe?g|gif)$/i,
          loader: 'file-loader',
          options: {
            name: isDev ? '[path][name].[ext]' : '[contenthash:8].[ext]',
          },
        },
        {
          test: /\.css$/,
          use: ['style-loader', 'css-loader'],
        },
      ],
    },
    plugins: [
      new Dotenv({
        path: './.env',
      }),
      new ModuleFederationPlugin({
        remotes: {},
        shared: {
          react: {
            eager: true,
            singleton: true,
            requiredVersion: deps.react,
          },
          'react-dom': {
            eager: true,
            singleton: true,
            requiredVersion: deps['react-dom'],
          },
          '@apollo/client': {
            eager: true,
            singleton: true,
            requiredVersion: deps['@apollo/client'],
          },
          lodash: {
            eager: true,
            singleton: true,
            requiredVersion: deps.lodash,
          },
        },
      }),
      new HtmlWebPackPlugin({
        template: './src/index.html',
      }),
    ],
  };
};
fxOne commented 3 years ago

The CSS is definitely on the page with the mentions CSS and draft-js CSS

You mean by this the CSS from @draft-js-plugins/mention/lib/plugin.css is in the CSS file which is used on the page?

nimahkh commented 3 years ago

using a simpler rule like this

module: { rules: [ { test: /.css$/, use: ['style-loader', 'css-loader'], }, ], },

works?

No, not work on webpack 5

sibelius commented 3 years ago

can you try disable tree shaking?

or sideEffects: false from the package.json

Naspo88 commented 3 years ago

The CSS is definitely on the page with the mentions CSS and draft-js CSS

You mean by this the CSS from @draft-js-plugins/mention/lib/plugin.css is in the CSS file which is used on the page?

No I mean from draft-js-mention-plugin

sibelius commented 3 years ago

Can you send us a screenshot of the final styles of this components?

Like from chrome devtools?

Naspo88 commented 3 years ago
/**
 * Draft v0.11.7
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:rgba(255,255,255,0);border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;width:100%;z-index:1}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1,lower-alpha) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2,lower-roman) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4,lower-alpha) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4}
.draftJsMentionPlugin__mention__29BEd, .draftJsMentionPlugin__mention__29BEd:visited {
  color: #575f67;
  cursor: pointer;
  display: inline-block;
  background: #e6f3ff;
  padding-left: 2px;
  padding-right: 2px;
  border-radius: 2px;
  text-decoration: none;
}

.draftJsMentionPlugin__mention__29BEd:hover, .draftJsMentionPlugin__mention__29BEd:focus {
  color: #677584;
  background: #edf5fd;
  outline: 0; /* reset for :focus */
}

.draftJsMentionPlugin__mention__29BEd:active {
  color: #222;
  background: #455261;
}
.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm {
  padding: 7px 10px 3px 10px;
  transition: background-color 0.4s cubic-bezier(.27,1.27,.48,.56);
}

.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm:active {
  background-color: #cce7ff;
}

.draftJsMentionPlugin__mentionSuggestionsEntryFocused__3LcTd {
  background-color: #e6f3ff;
}

.draftJsMentionPlugin__mentionSuggestionsEntryText__3Jobq {
  display: inline-block;
  margin-left: 8px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 368px;
  font-size: 0.9em;
  margin-bottom: 0.2em;
}

.draftJsMentionPlugin__mentionSuggestionsEntryAvatar__1xgA9 {
  display: inline-block;
  width: 24px;
  height: 24px;
  border-radius: 12px;
}
.draftJsMentionPlugin__mentionSuggestions__2DWjA {
  border: 1px solid #eee;
  margin-top: 0.4em;
  position: absolute;
  min-width: 220px;
  max-width: 440px;
  background: #fff;
  border-radius: 2px;
  box-shadow: 0px 4px 30px 0px rgba(220,220,220,1);
  cursor: pointer;
  padding-top: 8px;
  padding-bottom: 8px;
  z-index: 2;
  display: -webkit-box;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
          flex-direction: column;
  box-sizing: border-box;
  -webkit-transform: scale(0);
          transform: scale(0);
}
sibelius commented 3 years ago

we can only debug further having a github repro

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

DiFuks commented 3 years ago

@Naspo88 I am having a similar problem. Did you manage to solve it?

sibelius commented 3 years ago

provide a repro if you wanna help

DiFuks commented 3 years ago

It looks like the problem is similar to this https://github.com/fkhadra/react-toastify/issues/334#issuecomment-482151174. This confirms that when imported via require, styles are included in the bundle.

Not working in production:

import '@draft-js-plugins/emoji/lib/plugin.css';

This work:

require('@draft-js-plugins/emoji/lib/plugin.css');
sibelius commented 3 years ago

do you have sideEffects: false somewhere?

fxOne commented 3 years ago

Can you try to change the sideEffects option in the @draft-js-plugins/* packages to

"sideEffects": [
  "*.css"
]

If this solves the issue I will replace them here.

DiFuks commented 3 years ago

Can you try to change the sideEffects option in the @draft-js-plugins/* packages to

"sideEffects": [
  "*.css"
]

If this solves the issue I will replace them here.

After changing to

"sideEffects": [
   "*.css"
] 

in @ draft-js-plugins /**/ package.json everything works fine