Commit d0da616d authored by Benjamin Franzke's avatar Benjamin Franzke
Browse files

[TASK] Update to Lit v2-rc1

Lit is the umbrella term for the next major
lit-html (v2) and lit-element (v3) versions.
Therefore we will refer to these components as
*Lit* in TYPO3 from now on as well.

These two libraries also have been migrated into
a single entry point module named `lit`.
It is officially described as:
> The main module exports the core pieces needed for component
> development: LitElement, html, css, and the most

lit-html v2 and lit-element v3 are mostly compatible
to the previous major versions. Main changes are

 * Deprecation of the `lit-element` entry point in
   favor of the new `lit` module
 * @internalProperty changed to @state
 * shadow css declaration via static property
   instead of static getter method
 * The CSSResult type declaration is gone
 * Directive (currently unused in TYPO3) API has changed

Related testing framework change is:
https://github.com/TYPO3/testing-framework/pull/229

Commands used:

  rm -rf typo3/sysext/core/Resources/Public/JavaScript/Contrib/{@lit,lit-element,lit-html,lit}/
  yarn add lit@^2.0.0-rc.1 lit-html@^2.0.0-rc.2 lit-element@^3.0.0-rc.1
  yarn add --dev rollup@^2.32.0 @rollup/plugin-replace
  grunt build
  git add typo3/sysext/core/Resources/Public/JavaScript/Contrib/{@lit,lit-element,lit-html,lit}/

  composer require --dev typo3/testing-framework:^6.8.1
  composer require --dev typo3/testing-framework:^6.8.1 \
    --no-update --working-dir=typo3/sysext/core

Resolves: #93965
Releases: master
Change-Id: I9b659d851e6ad9dc3cc649bd40aab886b86fb0f8
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/68104

