Skip to content

Commit f26a5c9

Browse files
authored
Merge branch 'main' into bug/16601-Login-error
2 parents 0fa1f34 + 91db741 commit f26a5c9

File tree

1,463 files changed

+7503
-6600
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,463 files changed

+7503
-6600
lines changed

.storybook/preview.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ import { UmbIconRegistry } from '../src/packages/core/icon-registry/icon.registr
2020
import { UmbLitElement } from '../src/packages/core/lit-element';
2121
import { umbLocalizationRegistry } from '../src/packages/core/localization';
2222
import customElementManifests from '../dist-cms/custom-elements.json';
23-
import icons from '../src/packages/core/icon-registry/icons/icons';
23+
import icons from '../src/packages/core/icon-registry/icons';
2424

2525
import '../src/libs/context-api/provide/context-provider.element';
2626
import '../src/packages/core/components';
2727

28-
import { manifests as documentManifests } from '../src/packages/documents';
28+
import { manifests as documentManifests } from '../src/packages/documents/manifests';
2929
import { manifests as localizationManifests } from '../src/packages/core/localization/manifests';
3030
import { UmbNotificationContext } from '../src/packages/core/notification';
3131

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export default class MyElement extends UmbElementMixin(LitElement) {
126126
this._notificationContext?.peek('positive', { data: { message: '#h5yr' } });
127127
}
128128

