diff --git a/components/oscd-action-pane/.gitignore b/components/oscd-action-pane/.gitignore new file mode 100644 index 0000000..63cc1db --- /dev/null +++ b/components/oscd-action-pane/.gitignore @@ -0,0 +1,20 @@ +## editors +/.idea +/.vscode + +## system files +.DS_Store + +## npm +/node_modules/ +/npm-debug.log +.tsbuildinfo + +## testing +/coverage/ + +## docs +/doc/ + +# build +/dist/ diff --git a/components/oscd-action-pane/.npmignore b/components/oscd-action-pane/.npmignore new file mode 100644 index 0000000..28f225d --- /dev/null +++ b/components/oscd-action-pane/.npmignore @@ -0,0 +1,18 @@ +## editors +/.idea +/.vscode + +## system files +.DS_Store + +## npm +/node_modules/ +/npm-debug.log +.tsbuildinfo + +## testing +/coverage/ + +## docs +/doc/ + diff --git a/components/oscd-action-pane/.storybook/main.ts b/components/oscd-action-pane/.storybook/main.ts new file mode 100644 index 0000000..c8e9fee --- /dev/null +++ b/components/oscd-action-pane/.storybook/main.ts @@ -0,0 +1,30 @@ +import type { StorybookConfig } from '@storybook/web-components-vite'; + +const config: StorybookConfig = { + stories: ['../stories/**/*.stories.@(js|jsx|ts|tsx)', '../stories/**/*.mdx'], + addons: [ + '@storybook/addon-docs', + '@storybook/addon-controls', + '@storybook/addon-actions', + '@storybook/addon-a11y', + '@storybook/addon-links', + { + name: '@storybook/adddon-essentials', + options: { + background: false, + }, + }, + '@etchteam/storybook-addon-status/register', + 'storybook-addon-root-attribute/register', + ], + framework: { + name: '@storybook/web-components-vite', + options: { + builder: { + viteConfigPath: '', + }, + }, + }, +}; + +export default config; diff --git a/components/oscd-action-pane/.storybook/manager.ts b/components/oscd-action-pane/.storybook/manager.ts new file mode 100644 index 0000000..66b6e89 --- /dev/null +++ b/components/oscd-action-pane/.storybook/manager.ts @@ -0,0 +1,5 @@ +import { addons } from '@storybook/manager-api'; + +addons.setConfig({ + enableShortcuts: false +}); diff --git a/components/oscd-action-pane/.storybook/preview-head.html b/components/oscd-action-pane/.storybook/preview-head.html new file mode 100644 index 0000000..89f0ee1 --- /dev/null +++ b/components/oscd-action-pane/.storybook/preview-head.html @@ -0,0 +1,16 @@ + + + diff --git a/components/oscd-action-pane/.storybook/preview.ts b/components/oscd-action-pane/.storybook/preview.ts new file mode 100644 index 0000000..94c4d5d --- /dev/null +++ b/components/oscd-action-pane/.storybook/preview.ts @@ -0,0 +1,44 @@ +import { setCustomElementsManifest } from '@storybook/web-components'; + +import { html } from 'lit'; +import { withRootAttribute } from 'storybook-addon-root-attribute'; + +import '../../../themes/prebuilt/oscd.css'; + +import customElements from '../custom-elements.json'; + +setCustomElementsManifest(customElements); + +export const decorators = [withRootAttribute]; + +export const parameters = { + controls: { expanded: true }, + actions: { argTypesRegex: '^on.*' }, + + statuses: { + released: { + background: '#0000ff', + color: '#ffffff', + description: 'This component is stable and released', + }, + beta: { + background: '#FF0000', + color: '#FFFFFF', + description: 'This component is still in beta', + }, + }, + rootAttribute: { + defaultState: { + name: 'Light', + value: null, + }, + attribute: 'dark', + tooltip: true, + states: [ + { + name: 'Dark', + value: 'dark', + }, + ], + }, +}; diff --git a/components/oscd-action-pane/CHANGELOG.md b/components/oscd-action-pane/CHANGELOG.md new file mode 100644 index 0000000..825c32f --- /dev/null +++ b/components/oscd-action-pane/CHANGELOG.md @@ -0,0 +1 @@ +# Changelog diff --git a/components/oscd-action-pane/EXAMPLE.md b/components/oscd-action-pane/EXAMPLE.md new file mode 100644 index 0000000..19b6555 --- /dev/null +++ b/components/oscd-action-pane/EXAMPLE.md @@ -0,0 +1,3 @@ +```html + +``` diff --git a/components/oscd-action-pane/INTRO.md b/components/oscd-action-pane/INTRO.md new file mode 100644 index 0000000..e69de29 diff --git a/components/oscd-action-pane/LICENSE.md b/components/oscd-action-pane/LICENSE.md new file mode 100644 index 0000000..c61b663 --- /dev/null +++ b/components/oscd-action-pane/LICENSE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/components/oscd-action-pane/README.md b/components/oscd-action-pane/README.md new file mode 100644 index 0000000..ef9d1a7 --- /dev/null +++ b/components/oscd-action-pane/README.md @@ -0,0 +1,29 @@ +# `` ![NPM](https://img.shields.io/badge/NPM-0.0.1-cb0001) ![Status](https://img.shields.io/badge/WIP-3b72bf) + +--- + + + +## Example + +```html + +``` + +--- + +### Attributes + +| Name | Type | Description | +| ---- | ---- | ----------- | + +### Css Properties + +| Name | Default | Description | +| ----------------------------------- | ----------------------- | ---------------------------------- | +| --oscd-action-icon-theme-primary | --oscd-theme-primary | Color for border on even levels. | +| --oscd-action-icon-theme-on-primary | --oscd-theme-on-primary | Pane color for the uneven levels. | +| --oscd-action-icon-theme-secondary | --oscd-theme-secondary | Color for border on uneven levels. | +| --oscd-action-pane-theme-surface | --oscd-theme-surface | Pane color for the even levels. | +| --oscd-action-icon-theme-on-surface | --oscd-theme-on-surface | Icon and label color. | +| --oscd-action-icon-theme-font | --oscd-theme-font | Font for label. | \ No newline at end of file diff --git a/components/oscd-action-pane/custom-elements-manifest.config.js b/components/oscd-action-pane/custom-elements-manifest.config.js new file mode 100644 index 0000000..562fc21 --- /dev/null +++ b/components/oscd-action-pane/custom-elements-manifest.config.js @@ -0,0 +1,6 @@ +export default { + globs: ['src/*.ts'], + exclude: ['test/*.ts'], + litelement: true, + plugins: [], +}; diff --git a/components/oscd-action-pane/custom-elements.json b/components/oscd-action-pane/custom-elements.json new file mode 100644 index 0000000..7715414 --- /dev/null +++ b/components/oscd-action-pane/custom-elements.json @@ -0,0 +1,187 @@ +{ + "schemaVersion": "1.0.0", + "readme": "", + "modules": [ + { + "kind": "javascript-module", + "path": "src/OscdActionPane.ts", + "declarations": [], + "exports": [ + { + "kind": "custom-element-definition", + "name": "oscd-action-pane", + "declaration": { + "name": "OscdActionPane", + "module": "/src/oscd-action-pane" + } + }, + { + "kind": "js", + "name": "OscdActionPane", + "declaration": { + "name": "OscdActionPane", + "module": "src/OscdActionPane.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/index.ts", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "*", + "declaration": { + "name": "*", + "package": "./OscdActionPane.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/oscd-action-pane.styles.ts", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "module": "src/oscd-action-pane.styles.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/oscd-action-pane.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "OscdActionPane", + "cssProperties": [ + { + "description": "Color for border on even levels.", + "name": "--oscd-action-icon-theme-primary", + "default": "--oscd-theme-primary" + }, + { + "description": "Pane color for the uneven levels.", + "name": "--oscd-action-icon-theme-on-primary", + "default": "--oscd-theme-on-primary" + }, + { + "description": "Color for border on uneven levels.", + "name": "--oscd-action-icon-theme-secondary", + "default": "--oscd-theme-secondary" + }, + { + "description": "Pane color for the even levels.", + "name": "--oscd-action-pane-theme-surface", + "default": "--oscd-theme-surface" + }, + { + "description": "Icon and label color.", + "name": "--oscd-action-icon-theme-on-surface", + "default": "--oscd-theme-on-surface" + }, + { + "description": "Font for label.", + "name": "--oscd-action-icon-theme-font", + "default": "--oscd-theme-font" + } + ], + "slots": [ + { + "description": "May contain up to eight icon buttons.", + "name": "`action`" + }, + { + "description": "If filled overrides the icon property.", + "name": "`icon`" + }, + { + "description": "The default slot will be rendered into the pane body in a single column.", + "name": "`[default]`" + } + ], + "members": [ + { + "kind": "field", + "name": "label", + "type": { + "text": "string" + }, + "description": "Caption text, displayed in the header" + }, + { + "kind": "field", + "name": "icon", + "type": { + "text": "string" + }, + "description": "Icon name, displayed unless the \"icon\" slot is filled" + }, + { + "kind": "field", + "name": "secondary", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Color header with Secondary theme color while focus is within" + }, + { + "kind": "field", + "name": "highlighted", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Highlight pane with dotted outline" + }, + { + "kind": "field", + "name": "level", + "type": { + "text": "number" + }, + "default": "1", + "description": "Nesting level, default (closes pane ancestors level) + 1" + }, + { + "kind": "method", + "name": "renderHeader", + "privacy": "private", + "return": { + "type": { + "text": "TemplateResult" + } + } + } + ], + "superclass": { + "name": "OscdComponent", + "package": "@openscd/core" + }, + "tagName": "oscd-action-pane", + "summary": "A responsive container rendering actions in a header.", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "OscdActionPane", + "declaration": { + "name": "OscdActionPane", + "module": "src/oscd-action-pane.ts" + } + } + ] + } + ] +} diff --git a/components/oscd-action-pane/package.json b/components/oscd-action-pane/package.json new file mode 100644 index 0000000..f629838 --- /dev/null +++ b/components/oscd-action-pane/package.json @@ -0,0 +1,61 @@ +{ + "name": "@openscd/oscd-action-pane", + "description": "Webcomponent oscd-action-pane following open-wc recommendations", + "license": "Apache-2.0", + "author": "OpenSCD", + "version": "0.0.1", + "browser": "./dist/OscdActionPane.js", + "module": "./dist/OscdActionPane.js", + "types": "./dist/OscdActionPane.d.ts", + "files": [ + "./dist/**/*" + ], + "exports": { + ".": "./dist/OscdActionPane.js", + "./oscd-action-pane.js": "./dist/oscd-action-pane.js" + }, + "type": "module", + "readme": "./README.md", + "scripts": { + "analyze": "cem analyze", + "build": "tsc", + "clean": "rimraf .tsbuildinfo dist", + "storybook": "npx nx storybook oscd-action-pane", + "typedoc": "typedoc", + "test": "tsc --p tsconfig.test.json && wtr --coverage", + "test:unit": "tsc --p tsconfig.test.json && wtr --group default", + "test:visual": "tsc --p tsconfig.test.json && wtr --group visual", + "test:update": "tsc --p tsconfig.test.json && wtr --group visual --update-visual-baseline", + "test:watch": "tsc --p tsconfig.test.json && concurrently -k -r \"tsc --p tsconfig.test.json --watch --preserveWatchOutput\" \"wtr --watch\"" + }, + "dependencies": { + "@openscd/core": "*", + "lit": "^2.7.6" + }, + "devDependencies": { + "@commitlint/cli": "^17.3.0", + "@commitlint/config-conventional": "^17.3.0", + "@custom-elements-manifest/analyzer": "^0.4.17", + "@open-wc/demoing-storybook": "^2.4.7", + "@open-wc/eslint-config": "^8.0.2", + "@open-wc/scoped-elements": "^2.2.0", + "@open-wc/testing": "^3.1.6", + "@oscd/utils": "*", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.33.0", + "@web/dev-server": "^0.1.34", + "@web/dev-server-storybook": "^0.5.4", + "@web/test-runner": "^0.14.0", + "@web/test-runner-playwright": "^0.9.0", + "@web/test-runner-visual-regression": "^0.7.0", + "concurrently": "^8.2.0", + "storybook-addon-root-attribute": "^1.0.2", + "tslib": "^2.6.0", + "typedoc": "^0.24.8", + "typescript": "^5.1.6" + }, + "customElements": "custom-elements.json", + "oscd": { + "status": "WIP" + } +} diff --git a/components/oscd-action-pane/project.json b/components/oscd-action-pane/project.json new file mode 100644 index 0000000..ed0e69e --- /dev/null +++ b/components/oscd-action-pane/project.json @@ -0,0 +1,33 @@ +{ + "name": "oscd-action-pane", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "components/oscd-action-pane/src", + "targets": { + "storybook": { + "executor": "@nx/storybook:storybook", + "options": { + "port": 4400, + "configDir": "components/oscd-action-pane/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + }, + "build-storybook": { + "executor": "@nx/storybook:build", + "outputs": ["{options.outputDir}"], + "options": { + "outputDir": "dist/storybook/oscd-action-pane", + "configDir": "components/oscd-action-pane/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + } + } +} diff --git a/components/oscd-action-pane/screenshots/Chromium/baseline/oscd-action-pane-icon.png b/components/oscd-action-pane/screenshots/Chromium/baseline/oscd-action-pane-icon.png new file mode 100644 index 0000000..5c0c0f0 Binary files /dev/null and b/components/oscd-action-pane/screenshots/Chromium/baseline/oscd-action-pane-icon.png differ diff --git a/components/oscd-action-pane/screenshots/Chromium/baseline/oscd-action-pane.png b/components/oscd-action-pane/screenshots/Chromium/baseline/oscd-action-pane.png new file mode 100644 index 0000000..b03f3a4 Binary files /dev/null and b/components/oscd-action-pane/screenshots/Chromium/baseline/oscd-action-pane.png differ diff --git a/components/oscd-action-pane/screenshots/Firefox/baseline/oscd-action-pane-icon.png b/components/oscd-action-pane/screenshots/Firefox/baseline/oscd-action-pane-icon.png new file mode 100644 index 0000000..ca646f7 Binary files /dev/null and b/components/oscd-action-pane/screenshots/Firefox/baseline/oscd-action-pane-icon.png differ diff --git a/components/oscd-action-pane/screenshots/Firefox/baseline/oscd-action-pane.png b/components/oscd-action-pane/screenshots/Firefox/baseline/oscd-action-pane.png new file mode 100644 index 0000000..c646f0e Binary files /dev/null and b/components/oscd-action-pane/screenshots/Firefox/baseline/oscd-action-pane.png differ diff --git a/components/oscd-action-pane/screenshots/Firefox/failed/oscd-action-pane-icon.png b/components/oscd-action-pane/screenshots/Firefox/failed/oscd-action-pane-icon.png new file mode 100644 index 0000000..ca646f7 Binary files /dev/null and b/components/oscd-action-pane/screenshots/Firefox/failed/oscd-action-pane-icon.png differ diff --git a/components/oscd-action-pane/screenshots/Firefox/failed/oscd-action-pane.png b/components/oscd-action-pane/screenshots/Firefox/failed/oscd-action-pane.png new file mode 100644 index 0000000..c646f0e Binary files /dev/null and b/components/oscd-action-pane/screenshots/Firefox/failed/oscd-action-pane.png differ diff --git a/components/oscd-action-pane/screenshots/Webkit/baseline/oscd-action-pane-icon.png b/components/oscd-action-pane/screenshots/Webkit/baseline/oscd-action-pane-icon.png new file mode 100644 index 0000000..858f623 Binary files /dev/null and b/components/oscd-action-pane/screenshots/Webkit/baseline/oscd-action-pane-icon.png differ diff --git a/components/oscd-action-pane/screenshots/Webkit/baseline/oscd-action-pane.png b/components/oscd-action-pane/screenshots/Webkit/baseline/oscd-action-pane.png new file mode 100644 index 0000000..69f973c Binary files /dev/null and b/components/oscd-action-pane/screenshots/Webkit/baseline/oscd-action-pane.png differ diff --git a/components/oscd-action-pane/screenshots/Webkit/failed/oscd-action-pane-icon.png b/components/oscd-action-pane/screenshots/Webkit/failed/oscd-action-pane-icon.png new file mode 100644 index 0000000..858f623 Binary files /dev/null and b/components/oscd-action-pane/screenshots/Webkit/failed/oscd-action-pane-icon.png differ diff --git a/components/oscd-action-pane/screenshots/Webkit/failed/oscd-action-pane.png b/components/oscd-action-pane/screenshots/Webkit/failed/oscd-action-pane.png new file mode 100644 index 0000000..69f973c Binary files /dev/null and b/components/oscd-action-pane/screenshots/Webkit/failed/oscd-action-pane.png differ diff --git a/components/oscd-action-pane/src/OscdActionPane.ts b/components/oscd-action-pane/src/OscdActionPane.ts new file mode 100644 index 0000000..9adacd6 --- /dev/null +++ b/components/oscd-action-pane/src/OscdActionPane.ts @@ -0,0 +1,5 @@ +import { OscdActionPane } from './oscd-action-pane'; + +window.customElements.define('oscd-action-pane', OscdActionPane); + +export { OscdActionPane }; diff --git a/components/oscd-action-pane/src/oscd-action-pane.styles.ts b/components/oscd-action-pane/src/oscd-action-pane.styles.ts new file mode 100644 index 0000000..e3a6d2b --- /dev/null +++ b/components/oscd-action-pane/src/oscd-action-pane.styles.ts @@ -0,0 +1,101 @@ +import { css } from 'lit-element'; + +import { styles } from '@openscd/core'; + +export default css` + ${styles} + + :host { + outline: none; + } + + :host(:focus-within) section { + box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.2); + outline-width: 4px; + transition: all 250ms linear; + } + + section { + background-color: var( + --oscd-action-pane-theme-surface, + var(--oscd-theme-surface) + ); + transition: all 200ms linear; + outline-style: solid; + margin: 0px; + outline-width: 0px; + outline-color: var( + --oscd-action-pane-theme-primary, + var(--oscd-theme-primary) + ); + color: var(--oscd-theme-text-color); + } + + section.secondary { + outline-color: var( + --oscd-action-pane-theme-secondary, + var(--oscd-theme-secondary) + ); + } + + section > div { + display: flex; + flex-direction: column; + gap: 12px; + padding: 8px 12px 16px; + clear: right; + } + + .highlighted { + outline-style: dotted; + outline-width: 2px; + } + + :host(:focus-within) .highlighted { + outline-style: solid; + } + + .contrasted { + background-color: var( + --oscd-action-pane-theme-on-primary, + var(--oscd-theme-on-primary) + ); + } + + h1, + h2, + h3, + h4 { + color: var( + --oscd-action-pane-theme-on-surface, + var(--oscd-theme-on-surface) + ); + font-family: var(--oscd-action-pane-theme-font, var(--oscd-theme-font)); + font-weight: 300; + overflow: clip visible; + white-space: nowrap; + text-overflow: ellipsis; + margin: 0px; + line-height: 52px; + padding-left: 0.3em; + } + + nav { + float: right; + } + + mwc-icon { + vertical-align: middle; + position: relative; + top: -0.1em; + --mdc-icon-size: 1em; + } + + ::slotted([slot='icon']) { + vertical-align: middle; + position: relative; + top: -0.1em; + --mdc-icon-size: 1em; + } +`; diff --git a/components/oscd-action-pane/src/oscd-action-pane.ts b/components/oscd-action-pane/src/oscd-action-pane.ts new file mode 100644 index 0000000..079409c --- /dev/null +++ b/components/oscd-action-pane/src/oscd-action-pane.ts @@ -0,0 +1,131 @@ +import { + html, + CSSResultGroup, + TemplateResult, + property, + nothing, +} from 'lit-element'; +import { classMap } from 'lit/directives/class-map.js'; + +import { OscdComponent } from '@openscd/core'; + +import styles from './oscd-action-pane.styles.js'; + +function closestTo(node: Node, selector: string): E | null { + const closest = + node.nodeType === Node.ELEMENT_NODE + ? (node).closest(selector) + : null; + + if (closest) return closest; + + const root = node.getRootNode(); + + if (root instanceof ShadowRoot) return closestTo(root.host, selector); + + return null; +} + +/** + * + * @slot `action` - May contain up to eight icon buttons. + * @slot `icon` - If filled overrides the icon property. + * @slot `[default]` - The default slot will be rendered into the pane body in a single column. + * + * @cssprop [--oscd-action-icon-theme-primary=--oscd-theme-primary] - Color for border on even levels. + * @cssprop [--oscd-action-icon-theme-on-primary=--oscd-theme-on-primary] - Pane color for the uneven levels. + * @cssprop [--oscd-action-icon-theme-secondary=--oscd-theme-secondary] - Color for border on uneven levels. + * @cssprop [--oscd-action-pane-theme-surface=--oscd-theme-surface] - Pane color for the even levels. + * @cssprop [--oscd-action-icon-theme-on-surface=--oscd-theme-on-surface] - Icon and label color. + * @cssprop [--oscd-action-icon-theme-font=--oscd-theme-font] - Font for label. + * + * @prop {string} label - Caption text, displayed in the header + * @prop {string} icon - Icon name, displayed unless the "icon" slot is filled + * @prop {boolean} secondary - Color header with Secondary theme color while focus is within + * @prop {boolean} highlighted - Highlight pane with dotted outline + * @prop {number} level - Nesting level, default (closes pane ancestors level) + 1 + * + * @summary A responsive container rendering actions in a header. + * @tag oscd-action-pane + */ +export class OscdActionPane extends OscdComponent { + static styles: CSSResultGroup = styles; + + /** + * @internal + */ + static get scopedElements() { + return {}; + } + + /** caption text, displayed in the header */ + @property({ type: String }) + label?: string; + + /** icon name, displayed unless the "icon" slot is filled */ + @property({ type: String }) + icon?: string; + + /** color header with secondary theme color while focus is within */ + @property({ type: Boolean }) + secondary = false; + + /** highlight pane with dotted outline */ + @property({ type: Boolean }) + highlighted = false; + + /** nesting level, default (closest pane ancestor's level) + 1 */ + @property({ type: Number }) + level = 1; + + async firstUpdated(): Promise { + this.tabIndex = 0; + + const parentPane = closestTo( + this.parentNode!, + 'oscd-action-pane' + ); + if (parentPane) this.level = parentPane.level + 1; + + this.level = Math.floor(this.level); + } + + private renderHeader(): TemplateResult { + const content = html`${this.icon + ? html`${this.icon}` + : nothing} + ${this.label ?? nothing} + `; + + const headingLevel = Math.floor(Math.max(this.level, 1)); + // Sometimes a TemplateResult is passed in as Label, not a string. So only when it's a string show a title. + const title = typeof this.label === 'string' ? this.label : ''; + switch (headingLevel) { + case 1: + return html`

