diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/npm-publish-github-packages.yml b/src/Umbraco.Web.UI.Client/.github/workflows/npm-publish-github-packages.yml new file mode 100644 index 0000000000..62c7b01446 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/.github/workflows/npm-publish-github-packages.yml @@ -0,0 +1,72 @@ +# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created +# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages +# The @umbraco-cms scope is owned by Umbraco HQ + +name: Node.js Libraries Package + +on: + push: + branches: [ main ] + paths: + - 'libs/**' + - 'package.json' + - 'package-lock.json' + - '.github/workflows/npm-publish-github-packages.yml' + - './rollup-libs.config.js' + - 'src/**/*.element.ts' + pull_request: + branches: [ main ] + paths: + - 'libs/**' + - 'package.json' + - 'package-lock.json' + - '.github/workflows/npm-publish-github-packages.yml' + - './rollup-libs.config.js' + - 'src/**/*.element.ts' + workflow_dispatch: + +env: + NODE_OPTIONS: --max-old-space-size=16384 + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + - run: npm ci + - run: npm run build:libs + - uses: actions/upload-artifact@v3 + with: + name: artifact + path: ./dist/libs + + publish-npm: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: build + runs-on: ubuntu-latest + concurrency: + group: npm-publish + cancel-in-progress: true + steps: + - uses: actions/download-artifact@v3 + with: + name: artifact + - uses: actions/setup-node@v3 + with: + node-version: 18 + registry-url: https://registry.npmjs.org/ + scope: '@umbraco-cms' + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} + - name: Version and publish + run: | + SHA_SHORT=$(echo $GITHUB_SHA | cut -c1-8) + npm whoami + npm version 1.0.0-next.$SHA_SHORT --allow-same-version --no-git-tag-version + npm publish --tag next --access public + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/src/Umbraco.Web.UI.Client/.gitignore b/src/Umbraco.Web.UI.Client/.gitignore index 48fcabe2ce..d2ebc9b225 100644 --- a/src/Umbraco.Web.UI.Client/.gitignore +++ b/src/Umbraco.Web.UI.Client/.gitignore @@ -41,3 +41,8 @@ playwright/.cache/ storybook-static/ custom-elements.json + +# JSON for HTML Custom Data +# https://github.com/runem/web-component-analyzer#vscode +# https://github.com/microsoft/vscode-custom-data +vscode-html-custom-data.json \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/libs/README.md b/src/Umbraco.Web.UI.Client/libs/README.md new file mode 100644 index 0000000000..8796b8f582 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/libs/README.md @@ -0,0 +1,168 @@ +# @umbraco-cms/backoffice + +This package contains the types for the libraries for Umbraco 13. + +## Installation + +```bash +npm install -D @umbraco-cms/backoffice +``` + +## Usage + +### Vanilla JavaScript + +Create an umbraco-package.json file in the root of your package. + +```json +{ + "name": "My.Package", + "version": "0.1.0", + "extensions": [ + { + "type": "dashboard", + "alias": "my.custom.dashboard", + "name": "My Dashboard", + "js": "/App_Plugins/MyPackage/dashboard.js", + "weight": -1, + "meta": { + "label": "My Dashboard", + "pathname": "my-dashboard" + }, + "conditions": { + "sections": ["Umb.Section.Content"] + } + } + ] +} +``` + +Then create a dashboard.js file the same folder. + +```javascript +import { UmbElementMixin } from '@umbraco-cms/backoffice/element'; +import { UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; + +const template = document.createElement('template'); +template.innerHTML = ` + + + +

Welcome to my dashboard

+

Example of vanilla JS code

+ + +
+`; + +export default class MyDashboardElement extends UmbElementMixin(HTMLElement) { + /** @type {import('@umbraco-cms/backoffice/notification').UmbNotificationContext} */ + #notificationContext; + + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + this.shadowRoot.appendChild(template.content.cloneNode(true)); + + this.shadowRoot.getElementById('clickMe').addEventListener('click', this.onClick.bind(this)); + + this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (_instance) => { + this.#notificationContext = _instance; + }); + } + + onClick = () => { + this.#notificationContext?.peek('positive', { data: { headline: 'Hello' } }); + }; +} + +customElements.define('my-custom-dashboard', MyDashboardElement); +``` + +### TypeScript with Lit + +First install Lit and Vite. This command will create a new folder called `my-package` which will have the Vite tooling and Lit for WebComponent development setup. + +```bash +npm create vite@latest -- --template lit-ts my-package +``` + +Go to the new folder and install the backoffice package. + +```bash +cd my-package +npm install -D @umbraco-cms/backoffice +``` + +Then go to the element located in `src/my-element.ts` and replace it with the following code. + +```typescript +// src/my-element.ts +import { LitElement, html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbElementMixin } from '@umbraco-cms/backoffice/element'; +import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; + +@customElement('my-element') +export default class MyElement extends UmbElementMixin(LitElement) { + + private _notificationContext?: UmbNotificationContext; + + constructor() { + super(); + this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (_instance) => { + this._notificationContext = _instance; + }); + } + + onClick() { + this._notificationContext?.peek('positive', { data: { message: '#h5yr' } }); + } + + render() { + return html` + +