Tested-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Reviewed-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
parent 0005bc5b
......@@ -451,37 +451,43 @@ module.exports = function (grunt) {
},
rollup: {
options: {
format: 'amd',
onwarn: function(warning) {
if (warning.code === 'THIS_IS_UNDEFINED' && grunt.file.match('*/lit-html/directives/async-*.js')) {
// lit-html's Symbol.asyncIterator polyfill in async-{append/replace}.js contains
// a global check for `this`: `(this && this.__asyncValues) || function (o) {`.
// rollup will rewrite that to `function (o) {` and warn about rewriting `this`.
// The rewrite is perfectly ok, the AMD module will act as a singleton, so no
// global window object is needed here. The warning is therefore silenced.
return;
}
console.warn( warning.message );
}
format: 'amd'
},
'lit-html': {
options: {
preserveModules: true,
plugins: () => [
require('@rollup/plugin-replace')({ values: { 'globalThis': 'window' }, preventAssignment: false }),
{
name: 'terser',
renderChunk: code => require('terser').minify(code, grunt.config.get('terser.options'))
renderChunk: code => require('terser').minify(code, {...grunt.config.get('terser.options'), ...{mangle: false}})
}
]
},
files: {
'<%= paths.core %>Public/JavaScript/Contrib/lit-html': [
'node_modules/lit-html/lit-html.js',
'node_modules/lit-html/*.js',
'node_modules/lit-html/directives/*.js',
'node_modules/lit-html/lib/*.js',
]
}
},
'@lit/reactive-element': {
options: {
preserveModules: true,
plugins: () => [
require('@rollup/plugin-replace')({ values: { 'globalThis': 'window' }, preventAssignment: false }),
{
name: 'terser',
renderChunk: code => require('terser').minify(code, {...grunt.config.get('terser.options'), ...{mangle: false}})
},
]
},
files: {
'<%= paths.core %>Public/JavaScript/Contrib/@lit/reactive-element': [
'node_modules/@lit/reactive-element/*.js',
'node_modules/@lit/reactive-element/decorators/*.js',
// omitted, empty
'!node_modules/lit-html/lib/render-options.js',
'!node_modules/lit-html/lib/template-processor.js',
'!node_modules/@lit/reactive-element/reactive-controller.js'
]
}
},
......@@ -489,18 +495,16 @@ module.exports = function (grunt) {
options: {
preserveModules: true,
plugins: () => [
require('@rollup/plugin-replace')({ values: { 'globalThis': 'window' }, preventAssignment: false }),
{
name: 'terser',
renderChunk: code => require('terser').minify(code, grunt.config.get('terser.options'))
renderChunk: code => require('terser').minify(code, {...grunt.config.get('terser.options'), ...{mangle: false}})
},
{
name: 'externals',
resolveId: (source) => {
if (source === 'lit-html/lit-html.js') {
return {id: 'lit-html', external: true}
}
if (source === 'lit-html/lib/shady-render.js') {
return {id: 'lit-html/lib/shady-render', external: true}
if (source.startsWith('lit-html') || source.startsWith('@lit/reactive-element')) {
return {id: source.replace(/\.js$/, ''), external: true}
}
return null
}
......@@ -509,8 +513,36 @@ module.exports = function (grunt) {
},
files: {
'<%= paths.core %>Public/JavaScript/Contrib/lit-element': [
'node_modules/lit-element/lit-element.js',
'node_modules/lit-element/lib/*.js',
'node_modules/lit-element/*.js',
'node_modules/lit-element/decorators/*.js',
]
}
},
'lit': {
options: {
preserveModules: true,
plugins: () => [
require('@rollup/plugin-replace')({ values: { 'globalThis': 'window' }, preventAssignment: false }),
{
name: 'terser',
renderChunk: code => require('terser').minify(code, {...grunt.config.get('terser.options'), ...{mangle: false}})
},
{
name: 'externals',
resolveId: (source) => {
if (source.startsWith('lit-html') || source.startsWith('lit-element') || source.startsWith('@lit/reactive-element')) {
return {id: source.replace(/\.js$/, ''), external: true}
}
return null
}
}
]
},
files: {
'<%= paths.core %>Public/JavaScript/Contrib/lit': [
'node_modules/lit/*.js',
'node_modules/lit/decorators/*.js',
'node_modules/lit/directives/*.js',
]
}
},
......
......@@ -12,13 +12,22 @@
*/
import module = require('module');
import {html, css, unsafeCSS, customElement, property, LitElement, TemplateResult, CSSResult} from 'lit-element';
import {unsafeHTML} from 'lit-html/directives/unsafe-html';
import {until} from 'lit-html/directives/until';
import {html, css, unsafeCSS, LitElement, TemplateResult, CSSResult} from 'lit';
import {customElement, property} from 'lit/decorators';
import {unsafeHTML} from 'lit/directives/unsafe-html';
import {until} from 'lit/directives/until';
import {Sizes, States, MarkupIdentifiers} from '../Enum/IconTypes';
import Icons = require('../Icons');
import 'TYPO3/CMS/Backend/Element/SpinnerElement';
const iconUnifyModifier = 0.86;
const iconSize = (identifier: CSSResult, size: number) => css`
:host([size=${identifier}]),
:host([raw]) .icon-size-${identifier} {
font-size: ${size}px;
}
`;
/**
* Module: TYPO3/CMS/Backend/Element/IconElement
*
......@@ -45,106 +54,94 @@ export class IconElement extends LitElement {
*/
@property({type: String}) raw?: string = null;
public static get styles(): CSSResult[]
{
const iconUnifyModifier = 0.86;
const iconSize = (identifier: CSSResult, size: number) => css`
:host([size=${identifier}]),
:host([raw]) .icon-size-${identifier} {
font-size: ${size}px;
static styles = [
css`
:host {
display: flex;
font-size: 1em;
width: 1em;
height: 1em;
line-height: 0;
}
`;
return [
css`
:host {
display: flex;
font-size: 1em;
width: 1em;
height: 1em;
line-height: 0;
}
typo3-backend-spinner {
font-size: 1em;
}
.icon {
position: relative;
display: block;
overflow: hidden;
white-space: nowrap;
height: 1em;
width: 1em;
line-height: 1;
}
.icon svg,
.icon img {
display: block;
height: 1em;
width: 1em;
transform: translate3d(0, 0, 0);
}
typo3-backend-spinner {
font-size: 1em;
}
.icon {
position: relative;
display: block;
overflow: hidden;
white-space: nowrap;
height: 1em;
width: 1em;
line-height: 1;
}
.icon * {
display: block;
line-height: inherit;
}
.icon svg,
.icon img {
display: block;
height: 1em;
width: 1em;
transform: translate3d(0, 0, 0);
}
.icon-markup {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.icon * {
display: block;
line-height: inherit;
}
.icon-overlay {
position: absolute;
bottom: 0;
right: 0;
font-size: 0.6875em;
text-align: center;
}
.icon-markup {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.icon-color {
fill: currentColor;
}
.icon-overlay {
position: absolute;
bottom: 0;
right: 0;
font-size: 0.6875em;
text-align: center;
}
.icon-state-disabled .icon-markup {
opacity: .5;
}
.icon-color {
fill: currentColor;
}
.icon-unify {
font-size: ${iconUnifyModifier}em;
line-height: ${1 / iconUnifyModifier};
}
.icon-state-disabled .icon-markup {
opacity: .5;
}
.icon-spin .icon-markup {
animation: icon-spin 2s infinite linear;
}
.icon-unify {
font-size: ${iconUnifyModifier}em;
line-height: ${1 / iconUnifyModifier};
}
@keyframes icon-spin {
0% {
transform: rotate(0deg);
}
.icon-spin .icon-markup {
animation: icon-spin 2s infinite linear;
}
100% {
transform: rotate(360deg);
}
@keyframes icon-spin {
0% {
transform: rotate(0deg);
}
`,
iconSize(unsafeCSS(Sizes.small), 16),
iconSize(unsafeCSS(Sizes.default), 32),
iconSize(unsafeCSS(Sizes.large), 48),
iconSize(unsafeCSS(Sizes.mega), 64),
];
}
100% {
transform: rotate(360deg);
}
}
`,
iconSize(unsafeCSS(Sizes.small), 16),
iconSize(unsafeCSS(Sizes.default), 32),
iconSize(unsafeCSS(Sizes.large), 48),
iconSize(unsafeCSS(Sizes.mega), 64),
];
public render(): TemplateResult {
if (this.raw) {
......
......@@ -11,7 +11,8 @@
* The TYPO3 project - inspiring people to share!
*/
import {html, css, customElement, property, LitElement, TemplateResult, CSSResult} from 'lit-element';
import {html, css, LitElement, TemplateResult} from 'lit';
import {customElement, property} from 'lit/decorators';
import {Sizes} from '../Enum/IconTypes';
/**
......@@ -25,42 +26,39 @@ import {Sizes} from '../Enum/IconTypes';
export class SpinnerElement extends LitElement {
@property({type: String}) size: Sizes = Sizes.default;
public static get styles(): CSSResult
{
return css`
:host {
font-size: 32px;
width: 1em;
height: 1em;
display: flex;
justify-content: center;
align-items: center;
}
.spinner {
display: block;
border-style: solid;
border-color: #212121 #bababa #bababa;
border-radius: 50%;
width: 0.625em;
height: 0.625em;
border-width: 0.0625em;
animation: spin 1s linear infinite;
}
:host([size=small]) .spinner {
font-size: 16px;
}
:host([size=large]) .spinner {
font-size: 48px;
}
:host([size=mega]) .spinner {
font-size: 64px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`;
}
static styles = css`
:host {
font-size: 32px;
width: 1em;
height: 1em;
display: flex;
justify-content: center;
align-items: center;
}
.spinner {
display: block;
border-style: solid;
border-color: #212121 #bababa #bababa;
border-radius: 50%;
width: 0.625em;
height: 0.625em;
border-width: 0.0625em;
animation: spin 1s linear infinite;
}
:host([size=small]) .spinner {
font-size: 16px;
}
:host([size=large]) .spinner {
font-size: 48px;
}
:host([size=mega]) .spinner {
font-size: 64px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`;
public render(): TemplateResult {
return html`<div class="spinner"></div>`
......
......@@ -11,7 +11,8 @@
* The TYPO3 project - inspiring people to share!
*/
import {html, customElement, property, LitElement, TemplateResult} from 'lit-element';
import {html, LitElement, TemplateResult} from 'lit';
import {customElement, property} from 'lit/decorators';
import {lll} from 'TYPO3/CMS/Core/lit-helper';
import 'TYPO3/CMS/Backend/Element/IconElement';
......
......@@ -14,7 +14,7 @@
import * as d3selection from 'd3-selection';
import {SvgTree, SvgTreeSettings, TreeNodeSelection} from '../../SvgTree';
import {TreeNode} from '../../Tree/TreeNode';
import {customElement} from 'lit-element';
import {customElement} from 'lit/decorators';
interface SelectTreeSettings extends SvgTreeSettings {
exclusiveNodesIdentifiers: '';
......
......@@ -13,7 +13,8 @@
import type {SelectTree} from './SelectTree';
import {Tooltip} from 'bootstrap';
import {html, customElement, LitElement, TemplateResult} from 'lit-element';
import {html, LitElement, TemplateResult} from 'lit';
import {customElement} from 'lit/decorators';
import {lll} from 'TYPO3/CMS/Core/lit-helper';
import 'TYPO3/CMS/Backend/Element/IconElement';
import './SelectTree';
......
......@@ -11,7 +11,8 @@
* The TYPO3 project - inspiring people to share!
*/
import {customElement, property, LitElement} from 'lit-element';
import {LitElement} from 'lit';
import {customElement, property} from 'lit/decorators';
import FormEngine = require('TYPO3/CMS/Backend/FormEngine');
enum UpdateMode {
......
......@@ -16,8 +16,8 @@ import Viewport = require('./Viewport');
import Icons = require('./Icons');
import 'jquery/autocomplete';
import './Input/Clearable';
import {html, render} from 'lit-html';
import {unsafeHTML} from 'lit-html/directives/unsafe-html';
import {html, render} from 'lit';
import {unsafeHTML} from 'lit/directives/unsafe-html';
import {renderHTML} from 'TYPO3/CMS/Core/lit-helper';
enum Identifiers {
......
......@@ -11,9 +11,10 @@
* The TYPO3 project - inspiring people to share!
*/
import {LitElement, html, customElement, property, internalProperty} from 'lit-element';
import {classMap} from 'lit-html/directives/class-map';
import {ifDefined} from 'lit-html/directives/if-defined';
import {LitElement, html} from 'lit';
import {customElement, property, state} from 'lit/decorators';
import {classMap} from 'lit/directives/class-map';
import {ifDefined} from 'lit/directives/if-defined';
import {AbstractAction} from './ActionButton/AbstractAction';
import {SeverityEnum} from './Enum/Severity';
import Severity = require('./Severity');
......@@ -136,8 +137,8 @@ class NotificationMessage extends LitElement {
@property() duration: number = 0;
@property({type: Array, attribute: false}) actions: Array<Action> = [];
@internalProperty() visible: boolean = false;
@internalProperty() executingAction: number = -1;
@state() visible: boolean = false;
@state() executingAction: number = -1;
createRenderRoot(): Element|ShadowRoot {
return this;
......
......@@ -11,8 +11,9 @@
* The TYPO3 project - inspiring people to share!
*/
import {html, customElement, property, query, LitElement, TemplateResult, PropertyValues} from 'lit-element';
import {until} from 'lit-html/directives/until';
import {html, LitElement, TemplateResult, PropertyValues} from 'lit';
import {customElement, property, query} from 'lit/decorators';
import {until} from 'lit/directives/until';
import {lll} from 'TYPO3/CMS/Core/lit-helper';
import {PageTree} from './PageTree';
import {TreeNode} from './../Tree/TreeNode';
......
......@@ -11,7 +11,8 @@
* The TYPO3 project - inspiring people to share!
*/
import {html, property, internalProperty, LitElement, TemplateResult, customElement} from 'lit-element';
import {html, LitElement, TemplateResult} from 'lit';
import {customElement, property, state} from 'lit/decorators';
import {TreeNode} from './Tree/TreeNode';
import * as d3selection from 'd3-selection';
import AjaxRequest from 'TYPO3/CMS/Core/Ajax/AjaxRequest';
......@@ -56,7 +57,7 @@ export interface SvgTreeWrapper extends HTMLElement {
export class SvgTree extends LitElement {
@property({type: Object}) setup?: {[keys: string]: any} = null;
@internalProperty() settings: SvgTreeSettings = {
@state() settings: SvgTreeSettings = {
showIcons: false,
marginTop: 15,
nodeHeight: 20,
......
......@@ -11,7 +11,7 @@
* The TYPO3 project - inspiring people to share!
*/
import {html, TemplateResult} from 'lit-element';
import {html, TemplateResult} from 'lit';
import {renderNodes} from 'TYPO3/CMS/Core/lit-helper';
import * as d3drag from 'd3-drag';
import * as d3selection from 'd3-selection';
......
......@@ -11,7 +11,8 @@
* The TYPO3 project - inspiring people to share!
*/
import {customElement, html, LitElement, query, TemplateResult} from 'lit-element';
import {html, LitElement, TemplateResult} from 'lit';
import {customElement, query} from 'lit/decorators';
import AjaxRequest from 'TYPO3/CMS/Core/Ajax/AjaxRequest';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {TreeNode} from './TreeNode';
......
......@@ -11,7 +11,8 @@
* The TYPO3 project - inspiring people to share!
*/
import {html, customElement, query, LitElement, TemplateResult} from 'lit-element';
import {html, LitElement, TemplateResult} from 'lit';
import {customElement, query} from 'lit/decorators';
import {FileStorageTree} from './FileStorageTree';
import 'TYPO3/CMS/Backend/Element/IconElement';
import {TreeNode} from 'TYPO3/CMS/Backend/Tree/TreeNode';
......
......@@ -11,14 +11,15 @@
* The TYPO3 project - inspiring people to share!
*/
import {customElement, html, LitElement, query, property, TemplateResult} from 'lit-element';
import {html, LitElement, TemplateResult} from 'lit';
import {customElement, property, query} from 'lit/decorators';
import {until} from 'lit/directives/until';
import {lll} from 'TYPO3/CMS/Core/lit-helper';