${content}

`; + case 2: + return html`

${content}

`; + case 3: + return html`

${content}

`; + default: + return html`

${content}

`; + } + } + + render(): TemplateResult { + return html`
+ ${this.renderHeader()} +
+
`; + } +} diff --git a/components/oscd-action-pane/stories/oscd-action-pane.mdx b/components/oscd-action-pane/stories/oscd-action-pane.mdx new file mode 100644 index 0000000..f4c3c2f --- /dev/null +++ b/components/oscd-action-pane/stories/oscd-action-pane.mdx @@ -0,0 +1,28 @@ +import { Meta, Story, Canvas, Source, ArgTypes, Title, Description, Subtitle } from '@storybook/blocks'; + +import { Markdown } from '@storybook/addon-docs'; + +import * as OscdActionPaneStories from './oscd-action-pane.stories'; + +import Readme from '../README.md?raw'; +import Changelog from '../CHANGELOG.md?raw'; + + +Oscd-Action-Pane + + +Properties + + + + + + +# Example + + +{Readme} + +# Changelog + +{Changelog} diff --git a/components/oscd-action-pane/stories/oscd-action-pane.stories.ts b/components/oscd-action-pane/stories/oscd-action-pane.stories.ts new file mode 100644 index 0000000..52eddd5 --- /dev/null +++ b/components/oscd-action-pane/stories/oscd-action-pane.stories.ts @@ -0,0 +1,102 @@ +import type { Meta, StoryObj } from '@storybook/web-components'; +import { action } from '@storybook/addon-actions'; + +import { html, TemplateResult } from 'lit'; + +import '../src/OscdActionPane'; + +import { createBadge } from '@oscd/utils'; + +import pckgJson from '../package.json'; + +const meta: Meta = { + title: 'Action/OscdActionPane', + component: 'oscd-action-pane', + parameters: { + status: { + type: createBadge(pckgJson), + }, + }, +}; + +export default meta; + +type Story = StoryObj; + +/** Basic */ +export const Basic: Story = { + render: ({ label, description, highlighted, secondary, level, icon }) => + html`${description}`, + args: { + label: 'Label', + description: 'Some Text', + level: 0, + }, +}; + +/** + * Nested + */ +export const Nested: Story = { + render: ({ label, description, highlighted, secondary, level }) => + html` + ${description} + `, + args: { + ...Basic.args, + }, +}; + +/** + * With Icon + */ +export const WithIcon: Story = { + render: ({ label, description, highlighted, secondary, level, icon }) => + html`${description}`, + args: { + ...Basic.args, + icon: 'edit', + }, +}; + +/** + * With Actions + */ +export const WithActions: Story = { + render: ({ label, description, highlighted, secondary, level, icon }) => + html` + ${description} + edit + delete + `, + args: { + ...Basic.args, + icon: 'edit', + }, +}; diff --git a/components/oscd-action-pane/test/oscd-action-pane.spec.ts b/components/oscd-action-pane/test/oscd-action-pane.spec.ts new file mode 100644 index 0000000..8e5540b --- /dev/null +++ b/components/oscd-action-pane/test/oscd-action-pane.spec.ts @@ -0,0 +1,148 @@ +import { expect, fixture, html } from '@open-wc/testing'; + +import '../src/OscdActionPane.js'; +import { OscdActionPane } from '../src/OscdActionPane.js'; + +describe('oscd-action-pane', () => { + let element: OscdActionPane; + const label = 'test label'; + + beforeEach(async () => { + element = await fixture( + html`` + ); + await element.updateComplete; + }); + + it('looks like the latest snapshot', () => { + expect(element).shadowDom.to.equalSnapshot(); + }); + it('renders the header as

per default', () => { + const header: HTMLElement | null = + element.shadowRoot?.querySelector(`[title="${label}"]`) ?? null; + expect(header).to.exist; + expect(header?.tagName).to.equal('H1'); + }); + + it('renders the header as

with level 1', async () => { + element.level = 1; + await element.updateComplete; + const header: HTMLElement | null = + element.shadowRoot?.querySelector(`[title="${label}"]`) ?? null; + expect(header).to.exist; + expect(header?.tagName).to.equal('H1'); + }); + + it('renders the header as

with level 2', async () => { + element.level = 2; + await element.updateComplete; + const header: HTMLElement | null = + element.shadowRoot?.querySelector(`[title="${label}"]`) ?? null; + expect(header).to.exist; + expect(header?.tagName).to.equal('H2'); + }); + + it('renders the header as

with level 3', async () => { + element.level = 3; + await element.updateComplete; + const header: HTMLElement | null = + element.shadowRoot?.querySelector(`[title="${label}"]`) ?? null; + expect(header).to.exist; + expect(header?.tagName).to.equal('H3'); + }); + + it('renders the header as

with level 4', async () => { + element.level = 4; + await element.updateComplete; + const header: HTMLElement | null = + element.shadowRoot?.querySelector(`[title="${label}"]`) ?? null; + expect(header).to.exist; + expect(header?.tagName).to.equal('H4'); + }); + + it('renders the header as

for levels > 4', async () => { + element.level = 7; + await element.updateComplete; + const header: HTMLElement | null = + element.shadowRoot?.querySelector(`[title="${label}"]`) ?? null; + expect(header).to.exist; + expect(header?.tagName).to.equal('H4'); + }); + + it('renders the header as

for levels < 1', async () => { + element.level = -1; + await element.updateComplete; + const header: HTMLElement | null = + element.shadowRoot?.querySelector(`[title="${label}"]`) ?? null; + expect(header).to.exist; + expect(header?.tagName).to.equal('H1'); + }); + + it('renders the title on the

', async () => { + element.level = 1; + await element.updateComplete; + expect( + element.shadowRoot?.querySelector('h1')!.getAttribute('title') + ).to.be.equals(label); + }); + + it('renders the title on the

', async () => { + element.level = 2; + await element.updateComplete; + expect( + element.shadowRoot?.querySelector('h2')!.getAttribute('title') + ).to.be.equals(label); + }); + + it('renders the title on the

', async () => { + element.level = 3; + await element.updateComplete; + expect( + element.shadowRoot?.querySelector('h3')!.getAttribute('title') + ).to.be.equals(label); + }); + + it('renders the title on the

', async () => { + element.level = 4; + await element.updateComplete; + expect( + element.shadowRoot?.querySelector('h4')!.getAttribute('title') + ).to.be.equals(label); + }); + + it('does not set contrasted class property with odd level', async () => { + element.level = 3; + await element.updateComplete; + + expect( + element.shadowRoot + ?.querySelector('section') + ?.classList.contains('contrasted') + ).to.be.false; + }); + + it('sets contrasted class property with even levels', async () => { + element.level = 4; + await element.updateComplete; + + expect( + element.shadowRoot + ?.querySelector('section') + ?.classList.contains('contrasted') + ).to.be.true; + }); + + describe('with icon property set', () => { + beforeEach(async () => { + element.icon = 'edit'; + await element.updateComplete; + }); + + it('looks like the latest snapshot', () => { + expect(element).shadowDom.to.equalSnapshot(); + }); + }); +}); diff --git a/components/oscd-action-pane/test/oscd-action-pane.test.ts b/components/oscd-action-pane/test/oscd-action-pane.test.ts new file mode 100644 index 0000000..d894bef --- /dev/null +++ b/components/oscd-action-pane/test/oscd-action-pane.test.ts @@ -0,0 +1,44 @@ +import { fixture } from '@open-wc/testing'; +import { html } from 'lit-html'; + +import { visualDiff } from '@web/test-runner-visual-regression'; + +import '../src/OscdActionPane.js'; +import type { OscdActionPane } from '../src/OscdActionPane.js'; + +const factor = process.env.CI ? 2 : 1; + +function timeout(ms: number) { + return new Promise((res) => { + setTimeout(res, ms * factor); + }); +} + +mocha.timeout(2000 * factor); + +describe('oscd-action-pane', () => { + let element: OscdActionPane; + const label = 'Test Title'; + + beforeEach(async () => { + element = await fixture( + html`Testing` + ); + document.body.prepend(element); + }); + + afterEach(() => element.remove()); + + it('displays the title', async () => { + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-action-pane'); + }); + + it('displays the title and icon', async () => { + element.icon = 'arrow_back'; + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-action-pane-icon'); + }); +}); diff --git a/components/oscd-action-pane/tsconfig.json b/components/oscd-action-pane/tsconfig.json new file mode 100644 index 0000000..4627f8a --- /dev/null +++ b/components/oscd-action-pane/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "lib": ["es2018", "dom"], + "strict": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "declaration": true, + "importHelpers": true, + "outDir": "dist", + "sourceMap": true, + "inlineSources": true, + "rootDir": "./src", + "tsBuildInfoFile": ".tsbuildinfo", + "incremental": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": ["./src/**/*.ts"], + "exclude": ["**/*.stories.ts", "**/*.stories.js"] +} diff --git a/components/oscd-action-pane/tsconfig.storybook.json b/components/oscd-action-pane/tsconfig.storybook.json new file mode 100644 index 0000000..cda53dc --- /dev/null +++ b/components/oscd-action-pane/tsconfig.storybook.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "composite": true, + "incremental": false, + "tsBuildInfoFile": null, + "rootDir": "./" + }, + "exclude": ["./test/**/*.ts"], + "include": [ + "./stories/**/*.stories.ts", + "./src/**/*.ts", + "./src/*.ts", + "./.storybook/*.js", + "./.storybook/*.ts" + ] +} diff --git a/components/oscd-action-pane/tsconfig.test.json b/components/oscd-action-pane/tsconfig.test.json new file mode 100644 index 0000000..29717e3 --- /dev/null +++ b/components/oscd-action-pane/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "rootDir": "./" + }, + "extends": "./tsconfig", + "include": ["*/*.ts"] +} diff --git a/components/oscd-action-pane/typedoc.json b/components/oscd-action-pane/typedoc.json new file mode 100644 index 0000000..2c43ad9 --- /dev/null +++ b/components/oscd-action-pane/typedoc.json @@ -0,0 +1,4 @@ +{ + "entryPoints": ["src/index.ts"], + "out": "docs" +} diff --git a/components/oscd-action-pane/web-test-runner.config.js b/components/oscd-action-pane/web-test-runner.config.js new file mode 100644 index 0000000..28aec99 --- /dev/null +++ b/components/oscd-action-pane/web-test-runner.config.js @@ -0,0 +1,182 @@ +import { visualRegressionPlugin } from '@web/test-runner-visual-regression/plugin'; +import { playwrightLauncher } from '@web/test-runner-playwright'; + +import pixelmatch from 'pixelmatch'; +import { PNG } from 'pngjs'; + +const fuzzy = ['win32', 'darwin'].includes(process.platform); // allow for 1% difference on non-linux OSs +const local = !process.env.CI; + +console.assert(local, 'Running in CI!'); +console.assert(!fuzzy, 'Running on OS with 1% test pixel diff threshold!'); + +const thresholdPercentage = fuzzy && local ? 0 : 0; + +const filteredLogs = [ + 'Running in dev mode', + 'Lit is in dev mode', + 'mwc-list-item scheduled an update', +]; + +const browsers = [ + playwrightLauncher({ + product: 'chromium', + }), + playwrightLauncher({ product: 'firefox' }), + playwrightLauncher({ product: 'webkit' }), +]; + +function defaultGetImageDiff({ baselineImage, image, options }) { + let error = ''; + let basePng = PNG.sync.read(baselineImage); + let png = PNG.sync.read(image); + let { width, height } = png; + + if (basePng.width !== png.width || basePng.height !== png.height) { + error = + `Screenshot is not the same width and height as the baseline. ` + + `Baseline: { width: ${basePng.width}, height: ${basePng.height} }` + + `Screenshot: { width: ${png.width}, height: ${png.height} }`; + width = Math.max(basePng.width, png.width); + height = Math.max(basePng.height, png.height); + let oldPng = basePng; + basePng = new PNG({ width, height }); + oldPng.data.copy(basePng.data, 0, 0, oldPng.data.length); + oldPng = png; + png = new PNG({ width, height }); + oldPng.data.copy(png.data, 0, 0, oldPng.data.length); + } + + const diff = new PNG({ width, height }); + + const numDiffPixels = pixelmatch( + basePng.data, + png.data, + diff.data, + width, + height, + options + ); + const diffPercentage = (numDiffPixels / (width * height)) * 100; + + return { + error, + diffImage: PNG.sync.write(diff), + diffPercentage, + }; +} + +export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({ + plugins: [ + visualRegressionPlugin({ + update: process.argv.includes('--update-visual-baseline'), + getImageDiff: (options) => { + const result = defaultGetImageDiff(options); + if (result.diffPercentage < thresholdPercentage) + result.diffPercentage = 0; + return result; + }, + }), + ], + + files: 'dist/**/*.spec.js', + + groups: [ + { + name: 'visual', + files: 'dist/**/*.test.js', + testRunnerHtml: (testFramework) => ` + + + + + + + + + + + + + +`, + }, + ], + + /** Resolve bare module imports */ + nodeResolve: { + exportConditions: ['browser', 'development'], + }, + + /** Filter out lit dev mode logs */ + filterBrowserLogs(log) { + for (const arg of log.args) { + if ( + typeof arg === 'string' && + filteredLogs.some((l) => arg.includes(l)) + ) { + return false; + } + } + return true; + }, + + /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */ + // esbuildTarget: 'auto', + + /** Amount of browsers to run concurrently */ + concurrentBrowsers: 3, + + /** Amount of test files per browser to test concurrently */ + concurrency: 2, + + /** Browsers to run tests on */ + browsers, + + // See documentation for all available options +}); diff --git a/components/oscd-button/.gitignore b/components/oscd-button/.gitignore new file mode 100644 index 0000000..63cc1db --- /dev/null +++ b/components/oscd-button/.gitignore @@ -0,0 +1,20 @@ +## editors +/.idea +/.vscode + +## system files +.DS_Store + +## npm +/node_modules/ +/npm-debug.log +.tsbuildinfo + +## testing +/coverage/ + +## docs +/doc/ + +# build +/dist/ diff --git a/components/oscd-button/.npmignore b/components/oscd-button/.npmignore new file mode 100644 index 0000000..28f225d --- /dev/null +++ b/components/oscd-button/.npmignore @@ -0,0 +1,18 @@ +## editors +/.idea +/.vscode + +## system files +.DS_Store + +## npm +/node_modules/ +/npm-debug.log +.tsbuildinfo + +## testing +/coverage/ + +## docs +/doc/ + diff --git a/components/oscd-button/.storybook/main.ts b/components/oscd-button/.storybook/main.ts new file mode 100644 index 0000000..c8e9fee --- /dev/null +++ b/components/oscd-button/.storybook/main.ts @@ -0,0 +1,30 @@ +import type { StorybookConfig } from '@storybook/web-components-vite'; + +const config: StorybookConfig = { + stories: ['../stories/**/*.stories.@(js|jsx|ts|tsx)', '../stories/**/*.mdx'], + addons: [ + '@storybook/addon-docs', + '@storybook/addon-controls', + '@storybook/addon-actions', + '@storybook/addon-a11y', + '@storybook/addon-links', + { + name: '@storybook/adddon-essentials', + options: { + background: false, + }, + }, + '@etchteam/storybook-addon-status/register', + 'storybook-addon-root-attribute/register', + ], + framework: { + name: '@storybook/web-components-vite', + options: { + builder: { + viteConfigPath: '', + }, + }, + }, +}; + +export default config; diff --git a/components/oscd-button/.storybook/manager.ts b/components/oscd-button/.storybook/manager.ts new file mode 100644 index 0000000..66b6e89 --- /dev/null +++ b/components/oscd-button/.storybook/manager.ts @@ -0,0 +1,5 @@ +import { addons } from '@storybook/manager-api'; + +addons.setConfig({ + enableShortcuts: false +}); diff --git a/components/oscd-button/.storybook/preview-head.html b/components/oscd-button/.storybook/preview-head.html new file mode 100644 index 0000000..89f0ee1 --- /dev/null +++ b/components/oscd-button/.storybook/preview-head.html @@ -0,0 +1,16 @@ + + + diff --git a/components/oscd-button/.storybook/preview.ts b/components/oscd-button/.storybook/preview.ts new file mode 100644 index 0000000..455de07 --- /dev/null +++ b/components/oscd-button/.storybook/preview.ts @@ -0,0 +1,39 @@ +import { setCustomElementsManifest } from '@storybook/web-components'; +import { withRootAttribute } from 'storybook-addon-root-attribute'; + +import '../../../themes/prebuilt/oscd.css'; + +import customElements from '../custom-elements.json'; + +setCustomElementsManifest(customElements); + +export const decorators = [withRootAttribute]; + +export const parameters = { + statuses: { + released: { + background: '#0000ff', + color: '#ffffff', + description: 'This component is stable and released', + }, + beta: { + background: '#FF0000', + color: '#FFFFFF', + description: 'This component is still in beta', + }, + }, + rootAttribute: { + defaultState: { + name: 'Light', + value: null, + }, + attribute: 'dark', + tooltip: true, + states: [ + { + name: 'Dark', + value: 'dark', + }, + ], + }, +}; diff --git a/components/oscd-button/CHANGELOG.md b/components/oscd-button/CHANGELOG.md new file mode 100644 index 0000000..825c32f --- /dev/null +++ b/components/oscd-button/CHANGELOG.md @@ -0,0 +1 @@ +# Changelog diff --git a/components/oscd-button/EXAMPLE.md b/components/oscd-button/EXAMPLE.md new file mode 100644 index 0000000..090b738 --- /dev/null +++ b/components/oscd-button/EXAMPLE.md @@ -0,0 +1,3 @@ +```html + +``` diff --git a/components/oscd-button/INTRO.md b/components/oscd-button/INTRO.md new file mode 100644 index 0000000..e69de29 diff --git a/components/oscd-button/LICENSE.md b/components/oscd-button/LICENSE.md new file mode 100644 index 0000000..c61b663 --- /dev/null +++ b/components/oscd-button/LICENSE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/components/oscd-button/README.md b/components/oscd-button/README.md new file mode 100644 index 0000000..92e9c77 --- /dev/null +++ b/components/oscd-button/README.md @@ -0,0 +1,23 @@ +# `` ![NPM](https://img.shields.io/badge/NPM-0.0.1-cb0001) ![Status](https://img.shields.io/badge/WIP-3b72bf) + +--- + + + +## Example + +```html + +``` + +--- + +### Attributes + +| Name | Type | Description | +| ---- | ---- | ----------- | + +### Css Properties + +| Name | Default | Description | +| ---- | ------- | ----------- | \ No newline at end of file diff --git a/components/oscd-button/custom-elements-manifest.config.js b/components/oscd-button/custom-elements-manifest.config.js new file mode 100644 index 0000000..562fc21 --- /dev/null +++ b/components/oscd-button/custom-elements-manifest.config.js @@ -0,0 +1,6 @@ +export default { + globs: ['src/*.ts'], + exclude: ['test/*.ts'], + litelement: true, + plugins: [], +}; diff --git a/components/oscd-button/custom-elements.json b/components/oscd-button/custom-elements.json new file mode 100644 index 0000000..bf55585 --- /dev/null +++ b/components/oscd-button/custom-elements.json @@ -0,0 +1,116 @@ +{ + "schemaVersion": "1.0.0", + "readme": "", + "modules": [ + { + "kind": "javascript-module", + "path": "src/OscdButton.ts", + "declarations": [], + "exports": [ + { + "kind": "custom-element-definition", + "name": "oscd-button", + "declaration": { + "name": "OscdButton", + "module": "/src/oscd-button" + } + }, + { + "kind": "js", + "name": "OscdButton", + "declaration": { + "name": "OscdButton", + "module": "src/OscdButton.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/oscd-button.styles.ts", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "module": "src/oscd-button.styles.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/oscd-button.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "OscdButton", + "members": [ + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the Button is disabled or not" + }, + { + "kind": "field", + "name": "label", + "type": { + "text": "string" + }, + "default": "''", + "description": "Text for the Button" + }, + { + "kind": "field", + "name": "icon", + "type": { + "text": "string" + }, + "description": "The icon for the Button" + }, + { + "kind": "field", + "name": "raised", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the Button is raised or not" + }, + { + "kind": "field", + "name": "outlined", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Whether the Button is outlined or not" + } + ], + "superclass": { + "name": "OscdComponent", + "package": "@openscd/core" + }, + "tagName": "oscd-button", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "OscdButton", + "declaration": { + "name": "OscdButton", + "module": "src/oscd-button.ts" + } + } + ] + } + ] +} diff --git a/components/oscd-button/package.json b/components/oscd-button/package.json new file mode 100644 index 0000000..00d299a --- /dev/null +++ b/components/oscd-button/package.json @@ -0,0 +1,61 @@ +{ + "name": "@openscd/oscd-button", + "description": "Webcomponent oscd-button following open-wc recommendations", + "license": "Apache-2.0", + "author": "OpenSCD", + "version": "0.0.1", + "browser": "./dist/OscdButton.js", + "module": "./dist/OscdButton.js", + "files": [ + "dist/**/*" + ], + "exports": { + ".": "./dist/OscdButton.js", + "./oscd-button.js": "./dist/oscd-button.js" + }, + "type": "module", + "readme": "./README.md", + "scripts": { + "analyze": "cem analyze", + "build": "tsc", + "clean": "rimraf .tsbuildinfo dist", + "storybook": "npx nx storybook oscd-button", + "typedoc": "typedoc", + "test": "tsc --p tsconfig.test.json && wtr --coverage", + "test:unit": "tsc --p tsconfig.test.json && wtr --group default", + "test:visual": "tsc --p tsconfig.test.json && wtr --group visual", + "test:update": "tsc --p tsconfig.test.json && wtr --group visual --update-visual-baseline", + "test:watch": "tsc --p tsconfig.test.json && concurrently -k -r \"tsc --p tsconfig.test.json --watch --preserveWatchOutput\" \"wtr --watch\"" + }, + "dependencies": { + "@openscd/core": "*", + "lit": "^2.7.6", + "@material/mwc-button": "0.27.0" + }, + "devDependencies": { + "@commitlint/cli": "^17.3.0", + "@commitlint/config-conventional": "^17.3.0", + "@custom-elements-manifest/analyzer": "^0.4.17", + "@open-wc/demoing-storybook": "^2.4.7", + "@open-wc/eslint-config": "^8.0.2", + "@open-wc/scoped-elements": "^2.2.0", + "@open-wc/testing": "^3.1.6", + "@oscd/utils": "*", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.33.0", + "@web/dev-server": "^0.1.34", + "@web/dev-server-storybook": "^0.5.4", + "@web/test-runner": "^0.14.0", + "@web/test-runner-playwright": "^0.9.0", + "@web/test-runner-visual-regression": "^0.7.0", + "concurrently": "^8.2.0", + "storybook-addon-root-attribute": "^1.0.2", + "tslib": "^2.6.0", + "typedoc": "^0.24.8", + "typescript": "^5.1.6" + }, + "customElements": "custom-elements.json", + "oscd": { + "status": "WIP" + } +} diff --git a/components/oscd-button/project.json b/components/oscd-button/project.json new file mode 100644 index 0000000..059ab84 --- /dev/null +++ b/components/oscd-button/project.json @@ -0,0 +1,33 @@ +{ + "name": "oscd-button", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "components/oscd-button/src", + "targets": { + "storybook": { + "executor": "@nx/storybook:storybook", + "options": { + "port": 4400, + "configDir": "components/oscd-button/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + }, + "build-storybook": { + "executor": "@nx/storybook:build", + "outputs": ["{options.outputDir}"], + "options": { + "outputDir": "dist/storybook/oscd-button", + "configDir": "components/oscd-button/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + } + } +} diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined-disabled.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined-disabled.png new file mode 100644 index 0000000..ef28d14 Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined-disabled.png differ diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined-icon.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined-icon.png new file mode 100644 index 0000000..e6ff501 Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined-icon.png differ diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined.png new file mode 100644 index 0000000..c2c028e Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--outlined.png differ diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised-disabled.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised-disabled.png new file mode 100644 index 0000000..fcc2340 Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised-disabled.png differ diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised-icon.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised-icon.png new file mode 100644 index 0000000..f7e3d98 Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised-icon.png differ diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised.png new file mode 100644 index 0000000..a72e0a0 Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button--raised.png differ diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button-disabled.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button-disabled.png new file mode 100644 index 0000000..6944910 Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button-disabled.png differ diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button-icon.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button-icon.png new file mode 100644 index 0000000..b9fce29 Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button-icon.png differ diff --git a/components/oscd-button/screenshots/Chromium/baseline/oscd-button.png b/components/oscd-button/screenshots/Chromium/baseline/oscd-button.png new file mode 100644 index 0000000..6708a26 Binary files /dev/null and b/components/oscd-button/screenshots/Chromium/baseline/oscd-button.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined-disabled.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined-disabled.png new file mode 100644 index 0000000..4b362d8 Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined-disabled.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined-icon.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined-icon.png new file mode 100644 index 0000000..a3ad004 Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined-icon.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined.png new file mode 100644 index 0000000..4b421f7 Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--outlined.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised-disabled.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised-disabled.png new file mode 100644 index 0000000..11e14a3 Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised-disabled.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised-icon.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised-icon.png new file mode 100644 index 0000000..4ac17be Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised-icon.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised.png new file mode 100644 index 0000000..70b0c7a Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button--raised.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button-disabled.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button-disabled.png new file mode 100644 index 0000000..f7ee696 Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button-disabled.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button-icon.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button-icon.png new file mode 100644 index 0000000..aa30a7b Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button-icon.png differ diff --git a/components/oscd-button/screenshots/Firefox/baseline/oscd-button.png b/components/oscd-button/screenshots/Firefox/baseline/oscd-button.png new file mode 100644 index 0000000..396aebd Binary files /dev/null and b/components/oscd-button/screenshots/Firefox/baseline/oscd-button.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined-disabled.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined-disabled.png new file mode 100644 index 0000000..09b0647 Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined-disabled.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined-icon.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined-icon.png new file mode 100644 index 0000000..a59f1d8 Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined-icon.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined.png new file mode 100644 index 0000000..449217c Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--outlined.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised-disabled.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised-disabled.png new file mode 100644 index 0000000..effde2c Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised-disabled.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised-icon.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised-icon.png new file mode 100644 index 0000000..bdaa05b Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised-icon.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised.png new file mode 100644 index 0000000..aff50bf Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button--raised.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button-disabled.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button-disabled.png new file mode 100644 index 0000000..f6cef8d Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button-disabled.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button-icon.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button-icon.png new file mode 100644 index 0000000..7112e21 Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button-icon.png differ diff --git a/components/oscd-button/screenshots/Webkit/baseline/oscd-button.png b/components/oscd-button/screenshots/Webkit/baseline/oscd-button.png new file mode 100644 index 0000000..c370ac1 Binary files /dev/null and b/components/oscd-button/screenshots/Webkit/baseline/oscd-button.png differ diff --git a/components/oscd-button/src/OscdButton.ts b/components/oscd-button/src/OscdButton.ts new file mode 100644 index 0000000..8a5ae76 --- /dev/null +++ b/components/oscd-button/src/OscdButton.ts @@ -0,0 +1,5 @@ +import { OscdButton } from './oscd-button'; + +window.customElements.define('oscd-button', OscdButton); + +export { OscdButton }; diff --git a/components/oscd-button/src/oscd-button.styles.ts b/components/oscd-button/src/oscd-button.styles.ts new file mode 100644 index 0000000..4388eb8 --- /dev/null +++ b/components/oscd-button/src/oscd-button.styles.ts @@ -0,0 +1,14 @@ +import { css } from 'lit-element'; + +import { styles } from '@openscd/core'; + +export default css` + ${styles} + + :host { + display: inline-flex; + + --mdc-theme-primary: var(--oscd-theme-primary); + --mdc-theme-on-primary: var(--oscd-theme-on-primary); + } +`; diff --git a/components/oscd-button/src/oscd-button.ts b/components/oscd-button/src/oscd-button.ts new file mode 100644 index 0000000..57818d7 --- /dev/null +++ b/components/oscd-button/src/oscd-button.ts @@ -0,0 +1,64 @@ +import { html, CSSResultGroup, TemplateResult, property } from 'lit-element'; + +import { OscdComponent } from '@openscd/core'; + +import styles from './oscd-button.styles.js'; + +import '@material/mwc-button'; + +/** + * @prop {string} label - Text for the Button + * @prop {boolean} raised - Whether the Button is raised or not + * @prop {boolean} disabled - Whether the Button is disabled or not + * @prop {string} icon - The icon for the Button + * @prop {boolean} outlined - Whether the Button is outlined or not + * + * @example + * @tagname oscd-button + */ +export class OscdButton extends OscdComponent { + static styles: CSSResultGroup = styles; + + /** + * @internal + */ + static get scopedElements() { + return {}; + } + + @property({ + type: Boolean, + }) + disabled?: boolean = false; + + @property({ + type: String, + }) + label: string = ''; + + @property({ + type: String, + }) + icon?: string; + + @property({ + type: Boolean, + }) + raised?: boolean = false; + + @property({ + type: Boolean, + }) + outlined?: boolean = false; + + render(): TemplateResult { + return html` + `; + } +} diff --git a/components/oscd-button/stories/oscd-button.mdx b/components/oscd-button/stories/oscd-button.mdx new file mode 100644 index 0000000..068ddc8 --- /dev/null +++ b/components/oscd-button/stories/oscd-button.mdx @@ -0,0 +1,38 @@ +import { + Meta, + Story, + Canvas, + Source, + ArgTypes, + Title, + Description, + Subtitle, +} from '@storybook/blocks'; + +import { Markdown } from '@storybook/addon-docs'; + +import * as OscdButtonStories from './oscd-button.stories'; + +import Readme from '../README.md?raw'; +import Changelog from '../CHANGELOG.md?raw'; + + +oscd-button + + +Properties + + + + + + +# Example + + + +{Readme} + +# Changelog + +{Changelog} diff --git a/components/oscd-button/stories/oscd-button.stories.ts b/components/oscd-button/stories/oscd-button.stories.ts new file mode 100644 index 0000000..13e7594 --- /dev/null +++ b/components/oscd-button/stories/oscd-button.stories.ts @@ -0,0 +1,123 @@ +import type { Meta, StoryObj } from '@storybook/web-components'; +import { action } from '@storybook/addon-actions'; + +import { html, TemplateResult } from 'lit'; + +import '../src/OscdButton'; + +import { createBadge } from '@oscd/utils'; + +import pckgJson from '../package.json'; + +const meta: Meta = { + title: 'Buttons/OscdButton', + component: 'oscd-button', + parameters: { + status: { + type: createBadge(pckgJson), + }, + }, + args: { + onclick: action('Clicked'), + }, +}; + +export default meta; + +type Story = StoryObj; + +/** + * Basic + */ +export const Basic: Story = { + args: { + label: 'Click me!', + }, + parameters: { + docs: { + description: { + story: 'Basic oscd-button', + }, + }, + }, +}; + +/** + * Raised + */ +export const Raised: Story = { + args: { + ...Basic.args, + raised: true, + }, +}; + +/** + * Outliend + */ +export const Outlined: Story = { + args: { + ...Basic.args, + outlined: true, + }, +}; + +/** + * Disabled + */ +export const Disabled: Story = { + args: { + ...Basic.args, + disabled: true, + }, +}; + +/** + * Raised Disabled + */ +export const RaisedDisabled: Story = { + args: { + ...Raised.args, + ...Disabled.args, + }, +}; + +/** + * Outlined Disabled + */ +export const OutlinedDisabled: Story = { + args: { + ...Outlined.args, + ...Disabled.args, + }, +}; + +/** + * With Icon + */ +export const WithIcon: Story = { + args: { + ...Basic.args, + icon: 'edit', + }, +}; + +/** + * Raised with Icon + */ +export const RaisedWithIcon: Story = { + args: { + ...Raised.args, + ...WithIcon.args, + }, +}; + +/** + * Outlined with Icon + */ +export const OutlinedWithIcon: Story = { + args: { + ...Outlined.args, + ...WithIcon.args, + }, +}; diff --git a/components/oscd-button/test/oscd-button.spec.ts b/components/oscd-button/test/oscd-button.spec.ts new file mode 100644 index 0000000..055b5f9 --- /dev/null +++ b/components/oscd-button/test/oscd-button.spec.ts @@ -0,0 +1,61 @@ +import { expect, fixture, html } from '@open-wc/testing'; + +import '../src/OscdButton.js'; +import type { OscdButton } from '../src/oscd-button.js'; + +describe('Basic component oscd-button', () => { + let element: OscdButton; + + beforeEach(async () => { + element = await fixture(html``); + await element.updateComplete; + }); + + it('Should have basic text', async () => { + const label = 'Click me!'; + element.label = label; + + await element.updateComplete; + + expect(element.shadowRoot!.querySelector('mwc-button')?.label).to.equal( + label + ); + }); + + it('Should be raised', async () => { + element.raised = true; + + await element.updateComplete; + + expect(element.shadowRoot?.querySelector('mwc-button')!.raised).to.be.true; + }); + + it('Should be outlined', async () => { + element.outlined = true; + + await element.updateComplete; + + expect(element.shadowRoot?.querySelector('mwc-button')?.outlined).to.be + .true; + }); + + it('Should be disabled', async () => { + element.disabled = true; + + await element.updateComplete; + + expect(element.shadowRoot?.querySelector('mwc-button')?.disabled).to.be + .true; + }); + + it('Should have icon', async () => { + const icon = 'edit'; + element.icon = icon; + + await element.updateComplete; + + expect(element.shadowRoot?.querySelector('mwc-button')?.icon).to.equal( + icon + ); + }); +}); diff --git a/components/oscd-button/test/oscd-button.test.ts b/components/oscd-button/test/oscd-button.test.ts new file mode 100644 index 0000000..6ce21c1 --- /dev/null +++ b/components/oscd-button/test/oscd-button.test.ts @@ -0,0 +1,107 @@ +import { fixture, html } from '@open-wc/testing'; + +import { visualDiff } from '@web/test-runner-visual-regression'; + +import '../src/OscdButton.js'; +import type { OscdButton } from '../src/oscd-button.js'; + +const factor = process.env.CI ? 2 : 1; + +function timeout(ms: number) { + return new Promise((res) => { + setTimeout(res, ms * factor); + }); +} + +mocha.timeout(2000 * factor); + +describe('oscd-button', () => { + let element: OscdButton; + + beforeEach(async () => { + element = await fixture( + html`` + ); + document.body.prepend(element); + }); + + afterEach(() => element.remove()); + + it('displays the label', async () => { + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button'); + }); + + it('displays the icon', async () => { + element.icon = 'arrow_back'; + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button-icon'); + }); + + it('is disabled', async () => { + element.disabled = true; + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button-disabled'); + }); + + describe('raised', () => { + beforeEach(async () => { + element = await fixture( + html`` + ); + document.body.prepend(element); + }); + + it('displays the label', async () => { + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button--raised'); + }); + + it('displays the icon', async () => { + element.icon = 'arrow_back'; + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button--raised-icon'); + }); + + it('is disabled', async () => { + element.disabled = true; + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button--raised-disabled'); + }); + }); + + describe('outlined', () => { + beforeEach(async () => { + element = await fixture( + html`` + ); + document.body.prepend(element); + }); + + it('displays the label', async () => { + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button--outlined'); + }); + + it('displays the icon', async () => { + element.icon = 'arrow_back'; + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button--outlined-icon'); + }); + + it('is disabled', async () => { + element.disabled = true; + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-button--outlined-disabled'); + }); + }); +}); diff --git a/components/oscd-button/tsconfig.json b/components/oscd-button/tsconfig.json new file mode 100644 index 0000000..4627f8a --- /dev/null +++ b/components/oscd-button/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "lib": ["es2018", "dom"], + "strict": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "declaration": true, + "importHelpers": true, + "outDir": "dist", + "sourceMap": true, + "inlineSources": true, + "rootDir": "./src", + "tsBuildInfoFile": ".tsbuildinfo", + "incremental": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": ["./src/**/*.ts"], + "exclude": ["**/*.stories.ts", "**/*.stories.js"] +} diff --git a/components/oscd-button/tsconfig.storybook.json b/components/oscd-button/tsconfig.storybook.json new file mode 100644 index 0000000..cda53dc --- /dev/null +++ b/components/oscd-button/tsconfig.storybook.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "composite": true, + "incremental": false, + "tsBuildInfoFile": null, + "rootDir": "./" + }, + "exclude": ["./test/**/*.ts"], + "include": [ + "./stories/**/*.stories.ts", + "./src/**/*.ts", + "./src/*.ts", + "./.storybook/*.js", + "./.storybook/*.ts" + ] +} diff --git a/components/oscd-button/tsconfig.test.json b/components/oscd-button/tsconfig.test.json new file mode 100644 index 0000000..29717e3 --- /dev/null +++ b/components/oscd-button/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "rootDir": "./" + }, + "extends": "./tsconfig", + "include": ["*/*.ts"] +} diff --git a/components/oscd-button/typedoc.json b/components/oscd-button/typedoc.json new file mode 100644 index 0000000..2c43ad9 --- /dev/null +++ b/components/oscd-button/typedoc.json @@ -0,0 +1,4 @@ +{ + "entryPoints": ["src/index.ts"], + "out": "docs" +} diff --git a/components/oscd-button/web-test-runner.config.js b/components/oscd-button/web-test-runner.config.js new file mode 100644 index 0000000..28aec99 --- /dev/null +++ b/components/oscd-button/web-test-runner.config.js @@ -0,0 +1,182 @@ +import { visualRegressionPlugin } from '@web/test-runner-visual-regression/plugin'; +import { playwrightLauncher } from '@web/test-runner-playwright'; + +import pixelmatch from 'pixelmatch'; +import { PNG } from 'pngjs'; + +const fuzzy = ['win32', 'darwin'].includes(process.platform); // allow for 1% difference on non-linux OSs +const local = !process.env.CI; + +console.assert(local, 'Running in CI!'); +console.assert(!fuzzy, 'Running on OS with 1% test pixel diff threshold!'); + +const thresholdPercentage = fuzzy && local ? 0 : 0; + +const filteredLogs = [ + 'Running in dev mode', + 'Lit is in dev mode', + 'mwc-list-item scheduled an update', +]; + +const browsers = [ + playwrightLauncher({ + product: 'chromium', + }), + playwrightLauncher({ product: 'firefox' }), + playwrightLauncher({ product: 'webkit' }), +]; + +function defaultGetImageDiff({ baselineImage, image, options }) { + let error = ''; + let basePng = PNG.sync.read(baselineImage); + let png = PNG.sync.read(image); + let { width, height } = png; + + if (basePng.width !== png.width || basePng.height !== png.height) { + error = + `Screenshot is not the same width and height as the baseline. ` + + `Baseline: { width: ${basePng.width}, height: ${basePng.height} }` + + `Screenshot: { width: ${png.width}, height: ${png.height} }`; + width = Math.max(basePng.width, png.width); + height = Math.max(basePng.height, png.height); + let oldPng = basePng; + basePng = new PNG({ width, height }); + oldPng.data.copy(basePng.data, 0, 0, oldPng.data.length); + oldPng = png; + png = new PNG({ width, height }); + oldPng.data.copy(png.data, 0, 0, oldPng.data.length); + } + + const diff = new PNG({ width, height }); + + const numDiffPixels = pixelmatch( + basePng.data, + png.data, + diff.data, + width, + height, + options + ); + const diffPercentage = (numDiffPixels / (width * height)) * 100; + + return { + error, + diffImage: PNG.sync.write(diff), + diffPercentage, + }; +} + +export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({ + plugins: [ + visualRegressionPlugin({ + update: process.argv.includes('--update-visual-baseline'), + getImageDiff: (options) => { + const result = defaultGetImageDiff(options); + if (result.diffPercentage < thresholdPercentage) + result.diffPercentage = 0; + return result; + }, + }), + ], + + files: 'dist/**/*.spec.js', + + groups: [ + { + name: 'visual', + files: 'dist/**/*.test.js', + testRunnerHtml: (testFramework) => ` + + + + + + + + + + + + + +`, + }, + ], + + /** Resolve bare module imports */ + nodeResolve: { + exportConditions: ['browser', 'development'], + }, + + /** Filter out lit dev mode logs */ + filterBrowserLogs(log) { + for (const arg of log.args) { + if ( + typeof arg === 'string' && + filteredLogs.some((l) => arg.includes(l)) + ) { + return false; + } + } + return true; + }, + + /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */ + // esbuildTarget: 'auto', + + /** Amount of browsers to run concurrently */ + concurrentBrowsers: 3, + + /** Amount of test files per browser to test concurrently */ + concurrency: 2, + + /** Browsers to run tests on */ + browsers, + + // See documentation for all available options +}); diff --git a/components/oscd-dialog/.gitignore b/components/oscd-dialog/.gitignore new file mode 100644 index 0000000..63cc1db --- /dev/null +++ b/components/oscd-dialog/.gitignore @@ -0,0 +1,20 @@ +## editors +/.idea +/.vscode + +## system files +.DS_Store + +## npm +/node_modules/ +/npm-debug.log +.tsbuildinfo + +## testing +/coverage/ + +## docs +/doc/ + +# build +/dist/ diff --git a/components/oscd-dialog/.npmignore b/components/oscd-dialog/.npmignore new file mode 100644 index 0000000..28f225d --- /dev/null +++ b/components/oscd-dialog/.npmignore @@ -0,0 +1,18 @@ +## editors +/.idea +/.vscode + +## system files +.DS_Store + +## npm +/node_modules/ +/npm-debug.log +.tsbuildinfo + +## testing +/coverage/ + +## docs +/doc/ + diff --git a/components/oscd-dialog/.storybook/main.ts b/components/oscd-dialog/.storybook/main.ts new file mode 100644 index 0000000..c8e9fee --- /dev/null +++ b/components/oscd-dialog/.storybook/main.ts @@ -0,0 +1,30 @@ +import type { StorybookConfig } from '@storybook/web-components-vite'; + +const config: StorybookConfig = { + stories: ['../stories/**/*.stories.@(js|jsx|ts|tsx)', '../stories/**/*.mdx'], + addons: [ + '@storybook/addon-docs', + '@storybook/addon-controls', + '@storybook/addon-actions', + '@storybook/addon-a11y', + '@storybook/addon-links', + { + name: '@storybook/adddon-essentials', + options: { + background: false, + }, + }, + '@etchteam/storybook-addon-status/register', + 'storybook-addon-root-attribute/register', + ], + framework: { + name: '@storybook/web-components-vite', + options: { + builder: { + viteConfigPath: '', + }, + }, + }, +}; + +export default config; diff --git a/components/oscd-dialog/.storybook/manager.ts b/components/oscd-dialog/.storybook/manager.ts new file mode 100644 index 0000000..66b6e89 --- /dev/null +++ b/components/oscd-dialog/.storybook/manager.ts @@ -0,0 +1,5 @@ +import { addons } from '@storybook/manager-api'; + +addons.setConfig({ + enableShortcuts: false +}); diff --git a/components/oscd-dialog/.storybook/preview-head.html b/components/oscd-dialog/.storybook/preview-head.html new file mode 100644 index 0000000..cee1d43 --- /dev/null +++ b/components/oscd-dialog/.storybook/preview-head.html @@ -0,0 +1,15 @@ + + + diff --git a/components/oscd-dialog/.storybook/preview.ts b/components/oscd-dialog/.storybook/preview.ts new file mode 100644 index 0000000..738938f --- /dev/null +++ b/components/oscd-dialog/.storybook/preview.ts @@ -0,0 +1,40 @@ +import { setCustomElementsManifest } from '@storybook/web-components'; + +import { withRootAttribute } from 'storybook-addon-root-attribute'; + +import '../../../themes/prebuilt/oscd.css'; + +import customElements from '../custom-elements.json'; + +setCustomElementsManifest(customElements); + +export const decorators = [withRootAttribute]; + +export const parameters = { + statuses: { + released: { + background: '#0000ff', + color: '#ffffff', + description: 'This component is stable and released', + }, + beta: { + background: '#FF0000', + color: '#FFFFFF', + description: 'This component is still in beta', + }, + }, + rootAttribute: { + defaultState: { + name: 'Light', + value: null, + }, + attribute: 'dark', + tooltip: true, + states: [ + { + name: 'Dark', + value: 'dark', + }, + ], + }, +}; diff --git a/components/oscd-dialog/CHANGELOG.md b/components/oscd-dialog/CHANGELOG.md new file mode 100644 index 0000000..825c32f --- /dev/null +++ b/components/oscd-dialog/CHANGELOG.md @@ -0,0 +1 @@ +# Changelog diff --git a/components/oscd-dialog/EXAMPLE.md b/components/oscd-dialog/EXAMPLE.md new file mode 100644 index 0000000..db17cf8 --- /dev/null +++ b/components/oscd-dialog/EXAMPLE.md @@ -0,0 +1,3 @@ +```html + +``` diff --git a/components/oscd-dialog/INTRO.md b/components/oscd-dialog/INTRO.md new file mode 100644 index 0000000..e69de29 diff --git a/components/oscd-dialog/LICENSE.md b/components/oscd-dialog/LICENSE.md new file mode 100644 index 0000000..c61b663 --- /dev/null +++ b/components/oscd-dialog/LICENSE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/components/oscd-dialog/README.md b/components/oscd-dialog/README.md new file mode 100644 index 0000000..c5c4d6e --- /dev/null +++ b/components/oscd-dialog/README.md @@ -0,0 +1,23 @@ +# `` ![NPM](https://img.shields.io/badge/NPM-0.0.1-cb0001) ![Status](https://img.shields.io/badge/WIP-3b72bf) + +--- + + + +## Example + +```html + +``` + +--- + +### Attributes + +| Name | Type | Description | +| ---- | ---- | ----------- | + +### Css Properties + +| Name | Default | Description | +| ---- | ------- | ----------- | \ No newline at end of file diff --git a/components/oscd-dialog/custom-elements-manifest.config.js b/components/oscd-dialog/custom-elements-manifest.config.js new file mode 100644 index 0000000..562fc21 --- /dev/null +++ b/components/oscd-dialog/custom-elements-manifest.config.js @@ -0,0 +1,6 @@ +export default { + globs: ['src/*.ts'], + exclude: ['test/*.ts'], + litelement: true, + plugins: [], +}; diff --git a/components/oscd-dialog/custom-elements.json b/components/oscd-dialog/custom-elements.json new file mode 100644 index 0000000..9a4ef94 --- /dev/null +++ b/components/oscd-dialog/custom-elements.json @@ -0,0 +1,131 @@ +{ + "schemaVersion": "1.0.0", + "readme": "", + "modules": [ + { + "kind": "javascript-module", + "path": "src/OscdDialog.ts", + "declarations": [], + "exports": [ + { + "kind": "custom-element-definition", + "name": "oscd-dialog", + "declaration": { + "name": "OscdDialog", + "module": "/src/oscd-dialog" + } + }, + { + "kind": "js", + "name": "OscdDialog", + "declaration": { + "name": "OscdDialog", + "module": "src/OscdDialog.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/index.ts", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "*", + "declaration": { + "name": "*", + "package": "./OscdDialog.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/oscd-dialog.styles.ts", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "module": "src/oscd-dialog.styles.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/oscd-dialog.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "OscdDialog", + "members": [ + { + "kind": "field", + "name": "open", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Determines if the Dialog is open or not" + }, + { + "kind": "method", + "name": "show", + "return": { + "type": { + "text": "void" + } + } + }, + { + "kind": "method", + "name": "hide", + "return": { + "type": { + "text": "void" + } + } + }, + { + "kind": "method", + "name": "onClosed", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "evt", + "type": { + "text": "Event" + } + } + ] + } + ], + "superclass": { + "name": "OscdComponent", + "package": "@openscd/core" + }, + "tagName": "oscd-dialog", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "OscdDialog", + "declaration": { + "name": "OscdDialog", + "module": "src/oscd-dialog.ts" + } + } + ] + } + ] +} diff --git a/components/oscd-dialog/package.json b/components/oscd-dialog/package.json new file mode 100644 index 0000000..75bf7cb --- /dev/null +++ b/components/oscd-dialog/package.json @@ -0,0 +1,61 @@ +{ + "name": "@openscd/oscd-dialog", + "description": "Webcomponent oscd-dialog following open-wc recommendations", + "license": "Apache-2.0", + "author": "OpenSCD", + "version": "0.0.1", + "browser": "./dist/OscdDialog.js", + "module": "./dist/OscdDialog.js", + "files": [ + "dist/**/*" + ], + "exports": { + ".": "./dist/OscdDialog.js", + "./oscd-dialog.js": "./dist/oscd-dialog.js" + }, + "type": "module", + "readme": "./README.md", + "scripts": { + "analyze": "cem analyze", + "build": "tsc", + "clean": "rimraf .tsbuildinfo dist", + "storybook": "npx nx storybook oscd-dialog", + "typedoc": "typedoc", + "test": "tsc --p tsconfig.test.json && wtr --coverage", + "test:unit": "tsc --p tsconfig.test.json && wtr --group default", + "test:visual": "tsc --p tsconfig.test.json && wtr --group visual", + "test:update": "tsc --p tsconfig.test.json && wtr --group visual --update-visual-baseline", + "test:watch": "tsc --p tsconfig.test.json && concurrently -k -r \"tsc --p tsconfig.test.json --watch --preserveWatchOutput\" \"wtr --watch\"" + }, + "dependencies": { + "@openscd/core": "*", + "@material/mwc-dialog": "0.27.0", + "lit": "^2.7.6" + }, + "devDependencies": { + "@commitlint/cli": "^17.3.0", + "@commitlint/config-conventional": "^17.3.0", + "@custom-elements-manifest/analyzer": "^0.4.17", + "@open-wc/demoing-storybook": "^2.4.7", + "@open-wc/eslint-config": "^8.0.2", + "@open-wc/scoped-elements": "^2.2.0", + "@open-wc/testing": "^3.1.6", + "@oscd/utils": "*", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.33.0", + "@web/dev-server": "^0.1.34", + "@web/dev-server-storybook": "^0.5.4", + "@web/test-runner": "^0.14.0", + "@web/test-runner-playwright": "^0.9.0", + "@web/test-runner-visual-regression": "^0.7.0", + "concurrently": "^8.2.0", + "storybook-addon-root-attribute": "^1.0.2", + "tslib": "^2.6.0", + "typedoc": "^0.24.8", + "typescript": "^5.1.6" + }, + "customElements": "custom-elements.json", + "oscd": { + "status": "WIP" + } +} diff --git a/components/oscd-dialog/project.json b/components/oscd-dialog/project.json new file mode 100644 index 0000000..ffb4f35 --- /dev/null +++ b/components/oscd-dialog/project.json @@ -0,0 +1,33 @@ +{ + "name": "oscd-dialog", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "components/oscd-dialog/src", + "targets": { + "storybook": { + "executor": "@nx/storybook:storybook", + "options": { + "port": 4400, + "configDir": "components/oscd-dialog/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + }, + "build-storybook": { + "executor": "@nx/storybook:build", + "outputs": ["{options.outputDir}"], + "options": { + "outputDir": "dist/storybook/oscd-dialog", + "configDir": "components/oscd-dialog/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + } + } +} diff --git a/components/oscd-dialog/src/OscdDialog.ts b/components/oscd-dialog/src/OscdDialog.ts new file mode 100644 index 0000000..f97df35 --- /dev/null +++ b/components/oscd-dialog/src/OscdDialog.ts @@ -0,0 +1,5 @@ +import { OscdDialog } from './oscd-dialog'; + +window.customElements.define('oscd-dialog', OscdDialog); + +export { OscdDialog }; diff --git a/components/oscd-dialog/src/oscd-dialog.styles.ts b/components/oscd-dialog/src/oscd-dialog.styles.ts new file mode 100644 index 0000000..59d6881 --- /dev/null +++ b/components/oscd-dialog/src/oscd-dialog.styles.ts @@ -0,0 +1,7 @@ +import { css } from 'lit-element'; + +import { styles } from '@openscd/core'; + +export default css` + ${styles} +`; diff --git a/components/oscd-dialog/src/oscd-dialog.ts b/components/oscd-dialog/src/oscd-dialog.ts new file mode 100644 index 0000000..49f4663 --- /dev/null +++ b/components/oscd-dialog/src/oscd-dialog.ts @@ -0,0 +1,58 @@ +import { + html, + CSSResultGroup, + TemplateResult, + property, + query, +} from 'lit-element'; + +import '@material/mwc-dialog'; + +import { OscdComponent, redispatchEvent } from '@openscd/core'; + +import styles from './oscd-dialog.styles.js'; + +/** + * + * @prop {boolean} open - Determines if the Dialog is open or not + * + * @example + * @tagname oscd-dialog + */ +export class OscdDialog extends OscdComponent { + static styles: CSSResultGroup = styles; + + /** + * @internal + */ + static get scopedElements() { + return {}; + } + + @property({ + type: Boolean, + reflect: true, + }) + open = false; + + show(): void { + this.open = true; + } + + hide(): void { + this.open = false; + } + + onClosed(evt: Event): void { + this.hide(); + redispatchEvent(this, evt); + } + + render(): TemplateResult { + return html``; + } +} diff --git a/components/oscd-dialog/stories/oscd-dialog.mdx b/components/oscd-dialog/stories/oscd-dialog.mdx new file mode 100644 index 0000000..a119c22 --- /dev/null +++ b/components/oscd-dialog/stories/oscd-dialog.mdx @@ -0,0 +1,38 @@ +import { + Meta, + Story, + Canvas, + Source, + ArgTypes, + Title, + Description, + Subtitle, +} from '@storybook/blocks'; + +import { Markdown } from '@storybook/addon-docs'; + +import * as OscdDialogStories from './oscd-dialog.stories'; + +import Readme from '../README.md?raw'; +import Changelog from '../CHANGELOG.md?raw'; + + +oscd-dialog + + +Properties + + + + + + +# Example + + + +{Readme} + +# Changelog + +{Changelog} diff --git a/components/oscd-dialog/stories/oscd-dialog.stories.ts b/components/oscd-dialog/stories/oscd-dialog.stories.ts new file mode 100644 index 0000000..be7544e --- /dev/null +++ b/components/oscd-dialog/stories/oscd-dialog.stories.ts @@ -0,0 +1,93 @@ +import type { Meta, StoryObj } from '@storybook/web-components'; +import { action } from '@storybook/addon-actions'; + +import { html } from 'lit'; + +import '../src/OscdDialog'; + +import { createBadge } from '@oscd/utils'; + +import pckgJson from '../package.json'; + +const meta: Meta = { + title: 'Dialog/OscdDialog', + component: 'oscd-dialog', + parameters: { + status: { + type: createBadge(pckgJson), + }, + }, +}; + +export default meta; + +type Story = StoryObj; + +/** + * Basic + */ +export const Basic: Story = { + render: ({ content, open, onClose }) => + html`${content}`, + args: { + content: html`This is the content for the dialog`, + open: true, + onClose: action('on close'), + }, + parameters: { + docs: { + description: { + story: 'Basic oscd-dialog', + }, + }, + }, +}; + +/** + * With Primary Action + */ +export const WithPrimaryAction: Story = { + render: ({ content, open, onClose }) => + html`${content}`, + args: { + ...Basic.args, + }, +}; + +/** + * With Secondary Action + */ +export const WithSecondaryAction: Story = { + render: ({ content, open, onClose }) => + html`${content}`, + args: { + ...Basic.args, + }, +}; + +/** + * With Actions + */ +export const WithActions: Story = { + render: ({ content, open, onClose }) => + html`${content}`, + args: { + ...Basic.args, + }, +}; diff --git a/components/oscd-dialog/test/oscd-dialog.spec.ts b/components/oscd-dialog/test/oscd-dialog.spec.ts new file mode 100644 index 0000000..4c7d8e4 --- /dev/null +++ b/components/oscd-dialog/test/oscd-dialog.spec.ts @@ -0,0 +1,13 @@ +import { expect, fixture, html } from '@open-wc/testing'; + +import '../src'; +import type { OscdDialog } from '../src'; + +describe('Basic component oscd-dialog', () => { + let element: OscdDialog; + + beforeEach(async () => { + element = await fixture(html``); + await element.updateComplete; + }); +}); diff --git a/components/oscd-dialog/test/oscd-dialog.test.ts b/components/oscd-dialog/test/oscd-dialog.test.ts new file mode 100644 index 0000000..0320b3a --- /dev/null +++ b/components/oscd-dialog/test/oscd-dialog.test.ts @@ -0,0 +1,27 @@ +import { fixture, html } from '@open-wc/testing'; + +import { visualDiff } from '@web/test-runner-visual-regression'; + +import '../src'; +import { OscdDialog } from '../src'; + +const factor = process.env.CI ? 2 : 1; + +function timeout(ms: number) { + return new Promise((res) => { + setTimeout(res, ms * factor); + }); +} + +mocha.timeout(2000 * factor); + +describe('oscd-dialog', () => { + let element: OscdDialog; + + beforeEach(async () => { + element = await fixture(html``); + document.body.prepend(element); + }); + + afterEach(() => element.remove()); +}); diff --git a/components/oscd-dialog/tsconfig.json b/components/oscd-dialog/tsconfig.json new file mode 100644 index 0000000..4627f8a --- /dev/null +++ b/components/oscd-dialog/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "lib": ["es2018", "dom"], + "strict": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "declaration": true, + "importHelpers": true, + "outDir": "dist", + "sourceMap": true, + "inlineSources": true, + "rootDir": "./src", + "tsBuildInfoFile": ".tsbuildinfo", + "incremental": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": ["./src/**/*.ts"], + "exclude": ["**/*.stories.ts", "**/*.stories.js"] +} diff --git a/components/oscd-dialog/tsconfig.storybook.json b/components/oscd-dialog/tsconfig.storybook.json new file mode 100644 index 0000000..cda53dc --- /dev/null +++ b/components/oscd-dialog/tsconfig.storybook.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "composite": true, + "incremental": false, + "tsBuildInfoFile": null, + "rootDir": "./" + }, + "exclude": ["./test/**/*.ts"], + "include": [ + "./stories/**/*.stories.ts", + "./src/**/*.ts", + "./src/*.ts", + "./.storybook/*.js", + "./.storybook/*.ts" + ] +} diff --git a/components/oscd-dialog/tsconfig.test.json b/components/oscd-dialog/tsconfig.test.json new file mode 100644 index 0000000..29717e3 --- /dev/null +++ b/components/oscd-dialog/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "rootDir": "./" + }, + "extends": "./tsconfig", + "include": ["*/*.ts"] +} diff --git a/components/oscd-dialog/typedoc.json b/components/oscd-dialog/typedoc.json new file mode 100644 index 0000000..2c43ad9 --- /dev/null +++ b/components/oscd-dialog/typedoc.json @@ -0,0 +1,4 @@ +{ + "entryPoints": ["src/index.ts"], + "out": "docs" +} diff --git a/components/oscd-dialog/web-test-runner.config.js b/components/oscd-dialog/web-test-runner.config.js new file mode 100644 index 0000000..28aec99 --- /dev/null +++ b/components/oscd-dialog/web-test-runner.config.js @@ -0,0 +1,182 @@ +import { visualRegressionPlugin } from '@web/test-runner-visual-regression/plugin'; +import { playwrightLauncher } from '@web/test-runner-playwright'; + +import pixelmatch from 'pixelmatch'; +import { PNG } from 'pngjs'; + +const fuzzy = ['win32', 'darwin'].includes(process.platform); // allow for 1% difference on non-linux OSs +const local = !process.env.CI; + +console.assert(local, 'Running in CI!'); +console.assert(!fuzzy, 'Running on OS with 1% test pixel diff threshold!'); + +const thresholdPercentage = fuzzy && local ? 0 : 0; + +const filteredLogs = [ + 'Running in dev mode', + 'Lit is in dev mode', + 'mwc-list-item scheduled an update', +]; + +const browsers = [ + playwrightLauncher({ + product: 'chromium', + }), + playwrightLauncher({ product: 'firefox' }), + playwrightLauncher({ product: 'webkit' }), +]; + +function defaultGetImageDiff({ baselineImage, image, options }) { + let error = ''; + let basePng = PNG.sync.read(baselineImage); + let png = PNG.sync.read(image); + let { width, height } = png; + + if (basePng.width !== png.width || basePng.height !== png.height) { + error = + `Screenshot is not the same width and height as the baseline. ` + + `Baseline: { width: ${basePng.width}, height: ${basePng.height} }` + + `Screenshot: { width: ${png.width}, height: ${png.height} }`; + width = Math.max(basePng.width, png.width); + height = Math.max(basePng.height, png.height); + let oldPng = basePng; + basePng = new PNG({ width, height }); + oldPng.data.copy(basePng.data, 0, 0, oldPng.data.length); + oldPng = png; + png = new PNG({ width, height }); + oldPng.data.copy(png.data, 0, 0, oldPng.data.length); + } + + const diff = new PNG({ width, height }); + + const numDiffPixels = pixelmatch( + basePng.data, + png.data, + diff.data, + width, + height, + options + ); + const diffPercentage = (numDiffPixels / (width * height)) * 100; + + return { + error, + diffImage: PNG.sync.write(diff), + diffPercentage, + }; +} + +export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({ + plugins: [ + visualRegressionPlugin({ + update: process.argv.includes('--update-visual-baseline'), + getImageDiff: (options) => { + const result = defaultGetImageDiff(options); + if (result.diffPercentage < thresholdPercentage) + result.diffPercentage = 0; + return result; + }, + }), + ], + + files: 'dist/**/*.spec.js', + + groups: [ + { + name: 'visual', + files: 'dist/**/*.test.js', + testRunnerHtml: (testFramework) => ` + + + + + + + + + + + + + +`, + }, + ], + + /** Resolve bare module imports */ + nodeResolve: { + exportConditions: ['browser', 'development'], + }, + + /** Filter out lit dev mode logs */ + filterBrowserLogs(log) { + for (const arg of log.args) { + if ( + typeof arg === 'string' && + filteredLogs.some((l) => arg.includes(l)) + ) { + return false; + } + } + return true; + }, + + /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */ + // esbuildTarget: 'auto', + + /** Amount of browsers to run concurrently */ + concurrentBrowsers: 3, + + /** Amount of test files per browser to test concurrently */ + concurrency: 2, + + /** Browsers to run tests on */ + browsers, + + // See documentation for all available options +}); diff --git a/components/oscd-switch/.gitignore b/components/oscd-switch/.gitignore new file mode 100644 index 0000000..63cc1db --- /dev/null +++ b/components/oscd-switch/.gitignore @@ -0,0 +1,20 @@ +## editors +/.idea +/.vscode + +## system files +.DS_Store + +## npm +/node_modules/ +/npm-debug.log +.tsbuildinfo + +## testing +/coverage/ + +## docs +/doc/ + +# build +/dist/ diff --git a/components/oscd-switch/.npmignore b/components/oscd-switch/.npmignore new file mode 100644 index 0000000..28f225d --- /dev/null +++ b/components/oscd-switch/.npmignore @@ -0,0 +1,18 @@ +## editors +/.idea +/.vscode + +## system files +.DS_Store + +## npm +/node_modules/ +/npm-debug.log +.tsbuildinfo + +## testing +/coverage/ + +## docs +/doc/ + diff --git a/components/oscd-switch/.storybook/main.ts b/components/oscd-switch/.storybook/main.ts new file mode 100644 index 0000000..c8e9fee --- /dev/null +++ b/components/oscd-switch/.storybook/main.ts @@ -0,0 +1,30 @@ +import type { StorybookConfig } from '@storybook/web-components-vite'; + +const config: StorybookConfig = { + stories: ['../stories/**/*.stories.@(js|jsx|ts|tsx)', '../stories/**/*.mdx'], + addons: [ + '@storybook/addon-docs', + '@storybook/addon-controls', + '@storybook/addon-actions', + '@storybook/addon-a11y', + '@storybook/addon-links', + { + name: '@storybook/adddon-essentials', + options: { + background: false, + }, + }, + '@etchteam/storybook-addon-status/register', + 'storybook-addon-root-attribute/register', + ], + framework: { + name: '@storybook/web-components-vite', + options: { + builder: { + viteConfigPath: '', + }, + }, + }, +}; + +export default config; diff --git a/components/oscd-switch/.storybook/manager.ts b/components/oscd-switch/.storybook/manager.ts new file mode 100644 index 0000000..66b6e89 --- /dev/null +++ b/components/oscd-switch/.storybook/manager.ts @@ -0,0 +1,5 @@ +import { addons } from '@storybook/manager-api'; + +addons.setConfig({ + enableShortcuts: false +}); diff --git a/components/oscd-switch/.storybook/preview-head.html b/components/oscd-switch/.storybook/preview-head.html new file mode 100644 index 0000000..89f0ee1 --- /dev/null +++ b/components/oscd-switch/.storybook/preview-head.html @@ -0,0 +1,16 @@ + + + diff --git a/components/oscd-switch/.storybook/preview.ts b/components/oscd-switch/.storybook/preview.ts new file mode 100644 index 0000000..94c4d5d --- /dev/null +++ b/components/oscd-switch/.storybook/preview.ts @@ -0,0 +1,44 @@ +import { setCustomElementsManifest } from '@storybook/web-components'; + +import { html } from 'lit'; +import { withRootAttribute } from 'storybook-addon-root-attribute'; + +import '../../../themes/prebuilt/oscd.css'; + +import customElements from '../custom-elements.json'; + +setCustomElementsManifest(customElements); + +export const decorators = [withRootAttribute]; + +export const parameters = { + controls: { expanded: true }, + actions: { argTypesRegex: '^on.*' }, + + statuses: { + released: { + background: '#0000ff', + color: '#ffffff', + description: 'This component is stable and released', + }, + beta: { + background: '#FF0000', + color: '#FFFFFF', + description: 'This component is still in beta', + }, + }, + rootAttribute: { + defaultState: { + name: 'Light', + value: null, + }, + attribute: 'dark', + tooltip: true, + states: [ + { + name: 'Dark', + value: 'dark', + }, + ], + }, +}; diff --git a/components/oscd-switch/CHANGELOG.md b/components/oscd-switch/CHANGELOG.md new file mode 100644 index 0000000..825c32f --- /dev/null +++ b/components/oscd-switch/CHANGELOG.md @@ -0,0 +1 @@ +# Changelog diff --git a/components/oscd-switch/EXAMPLE.md b/components/oscd-switch/EXAMPLE.md new file mode 100644 index 0000000..aa26c80 --- /dev/null +++ b/components/oscd-switch/EXAMPLE.md @@ -0,0 +1,3 @@ +```html + +``` diff --git a/components/oscd-switch/INTRO.md b/components/oscd-switch/INTRO.md new file mode 100644 index 0000000..e69de29 diff --git a/components/oscd-switch/LICENSE.md b/components/oscd-switch/LICENSE.md new file mode 100644 index 0000000..c61b663 --- /dev/null +++ b/components/oscd-switch/LICENSE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/components/oscd-switch/README.md b/components/oscd-switch/README.md new file mode 100644 index 0000000..88e60f6 --- /dev/null +++ b/components/oscd-switch/README.md @@ -0,0 +1,23 @@ +# `` ![NPM](https://img.shields.io/badge/NPM-0.0.1-cb0001) ![Status](https://img.shields.io/badge/WIP-3b72bf) + +--- + + + +## Example + +```html + +``` + +--- + +### Attributes + +| Name | Type | Description | +| ---- | ---- | ----------- | + +### Css Properties + +| Name | Default | Description | +| ---- | ------- | ----------- | \ No newline at end of file diff --git a/components/oscd-switch/custom-elements-manifest.config.js b/components/oscd-switch/custom-elements-manifest.config.js new file mode 100644 index 0000000..562fc21 --- /dev/null +++ b/components/oscd-switch/custom-elements-manifest.config.js @@ -0,0 +1,6 @@ +export default { + globs: ['src/*.ts'], + exclude: ['test/*.ts'], + litelement: true, + plugins: [], +}; diff --git a/components/oscd-switch/custom-elements.json b/components/oscd-switch/custom-elements.json new file mode 100644 index 0000000..cac71e7 --- /dev/null +++ b/components/oscd-switch/custom-elements.json @@ -0,0 +1,126 @@ +{ + "schemaVersion": "1.0.0", + "readme": "", + "modules": [ + { + "kind": "javascript-module", + "path": "src/OscdSwitch.ts", + "declarations": [], + "exports": [ + { + "kind": "custom-element-definition", + "name": "oscd-switch", + "declaration": { + "name": "OscdSwitch", + "module": "/src/oscd-switch.js" + } + }, + { + "kind": "js", + "name": "OscdSwitch", + "declaration": { + "name": "OscdSwitch", + "module": "src/OscdSwitch.ts" + } + }, + { + "kind": "js", + "name": "OscdSwitchChangeEvent", + "declaration": { + "name": "OscdSwitchChangeEvent", + "module": "./oscd-switch.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/oscd-switch.styles.ts", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "module": "src/oscd-switch.styles.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/oscd-switch.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "OscdSwitch", + "members": [ + { + "kind": "field", + "name": "selected", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Selected state of the Switch" + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Disabled state of the Switch" + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "string" + }, + "default": "'on'", + "description": "Value of the Switch" + }, + { + "kind": "field", + "name": "name", + "type": { + "text": "string" + }, + "default": "''", + "description": "Name of the Switch" + }, + { + "kind": "method", + "name": "onClick" + } + ], + "events": [ + { + "description": "{OscdSwitchChangeEvent} Fired whenever `selected` changes due to user interaction (bubbles and composed).", + "name": "change" + } + ], + "superclass": { + "name": "OscdComponent", + "package": "@openscd/core" + }, + "tagName": "oscd-switch", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "OscdSwitch", + "declaration": { + "name": "OscdSwitch", + "module": "src/oscd-switch.ts" + } + } + ] + } + ] +} diff --git a/components/oscd-switch/package.json b/components/oscd-switch/package.json new file mode 100644 index 0000000..acd5e4b --- /dev/null +++ b/components/oscd-switch/package.json @@ -0,0 +1,62 @@ +{ + "name": "@openscd/oscd-switch", + "description": "Webcomponent oscd-switch following open-wc recommendations", + "license": "Apache-2.0", + "author": "OpenSCD", + "version": "0.0.1", + "browser": "./dist/OscdSwitch.js", + "module": "./dist/OscdSwitch.js", + "types": "./dist/OscdSwitch.d.ts", + "files": [ + "./dist/**/*" + ], + "exports": { + ".": "./dist/OscdSwitch.js", + "./oscd-switch.js": "./dist/oscd-switch.js" + }, + "type": "module", + "readme": "./README.md", + "scripts": { + "analyze": "cem analyze", + "build": "tsc --build tsconfig.json", + "clean": "rimraf .tsbuildinfo dist", + "storybook": "npx nx storybook oscd-switch", + "typedoc": "typedoc", + "test": "tsc --p tsconfig.test.json && wtr --coverage", + "test:unit": "tsc --p tsconfig.test.json && wtr --group default", + "test:visual": "tsc --p tsconfig.test.json && wtr --group visual", + "test:update": "tsc --p tsconfig.test.json && wtr --group visual --update-visual-baseline", + "test:watch": "tsc --p tsconfig.test.json && concurrently -k -r \"tsc --p tsconfig.test.json --watch --preserveWatchOutput\" \"wtr --watch\"" + }, + "dependencies": { + "@openscd/core": "*", + "lit": "^2.7.6", + "@material/mwc-switch": "0.27.0" + }, + "devDependencies": { + "@commitlint/cli": "^17.3.0", + "@commitlint/config-conventional": "^17.3.0", + "@custom-elements-manifest/analyzer": "^0.4.17", + "@open-wc/demoing-storybook": "^2.4.7", + "@open-wc/eslint-config": "^8.0.2", + "@open-wc/scoped-elements": "^2.2.0", + "@open-wc/testing": "^3.1.6", + "@oscd/utils": "*", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.33.0", + "@web/dev-server": "^0.1.34", + "@web/dev-server-storybook": "^0.5.4", + "@web/test-runner": "^0.14.0", + "@web/test-runner-playwright": "^0.9.0", + "@web/test-runner-visual-regression": "^0.7.0", + "concurrently": "^8.2.0", + "storybook-addon-root-attribute": "^1.0.2", + "tslib": "^2.6.0", + "typedoc": "^0.24.8", + "typescript": "^5.1.6" + }, + "customElements": "custom-elements.json", + "oscd": { + "status": "WIP" + } +} diff --git a/components/oscd-switch/project.json b/components/oscd-switch/project.json new file mode 100644 index 0000000..2c7237b --- /dev/null +++ b/components/oscd-switch/project.json @@ -0,0 +1,33 @@ +{ + "name": "oscd-switch", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "components/oscd-switch/src", + "targets": { + "storybook": { + "executor": "@nx/storybook:storybook", + "options": { + "port": 4400, + "configDir": "components/oscd-switch/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + }, + "build-storybook": { + "executor": "@nx/storybook:build", + "outputs": ["{options.outputDir}"], + "options": { + "outputDir": "dist/storybook/oscd-switch", + "configDir": "components/oscd-switch/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + } + } +} diff --git a/components/oscd-switch/screenshots/Chromium/baseline/oscd-switch-selected.png b/components/oscd-switch/screenshots/Chromium/baseline/oscd-switch-selected.png new file mode 100644 index 0000000..4a018f8 Binary files /dev/null and b/components/oscd-switch/screenshots/Chromium/baseline/oscd-switch-selected.png differ diff --git a/components/oscd-switch/screenshots/Chromium/baseline/oscd-switch.png b/components/oscd-switch/screenshots/Chromium/baseline/oscd-switch.png new file mode 100644 index 0000000..831bd84 Binary files /dev/null and b/components/oscd-switch/screenshots/Chromium/baseline/oscd-switch.png differ diff --git a/components/oscd-switch/screenshots/Firefox/baseline/oscd-switch-selected.png b/components/oscd-switch/screenshots/Firefox/baseline/oscd-switch-selected.png new file mode 100644 index 0000000..4e2289c Binary files /dev/null and b/components/oscd-switch/screenshots/Firefox/baseline/oscd-switch-selected.png differ diff --git a/components/oscd-switch/screenshots/Firefox/baseline/oscd-switch.png b/components/oscd-switch/screenshots/Firefox/baseline/oscd-switch.png new file mode 100644 index 0000000..99efe74 Binary files /dev/null and b/components/oscd-switch/screenshots/Firefox/baseline/oscd-switch.png differ diff --git a/components/oscd-switch/screenshots/Webkit/baseline/oscd-switch-selected.png b/components/oscd-switch/screenshots/Webkit/baseline/oscd-switch-selected.png new file mode 100644 index 0000000..c050f30 Binary files /dev/null and b/components/oscd-switch/screenshots/Webkit/baseline/oscd-switch-selected.png differ diff --git a/components/oscd-switch/screenshots/Webkit/baseline/oscd-switch.png b/components/oscd-switch/screenshots/Webkit/baseline/oscd-switch.png new file mode 100644 index 0000000..38a6104 Binary files /dev/null and b/components/oscd-switch/screenshots/Webkit/baseline/oscd-switch.png differ diff --git a/components/oscd-switch/src/OscdSwitch.ts b/components/oscd-switch/src/OscdSwitch.ts new file mode 100644 index 0000000..4e9fa02 --- /dev/null +++ b/components/oscd-switch/src/OscdSwitch.ts @@ -0,0 +1,7 @@ +import { OscdSwitch } from './oscd-switch.js'; + +window.customElements.define('oscd-switch', OscdSwitch); + +export { OscdSwitch }; + +export type { OscdSwitchChangeEvent } from './oscd-switch.js'; diff --git a/components/oscd-switch/src/oscd-switch.styles.ts b/components/oscd-switch/src/oscd-switch.styles.ts new file mode 100644 index 0000000..5b1b934 --- /dev/null +++ b/components/oscd-switch/src/oscd-switch.styles.ts @@ -0,0 +1,54 @@ +import { css } from 'lit-element'; + +import { styles } from '@openscd/core'; + +export default css` + ${styles} + + mwc-switch { + --mdc-theme-primary: var( + --oscd-theme-switch-primary, + var(--oscd-theme-primary) + ); + + --mdc-switch-selected-track-color: var( + --oscd-theme-switch-primary-surface, + var(--oscd-theme-primary-surface) + ); + + --mdc-switch-selected-hover-track-color: var( + --oscd-theme-switch-primary-surface-active, + var(--oscd-theme-primary-surface-active) + ); + + --mdc-switch-selected-pressed-track-color: var( + --oscd-theme-switch-primary-surface-active, + var(--oscd-theme-primary-surface-active) + ); + + --mdc-switch-selected-focus-track-color: var( + --oscd-theme-switch-primary-surface-active, + var(--oscd-theme-primary-surface-active) + ); + + --mdc-switch-selected-hover-handle-color: var( + --oscd-theme-switch-primary-active, + var(--oscd-theme-primary-active) + ); + + --mdc-switch-selected-pressed-handle-color: var( + --oscd-theme-switch-primary-active, + var(--oscd-theme-primary-active) + ); + + --mdc-switch-selected-focus-handle-color: var( + --oscd-theme-switch-primary-active, + var(--oscd-theme-primary-active) + ); + + --mdc-switch-disabled-unselected-track-color: var( + --oscd-theme-switch-disabled, + var(--oscd-theme-disabled) + ); + +`; diff --git a/components/oscd-switch/src/oscd-switch.ts b/components/oscd-switch/src/oscd-switch.ts new file mode 100644 index 0000000..49b079c --- /dev/null +++ b/components/oscd-switch/src/oscd-switch.ts @@ -0,0 +1,102 @@ +import { + html, + CSSResultGroup, + TemplateResult, + property, + query, +} from 'lit-element'; + +import '@material/mwc-switch'; + +import type { Switch } from '@material/mwc-switch'; + +import { OscdComponent } from '@openscd/core'; + +import styles from './oscd-switch.styles.js'; + +export interface OscdSwitchChangeEvent extends CustomEvent { + detail: { + selected: boolean; + }; +} + +const newOscdSwitchChangeEvent = (selected: boolean): OscdSwitchChangeEvent => { + return new CustomEvent('change', { + detail: { selected: selected }, + bubbles: true, + composed: true, + }); +}; + +/** + * + * @prop {boolean} selected - Selected state of the Switch + * @prop {boolean} disabled - Disabled state of the Switch + * + * @prop {string} value - Value of the Switch + * @prop {string} name - Name of the Switch + * + * @fires change {OscdSwitchChangeEvent} Fired whenever `selected` changes due to user + * interaction (bubbles and composed). + * + * @example + * @tagname oscd-switch + */ +export class OscdSwitch extends OscdComponent { + static styles: CSSResultGroup = styles; + + @property({ + type: Boolean, + }) + selected?: boolean = false; + + @property({ + type: Boolean, + }) + disabled?: boolean = false; + + @property({ + type: String, + }) + value: string = 'on'; + + @property({ + type: String, + }) + name: string = ''; + + /** + * @internal + */ + @query('mwc-switch') + switch!: Switch; + + /** + * @internal + */ + static get scopedElements() { + return {}; + } + + constructor() { + super(); + } + + render(): TemplateResult { + return html``; + } + + onClick() { + if (this.disabled) { + return; + } + + this.dispatchEvent(newOscdSwitchChangeEvent(this.switch.selected)); + } +} diff --git a/components/oscd-switch/stories/oscd-switch.mdx b/components/oscd-switch/stories/oscd-switch.mdx new file mode 100644 index 0000000..7bbf495 --- /dev/null +++ b/components/oscd-switch/stories/oscd-switch.mdx @@ -0,0 +1,28 @@ +import { Meta, Story, Canvas, Source, ArgTypes, Title, Description, Subtitle } from '@storybook/blocks'; + +import { Markdown } from '@storybook/addon-docs'; + +import * as OscdSwitchStories from './oscd-switch.stories'; + +import Readme from '../README.md?raw'; +import Changelog from '../CHANGELOG.md?raw'; + + +Oscd-Switch + + +Properties + + + + + + +# Example + + +{Readme} + +# Changelog + +{Changelog} diff --git a/components/oscd-switch/stories/oscd-switch.stories.ts b/components/oscd-switch/stories/oscd-switch.stories.ts new file mode 100644 index 0000000..022aae5 --- /dev/null +++ b/components/oscd-switch/stories/oscd-switch.stories.ts @@ -0,0 +1,84 @@ +import type { Meta, StoryObj } from '@storybook/web-components'; +import { action } from '@storybook/addon-actions'; + +import { html } from 'lit'; + +import { createBadge } from '@oscd/utils'; + +import pckgJson from '../package.json'; + +import '../src/OscdSwitch'; + +const meta: Meta = { + title: 'Forms/OscdSwitch', + component: 'oscd-switch', + parameters: { + status: { + type: createBadge(pckgJson), + }, + }, + args: { + onChange: action('Changed'), + }, +}; + +export default meta; + +type Story = StoryObj; + +/** + * Basic + */ +export const Basic: Story = { + render: ({ selected, disabled, name, value, onChange }) => + html``, + args: { + onChange: action('Changed'), + }, + parameters: { + docs: { + description: { + story: 'Basic OSCD Switch', + }, + }, + }, +}; + +/** Selected */ +export const Selected: Story = { + render: ({ selected, onChange }) => + html``, + args: { + selected: true, + onChange: action('Changed'), + }, + parameters: { + docs: { + description: { + story: 'Default Selected OSCD Switch', + }, + }, + }, +}; +/** Disabled */ +export const Disabled: Story = { + render: ({ disabled, onChange }) => + html``, + args: { + disabled: true, + onChange: action('Changed'), + }, + parameters: { + docs: { + description: { + story: 'Default disabled OSCD Switch', + }, + }, + }, +}; diff --git a/components/oscd-switch/test/oscd-switch.spec.ts b/components/oscd-switch/test/oscd-switch.spec.ts new file mode 100644 index 0000000..0cf095b --- /dev/null +++ b/components/oscd-switch/test/oscd-switch.spec.ts @@ -0,0 +1,24 @@ +import { Switch } from '@material/mwc-switch'; +import { expect, fixture, html } from '@open-wc/testing'; + +import '../src/OscdSwitch.js'; +import type { OscdSwitch } from '../src/OscdSwitch.js'; + +describe('Basic component oscd-switch', () => { + let element: OscdSwitch; + + beforeEach(async () => { + element = await fixture(html``); + await element.updateComplete; + }); + + it('Should be selected', async () => { + element.selected = true; + + await element.updateComplete; + + const el: Switch = element.shadowRoot!.querySelector('mwc-switch')!; + + expect(el.selected).to.be.true; + }); +}); diff --git a/components/oscd-switch/test/oscd-switch.test.ts b/components/oscd-switch/test/oscd-switch.test.ts new file mode 100644 index 0000000..11af110 --- /dev/null +++ b/components/oscd-switch/test/oscd-switch.test.ts @@ -0,0 +1,42 @@ +import { fixture, html } from '@open-wc/testing'; + +import { visualDiff } from '@web/test-runner-visual-regression'; + +import '../src/OscdSwitch.js'; +import { OscdSwitch } from '../src/OscdSwitch.js'; + +const factor = process.env.CI ? 2 : 1; + +function timeout(ms: number) { + return new Promise((res) => { + setTimeout(res, ms * factor); + }); +} + +mocha.timeout(2000 * factor); + +describe('oscd-switch', () => { + let element: OscdSwitch; + + beforeEach(async () => { + element = await fixture(html``); + document.body.prepend(element); + }); + + it('Should look like screenshot', async () => { + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-switch'); + }); + + describe('selected', () => { + it('Should look like screenshot', async () => { + element.selected = true; + await element.updateComplete; + await timeout(500); + await visualDiff(element, 'oscd-switch-selected'); + }); + }); + + afterEach(() => element.remove()); +}); diff --git a/components/oscd-switch/tsconfig.json b/components/oscd-switch/tsconfig.json new file mode 100644 index 0000000..05497c6 --- /dev/null +++ b/components/oscd-switch/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "lib": ["es2018", "dom"], + "strict": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "declaration": true, + "importHelpers": true, + "outDir": "./dist", + "sourceMap": true, + "inlineSources": true, + "rootDir": "./src", + "tsBuildInfoFile": ".tsbuildinfo", + "incremental": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": ["./src/**/*.ts"], + "exclude": ["**/*.stories.ts", "**/*.stories.js"], +} diff --git a/components/oscd-switch/tsconfig.storybook.json b/components/oscd-switch/tsconfig.storybook.json new file mode 100644 index 0000000..da8737c --- /dev/null +++ b/components/oscd-switch/tsconfig.storybook.json @@ -0,0 +1,17 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "composite": true, + "incremental": false, + "rootDir": "./" + }, + "exclude": ["./test/**/*.ts"], + "include": [ + "./stories/**/*.stories.ts", + "./src/**/*.ts", + "./src/*.ts", + "./.storybook/*.js", + "./.storybook/*.ts" + ] +} diff --git a/components/oscd-switch/tsconfig.test.json b/components/oscd-switch/tsconfig.test.json new file mode 100644 index 0000000..29717e3 --- /dev/null +++ b/components/oscd-switch/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "rootDir": "./" + }, + "extends": "./tsconfig", + "include": ["*/*.ts"] +} diff --git a/components/oscd-switch/typedoc.json b/components/oscd-switch/typedoc.json new file mode 100644 index 0000000..2c43ad9 --- /dev/null +++ b/components/oscd-switch/typedoc.json @@ -0,0 +1,4 @@ +{ + "entryPoints": ["src/index.ts"], + "out": "docs" +} diff --git a/components/oscd-switch/web-test-runner.config.js b/components/oscd-switch/web-test-runner.config.js new file mode 100644 index 0000000..28aec99 --- /dev/null +++ b/components/oscd-switch/web-test-runner.config.js @@ -0,0 +1,182 @@ +import { visualRegressionPlugin } from '@web/test-runner-visual-regression/plugin'; +import { playwrightLauncher } from '@web/test-runner-playwright'; + +import pixelmatch from 'pixelmatch'; +import { PNG } from 'pngjs'; + +const fuzzy = ['win32', 'darwin'].includes(process.platform); // allow for 1% difference on non-linux OSs +const local = !process.env.CI; + +console.assert(local, 'Running in CI!'); +console.assert(!fuzzy, 'Running on OS with 1% test pixel diff threshold!'); + +const thresholdPercentage = fuzzy && local ? 0 : 0; + +const filteredLogs = [ + 'Running in dev mode', + 'Lit is in dev mode', + 'mwc-list-item scheduled an update', +]; + +const browsers = [ + playwrightLauncher({ + product: 'chromium', + }), + playwrightLauncher({ product: 'firefox' }), + playwrightLauncher({ product: 'webkit' }), +]; + +function defaultGetImageDiff({ baselineImage, image, options }) { + let error = ''; + let basePng = PNG.sync.read(baselineImage); + let png = PNG.sync.read(image); + let { width, height } = png; + + if (basePng.width !== png.width || basePng.height !== png.height) { + error = + `Screenshot is not the same width and height as the baseline. ` + + `Baseline: { width: ${basePng.width}, height: ${basePng.height} }` + + `Screenshot: { width: ${png.width}, height: ${png.height} }`; + width = Math.max(basePng.width, png.width); + height = Math.max(basePng.height, png.height); + let oldPng = basePng; + basePng = new PNG({ width, height }); + oldPng.data.copy(basePng.data, 0, 0, oldPng.data.length); + oldPng = png; + png = new PNG({ width, height }); + oldPng.data.copy(png.data, 0, 0, oldPng.data.length); + } + + const diff = new PNG({ width, height }); + + const numDiffPixels = pixelmatch( + basePng.data, + png.data, + diff.data, + width, + height, + options + ); + const diffPercentage = (numDiffPixels / (width * height)) * 100; + + return { + error, + diffImage: PNG.sync.write(diff), + diffPercentage, + }; +} + +export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({ + plugins: [ + visualRegressionPlugin({ + update: process.argv.includes('--update-visual-baseline'), + getImageDiff: (options) => { + const result = defaultGetImageDiff(options); + if (result.diffPercentage < thresholdPercentage) + result.diffPercentage = 0; + return result; + }, + }), + ], + + files: 'dist/**/*.spec.js', + + groups: [ + { + name: 'visual', + files: 'dist/**/*.test.js', + testRunnerHtml: (testFramework) => ` + + + + + + + + + + + + + +`, + }, + ], + + /** Resolve bare module imports */ + nodeResolve: { + exportConditions: ['browser', 'development'], + }, + + /** Filter out lit dev mode logs */ + filterBrowserLogs(log) { + for (const arg of log.args) { + if ( + typeof arg === 'string' && + filteredLogs.some((l) => arg.includes(l)) + ) { + return false; + } + } + return true; + }, + + /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */ + // esbuildTarget: 'auto', + + /** Amount of browsers to run concurrently */ + concurrentBrowsers: 3, + + /** Amount of test files per browser to test concurrently */ + concurrency: 2, + + /** Browsers to run tests on */ + browsers, + + // See documentation for all available options +}); diff --git a/lib/core/src/index.ts b/lib/core/src/index.ts index f1a025e..833672e 100644 --- a/lib/core/src/index.ts +++ b/lib/core/src/index.ts @@ -1,2 +1,3 @@ export * from './oscd-component'; export * from './oscd-component.styles'; +export * from './redispatch-event'; diff --git a/lib/core/src/oscd-component.styles.ts b/lib/core/src/oscd-component.styles.ts index 28a8b3a..7b1646c 100644 --- a/lib/core/src/oscd-component.styles.ts +++ b/lib/core/src/oscd-component.styles.ts @@ -1,6 +1,6 @@ -import { css } from 'lit-element'; +import { css, CSSResult } from 'lit-element'; -export const styles = css` +export const styles: CSSResult = css` :host { box-sizing: border-box; } diff --git a/lib/core/src/redispatch-event.ts b/lib/core/src/redispatch-event.ts new file mode 100644 index 0000000..0b169e7 --- /dev/null +++ b/lib/core/src/redispatch-event.ts @@ -0,0 +1,17 @@ +import { OscdComponent } from './oscd-component'; + +export function redispatchEvent(element: OscdComponent, event: Event) { + element.requestUpdate(); + // For bubbling events in SSR light DOM (or composed), stop their propagation // and dispatch the copy. + const copy = Reflect.construct(event.constructor, [event.type, event]); + if (event.bubbles && (!element.shadowRoot || event.composed)) { + event.stopPropagation(); + copy.stopPropagation(); + } + + const dispatched = element.dispatchEvent(copy); + if (!dispatched) { + event.preventDefault(); + } + return dispatched; +} diff --git a/lib/core/tsconfig.json b/lib/core/tsconfig.json index ced6010..14fe222 100644 --- a/lib/core/tsconfig.json +++ b/lib/core/tsconfig.json @@ -11,7 +11,7 @@ "experimentalDecorators": true, "declaration": true, "importHelpers": true, - "outDir": "dist", + "outDir": "./dist", "sourceMap": true, "inlineSources": true, "rootDir": "./src", diff --git a/lib/form/.tsbuildinfo b/lib/form/.tsbuildinfo new file mode 100644 index 0000000..4f8f532 --- /dev/null +++ b/lib/form/.tsbuildinfo @@ -0,0 +1 @@ +{"program":{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../node_modules/tslib/tslib.d.ts","../../node_modules/@lit/reactive-element/css-tag.d.ts","../../node_modules/@lit/reactive-element/reactive-controller.d.ts","../../node_modules/@lit/reactive-element/reactive-element.d.ts","../../node_modules/@types/trusted-types/lib/index.d.ts","../../node_modules/@types/trusted-types/index.d.ts","../../node_modules/lit-html/directive.d.ts","../../node_modules/lit-html/lit-html.d.ts","../../node_modules/lit-element/lit-element.d.ts","../../node_modules/@lit/reactive-element/decorators/base.d.ts","../../node_modules/@lit/reactive-element/decorators/custom-element.d.ts","../../node_modules/@lit/reactive-element/decorators/property.d.ts","../../node_modules/@lit/reactive-element/decorators/state.d.ts","../../node_modules/@lit/reactive-element/decorators/event-options.d.ts","../../node_modules/@lit/reactive-element/decorators/query.d.ts","../../node_modules/@lit/reactive-element/decorators/query-all.d.ts","../../node_modules/@lit/reactive-element/decorators/query-async.d.ts","../../node_modules/@lit/reactive-element/decorators/query-assigned-nodes.d.ts","../../node_modules/@lit/reactive-element/decorators/query-assigned-elements.d.ts","../../node_modules/lit-element/decorators.d.ts","../../node_modules/lit-element/index.d.ts","../core/dist/oscd-component.d.ts","../core/dist/oscd-component.styles.d.ts","../core/dist/redispatch-event.d.ts","../core/dist/index.d.ts","../../node_modules/@material/base/foundation.d.ts","../../node_modules/lit-html/is-server.d.ts","../../node_modules/lit/index.d.ts","../../node_modules/@material/mwc-base/utils.d.ts","../../node_modules/@material/base/types.d.ts","../../node_modules/@material/mwc-base/base-element.d.ts","../../node_modules/@material/ripple/types.d.ts","../../node_modules/@material/ripple/adapter.d.ts","../../node_modules/@material/ripple/foundation.d.ts","../../node_modules/@material/mwc-ripple/mwc-ripple-base.d.ts","../../node_modules/@material/mwc-ripple/mwc-ripple.d.ts","../../node_modules/@material/mwc-base/form-element.d.ts","../../node_modules/@material/mwc-ripple/ripple-handlers.d.ts","../../node_modules/@material/switch/constants.d.ts","../../node_modules/@material/switch/adapter.d.ts","../../node_modules/@material/base/observer.d.ts","../../node_modules/@material/base/observer-foundation.d.ts","../../node_modules/@material/switch/foundation.d.ts","../../node_modules/lit-html/directives/class-map.d.ts","../../node_modules/lit/directives/class-map.d.ts","../../node_modules/@material/mwc-switch/mwc-switch-base.d.ts","../../node_modules/@material/mwc-switch/mwc-switch.d.ts","../../components/oscd-switch/dist/oscd-switch.d.ts","../../components/oscd-switch/dist/oscdswitch.d.ts","./src/oscd-form-component.ts","./src/oscd-form-component.styles.ts","./src/index.ts","../../node_modules/@types/node/assert.d.ts","../../node_modules/@types/node/assert/strict.d.ts","../../node_modules/@types/node/globals.d.ts","../../node_modules/@types/node/async_hooks.d.ts","../../node_modules/@types/node/buffer.d.ts","../../node_modules/@types/node/child_process.d.ts","../../node_modules/@types/node/cluster.d.ts","../../node_modules/@types/node/console.d.ts","../../node_modules/@types/node/constants.d.ts","../../node_modules/@types/node/crypto.d.ts","../../node_modules/@types/node/dgram.d.ts","../../node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/@types/node/dns.d.ts","../../node_modules/@types/node/dns/promises.d.ts","../../node_modules/@types/node/domain.d.ts","../../node_modules/@types/node/events.d.ts","../../node_modules/@types/node/fs.d.ts","../../node_modules/@types/node/fs/promises.d.ts","../../node_modules/@types/node/http.d.ts","../../node_modules/@types/node/http2.d.ts","../../node_modules/@types/node/https.d.ts","../../node_modules/@types/node/inspector.d.ts","../../node_modules/@types/node/module.d.ts","../../node_modules/@types/node/net.d.ts","../../node_modules/@types/node/os.d.ts","../../node_modules/@types/node/path.d.ts","../../node_modules/@types/node/perf_hooks.d.ts","../../node_modules/@types/node/process.d.ts","../../node_modules/@types/node/punycode.d.ts","../../node_modules/@types/node/querystring.d.ts","../../node_modules/@types/node/readline.d.ts","../../node_modules/@types/node/repl.d.ts","../../node_modules/@types/node/stream.d.ts","../../node_modules/@types/node/stream/promises.d.ts","../../node_modules/@types/node/stream/consumers.d.ts","../../node_modules/@types/node/stream/web.d.ts","../../node_modules/@types/node/string_decoder.d.ts","../../node_modules/@types/node/test.d.ts","../../node_modules/@types/node/timers.d.ts","../../node_modules/@types/node/timers/promises.d.ts","../../node_modules/@types/node/tls.d.ts","../../node_modules/@types/node/trace_events.d.ts","../../node_modules/@types/node/tty.d.ts","../../node_modules/@types/node/url.d.ts","../../node_modules/@types/node/util.d.ts","../../node_modules/@types/node/v8.d.ts","../../node_modules/@types/node/vm.d.ts","../../node_modules/@types/node/wasi.d.ts","../../node_modules/@types/node/worker_threads.d.ts","../../node_modules/@types/node/zlib.d.ts","../../node_modules/@types/node/globals.global.d.ts","../../node_modules/@types/node/index.d.ts","../../node_modules/@types/accepts/index.d.ts","../../node_modules/@types/estree/index.d.ts","../../node_modules/@types/acorn/index.d.ts","../../node_modules/@types/aria-query/index.d.ts","../../node_modules/@types/babel__code-frame/index.d.ts","../../node_modules/@babel/types/lib/index.d.ts","../../node_modules/@types/babel__generator/index.d.ts","../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../node_modules/@types/babel__template/index.d.ts","../../node_modules/@types/babel__traverse/index.d.ts","../../node_modules/@types/babel__core/index.d.ts","../../node_modules/@types/connect/index.d.ts","../../node_modules/@types/body-parser/index.d.ts","../../node_modules/@types/browserslist-useragent/index.d.ts","../../node_modules/keyv/src/index.d.ts","../../node_modules/@types/http-cache-semantics/index.d.ts","../../node_modules/@types/responselike/index.d.ts","../../node_modules/@types/cacheable-request/index.d.ts","../../node_modules/@types/caniuse-api/index.d.ts","../../node_modules/@types/chai/index.d.ts","../../node_modules/@types/chai-dom/index.d.ts","../../node_modules/@types/clean-css/node_modules/source-map/source-map.d.ts","../../node_modules/@types/clean-css/index.d.ts","../../node_modules/@types/qs/index.d.ts","../../node_modules/@types/co-body/index.d.ts","../../node_modules/@types/command-line-args/index.d.ts","../../node_modules/@types/command-line-usage/index.d.ts","../../node_modules/@types/content-disposition/index.d.ts","../../node_modules/@types/convert-source-map/index.d.ts","../../node_modules/@types/keygrip/index.d.ts","../../node_modules/@types/mime/index.d.ts","../../node_modules/@types/send/index.d.ts","../../node_modules/@types/range-parser/index.d.ts","../../node_modules/@types/express-serve-static-core/index.d.ts","../../node_modules/@types/http-errors/index.d.ts","../../node_modules/@types/serve-static/index.d.ts","../../node_modules/@types/express/index.d.ts","../../node_modules/@types/cookies/index.d.ts","../../node_modules/@types/cross-spawn/index.d.ts","../../node_modules/@types/debounce/index.d.ts","../../node_modules/@types/ms/index.d.ts","../../node_modules/@types/debug/index.d.ts","../../node_modules/@types/detect-port/index.d.ts","../../node_modules/@types/doctrine/index.d.ts","../../node_modules/@types/ejs/index.d.ts","../../node_modules/@types/emscripten/index.d.ts","../../node_modules/@types/eslint/helpers.d.ts","../../node_modules/@types/json-schema/index.d.ts","../../node_modules/@types/eslint/index.d.ts","../../node_modules/@types/eslint-scope/index.d.ts","../../node_modules/@types/estree-jsx/index.d.ts","../../node_modules/@types/etag/index.d.ts","../../node_modules/@types/find-cache-dir/index.d.ts","../../node_modules/@types/graceful-fs/index.d.ts","../../node_modules/@types/unist/index.d.ts","../../node_modules/@types/hast/index.d.ts","../../node_modules/@types/uglify-js/node_modules/source-map/source-map.d.ts","../../node_modules/@types/uglify-js/index.d.ts","../../node_modules/@types/relateurl/index.d.ts","../../node_modules/@types/html-minifier/index.d.ts","../../node_modules/@types/http-assert/index.d.ts","../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../node_modules/@types/istanbul-lib-report/index.d.ts","../../node_modules/@types/istanbul-reports/index.d.ts","../../node_modules/chalk/index.d.ts","../../node_modules/@types/jest/node_modules/@sinclair/typebox/typebox.d.ts","../../node_modules/@types/jest/node_modules/@jest/schemas/build/index.d.ts","../../node_modules/@types/jest/node_modules/pretty-format/build/index.d.ts","../../node_modules/@types/jest/node_modules/jest-diff/build/index.d.ts","../../node_modules/@types/jest/node_modules/jest-matcher-utils/build/index.d.ts","../../node_modules/@types/jest/index.d.ts","../../node_modules/@types/json5/index.d.ts","../../node_modules/@types/keyv/index.d.ts","../../node_modules/@types/koa-compose/index.d.ts","../../node_modules/@types/koa/index.d.ts","../../node_modules/@types/koa-compress/index.d.ts","../../node_modules/@types/koa-etag/index.d.ts","../../node_modules/@types/koa-send/index.d.ts","../../node_modules/@types/koa-static/index.d.ts","../../node_modules/@types/koa__cors/index.d.ts","../../node_modules/@types/lodash/common/common.d.ts","../../node_modules/@types/lodash/common/array.d.ts","../../node_modules/@types/lodash/common/collection.d.ts","../../node_modules/@types/lodash/common/date.d.ts","../../node_modules/@types/lodash/common/function.d.ts","../../node_modules/@types/lodash/common/lang.d.ts","../../node_modules/@types/lodash/common/math.d.ts","../../node_modules/@types/lodash/common/number.d.ts","../../node_modules/@types/lodash/common/object.d.ts","../../node_modules/@types/lodash/common/seq.d.ts","../../node_modules/@types/lodash/common/string.d.ts","../../node_modules/@types/lodash/common/util.d.ts","../../node_modules/@types/lodash/index.d.ts","../../node_modules/@types/lru-cache/index.d.ts","../../node_modules/@types/mdast/index.d.ts","../../node_modules/@types/mdx/types.d.ts","../../node_modules/@types/mdx/index.d.ts","../../node_modules/@types/mime-types/index.d.ts","../../node_modules/@types/minimatch/index.d.ts","../../node_modules/@types/minimist/index.d.ts","../../node_modules/@types/mkdirp/index.d.ts","../../node_modules/@types/mocha/index.d.ts","../../node_modules/form-data/index.d.ts","../../node_modules/@types/node-fetch/externals.d.ts","../../node_modules/@types/node-fetch/index.d.ts","../../node_modules/@types/normalize-package-data/index.d.ts","../../node_modules/@types/parse-json/index.d.ts","../../node_modules/@types/parse5/lib/tree-adapters/default.d.ts","../../node_modules/@types/parse5/index.d.ts","../../node_modules/@types/path-is-inside/index.d.ts","../../node_modules/@types/pixelmatch/index.d.ts","../../node_modules/@types/pngjs/index.d.ts","../../node_modules/@types/pretty-hrtime/index.d.ts","../../node_modules/@types/prismjs/index.d.ts","../../node_modules/@types/prop-types/index.d.ts","../../node_modules/@types/react/global.d.ts","../../node_modules/csstype/index.d.ts","../../node_modules/@types/scheduler/tracing.d.ts","../../node_modules/@types/react/index.d.ts","../../node_modules/@types/react-transition-group/transition.d.ts","../../node_modules/@types/react-transition-group/csstransition.d.ts","../../node_modules/@types/react-transition-group/transitiongroup.d.ts","../../node_modules/@types/react-transition-group/switchtransition.d.ts","../../node_modules/@types/react-transition-group/config.d.ts","../../node_modules/@types/react-transition-group/index.d.ts","../../node_modules/@types/resolve/index.d.ts","../../node_modules/@types/scheduler/index.d.ts","../../node_modules/@types/semver/classes/semver.d.ts","../../node_modules/@types/semver/functions/parse.d.ts","../../node_modules/@types/semver/functions/valid.d.ts","../../node_modules/@types/semver/functions/clean.d.ts","../../node_modules/@types/semver/functions/inc.d.ts","../../node_modules/@types/semver/functions/diff.d.ts","../../node_modules/@types/semver/functions/major.d.ts","../../node_modules/@types/semver/functions/minor.d.ts","../../node_modules/@types/semver/functions/patch.d.ts","../../node_modules/@types/semver/functions/prerelease.d.ts","../../node_modules/@types/semver/functions/compare.d.ts","../../node_modules/@types/semver/functions/rcompare.d.ts","../../node_modules/@types/semver/functions/compare-loose.d.ts","../../node_modules/@types/semver/functions/compare-build.d.ts","../../node_modules/@types/semver/functions/sort.d.ts","../../node_modules/@types/semver/functions/rsort.d.ts","../../node_modules/@types/semver/functions/gt.d.ts","../../node_modules/@types/semver/functions/lt.d.ts","../../node_modules/@types/semver/functions/eq.d.ts","../../node_modules/@types/semver/functions/neq.d.ts","../../node_modules/@types/semver/functions/gte.d.ts","../../node_modules/@types/semver/functions/lte.d.ts","../../node_modules/@types/semver/functions/cmp.d.ts","../../node_modules/@types/semver/functions/coerce.d.ts","../../node_modules/@types/semver/classes/comparator.d.ts","../../node_modules/@types/semver/classes/range.d.ts","../../node_modules/@types/semver/functions/satisfies.d.ts","../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../node_modules/@types/semver/ranges/min-version.d.ts","../../node_modules/@types/semver/ranges/valid.d.ts","../../node_modules/@types/semver/ranges/outside.d.ts","../../node_modules/@types/semver/ranges/gtr.d.ts","../../node_modules/@types/semver/ranges/ltr.d.ts","../../node_modules/@types/semver/ranges/intersects.d.ts","../../node_modules/@types/semver/ranges/simplify.d.ts","../../node_modules/@types/semver/ranges/subset.d.ts","../../node_modules/@types/semver/internals/identifiers.d.ts","../../node_modules/@types/semver/index.d.ts","../../node_modules/@types/sinonjs__fake-timers/index.d.ts","../../node_modules/@types/sinon/index.d.ts","../../node_modules/@types/sinon-chai/index.d.ts","../../node_modules/@types/stack-utils/index.d.ts","../../node_modules/@types/testing-library__jest-dom/matchers.d.ts","../../node_modules/@types/testing-library__jest-dom/index.d.ts","../../node_modules/@types/whatwg-url/index.d.ts","../../node_modules/@types/ws/index.d.ts","../../node_modules/@types/yargs-parser/index.d.ts","../../node_modules/@types/yargs/index.d.ts","../../node_modules/@types/yauzl/index.d.ts"],"fileInfos":[{"version":"f59215c5f1d886b05395ee7aca73e0ac69ddfad2843aa88530e797879d511bad","affectsGlobalScope":true},"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","dc48272d7c333ccf58034c0026162576b7d50ea0e69c3b9292f803fc20720fd5","27147504487dc1159369da4f4da8a26406364624fa9bc3db632f7d94a5bae2c3","5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4",{"version":"3dda5344576193a4ae48b8d03f105c86f20b2f2aff0a1d1fd7935f5d68649654","affectsGlobalScope":true},{"version":"9d9885c728913c1d16e0d2831b40341d6ad9a0ceecaabc55209b306ad9c736a5","affectsGlobalScope":true},{"version":"17bea081b9c0541f39dd1ae9bc8c78bdd561879a682e60e2f25f688c0ecab248","affectsGlobalScope":true},{"version":"4443e68b35f3332f753eacc66a04ac1d2053b8b035a0e0ac1d455392b5e243b3","affectsGlobalScope":true},{"version":"ab22100fdd0d24cfc2cc59d0a00fc8cf449830d9c4030dc54390a46bd562e929","affectsGlobalScope":true},{"version":"f7bd636ae3a4623c503359ada74510c4005df5b36de7f23e1db8a5c543fd176b","affectsGlobalScope":true},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true},{"version":"0c20f4d2358eb679e4ae8a4432bdd96c857a2960fd6800b21ec4008ec59d60ea","affectsGlobalScope":true},{"version":"36ae84ccc0633f7c0787bc6108386c8b773e95d3b052d9464a99cd9b8795fbec","affectsGlobalScope":true},{"version":"82d0d8e269b9eeac02c3bd1c9e884e85d483fcb2cd168bccd6bc54df663da031","affectsGlobalScope":true},{"version":"b8deab98702588840be73d67f02412a2d45a417a3c097b2e96f7f3a42ac483d1","affectsGlobalScope":true},{"version":"4738f2420687fd85629c9efb470793bb753709c2379e5f85bc1815d875ceadcd","affectsGlobalScope":true},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true},{"version":"376d554d042fb409cb55b5cbaf0b2b4b7e669619493c5d18d5fa8bd67273f82a","affectsGlobalScope":true},{"version":"9fc46429fbe091ac5ad2608c657201eb68b6f1b8341bd6d670047d32ed0a88fa","affectsGlobalScope":true},{"version":"61c37c1de663cf4171e1192466e52c7a382afa58da01b1dc75058f032ddf0839","affectsGlobalScope":true},{"version":"c4138a3dd7cd6cf1f363ca0f905554e8d81b45844feea17786cdf1626cb8ea06","affectsGlobalScope":true},{"version":"6ff3e2452b055d8f0ec026511c6582b55d935675af67cdb67dd1dc671e8065df","affectsGlobalScope":true},{"version":"03de17b810f426a2f47396b0b99b53a82c1b60e9cba7a7edda47f9bb077882f4","affectsGlobalScope":true},{"version":"8184c6ddf48f0c98429326b428478ecc6143c27f79b79e85740f17e6feb090f1","affectsGlobalScope":true},{"version":"261c4d2cf86ac5a89ad3fb3fafed74cbb6f2f7c1d139b0540933df567d64a6ca","affectsGlobalScope":true},{"version":"6af1425e9973f4924fca986636ac19a0cf9909a7e0d9d3009c349e6244e957b6","affectsGlobalScope":true},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true},{"version":"15a630d6817718a2ddd7088c4f83e4673fde19fa992d2eae2cf51132a302a5d3","affectsGlobalScope":true},{"version":"f06948deb2a51aae25184561c9640fb66afeddb34531a9212d011792b1d19e0a","affectsGlobalScope":true},{"version":"01e0ee7e1f661acedb08b51f8a9b7d7f959e9cdb6441360f06522cc3aea1bf2e","affectsGlobalScope":true},{"version":"ac17a97f816d53d9dd79b0d235e1c0ed54a8cc6a0677e9a3d61efb480b2a3e4e","affectsGlobalScope":true},{"version":"bf14a426dbbf1022d11bd08d6b8e709a2e9d246f0c6c1032f3b2edb9a902adbe","affectsGlobalScope":true},{"version":"ec0104fee478075cb5171e5f4e3f23add8e02d845ae0165bfa3f1099241fa2aa","affectsGlobalScope":true},{"version":"2b72d528b2e2fe3c57889ca7baef5e13a56c957b946906d03767c642f386bbc3","affectsGlobalScope":true},{"version":"9cc66b0513ad41cb5f5372cca86ef83a0d37d1c1017580b7dace3ea5661836df","affectsGlobalScope":true},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true},{"version":"307c8b7ebbd7f23a92b73a4c6c0a697beca05b06b036c23a34553e5fe65e4fdc","affectsGlobalScope":true},{"version":"189c0703923150aa30673fa3de411346d727cc44a11c75d05d7cf9ef095daa22","affectsGlobalScope":true},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true},"7a1971efcba559ea9002ada4c4e3c925004fb67a755300d53b5edf9399354900","e59262ddaae67dec2d226f8a5d05cf6c4dc353c0d9b1e4980a61d7fcf9a2b051","5e30131b6a5587fe666926ad1d9807e733c0a597ed12d682669fcaa331aea576","470b8c2386c916bad4aa0d05e89b271a47dbe1250cb25dc0f93102b457228dde","2fcd2d22b1f30555e785105597cd8f57ed50300e213c4f1bbca6ae149f782c38",{"version":"3c150a2e1758724811db3bdc5c773421819343b1627714e09f29b1f40a5dfb26","affectsGlobalScope":true},"7000ec8572390d035ba5ef993953957150d0c38ffb31b56653c97dd78cb6e1aa","056892cca68dca10a914f1580ba0e5710d26794e8707225dca9b5717ed702f1e","4ddf3962990379d1ea59b369a5516c7533b7944010d6998e0e9b1ab35d5af1f0","2a8f0a19a927e83421597c056c90695557142f54ca96358f01eb1f2a5eb228be","d08415b3d6d7fd153ba6e7bf7707ffc57f3c6ad85730ea63544756610b4350c6","411f23da7a63c3d3fd4860c41a458e8df239776fd5d9cd36dd3ad6be92afccbd","6ada3e065916c0ef2dbc9bc0f9b5d59afb25d9176f81fa2c8993a536924140c6","356cc1b058e05e07d2acd73bfa87f83a6f4a343450ee375dad232ff4a55d41d8","df286e6b181ed08766bc19cf1a2fddc50bc5d540f233bc1ce4430a3c1c8c8379","f436800c0af503703110c93144fcc7392524636fb4216296411243b29fe0162d","0d5002560b45ce4fd6c4124632f61789e584be0634602486a2ce59541311d153","bbe13c947d7d6c3426e0e5815e2b3464fa03d34a4bf47298c43b9237cf59555b","9f7d0ee33b9f8fa4dc2e9628e0cdf8683104d01de9d3d24f62cd5da014a5bec4","23056c9b3dac109ce202026810f8b09b6978883d8fd038d17dbe89e7b41f84b5","f5edc7f57484ff1569209c7933f3576e7d791743d178756177a05cef9c4625c2","1ace5b091a00007142bda2b23980d7be85d279033be3d9b6b3d872984de82973","e3960955d262c89644fb68262ad0a2370c1a600d4e0dec6ee7efbb26dbe5fd82","d375e53e9239ed52ae39c2f560f3569c4087efb987e7e8e6be5fb45fb0a25e65","77fe45d1242d668a5fd63c99d3ffb81a4382179dede8534534f114f592810087","a0667520a6521c12128fc28cbd5b2af58eef11c5b2a7441e0f0d47f50bf6c8e3","1bcd560deed90a43c51b08aa18f7f55229f2e30974ab5ed1b7bb5721be379013","dc08fe04e50bc24d1baded4f33e942222bbdd5d77d6341a93cfe6e4e4586a3be","0dcf4c2bf1bb547e2ae5b8dce4656a56fbd15e3401ff5236ea0b93b6c60f9249","820c26194ad4089bc503b02bbedbd86a865e9c8a05c58ef88c8d19d9c019712a","790b453e1b76814112c3870d6e12f5db992d3194fdb3529445317dd75cb538be","d375de88ab19f6c105a65fc89eca1ae782362c5c395283b0c85ef39c7b835dfe","aeda2fffbc651fe1fa60b913d45f291f5544c4840206cb3b1badc16d9f01a0f0","7b3c1d688dcb8645b5a6c37bce5b047da92b4c298ed8709e03e987e0efb035b1","29c64e1acb5b73f08a60e71154c65c8a34f885f1f2cc55ffa06dfd244c058883",{"version":"7d176f155e5f6fc9756ddcc1a6d3eb2673030a066e2b7846dfc81b5271f3e269","affectsGlobalScope":true},{"version":"301b1a33102a2bf93e997834ff2f76a6766014572bfc3210310549225fbb023b","affectsGlobalScope":true},"aea18a267a0770c365cc390ad0a0b9725ed7a4540e9a96319b0f5094ee0ca124","05c8e6f2612075f7f856112b9c0ffa769e94913c535dfa22dd3713e64725923e","beb04cbdfe6da759ffb80e0149cfd2e08ec2a8f40994dea8026939297fe4d8cc","833bfbe9c3e25383e954bc3ca1fe399edf73edadaeb77e82fec890ee46a1e386","f66ffd63874851758c52e03d81766bd9461e5a73bf0a73371e3b7d94477aa329","3ff42786bfcced3f3b38b152d106c768ce97525e5ac79f45cb05328c8ff1028c","8a9b7a437bea4cc34e5e103e01573ab3afc4564a22c838942b6dcca0f68020e8","8bb8931e629d9adfac6fe0c067de1a3c2f82b47262f83fa76eb0772ef13808e8","df5befd9df9ff28d164a890c5baa7d142730f01a4c8b9e39199df603117ab69a",{"version":"fc0396f2aecb500d184800e7a5e76bb50d7e35b399758a51f12396e3e33b527a","affectsGlobalScope":true},"23e07ea5a770bfe07a275a409302610cde64a570ed55c536c2b6cae697f7f01f","e5920c994d4738d2026b96f0dffe7a720a80674d03ef7d352f8480cfe0225ff1",{"version":"47d98bdf3410cdbe8fa98f823d09144bdd7074db7c529fa9ad1b1cc15f41c4fd","signature":"847ab707b78056d3ae03237ef31676ac8258322f2b93a848b80455e69ed885ff"},{"version":"cbabab6652fc18c1b5467b3e67b9aff42e21d661e38e10fd1f8543e0fd6f29cf","signature":"e3960955d262c89644fb68262ad0a2370c1a600d4e0dec6ee7efbb26dbe5fd82"},{"version":"fabe2d01709fdc49fe146464cb3f0acdba7d67c96fb793803dd2bc0cb3637815","signature":"b80b8a77182803ad90a65b0cd4a84887bd9711e1febd2b3a3834c32397563889"},"9122ed7070e054b73ebab37c2373a196def2d90e7d1a9a7fcd9d46b0e51fae78","a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a",{"version":"77f0b5c6a193a699c9f7d7fb0578e64e562d271afa740783665d2a827104a873","affectsGlobalScope":true},"21a167fec8f933752fb8157f06d28fab6817af3ad9b0bdb1908a10762391eab9",{"version":"002d6d5f044365b3fbfba0ba9be3bb57cac09b81547c8df4b0795755d2081d90","affectsGlobalScope":true},"0c0cee62cb619aed81133b904f644515ba3064487002a7da83fd8aa07b1b4abd","5a94487653355b56018122d92392beb2e5f4a6c63ba5cef83bbe1c99775ef713",{"version":"d5135ad93b33adcce80b18f8065087934cdc1730d63db58562edcf017e1aad9b","affectsGlobalScope":true},"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","34ec1daf3566f26c43dbab380af0de1aac29166e57e4f9ef379a2f154e0cb290","bb9c4ffa5e6290c6980b63c815cdd1625876dadb2efaf77edbe82984be93e55e","75ecef44f126e2ae018b4abbd85b6e8a2e2ba1638ebec56cc64274643ce3567b","f30bb836526d930a74593f7b0f5c1c46d10856415a8f69e5e2fc3db80371e362","14b5aa23c5d0ae1907bc696ac7b6915d88f7d85799cc0dc2dcf98fbce2c5a67c","5c439dafdc09abe4d6c260a96b822fa0ba5be7203c71a63ab1f1423cd9e838ea",{"version":"bae4ea23beb8397755b935cb84d3cdc6cdb0b1b4a329b90de9fc6c8774d71994","affectsGlobalScope":true},"cec36af22f514322f870e81d30675c78df82ae8bf4863f5fd4e4424c040c678d","c57870f6664fd657ec2cf096bbb043b9556b0228ec0c12dd54193361ca563ea1","aeee0090b38de0dd47ca9a79ad5c2d156e3e09d92306719b0b45a3e96098e564","acfbb5aaef964e1d441f961a1846197f03241dba3c63b1e4d1903684888ef465","09416dd69576b03a3f485adf329a02f043e4a481e060ef5b208194e488d31fd9","8acf99b1c8682276a63ea5bb68433782715892726b97e4604a415e4e56bce41c",{"version":"e8b18c6385ff784228a6f369694fcf1a6b475355ba89090a88de13587a9391d5","affectsGlobalScope":true},"9499ba4dcd1ee0596d8c98d01341bc874840c5291156513bda667fecad54d5be","a907bf91df26df2400858ef75f749498fb5cf00062bf90a737ac3949cc07978d","cb92bc2e42b261e4299025756f1beb826b3d9666a3f0d46f8a7254ca512f57e4","4275d5f964e7fc7afc18538e26b3748c207dd772998346d17f409749aa1f3a63",{"version":"59104b2e80c588b813d03d3a45f57117ca4601ae3fc216c5ffbcbafc4effc1c5","affectsGlobalScope":true},"5153a2fd150e46ce57bb3f8db1318d33f6ad3261ed70ceeff92281c0608c74a3","d1a78a3c5708807e8de3e399f91df4797c62e44b02195eefc2209b2e713e54ee","8c4c1a64db28930732033c31418f817dcb9d09d706766707ae6d38f23faf0c53","25846d43937c672bab7e8195f3d881f93495df712ee901860effc109918938cc","556bf5c36deb62cffa1bf697c1789fe008ec82db0273025001db66732714e9d9","1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff",{"version":"806ef4cac3b3d9fa4a48d849c8e084d7c72fcd7b16d76e06049a9ed742ff79c0","affectsGlobalScope":true},"44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","23b89798789dffbd437c0c423f5d02d11f9736aea73d6abf16db4f812ff36eda","653968fc1b35c5eb3d273d36fac1c1dc66f9537edf28f33485b8776bd956e23d",{"version":"970a90f76d4d219ad60819d61f5994514087ba94c985647a3474a5a3d12714ed","affectsGlobalScope":true},"664d8f2d59164f2e08c543981453893bc7e003e4dfd29651ce09db13e9457980","a381f079c4804442f179d742fdb2e495fe28d67a47cac673485f75ae2e77aeca","3c13ef48634e7b5012fcf7e8fce7496352c2d779a7201389ca96a2a81ee4314d","5d0a25ec910fa36595f85a67ac992d7a53dd4064a1ba6aea1c9f14ab73a023f2",{"version":"bfe39beb986d2a2e512c091cbe924f1c415bc65de54de0e2f6a0dc6f84c183d9","affectsGlobalScope":true},"2d526e6f21d8cc66ac11ada32874e95ae88d870c6c9d3d9d4e03b1d1f9ad7b8e","06d7c42d256f0ce6afe1b2b6cfbc97ab391f29dadb00dd0ae8e8f23f5bc916c3","ec4bd1b200670fb567920db572d6701ed42a9641d09c4ff6869768c8f81b404c","e59a892d87e72733e2a9ca21611b9beb52977be2696c7ba4b216cbbb9a48f5aa","d2ec52f565f0570e90b659811347bd689f8c6039b11eaaccd0f243759d46da6e","8a300fa9b698845a1f9c41ecbe2c5966634582a8e2020d51abcace9b55aa959e",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"9c3df5971dc261aa29f25fdfcf7e8cfa248ff95a3d09ae4a6b81b1b09473f80f","6738101ae8e56cd3879ab3f99630ada7d78097fc9fd334df7e766216778ca219","bee89e1eb6425eb49894f3f25e4562dc2564e84e5aa7610b7e13d8ecddf8f5db","3777eb752cef9aa8dd35bb997145413310008aa54ec44766de81a7ad891526cd","21522c0f405e58c8dd89cd97eb3d1aa9865ba017fde102d01f86ab50b44e5610","b95f751a58d283cb5e32f2655361f6e2a27f0368f69edc463a3472aae21d1303","1905eab6570faf3010802b4c00196eda6285b028f0b41bdfa7f7a29427502b62","cc957354aa3c94c9961ebf46282cfde1e81d107fc5785a61f62c67f1dd3ac2eb","a2e86df4db576d80704e25293cec6f20fc6101a11f4747440e2eef58fb3c860c","93de1c6dab503f053efe8d304cb522bb3a89feab8c98f307a674a4fae04773e9","6704f0b54df85640baaeebd86c9d4a1dbb661d5a4d57a75bc84162f562f6531d","9d255af1b09c6697089d3c9bf438292a298d8b7a95c68793c9aae80afc9e5ca7","6d829824ead8999f87b6df21200df3c6150391b894b4e80662caa462bd48d073","afc559c1b93df37c25aef6b3dfa2d64325b0e112e887ee18bf7e6f4ec383fc90","9eb49645576740f4fb4cca25cadbc0d7e61a218c215e8578dd899b01d5db89d4","42baf4ca38c38deaf411ea73f37bc39ff56c6e5c761a968b64ac1b25c92b5cd8","cab425b5559edac18327eb2c3c0f47e7e9f71b667290b7689faafd28aac69eae","3cfb0cb51cc2c2e1b313d7c4df04dbf7e5bda0a133c6b309bf6af77cf614b971","f992cd6cc0bcbaa4e6c810468c90f2d8595f8c6c3cf050c806397d3de8585562","d59cea1102bba38053ca19260e37bda2715df10d147c40db92035c0420489358",{"version":"c3bc5d095c3c22fd20b5a6550b9c9a6d56c3ffbb87ef057ccce7764b6bed4428","affectsGlobalScope":true},{"version":"4cdd1b520504f86d680470dc91baa79d625fa20e1f9dc1f99eba242eae9fada4","affectsGlobalScope":true},"2887592574fcdfd087647c539dcb0fbe5af2521270dad4a37f9d17c16190d579","2d1323c55cb7a4f2cf73f03797b26645a7657dd0217beb41b0079b0490ec3370","ba601641fac98c229ccd4a303f747de376d761babb33229bb7153bed9356c9cc","495da6628b9474e31d0636d66c54448bb8d84dbce902e8f70539ef6a525a2d7b","629766229f541d92210f30a92b6038568ec165fab14b7ee53bdf13667da37ca3","29193c018378ca9c8033eaa974c02c1f503e8fcd8a2bf406057c53f7d3fa17a8","204dbe6c72467fb14bbe8f06510b11fb541b6ce29580c6e10ebd3bdb2eb0c1f9","13d94ac3ee5780f99988ae4cce0efd139598ca159553bc0100811eba74fc2351","ce013414484233b24f42c0fcfca48a60bb66ab4e13c82953662305e8f1ee4925","84e3bbd6f80983d468260fdbfeeb431cc81f7ea98d284d836e4d168e36875e86","aad5ffa61406b8e19524738fcf0e6fda8b3485bba98626268fdf252d1b2b630a","16d51f964ec125ad2024cf03f0af444b3bc3ec3614d9345cc54d09bab45c9a4c",{"version":"352fc8497a30bc806d7defa0043d85802e5f35a7688731ee9a21456f5cb32a94","affectsGlobalScope":true},"f463d61cf39c3a6a5f96cdf7adfdb72a0b1d663f7b5d5b6dd042adba835430c2","f7a9cb83c8fbc081a8b605880d191e0d0527cde2c1b2b2b623beca8f0203a2cd","43cdd474c5aa3340da4816bb8f1ae7f3b1bcf9e70d997afc36a0f2c432378c84","eb96a2321f717bccc3e49e104e299152984b927ea4546b559ae631c06565819c","5e3a55837aa1f42af2d2334c9b750f59f5f50a2205471875f5dd6aadc3e49ddb","68c559681a043ca6d622debcce75c4d82446fec08e06bf1066f71d6c325f224e","6a9c5127096b35264eb7cd21b2417bfc1d42cceca9ba4ce2bb0c3410b7816042","93b7325b49dfbf613d940ed0e471216657b2d77459dac34f1b5b1678f08f884c","4b4c4c74c41b52cada66c85638633d2b0fe7c43445daf877cfddb310d3f5e998","febcc45f9517827496659c229a21b058831eef4cf9b71b77fd9a364ae12c3b9e","de8877483ce1e67bced3ad1f4ac877fd5066f8465ab6a9e8b716662d727553e5",{"version":"3f547f989aa9c12dc888ae25c4afc076eb442f681ba17f50924642fe29c01da0","affectsGlobalScope":true},{"version":"64d4b35c5456adf258d2cf56c341e203a073253f229ef3208fc0d5020253b241","affectsGlobalScope":true},"dca41e86e89dfb2e85e6935260250f02eb6683b86c2fa16bec729ddd1bcd9b4b","facc7572c3330810ff4728113a324790679d4ed41fbd9e371028f08f1cad29f3","e050a0afcdbb269720a900c85076d18e0c1ab73e580202a2bf6964978181222a","99373707de2fdfdce847a4d138c36cf137b243ad206cf82d32e0653e2f0dcb4e","7e510fb0ca02da05976eb0dbfeb42bdb0dc64b78acbb3b5ecf77ddd57ce08cda","19f1159e1fa24300e2eaf72cb53f0815f5879ec53cad3c606802f0c55f0917e9","bf88ef4208a770ca39a844b182b3695df536326ea566893fdc5b8418702a331e","cddf5c26907c0b8378bc05543161c11637b830da9fadf59e02a11e675d11e180","3d2cd8f3047fff04a71e7037a6a4cb9f4accb28dbd8c0d83164d414811025af0","2887592574fcdfd087647c539dcb0fbe5af2521270dad4a37f9d17c16190d579","9dcd1a6ae84def6ce3e80b27a367912e5b8e9f15c039143820ab76f7ceb8f3ab","0def05b4e59413659e7f1cad8b0e32858d7d272a4701457e7fea95618f6ef7db","3f6bff86e78e065dad71ca8e395824703f56977f7309139127e58718d7915410","e98185f4249720ace1921d59c1ff4612fa5c633a183fc9bf28e2e7b8e3c7fd51","8b06ac3faeacb8484d84ddb44571d8f410697f98d7bfa86c0fda60373a9f5215","7eb06594824ada538b1d8b48c3925a83e7db792f47a081a62cf3e5c4e23cf0ee","f5638f7c2f12a9a1a57b5c41b3c1ea7db3876c003bab68e6a57afd6bcc169af0","0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","3054ef91b855e005b9c4681399e9d64d2a7b07a22d539314d794f09e53b876a7","ffcc5500e77223169833fc6eb59b3a507944a1f89574e0a1276b0ea7fc22c4a4","22f13de9e2fe5f0f4724797abd3d34a1cdd6e47ef81fc4933fea3b8bf4ad524b","e3ba509d3dce019b3190ceb2f3fc88e2610ab717122dabd91a9efaa37804040d","cda0cb09b995489b7f4c57f168cd31b83dcbaa7aad49612734fb3c9c73f6e4f2",{"version":"2abad7477cf6761b55c18bea4c21b5a5dcf319748c13696df3736b35f8ac149e","affectsGlobalScope":true},"96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","fec943fdb3275eb6e006b35e04a8e2e99e9adf3f4b969ddf15315ac7575a93e4","5006668996956580886022c05108e32c742823e1b5652aff7914917233731518","d8ff10c7c1f825a87b2b2a1cef499c7079d2d1b880323ce9edbb81282aceee8d","d1494c6dbbe5fca590ca73ccd21d013e6617e9ea19773c9ca7c0f3214df86628","97395602cea957af0cf517d84b651a07e010192db667ba379d36bec40cdbef52","f88d8a4ba9ad0270309cf46121d3dc9fb055bea08ac3e699d2b4673b1e6a25ea","b6360d5b5a52a1d6fc6b9838135f766b638e7c7a03b227974344200be603c150","0f141d684b22a8ff995c19137ec8a90b297461154ad4212b4f45b7e8b10357b7","675e702f2032766a91eeadee64f51014c64688525da99dccd8178f0c599f13a8","458111fc89d11d2151277c822dfdc1a28fa5b6b2493cf942e37d4cd0a6ee5f22","19c816167e076e7c24f074389c6cf3ed87bdbb917d1ea439ca281f9d26db2439","187119ff4f9553676a884e296089e131e8cc01691c546273b1d0089c3533ce42","febf0b2de54781102b00f61653b21377390a048fbf5262718c91860d11ff34a6","98f9d826db9cd99d27a01a59ee5f22863df00ccf1aaf43e1d7db80ebf716f7c3","0aaef8cded245bf5036a7a40b65622dd6c4da71f7a35343112edbe112b348a1e","00baffbe8a2f2e4875367479489b5d43b5fc1429ecb4a4cc98cfc3009095f52a","dcd91d3b697cb650b95db5471189b99815af5db2a1cd28760f91e0b12ede8ed5","3c92b6dfd43cc1c2485d9eba5ff0b74a19bb8725b692773ef1d66dac48cda4bd","b03afe4bec768ae333582915146f48b161e567a81b5ebc31c4d78af089770ac9","df996e25faa505f85aeb294d15ebe61b399cf1d1e49959cdfaf2cc0815c203f9","30abc554c7ad13063a02ddd06757929b34357aea1f6fcf4ca39114cb0fc19384","6d727c1f6a7122c04e4f7c164c5e6f460c21ada618856894cdaa6ac25e95f38c","5774751340e987a6a9e4a5dcc03ff68a6515adc2b91423e1af2f660fc8f30e81","62ba3a124b971abfc9cc9d42bfde270d7b1d74c4de8c2b74dbf0557552afc132","6571f33cd3c23ee70fb48839c9a7486381cd3f439e17d97d10fc908e41468052","c757372a092924f5c16eaf11a1475b80b95bb4dae49fe3242d2ad908f97d5abe","8841e2aa774b89bd23302dede20663306dc1b9902431ac64b24be8b8d0e3f649","209e814e8e71aec74f69686a9506dd7610b97ab59dcee9446266446f72a76d05","875d567ecf2f865a1b19d30f2acf3203817e19fd95f7675351d046914ee39ac8",{"version":"5f186a758a616c107c70e8918db4630d063bd782f22e6e0b17573b125765b40b","affectsGlobalScope":true},"736097ddbb2903bef918bb3b5811ef1c9c5656f2a73bd39b22a91b9cc2525e50","626bccaba2f61f03abe558a39501631565389a748bc47dd52b305c80176333c1","3663d1b50f356656a314e5df169bb51cb9d5fd75905fa703f75db6bb32030568","6fa0008bf91a4cc9c8963bace4bba0bd6865cbfa29c3e3ccc461155660fb113a","2b8264b2fefd7367e0f20e2c04eed5d3038831fe00f5efbc110ff0131aab899b","fc37aca06f6b8b296c42412a2e75ab53d30cd1fa8a340a3bb328a723fd678377","5f2c582b9ef260cb9559a64221b38606378c1fabe17694592cdfe5975a6d7efa","a0b27b55228349ea85cecd9479ace1009697af44b66527f30526a1539d4e78ea","f30350dd37c3f3c11f47adb7ce4e7a4928f578f4ae8a3197e0c8a0811da46b92","0b6a0b628776a3e3a4aeeba090438a26e7ffa15373ce658452c78c1f2254665d","c0a3ea3aee13c4946a6aefce3a6ab9292a40a29f6622cde0fda0b1067a1a1f5f","6484309596f594ae824513336bd2a2e04a1902b06bb149fa904f5cae5fbe5c50","6a386ff939f180ae8ef064699d8b7b6e62bc2731a62d7fbf5e02589383838dea",{"version":"549df62b64a71004aee17685b445a8289013daf96246ce4d9b087d13d7a27a61","affectsGlobalScope":true},"4c68749a564a6facdf675416d75789ee5a557afda8960e0803cf6711fa569288","f5a8b384f182b3851cec3596ccc96cb7464f8d3469f48c74bf2befb782a19de5",{"version":"571f3b382f9360208e56233415e07530ff2627c4e6f1d7c37076816f07d01286","affectsGlobalScope":true},"332c7ccf95426d3156ebedb7295979ef2435bd1c1a940024a4d068da3418718f","e03334588c63840b7054accd0b90f29c5890db6a6555ac0869a78a23297f1396","c3052485f32a96bfde75a2976c1238995522584ba464f04ff16a8a40af5e50d1","c220410b8e956fa157ce4e5e6ac871f0f433aa120c334d906ff1f5e2c7369e95","960a68ced7820108787135bdae5265d2cc4b511b7dcfd5b8f213432a8483daf1","5e8db4872785292074b394d821ae2fc10e4f8edc597776368aebbe8aefb24422","2880728492d6a6baa55411d14cc42fa55714a24b1d1d27ff9a8a610abd47c761","7ccce4adb23a87a044c257685613126b47160f6975b224cea5f6af36c7f37514","2b93035328f7778d200252681c1d86285d501ed424825a18f81e4c3028aa51d9","2ac9c8332c5f8510b8bdd571f8271e0f39b0577714d5e95c1e79a12b2616f069","42c21aa963e7b86fa00801d96e88b36803188018d5ad91db2a9101bccd40b3ff","d31eb848cdebb4c55b4893b335a7c0cca95ad66dee13cbb7d0893810c0a9c301","b9f96255e1048ed2ea33ec553122716f0e57fc1c3ad778e9aa15f5b46547bd23","7a9e0a564fee396cacf706523b5aeed96e04c6b871a8bebefad78499fbffc5bc","906c751ef5822ec0dadcea2f0e9db64a33fb4ee926cc9f7efa38afe5d5371b2a","5387c049e9702f2d2d7ece1a74836a14b47fbebe9bbeb19f94c580a37c855351","c68391fb9efad5d99ff332c65b1606248c4e4a9f1dd9a087204242b56c7126d6","e9cf02252d3a0ced987d24845dcb1f11c1be5541f17e5daa44c6de2d18138d0c","e8b02b879754d85f48489294f99147aeccc352c760d95a6fe2b6e49cd400b2fe","9f6908ab3d8a86c68b86e38578afc7095114e66b2fc36a2a96e9252aac3998e0","0eedb2344442b143ddcd788f87096961cd8572b64f10b4afc3356aa0460171c6","71405cc70f183d029cc5018375f6c35117ffdaf11846c35ebf85ee3956b1b2a6","c68baff4d8ba346130e9753cefe2e487a16731bf17e05fdacc81e8c9a26aae9d","2cd15528d8bb5d0453aa339b4b52e0696e8b07e790c153831c642c3dea5ac8af","479d622e66283ffa9883fbc33e441f7fc928b2277ff30aacbec7b7761b4e9579","ade307876dc5ca267ca308d09e737b611505e015c535863f22420a11fffc1c54","f8cdefa3e0dee639eccbe9794b46f90291e5fd3989fcba60d2f08fde56179fb9","86c5a62f99aac7053976e317dbe9acb2eaf903aaf3d2e5bb1cafe5c2df7b37a8","2b300954ce01a8343866f737656e13243e86e5baef51bd0631b21dcef1f6e954","a2d409a9ffd872d6b9d78ead00baa116bbc73cfa959fce9a2f29d3227876b2a1","b288936f560cd71f4a6002953290de9ff8dfbfbf37f5a9391be5c83322324898","61178a781ef82e0ff54f9430397e71e8f365fc1e3725e0e5346f2de7b0d50dfa","6a6ccb37feb3aad32d9be026a3337db195979cd5727a616fc0f557e974101a54","c649ea79205c029a02272ef55b7ab14ada0903db26144d2205021f24727ac7a3","38e2b02897c6357bbcff729ef84c736727b45cc152abe95a7567caccdfad2a1d","d6610ea7e0b1a7686dba062a1e5544dd7d34140f4545305b7c6afaebfb348341","3dee35db743bdba2c8d19aece7ac049bde6fa587e195d86547c882784e6ba34c","b15e55c5fa977c2f25ca0b1db52cfa2d1fd4bf0baf90a8b90d4a7678ca462ff1","f41d30972724714763a2698ae949fbc463afb203b5fa7c4ad7e4de0871129a17","843dd7b6a7c6269fd43827303f5cbe65c1fecabc30b4670a50d5a15d57daeeb9","f06d8b8567ee9fd799bf7f806efe93b67683ef24f4dea5b23ef12edff4434d9d","6017384f697ff38bc3ef6a546df5b230c3c31329db84cbfe686c83bec011e2b2","e1a5b30d9248549ca0c0bb1d653bafae20c64c4aa5928cc4cd3017b55c2177b0","a593632d5878f17295bd53e1c77f27bf4c15212822f764a2bfc1702f4b413fa0","a868a534ba1c2ca9060b8a13b0ffbbbf78b4be7b0ff80d8c75b02773f7192c29","da7545aba8f54a50fde23e2ede00158dc8112560d934cee58098dfb03aae9b9d","34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","a1a261624efb3a00ff346b13580f70f3463b8cdcc58b60f5793ff11785d52cab","f83b320cceccfc48457a818d18fc9a006ab18d0bdd727aa2c2e73dc1b4a45e98","5445b5383991fff958fe3a7b0a9c1b9c672a613bc30fda97aee6eddb4053c0d3",{"version":"4f0ad52a7fbd6bfba88ec22ec719b6956a0fc647030462f9db490e74236d116f","affectsGlobalScope":true},"b0d10e46cfe3f6c476b69af02eaa38e4ccc7430221ce3109ae84bb9fb8282298","3f36c0c7508302f3dca3dc5ab0a66d822b2222f70c24bb1796ddb5c9d1168a05",{"version":"b23d5b89c465872587e130f427b39458b8e3ad16385f98446e9e86151ba6eb15","affectsGlobalScope":true},"0f048a7e91a4c764f08be48e156c9d274a038cb454d312427214ab4d34a9a5ab","bc81aff061c53a7140270555f4b22da4ecfe8601e8027cf5aa175fbdc7927c31","70e9a18da08294f75bf23e46c7d69e67634c0765d355887b9b41f0d959e1426e","e9eb1b173aa166892f3eddab182e49cfe59aa2e14d33aedb6b49d175ed6a3750","65dfa4bc49ccd1355789abb6ae215b302a5b050fdee9651124fe7e826f33113c"],"root":[[94,96]],"options":{"allowSyntheticDefaultImports":true,"declaration":true,"esModuleInterop":false,"experimentalDecorators":true,"importHelpers":true,"inlineSources":true,"module":99,"noEmitOnError":true,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":5,"tsBuildInfoFile":"./.tsbuildinfo"},"fileIdsList":[[65,69,91,141],[92,141],[66,67,68,141],[65,141],[66,141],[45,69,94,95,141],[45,65,69,141],[45,65,69,93,141],[141,154],[141],[48,141],[54,141],[48,54,141],[48,54,62,141],[46,47,141],[70,85,141],[74,141],[70,72,73,74,141],[73,75,141],[72,73,75,77,78,141],[72,79,141],[73,141],[72,80,81,82,84,87,89,141],[72,90,141],[74,76,141],[70,77,141],[83,141],[84,86,141],[115,141,148],[141,150,199],[141,154,155,156,157,158],[141,154,156],[115,141,148,160],[112,115,140,141,148,163,164,165],[141,168],[115,117,141,148,170],[115,141,148,172],[115,141,148,160,178,185],[102,141,148],[141,189],[141,150,197,199],[141,150,195,196,199],[141,148],[112,115,141,148,172,180,181],[141,161,172,182,184],[113,141,148],[141,203],[141,171,206,207],[141,210],[141,211],[141,216,218],[141,214],[141,216],[141,213,217],[141,215],[112,141,148],[141,223],[141,146,148,223],[141,200,223],[113,141,223],[141,223,226],[112,115,116,120,126,140,141,148,149,176,178,183,186,209,222],[141,229,231,232,233,234,235,236,237,238,239,240,241],[141,229,230,232,233,234,235,236,237,238,239,240,241],[141,230,231,232,233,234,235,236,237,238,239,240,241],[141,229,230,231,233,234,235,236,237,238,239,240,241],[141,229,230,231,232,234,235,236,237,238,239,240,241],[141,229,230,231,232,233,235,236,237,238,239,240,241],[141,229,230,231,232,233,234,236,237,238,239,240,241],[141,229,230,231,232,233,234,235,237,238,239,240,241],[141,229,230,231,232,233,234,235,236,238,239,240,241],[141,229,230,231,232,233,234,235,236,237,239,240,241],[141,229,230,231,232,233,234,235,236,237,238,240,241],[141,229,230,231,232,233,234,235,236,237,238,239,241],[141,229,230,231,232,233,234,235,236,237,238,239,240],[141,244,245],[115,140,141,148,251,252],[97,141],[100,141],[101,106,141],[102,112,113,120,129,140,141],[102,103,112,120,141],[104,141],[105,106,113,121,141],[106,129,137,141],[107,109,112,120,141],[108,141],[109,110,141],[111,112,141],[112,141],[112,113,114,129,140,141],[112,113,114,129,132,141],[141,145],[115,120,129,140,141],[112,113,115,116,120,129,137,140,141],[115,117,129,137,140,141],[97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147],[112,118,141],[119,140,141],[109,112,120,129,141],[121,141],[122,141],[100,123,141],[124,139,141,145],[125,141],[126,141],[112,127,141],[127,128,141,143],[112,129,130,131,132,141],[129,131,141],[129,130,141],[132,141],[133,141],[112,135,136,141],[135,136,141],[106,120,129,137,141],[138,141],[120,139,141],[101,115,126,140,141],[106,141],[129,141,142],[141,143],[141,144],[101,106,112,114,123,129,140,141,143,145],[129,141,146],[141,256],[141,257],[129,141,146,148],[141,267,268],[141,268,269,270,271,272],[141,267],[141,263,264,265,266],[115,129,141,148],[141,276,315],[141,276,300,315],[141,315],[141,276],[141,276,301,315],[141,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314],[141,301,315],[113,129,141,148,179],[115,141,148,179,183],[141,168,317],[141,316],[141,219,320],[49,141],[141,170],[112,115,117,120,129,137,140,141,146,148],[141,324],[112,129,141,148],[54,55,56,57,58,59,60,61,62,63,141],[48,52,53,64,141],[48,52,141],[52,141],[51,52,141],[50,51,141],[88,141],[48,52,53,71,141],[69,94,95],[65],[65,69,93]],"referencedMap":[[92,1],[93,2],[69,3],[66,4],[67,4],[68,5],[96,6],[95,7],[94,8],[156,9],[154,10],[46,10],[54,11],[55,12],[58,13],[56,13],[60,13],[63,14],[62,10],[61,13],[59,13],[57,12],[47,10],[48,15],[70,10],[86,16],[85,17],[74,10],[75,18],[81,19],[73,10],[79,20],[80,21],[82,22],[90,23],[91,24],[77,25],[78,26],[76,10],[84,27],[83,10],[87,28],[149,29],[151,30],[152,10],[153,10],[159,31],[155,9],[157,32],[158,9],[161,33],[162,10],[166,34],[167,10],[169,35],[168,10],[171,36],[170,10],[173,37],[174,10],[175,10],[160,29],[176,10],[177,10],[186,38],[187,39],[188,10],[190,40],[191,10],[192,10],[193,10],[194,10],[198,41],[195,10],[197,42],[199,30],[150,10],[200,43],[182,44],[185,45],[201,10],[202,46],[204,47],[208,48],[209,10],[164,10],[183,10],[210,10],[211,49],[212,50],[219,51],[215,52],[214,10],[217,53],[218,54],[216,55],[196,10],[220,10],[178,10],[221,56],[222,57],[224,58],[225,59],[226,60],[227,61],[223,62],[228,57],[230,63],[231,64],[229,65],[232,66],[233,67],[234,68],[235,69],[236,70],[237,71],[238,72],[239,73],[240,74],[241,75],[242,10],[243,47],[245,76],[244,10],[246,10],[179,10],[247,10],[248,10],[249,46],[250,10],[189,10],[252,10],[253,77],[97,78],[98,78],[100,79],[101,80],[102,81],[103,82],[104,83],[105,84],[106,85],[107,86],[108,87],[109,88],[110,88],[111,89],[112,90],[113,91],[114,92],[99,93],[147,10],[115,94],[116,95],[117,96],[148,97],[118,98],[119,99],[120,100],[121,101],[122,102],[123,103],[124,104],[125,105],[126,106],[127,107],[128,108],[129,109],[131,110],[130,111],[132,112],[133,113],[134,10],[135,114],[136,115],[137,116],[138,117],[139,118],[140,119],[141,120],[142,121],[143,122],[144,123],[145,124],[146,125],[254,10],[255,10],[257,126],[256,127],[258,10],[259,43],[260,128],[261,10],[262,10],[263,10],[172,10],[181,10],[272,10],[269,129],[273,130],[271,131],[268,131],[270,129],[264,10],[267,132],[207,10],[274,43],[165,133],[275,10],[266,10],[300,134],[301,135],[276,136],[279,136],[298,134],[299,134],[289,134],[288,137],[286,134],[281,134],[294,134],[292,134],[296,134],[280,134],[293,134],[297,134],[282,134],[283,134],[295,134],[277,134],[284,134],[285,134],[287,134],[291,134],[302,138],[290,134],[278,134],[315,139],[314,10],[309,138],[311,140],[310,138],[303,138],[304,138],[306,138],[308,138],[312,140],[313,140],[305,140],[307,140],[180,141],[184,142],[318,143],[317,144],[316,10],[319,10],[321,145],[320,10],[50,146],[49,10],[206,147],[205,10],[203,10],[322,43],[323,148],[324,10],[325,149],[326,150],[213,10],[265,10],[251,133],[163,90],[64,151],[65,152],[53,153],[51,154],[88,155],[71,10],[52,156],[89,157],[72,158],[45,10],[43,10],[44,10],[8,10],[10,10],[9,10],[2,10],[11,10],[12,10],[13,10],[14,10],[15,10],[16,10],[17,10],[18,10],[3,10],[4,10],[22,10],[19,10],[20,10],[21,10],[23,10],[24,10],[25,10],[5,10],[26,10],[27,10],[28,10],[29,10],[6,10],[33,10],[30,10],[31,10],[32,10],[34,10],[7,10],[35,10],[40,10],[41,10],[36,10],[37,10],[38,10],[39,10],[1,10],[42,10]],"exportedModulesMap":[[92,1],[93,2],[69,3],[66,4],[67,4],[68,5],[96,159],[95,160],[94,161],[156,9],[154,10],[46,10],[54,11],[55,12],[58,13],[56,13],[60,13],[63,14],[62,10],[61,13],[59,13],[57,12],[47,10],[48,15],[70,10],[86,16],[85,17],[74,10],[75,18],[81,19],[73,10],[79,20],[80,21],[82,22],[90,23],[91,24],[77,25],[78,26],[76,10],[84,27],[83,10],[87,28],[149,29],[151,30],[152,10],[153,10],[159,31],[155,9],[157,32],[158,9],[161,33],[162,10],[166,34],[167,10],[169,35],[168,10],[171,36],[170,10],[173,37],[174,10],[175,10],[160,29],[176,10],[177,10],[186,38],[187,39],[188,10],[190,40],[191,10],[192,10],[193,10],[194,10],[198,41],[195,10],[197,42],[199,30],[150,10],[200,43],[182,44],[185,45],[201,10],[202,46],[204,47],[208,48],[209,10],[164,10],[183,10],[210,10],[211,49],[212,50],[219,51],[215,52],[214,10],[217,53],[218,54],[216,55],[196,10],[220,10],[178,10],[221,56],[222,57],[224,58],[225,59],[226,60],[227,61],[223,62],[228,57],[230,63],[231,64],[229,65],[232,66],[233,67],[234,68],[235,69],[236,70],[237,71],[238,72],[239,73],[240,74],[241,75],[242,10],[243,47],[245,76],[244,10],[246,10],[179,10],[247,10],[248,10],[249,46],[250,10],[189,10],[252,10],[253,77],[97,78],[98,78],[100,79],[101,80],[102,81],[103,82],[104,83],[105,84],[106,85],[107,86],[108,87],[109,88],[110,88],[111,89],[112,90],[113,91],[114,92],[99,93],[147,10],[115,94],[116,95],[117,96],[148,97],[118,98],[119,99],[120,100],[121,101],[122,102],[123,103],[124,104],[125,105],[126,106],[127,107],[128,108],[129,109],[131,110],[130,111],[132,112],[133,113],[134,10],[135,114],[136,115],[137,116],[138,117],[139,118],[140,119],[141,120],[142,121],[143,122],[144,123],[145,124],[146,125],[254,10],[255,10],[257,126],[256,127],[258,10],[259,43],[260,128],[261,10],[262,10],[263,10],[172,10],[181,10],[272,10],[269,129],[273,130],[271,131],[268,131],[270,129],[264,10],[267,132],[207,10],[274,43],[165,133],[275,10],[266,10],[300,134],[301,135],[276,136],[279,136],[298,134],[299,134],[289,134],[288,137],[286,134],[281,134],[294,134],[292,134],[296,134],[280,134],[293,134],[297,134],[282,134],[283,134],[295,134],[277,134],[284,134],[285,134],[287,134],[291,134],[302,138],[290,134],[278,134],[315,139],[314,10],[309,138],[311,140],[310,138],[303,138],[304,138],[306,138],[308,138],[312,140],[313,140],[305,140],[307,140],[180,141],[184,142],[318,143],[317,144],[316,10],[319,10],[321,145],[320,10],[50,146],[49,10],[206,147],[205,10],[203,10],[322,43],[323,148],[324,10],[325,149],[326,150],[213,10],[265,10],[251,133],[163,90],[64,151],[65,152],[53,153],[51,154],[88,155],[71,10],[52,156],[89,157],[72,158],[45,10],[43,10],[44,10],[8,10],[10,10],[9,10],[2,10],[11,10],[12,10],[13,10],[14,10],[15,10],[16,10],[17,10],[18,10],[3,10],[4,10],[22,10],[19,10],[20,10],[21,10],[23,10],[24,10],[25,10],[5,10],[26,10],[27,10],[28,10],[29,10],[6,10],[33,10],[30,10],[31,10],[32,10],[34,10],[7,10],[35,10],[40,10],[41,10],[36,10],[37,10],[38,10],[39,10],[1,10],[42,10]],"semanticDiagnosticsPerFile":[92,93,69,66,67,68,96,95,94,156,154,46,54,55,58,56,60,63,62,61,59,57,47,48,70,86,85,74,75,81,73,79,80,82,90,91,77,78,76,84,83,87,149,151,152,153,159,155,157,158,161,162,166,167,169,168,171,170,173,174,175,160,176,177,186,187,188,190,191,192,193,194,198,195,197,199,150,200,182,185,201,202,204,208,209,164,183,210,211,212,219,215,214,217,218,216,196,220,178,221,222,224,225,226,227,223,228,230,231,229,232,233,234,235,236,237,238,239,240,241,242,243,245,244,246,179,247,248,249,250,189,252,253,97,98,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,99,147,115,116,117,148,118,119,120,121,122,123,124,125,126,127,128,129,131,130,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,254,255,257,256,258,259,260,261,262,263,172,181,272,269,273,271,268,270,264,267,207,274,165,275,266,300,301,276,279,298,299,289,288,286,281,294,292,296,280,293,297,282,283,295,277,284,285,287,291,302,290,278,315,314,309,311,310,303,304,306,308,312,313,305,307,180,184,318,317,316,319,321,320,50,49,206,205,203,322,323,324,325,326,213,265,251,163,64,65,53,51,88,71,52,89,72,45,43,44,8,10,9,2,11,12,13,14,15,16,17,18,3,4,22,19,20,21,23,24,25,5,26,27,28,29,6,33,30,31,32,34,7,35,40,41,36,37,38,39,1,42]},"version":"5.1.6"} \ No newline at end of file diff --git a/lib/form/package.json b/lib/form/package.json new file mode 100644 index 0000000..2f2e928 --- /dev/null +++ b/lib/form/package.json @@ -0,0 +1,24 @@ +{ + "name": "@openscd/form", + "version": "0.0.1", + "description": "Core for Oscd Form Components", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "module": "./dist/index.js", + "private": true, + "scripts": { + "build": "tsc", + "clean": "rimraf .tsbuildinfo dist" + }, + "dependencies": { + "lit": "^2.7.6", + "@openscd/core": "*", + "@openscd/oscd-switch": "*" + }, + "author": "OpenSCD", + "license": "ISC", + "devDependencies": { + "tslib": "^2.6.0", + "typescript": "^5.1.6" + } +} \ No newline at end of file diff --git a/lib/form/project.json b/lib/form/project.json new file mode 100644 index 0000000..eec5674 --- /dev/null +++ b/lib/form/project.json @@ -0,0 +1,9 @@ +{ + "name": "form", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "lib/form/src", + "targets": { + } + } + \ No newline at end of file diff --git a/lib/form/src/index.ts b/lib/form/src/index.ts new file mode 100644 index 0000000..5b24e58 --- /dev/null +++ b/lib/form/src/index.ts @@ -0,0 +1,4 @@ +export * from './oscd-form-component'; +export * from './oscd-form-component.styles'; + +export { redispatchEvent } from '@openscd/core'; diff --git a/lib/form/src/oscd-form-component.styles.ts b/lib/form/src/oscd-form-component.styles.ts new file mode 100644 index 0000000..5685ed2 --- /dev/null +++ b/lib/form/src/oscd-form-component.styles.ts @@ -0,0 +1,21 @@ +import { css, CSSResult } from 'lit-element'; + +import { styles as coreStyles } from '@openscd/core'; + +export const styles: CSSResult = css` + ${coreStyles} + + .container { + display: flex; + flex-direction: row; + } + + .container > div { + flex: auto; + } + .container.container--switch { + align-items: center; + margin-left: 16px; + height: 56px; + } +`; diff --git a/lib/form/src/oscd-form-component.ts b/lib/form/src/oscd-form-component.ts new file mode 100644 index 0000000..01ff97e --- /dev/null +++ b/lib/form/src/oscd-form-component.ts @@ -0,0 +1,50 @@ +import { TemplateResult, html, property, state, query } from 'lit-element'; + +import { OscdComponent } from '@openscd/core'; + +import '@openscd/oscd-switch'; +import type { OscdSwitch, OscdSwitchChangeEvent } from '@openscd/oscd-switch'; + +export abstract class OscdFormComponent extends OscdComponent { + /** + * Form Control can be nullable. If true, use the [[maybeValue]] + * @default false + */ + @property({ + type: Boolean, + }) + nullable = false; + + /** + * @internal + */ + protected isNull = false; + + protected abstract get null(): boolean; + protected abstract set null(value: boolean); + + @state() + protected _disabledSwitch: boolean = false; + + /** + * @internal + */ + @query('oscd-switch') + protected nullSwitch?: OscdSwitch; + + /** + * @internal + */ + protected renderSwitch(): TemplateResult { + if (this.nullable) { + return html` { + this.null = !evt.detail.selected; + }} + >`; + } + return html``; + } +} diff --git a/lib/form/tsconfig.json b/lib/form/tsconfig.json new file mode 100644 index 0000000..14fe222 --- /dev/null +++ b/lib/form/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "lib": ["es2018", "dom"], + "strict": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "declaration": true, + "importHelpers": true, + "outDir": "./dist", + "sourceMap": true, + "inlineSources": true, + "rootDir": "./src", + "tsBuildInfoFile": ".tsbuildinfo", + "incremental": true, + "skipLibCheck": true + }, + "include": [ + "./src/**/*.ts" + ] + } + \ No newline at end of file