A TypeScript Lit Dashboard

+ this.onClick()}> +
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'my-element': MyElement; + } +} +``` + +Finally add an umbraco-package.json file in the root of your package folder `my-package`. + +```json +{ + "name": "My.Package", + "version": "0.1.0", + "extensions": [ + { + "type": "dashboard", + "alias": "my.custom.dashboard", + "name": "My Dashboard", + "js": "/App_Plugins/MyPackage/dist/my-package.js", + "weight": -1, + "meta": { + "label": "My Dashboard", + "pathname": "my-dashboard" + }, + "conditions": { + "sections": ["Umb.Section.Content"] + } + } + ] +} +``` diff --git a/src/Umbraco.Web.UI.Client/libs/package.json b/src/Umbraco.Web.UI.Client/libs/package.json index 0064a56274..e5f1036d7d 100644 --- a/src/Umbraco.Web.UI.Client/libs/package.json +++ b/src/Umbraco.Web.UI.Client/libs/package.json @@ -2,6 +2,10 @@ "name": "@umbraco-cms/backoffice", "version": "13.0.0-alpha.0", "license": "MIT", + "keywords": [ + "umbraco", + "backoffice" + ], "repository": { "url": "https://github.com/umbraco/Umbraco.CMS.Backoffice", "type": "git" @@ -15,9 +19,15 @@ "url": "https://umbraco.com" }, "type": "module", + "files": [ + "*.d.ts", + "*.json", + "*.md" + ], "peerDependencies": { "@types/uuid": "^9.0.1", "@umbraco-ui/uui": "^1.2.0-rc.0", "rxjs": "^7.8.0" - } + }, + "customElements": "custom-elements.json" } diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index b7c7554e86..ae3981ecb6 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -28,7 +28,7 @@ "scripts": { "dev": "vite", "build": "tsc && vite build --mode staging", - "build:libs": "rollup -c rollup-libs.config.js && node utils/move-libs.js", + "build:libs": "npm run wc-analyze && npm run wc-analyze:vscode && rollup -c rollup-libs.config.js && node utils/move-libs.js", "build:for:static": "tsc && vite build", "build:for:cms": "tsc && vite build -c vite.cms.config.ts && npm run build:libs", "build:for:cms:watch": "vite build -c vite.cms.config.ts --watch", @@ -50,6 +50,7 @@ "build-storybook": "npm run wc-analyze && storybook build", "generate:icons": "node ./devops/icons/index.js", "wc-analyze": "wca **/*.element.ts --outFile custom-elements.json", + "wc-analyze:vscode": "wca **/*.element.ts --format vscode --outFile vscode-html-custom-data.json", "new-extension": "plop --plopfile ./devops/plop/plop.js", "compile": "tsc", "check": "npm run lint && npm run compile && npm run build-storybook" diff --git a/src/Umbraco.Web.UI.Client/utils/move-libs.js b/src/Umbraco.Web.UI.Client/utils/move-libs.js index 0d19cfea8b..59c3f7d044 100644 --- a/src/Umbraco.Web.UI.Client/utils/move-libs.js +++ b/src/Umbraco.Web.UI.Client/utils/move-libs.js @@ -10,21 +10,30 @@ // Note: This script is not used in the build process, it is only used to transform the d.ts files // when the d.ts files are copied to the dist folder -import { readdirSync, readFileSync, writeFileSync, cpSync, mkdirSync, lstatSync } from 'fs'; +// Note: Updated to help copy the two JSON files generated from webcomponant analyzer tool +// One is specific to VSCode HTMLCutomData for intellisense and the other is a more broad format used in storybook etc +import { readdirSync, readFileSync, writeFileSync, cpSync, mkdirSync } from 'fs'; + +const rootDir = './'; const srcDir = './libs'; const inputDir = './dist/libs'; const outputDir = '../Umbraco.Cms.StaticAssets/wwwroot/umbraco/backoffice/libs'; -// Copy package.json +// Copy package files cpSync(`${srcDir}/package.json`, `${inputDir}/package.json`, { recursive: true }); +cpSync(`${srcDir}/README.md`, `${inputDir}/README.md`, { recursive: true }); +cpSync(`${rootDir}/custom-elements.json`, `${inputDir}/custom-elements.json`, { recursive: true }); +cpSync(`${rootDir}/vscode-html-custom-data.json`, `${inputDir}/vscode-html-custom-data.json`, { recursive: true }); const libs = readdirSync(inputDir); // Create output folder try { - mkdirSync(outputDir, {recursive: true}); -} catch {} + mkdirSync(outputDir, { recursive: true }); +} catch { + // Ignore +} // Transform all .d.ts files and copy all other files to the output folder libs.forEach(lib => {