129-
render() {
129+
override render() {
130130
return html`
131131
<uui-box headline="Welcome">
132132
<p>A TypeScript Lit Dashboard</p>

devops/icons/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const collectDictionaryIcons = async () => {
4646
legacy: iconDef.legacy,
4747
fileName: iconFileName,
4848
svg,
49-
output: `${iconsOutputDirectory}/${iconFileName}.js`,
49+
output: `${iconsOutputDirectory}/${iconFileName}.ts`,
5050
};
5151

5252
icons.push(icon);
@@ -77,7 +77,7 @@ const collectDictionaryIcons = async () => {
7777
legacy: iconDef.legacy,
7878
fileName: iconFileName,
7979
svg,
80-
output: `${iconsOutputDirectory}/${iconFileName}.js`,
80+
output: `${iconsOutputDirectory}/${iconFileName}.ts`,
8181
};
8282

8383
icons.push(icon);
@@ -102,7 +102,7 @@ const collectDictionaryIcons = async () => {
102102
legacy: iconDef.legacy,
103103
fileName: iconFileName,
104104
svg,
105-
output: `${iconsOutputDirectory}/${iconFileName}.js`,
105+
output: `${iconsOutputDirectory}/${iconFileName}.ts`,
106106
};
107107

108108
icons.push(icon);
@@ -141,7 +141,7 @@ const collectDiskIcons = async (icons) => {
141141
legacy: true,
142142
fileName: iconFileName,
143143
svg,
144-
output: `${iconsOutputDirectory}/${iconFileName}.js`,
144+
output: `${iconsOutputDirectory}/${iconFileName}.ts`,
145145
};
146146

147147
icons.push(icon);
@@ -168,13 +168,13 @@ const writeIconsToDisk = (icons) => {
168168
};
169169

170170
const generateJS = (icons) => {
171-
const JSPath = `${iconsOutputDirectory}/icons.ts`;
171+
const JSPath = `${moduleDirectory}/icons.ts`;
172172

173173
const iconDescriptors = icons.map((icon) => {
174174
return `{
175175
name: "${icon.name}",
176176
${icon.legacy ? 'legacy: true,' : ''}
177-
path: "./icons/${icon.fileName}.js",
177+
path: () => import("./icons/${icon.fileName}.js"),
178178
}`.replace(/\t/g, ''); // Regex removes white space [NL]
179179
});
180180

devops/tsc-override/index.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Notice: This script is not perfect and may not work in all cases. ex. it places the override term wrong for async and setter/getter methods. But its a help any way. [NL]
2+
3+
import ts from 'typescript';
4+
import path from 'node:path';
5+
import fs from 'node:fs/promises';
6+
7+
const tsconfigPath = './tsconfig.json';
8+
9+
const cwd = process.cwd();
10+
11+
async function fixOverride() {
12+
const configFile = path.isAbsolute(tsconfigPath)
13+
? tsconfigPath
14+
: ts.findConfigFile(cwd, ts.sys.fileExists, tsconfigPath);
15+
16+
if (!configFile) {
17+
console.error('No tsconfig file found for path:', tsconfigPath);
18+
process.exit(1);
19+
}
20+
21+
const config = ts.readConfigFile(configFile, ts.sys.readFile);
22+
23+
const { options, fileNames } = ts.parseJsonConfigFileContent(
24+
config.config,
25+
ts.sys,
26+
27+
// Resolve to the folder where the tsconfig file located
28+
path.dirname(tsconfigPath),
29+
);
30+
31+
const program = ts.createProgram({
32+
rootNames: fileNames,
33+
options,
34+
});
35+
36+
if (fileNames.length === 0) {
37+
console.error('No files in the project.', {
38+
fileNames,
39+
options,
40+
});
41+
42+
process.exit(1);
43+
}
44+
let emitResult = program.emit();
45+
46+
const overrideErrors = ts
47+
.getPreEmitDiagnostics(program)
48+
.concat(emitResult.diagnostics)
49+
.filter((diagnostic) =>
50+
[
51+
// This member must have an 'override' modifier because it overrides a member in the base class '{0}'.
52+
4114,
53+
// This parameter property must have an 'override' modifier because it overrides a member in base class '{0}'
54+
4115,
55+
// This member must have an 'override' modifier because it overrides an abstract method that is declared in the base class '{0}'.
56+
4116,
57+
].includes(diagnostic.code),
58+
);
59+
60+
const sortedErrors = sortErrors(overrideErrors);
61+
62+
for (const diagnostic of sortedErrors) {
63+
await addOverride(diagnostic);
64+
}
65+
}
66+
67+
/**
68+
*
69+
* @param {ts.Diagnostic} diagnostic
70+
* @returns {Promise<void>}
71+
*/
72+
async function addOverride(diagnostic) {
73+
const fileContent = (await fs.readFile(diagnostic.file.fileName, 'utf-8')).toString();
74+
let startIndex = diagnostic.start;
75+
76+
if (fileContent.slice(0, startIndex).endsWith(' get ')) {
77+
startIndex -= 'get '.length;
78+
}
79+
if (fileContent.slice(0, startIndex).endsWith(' async ')) {
80+
startIndex -= 'async '.length;
81+
}
82+
if (fileContent.slice(0, startIndex).endsWith(' readonly ')) {
83+
startIndex -= 'readonly '.length;
84+
}
85+
86+
const newFileContent = [fileContent.slice(0, startIndex), 'override ', fileContent.slice(startIndex)].join('');
87+
await fs.writeFile(diagnostic.file.fileName, newFileContent);
88+
}
89+
90+
/**
91+
*
92+
* @param {ts.Diagnostic[]} errors
93+
* @returns {ts.Diagnostic[]}
94+
*/
95+
function sortErrors(errors) {
96+
// Sort by file path and start position from end to start
97+
// so we can insert override keyword without changing the start position of other errors in the same file that happen before
98+
return errors.slice(0).sort((a, b) => {
99+
if (a.file && b.file) {
100+
if (a.file.fileName === b.file.fileName) {
101+
return b.start - a.start;
102+
}
103+
104+
return a.file.fileName.localeCompare(b.file.fileName);
105+
}
106+
107+
return 0;
108+
});
109+
}
110+
111+
fixOverride();

devops/tsconfig/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const tsConfigBase = {
2828
baseUrl: '.',
2929
incremental: true,
3030
skipLibCheck: true,
31+
noImplicitOverride: true,
3132
/* Bundler mode */
3233
moduleResolution: 'bundler',
3334
allowImportingTsExtensions: true,

examples/dashboard-with-property-dataset/dataset-dashboard.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class ExampleDatasetDashboard extends UmbElementMixin(LitElement) {
1818
this.requestUpdate('data', oldValue);
1919
}
2020

21-
render() {
21+
override render() {
2222
return html`
2323
<uui-box class="uui-text">
2424
<h1 class="uui-h2" style="margin-top: var(--uui-size-layout-1);">Dataset Example</h1>
@@ -39,7 +39,7 @@ export class ExampleDatasetDashboard extends UmbElementMixin(LitElement) {
3939
},
4040
{
4141
alias: 'items',
42-
value: [ 'First Option' , 'Second Option', 'Third Option' ],
42+
value: ['First Option', 'Second Option', 'Third Option'],
4343
},
4444
]}
4545
property-editor-ui-alias="Umb.PropertyEditorUi.Dropdown"></umb-property>
@@ -51,7 +51,7 @@ export class ExampleDatasetDashboard extends UmbElementMixin(LitElement) {
5151
`;
5252
}
5353

54-
static styles = [
54+
static override styles = [
5555
UmbTextStyles,
5656
css`
5757
:host {

examples/manifest-picker/manifest-picker-dashboard.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class ExampleManifestPickerDashboard extends UmbLitElement {
3838
this._selectedManifest = selectedManifest?.value ?? '';
3939
}
4040

41-
render() {
41+
override render() {
4242
return html`
4343
<uui-box>
4444
<umb-property-layout label="Select a extension type...">
@@ -77,7 +77,7 @@ export class ExampleManifestPickerDashboard extends UmbLitElement {
7777
`;
7878
}
7979

80-
static styles = [
80+
static override styles = [
8181
UmbTextStyles,
8282
css`
8383
:host {

examples/sorter-with-nested-containers/sorter-dashboard.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
22
import { css, html, customElement, LitElement } from '@umbraco-cms/backoffice/external/lit';
33
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
4-
import type { ModelEntryType } from './sorter-group.js';
4+
import type { ExampleSorterGroup, ModelEntryType } from './sorter-group.js';
55

66
import './sorter-group.js';
77
@customElement('example-sorter-dashboard')
@@ -53,19 +53,26 @@ export class ExampleSorterDashboard extends UmbElementMixin(LitElement) {
5353
},
5454
];
5555

56-
render() {
56+
override render() {
5757
return html`
5858
<uui-box class="uui-text">
5959
<div class="outer-wrapper">
60-
<h5>Notice this example still only support single group of Sorter.</h5>
61-
<example-sorter-group .initialItems=${this.groupOneItems}></example-sorter-group>
62-
<example-sorter-group .initialItems=${this.groupTwoItems}></example-sorter-group>
60+
<example-sorter-group
61+
.value=${this.groupOneItems}
62+
@change=${(e: Event) => {
63+
this.groupOneItems = (e.target as ExampleSorterGroup).value;
64+
}}></example-sorter-group>
65+
<example-sorter-group
66+
.value=${this.groupTwoItems}
67+
@change=${(e: Event) => {
68+
this.groupTwoItems = (e.target as ExampleSorterGroup).value;
69+
}}></example-sorter-group>
6370
</div>
6471
</uui-box>
6572
`;
6673
}
6774

68-
static styles = [
75+
static override styles = [
6976
UmbTextStyles,
7077
css`
7178
:host {

examples/sorter-with-nested-containers/sorter-group.ts

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,8 @@ export type ModelEntryType = {
1313

1414
@customElement('example-sorter-group')
1515
export class ExampleSorterGroup extends UmbElementMixin(LitElement) {
16-
@property({ type: Array, attribute: false })
17-
public get initialItems(): ModelEntryType[] {
18-
return this.items;
19-
}
20-
public set initialItems(value: ModelEntryType[]) {
21-
// Only want to set the model initially, cause any re-render should not set this again.
22-
if (this._items !== undefined) return;
23-
this.items = value;
24-
}
25-
26-
@property({ type: Array, attribute: false })
27-
public get items(): ModelEntryType[] {
28-
return this._items ?? [];
29-
}
30-
public set items(value: ModelEntryType[]) {
31-
const oldValue = this._items;
32-
this._items = value;
33-
this.#sorter.setModel(this._items);
34-
this.requestUpdate('items', oldValue);
35-
}
36-
private _items?: ModelEntryType[];
37-
16+
//
17+
// Sorter setup:
3818
#sorter = new UmbSorterController<ModelEntryType, ExampleSorterItem>(this, {
3919
getUniqueOfElement: (element) => {
4020
return element.name;
@@ -46,33 +26,52 @@ export class ExampleSorterGroup extends UmbElementMixin(LitElement) {
4626
itemSelector: 'example-sorter-item',
4727
containerSelector: '.sorter-container',
4828
onChange: ({ model }) => {
49-
const oldValue = this._items;
50-
this._items = model;
51-
this.requestUpdate('items', oldValue);
29+
const oldValue = this._value;
30+
this._value = model;
31+
this.requestUpdate('value', oldValue);
32+
// Fire an event for the parent to know that the model has changed.
33+
this.dispatchEvent(new CustomEvent('change'));
5234
},
5335
});
5436

37+
@property({ type: Array, attribute: false })
38+
public get value(): ModelEntryType[] {
39+
return this._value ?? [];
40+
}
41+
public set value(value: ModelEntryType[]) {
42+
const oldValue = this._value;
43+
this._value = value;
44+
this.#sorter.setModel(this._value);
45+
this.requestUpdate('value', oldValue);
46+
}
47+
private _value?: ModelEntryType[];
48+
5549
removeItem = (item: ModelEntryType) => {
56-
this.items = this.items.filter((r) => r.name !== item.name);
50+
this.value = this.value.filter((r) => r.name !== item.name);
5751
};
5852

59-
render() {
53+
override render() {
6054
return html`
6155
<div class="sorter-container">
6256
${repeat(
63-
this.items,
57+
this.value,
58+
// Note: ideally you have an unique identifier for each item, but for this example we use the `name` as identifier.
6459
(item) => item.name,
6560
(item) =>
6661
html`<example-sorter-item name=${item.name}>
6762
<button slot="action" @click=${() => this.removeItem(item)}>Delete</button>
68-
${item.children ? html`<example-sorter-group .initialItems=${item.children}></example-sorter-group>` : ''}
63+
<example-sorter-group
64+
.value=${item.children ?? []}
65+
@change=${(e: Event) => {
66+
item.children = (e.target as ExampleSorterGroup).value;
67+
}}></example-sorter-group>
6968
</example-sorter-item>`,
7069
)}
7170
</div>
7271
`;
7372
}
7473

75-
static styles = [
74+
static override styles = [
7675
UmbTextStyles,
7776
css`
7877
:host {

examples/sorter-with-nested-containers/sorter-item.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export class ExampleSorterItem extends UmbElementMixin(LitElement) {
1212
@property({ type: Boolean, reflect: true, attribute: 'drag-placeholder' })
1313
umbDragPlaceholder = false;
1414

15-
render() {
15+
override render() {
1616
return html`
1717
<div>
1818
${this.name}
@@ -23,7 +23,7 @@ export class ExampleSorterItem extends UmbElementMixin(LitElement) {
2323
`;
2424
}
2525

26-
static styles = [
26+
static override styles = [
2727
UmbTextStyles,
2828
css`
2929
:host {

0 commit comments

Comments
 (0)