├── .eslintignore ├── demo ├── src │ ├── index.ts │ ├── vite-env.d.ts │ ├── App.css │ ├── index.css │ └── App.tsx ├── vite.config.ts ├── package.json ├── public │ ├── index.html │ ├── vite.svg │ ├── jwc.svg │ └── jwc-dark.svg ├── index.html └── LICENSE ├── packages ├── shared │ ├── index.ts │ ├── src │ │ ├── constants │ │ │ ├── index.ts │ │ │ └── metas.constant.ts │ │ ├── index.ts │ │ └── types │ │ │ ├── index.ts │ │ │ ├── watcher.interface.ts │ │ │ ├── jwc-element.interface.ts │ │ │ └── local-jsx.ts │ └── package.json ├── runtime │ ├── v-dom │ │ ├── fragment.ts │ │ ├── index.ts │ │ ├── h.ts │ │ ├── vnode.ts │ │ ├── patch.ts │ │ └── diff.ts │ ├── dom │ │ ├── index.ts │ │ ├── attrs.ts │ │ └── dom.ts │ ├── index.ts │ ├── utils │ │ ├── others.ts │ │ └── attrs.ts │ ├── package.json │ └── LICENSE ├── core │ ├── src │ │ ├── index.ts │ │ ├── decorators │ │ │ ├── props.ts │ │ │ ├── event.ts │ │ │ ├── index.ts │ │ │ └── component.ts │ │ └── wc-class.ts │ ├── index.ts │ ├── rollup.config.mjs │ ├── LICENSE │ └── package.json └── reactively │ ├── index.ts │ ├── src │ ├── css-tag.ts │ ├── reactive.ts │ ├── call-reactive.ts │ └── define-reactive.ts │ ├── package.json │ └── LICENSE ├── pnpm-workspace.yaml ├── .prettierrc ├── .vscode └── launch.json ├── .gitignore ├── .github ├── renovate.json └── workflows │ └── release.yml ├── .eslintrc.js ├── tsconfig.json ├── package.json ├── README.md ├── LICENSE └── CHANGELOG.md /.eslintignore: -------------------------------------------------------------------------------- 1 | **/dist/** -------------------------------------------------------------------------------- /demo/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./App"; 2 | -------------------------------------------------------------------------------- /packages/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./src"; 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - packages/* 3 | - demo -------------------------------------------------------------------------------- /demo/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/runtime/v-dom/fragment.ts: -------------------------------------------------------------------------------- 1 | export const Fragment = "Fragment"; 2 | -------------------------------------------------------------------------------- /packages/shared/src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./metas.constant"; 2 | -------------------------------------------------------------------------------- /packages/runtime/dom/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./attrs"; 2 | export * from "./dom"; 3 | -------------------------------------------------------------------------------- /packages/shared/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./constants"; 2 | export * from "./types"; 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "useTabs": true, 4 | "endOfLine": "auto" 5 | } -------------------------------------------------------------------------------- /packages/runtime/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./v-dom"; 2 | export * from "./utils/attrs"; 3 | export * from "./dom"; 4 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | import "reflect-metadata"; 2 | 3 | export * from "./wc-class"; 4 | export * from "./decorators"; 5 | -------------------------------------------------------------------------------- /packages/shared/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./jwc-element.interface"; 2 | export * from "./watcher.interface"; 3 | export * from "./local-jsx"; 4 | -------------------------------------------------------------------------------- /packages/runtime/utils/others.ts: -------------------------------------------------------------------------------- 1 | export function camelToDash(str: string) { 2 | return str.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`); 3 | } 4 | -------------------------------------------------------------------------------- /packages/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from "@jwcjs/runtime"; 2 | export * from "@jwcjs/shared"; 3 | export * from "@jwcjs/reactively"; 4 | export * from "./src"; 5 | -------------------------------------------------------------------------------- /packages/runtime/v-dom/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./diff"; 2 | export * from "./h"; 3 | export * from "./fragment"; 4 | export * from "./vnode"; 5 | export * from "./patch"; 6 | -------------------------------------------------------------------------------- /packages/reactively/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./src/call-reactive"; 2 | export * from "./src/define-reactive"; 3 | export * from "./src/reactive"; 4 | export * from "./src/css-tag"; 5 | -------------------------------------------------------------------------------- /demo/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | export default defineConfig({ 3 | resolve: { 4 | alias: { 5 | jwcjs: "../../packages/core/index.ts", 6 | }, 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /packages/runtime/v-dom/h.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from "./vnode"; 2 | 3 | export function h(tag: string, props: any, ...children: any[]): VNode { 4 | return new VNode(tag, props, children); 5 | } 6 | -------------------------------------------------------------------------------- /packages/shared/src/constants/metas.constant.ts: -------------------------------------------------------------------------------- 1 | export const COMPONENT_PROP_METADATA_KEY = "jwc:component:props"; 2 | export const COMPONENT_WATCHER_METADATA_KEY = "jwc:component:watchers"; 3 | export const COMPONENT_EVENT_METADATA_KEY = "jwc:component:events"; 4 | -------------------------------------------------------------------------------- /packages/runtime/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jwcjs/runtime", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "chrome", 6 | "request": "launch", 7 | "name": "针对 localhost 启动 Chrome", 8 | "url": "http://localhost:5173", 9 | "webRoot": "${workspaceFolder}" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /packages/core/src/decorators/props.ts: -------------------------------------------------------------------------------- 1 | import { defineProps } from "@jwcjs/reactively"; 2 | import { PropOptions } from "@jwcjs/shared"; 3 | 4 | export function Prop(options: PropOptions): PropertyDecorator { 5 | return (target, key) => { 6 | defineProps(target, String(key), options); 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /packages/core/src/decorators/event.ts: -------------------------------------------------------------------------------- 1 | import { defineEvent } from "@jwcjs/reactively"; 2 | 3 | export function Event(event: string): MethodDecorator { 4 | return (target, key, descriptor) => { 5 | defineEvent(target, { 6 | name: event, 7 | handler: descriptor.value, 8 | }); 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /packages/reactively/src/css-tag.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Create a style element with the given CSS text. 3 | * Returns a DOM element. 4 | * 5 | * @param {string} css 6 | */ 7 | export function createCSSElement(css: string) { 8 | const style = document.createElement("style"); 9 | style.appendChild(document.createTextNode(css)); 10 | return style; 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/dist 2 | **/build 3 | **/out 4 | **/node_modules 5 | **/bower_components 6 | **/jspm_packages 7 | **/flow-typed 8 | **/coverage 9 | **/target 10 | **/.idea 11 | **/vendor 12 | **/tmp 13 | **/*.log 14 | **/*.log.* 15 | **/*.swp 16 | **/*.swo 17 | **/*.swn 18 | ~$* 19 | *.~ 20 | *.bak 21 | *.tmp 22 | **/.DS_Store 23 | **/Thumbs.db 24 | **/Desktop.ini 25 | -------------------------------------------------------------------------------- /packages/reactively/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jwcjs/reactively", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@jwcjs/shared": "workspace:*" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "vite": "^4.0.1", 16 | "jwcjs": "workspace:*" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/runtime/dom/attrs.ts: -------------------------------------------------------------------------------- 1 | export function updateAttributes(el: Node, attributes: { [key: string]: any }) { 2 | for (const key in attributes) { 3 | if (key === "style") { 4 | for (const styleKey in attributes[key]) { 5 | (el as HTMLElement).style[styleKey] = attributes[key][styleKey]; 6 | } 7 | } else { 8 | (el as HTMLElement).setAttribute(key, attributes[key]); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jwcjs/shared", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@jwcjs/runtime": "workspace:*", 14 | "csstype": "^3.1.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /demo/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Jwc.js App 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Jwc.js App 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/shared/src/types/watcher.interface.ts: -------------------------------------------------------------------------------- 1 | export interface WatcherOptions { 2 | /** 3 | * Whether the watcher should be called immediately. 4 | */ 5 | immediate?: boolean; 6 | 7 | /** 8 | * Callback function. 9 | */ 10 | callback?: any; 11 | 12 | /** 13 | * Callback name. 14 | * if handler is not provided, the callback will be called. 15 | */ 16 | callbackName?: string; 17 | 18 | /** 19 | * deep watch 20 | */ 21 | deep?: boolean; 22 | } 23 | -------------------------------------------------------------------------------- /packages/core/rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "rollup"; 2 | import nodeResolve from "@rollup/plugin-node-resolve"; 3 | import typescript from "rollup-plugin-ts"; 4 | import { minify } from "rollup-plugin-esbuild"; 5 | 6 | export default defineConfig({ 7 | input: "./index.ts", 8 | output: { 9 | file: "./dist/index.js", 10 | }, 11 | plugins: [ 12 | nodeResolve(), 13 | typescript({ 14 | tsconfig: "../../tsconfig.json", 15 | }), 16 | minify(), 17 | ], 18 | }); 19 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "labels": ["dependencies"], 4 | "extends": [ 5 | "config:base", 6 | ":automergePatch", 7 | ":automergeTypes", 8 | ":automergeTesters", 9 | ":automergeLinters", 10 | ":rebaseStalePrs" 11 | ], 12 | "packageRules": [ 13 | { 14 | "updateTypes": ["major"], 15 | "labels": ["dependencies", "UPDATE-MAJOR"] 16 | } 17 | ], 18 | "enabled": true 19 | } 20 | -------------------------------------------------------------------------------- /packages/core/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | import { defineWatcher } from "@jwcjs/reactively"; 2 | import { WatcherOptions } from "@jwcjs/shared"; 3 | 4 | export * from "./props"; 5 | export * from "./event"; 6 | export * from "./component"; 7 | 8 | export function Watcher(options: WatcherOptions): MethodDecorator { 9 | return (target, key, descriptor) => { 10 | defineWatcher(target, { 11 | ...options, 12 | callback: descriptor.value, 13 | callbackName: String(key), 14 | }); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/runtime/utils/attrs.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from "../v-dom"; 2 | 3 | export function removeAttrs( 4 | vnode: VNode | VNode[], 5 | attrs: string[] = ["isNew"] 6 | ) { 7 | if (vnode instanceof Array) { 8 | for (const node of vnode) { 9 | removeAttrs(node, attrs); 10 | } 11 | return vnode; 12 | } 13 | for (const attr of attrs) { 14 | vnode[attr] ? (vnode[attr] = false) : null; 15 | } 16 | if (vnode.children) { 17 | for (const child of Object.values(vnode.children)) { 18 | removeAttrs(child, attrs); 19 | } 20 | } 21 | return vnode; 22 | } 23 | -------------------------------------------------------------------------------- /packages/core/src/decorators/component.ts: -------------------------------------------------------------------------------- 1 | import { CustomElementProps } from "@jwcjs/shared"; 2 | 3 | export function Component(options: CustomElementProps) { 4 | return function (_class: any) { 5 | // set the default value for the isMounted option 6 | if (options.isMounted === undefined) options.isMounted = true; 7 | if (customElements.get(options.name)) { 8 | console.warn(`The component ${options.name} already exists.`); 9 | } 10 | _class.$options = options; // add the options to the class 11 | customElements.define(options.name, _class, options.options || {}); 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /packages/reactively/src/reactive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * We use getter and setter to make sure that the value is always 3 | * up to date. This is important because we want to be able to 4 | * use the value in a template. 5 | * 6 | * We use Reflect.get and Reflect.set to make sure that we can 7 | * use the value in a template. 8 | */ 9 | export function reactive(target: T): T { 10 | // console.log(target); 11 | 12 | return new Proxy(target, { 13 | get(target, key) { 14 | return Reflect.get(target, key); 15 | }, 16 | set(target, key, value) { 17 | Reflect.set(target, key, value); 18 | return true; 19 | }, 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /packages/runtime/v-dom/vnode.ts: -------------------------------------------------------------------------------- 1 | export class VNode { 2 | tagName: string; 3 | attributes: { 4 | [key: string]: any; 5 | }; 6 | children: VNode[]; 7 | 8 | // to assign status to the vnode 9 | isNew: boolean; 10 | isUpdated: boolean; 11 | isDeleted: boolean; 12 | 13 | // to record the dom node 14 | el: Node | null; 15 | 16 | constructor( 17 | tagName: string, 18 | attributes: { [key: string]: any }, 19 | children: VNode[] 20 | ) { 21 | this.tagName = tagName; 22 | this.attributes = attributes; 23 | this.children = children; 24 | this.isNew = true; 25 | this.isUpdated = false; 26 | this.isDeleted = false; 27 | this.el = document.createElement(tagName); 28 | } 29 | 30 | public static isVNode(vnode: any): vnode is VNode { 31 | return vnode instanceof VNode; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line no-undef 2 | module.exports = { 3 | env: { 4 | es2021: true, 5 | }, 6 | extends: [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:prettier/recommended", 10 | ], 11 | overrides: [], 12 | parser: "@typescript-eslint/parser", 13 | parserOptions: { 14 | ecmaVersion: "latest", 15 | sourceType: "module", 16 | }, 17 | plugins: ["@typescript-eslint"], 18 | rules: { 19 | "@typescript-eslint/no-unused-vars": "off", 20 | "@typescript-eslint/no-explicit-any": "off", 21 | "@typescript-eslint/no-non-null-assertion": "off", 22 | "@typescript-eslint/ban-ts-comment": "off", 23 | "@typescript-eslint/ban-types": "off", 24 | "@typescript-eslint/no-this-alias": "off", 25 | "@typescript-eslint/no-empty-function": "off", 26 | "no-self-assign": "off", 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /packages/reactively/src/call-reactive.ts: -------------------------------------------------------------------------------- 1 | import { CustomElementProps } from "@jwcjs/shared"; 2 | import { reactive } from "./reactive"; 3 | 4 | /** 5 | * There are two types of reactive functions: 6 | * 1. data 7 | * 2. event 8 | */ 9 | export type ReactiveData = CustomElementProps; 10 | 11 | export type ReactiveEvent = { 12 | name: any; 13 | handler: any; 14 | }; 15 | 16 | export function defineProxy(target: any, propertyKey: string, value: any) { 17 | const reactiveValue = reactive(value); 18 | Object.defineProperty(target, propertyKey, { 19 | get() { 20 | return reactiveValue.value; 21 | }, 22 | set(newValue) { 23 | reactiveValue.value = newValue; 24 | this.shouldUpdate = true; 25 | // callback the new value to the watcher 26 | this.watchersMap.get(propertyKey)?.forEach((watcher: any) => { 27 | watcher.callback.call(this, newValue, value); 28 | }); 29 | this.updateDiff(); 30 | }, 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "alwaysStrict": true, 4 | "allowSyntheticDefaultImports": true, 5 | "allowUnreachableCode": false, 6 | "declaration": true, 7 | "experimentalDecorators": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "jsx": "react", 10 | "jsxFactory": "h", 11 | "jsxFragmentFactory": "Fragment", 12 | "lib": ["dom", "es2018", "esnext.array"], 13 | "module": "esnext", 14 | "moduleResolution": "node", 15 | "noImplicitAny": false, 16 | "noImplicitOverride": true, 17 | "emitDecoratorMetadata": true, 18 | "noImplicitReturns": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": false, 21 | "outDir": "build", 22 | "pretty": true, 23 | "resolveJsonModule": true, 24 | "sourceMap": true, 25 | "target": "ES6", 26 | "useUnknownInCatchVariables": true, 27 | "baseUrl": "." 28 | }, 29 | "exclude": ["**/dist/**"] 30 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jwcjs/monorepo", 3 | "author": "wibus-wee ", 4 | "version": "0.1.0-alpha.1", 5 | "license": "MIT", 6 | "private": true, 7 | "scripts": { 8 | "lint": "eslint ./packages", 9 | "build:core": "pnpm -C packages/core run build", 10 | "build-packages": "npm run build:core", 11 | "bump": "bump-monorepo", 12 | "prepare": "npm run build-packages" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "^18.11.17", 16 | "@typescript-eslint/eslint-plugin": "^5.46.1", 17 | "@typescript-eslint/parser": "^5.46.1", 18 | "@wibus/bump-monorepo": "1.0.0-alpha.2", 19 | "eslint": "^8.29.0", 20 | "eslint-config-prettier": "^8.5.0", 21 | "eslint-plugin-prettier": "^4.2.1", 22 | "husky": "^8.0.2", 23 | "lint-staged": "^13.1.0", 24 | "pnpm": "^7.18.2", 25 | "prettier": "^2.8.1", 26 | "rimraf": "^4.0.0", 27 | "tslib": "^2.4.1", 28 | "typescript": "^4.9.4" 29 | }, 30 | "bump": { 31 | "activePackages": [ 32 | "core" 33 | ], 34 | "publish": true, 35 | "message": "release: %s" 36 | } 37 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | Jwc 5 | 6 | 7 | 8 | Jwc 9 | 10 | 11 | 12 | ### Simple. JSX. Web Components. 13 | 14 | [![Published on npm](https://img.shields.io/npm/v/jwcjs.svg?logo=npm)](https://www.npmjs.com/package/jwcjs) 15 | 16 | 🎨 A JavaScript framework for using JSX to write web components on the web. 17 | 18 |
19 | 20 | ## Getting Started 21 | 22 | Follow the documentation at [jwc.js.org](https://jwc.js.org)! 23 | 24 | > _**This project is still under development, so use it with caution in production**_ 25 | 26 | 27 | ## License 28 | 29 | [MIT](https://opensource.org/licenses/MIT) 30 | 31 | Made with ❤️ by Wibus and AkaraChen 32 | 33 | Copyright © 2022-PRESENT Jwc.js 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jwc.js 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /demo/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jwc.js 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/core/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jwc.js 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/runtime/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jwc.js 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/reactively/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jwc.js 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /demo/src/App.css: -------------------------------------------------------------------------------- 1 | 2 | :host { 3 | max-width: 1280px; 4 | margin: 0 auto; 5 | padding: 2rem; 6 | text-align: center; 7 | } 8 | 9 | .logo { 10 | height: 6em; 11 | padding: 1.5em; 12 | will-change: filter; 13 | transition: filter 0.25s; 14 | } 15 | .logo:hover { 16 | filter: drop-shadow(0 0 2em #646cffaa); 17 | } 18 | .logo.jwc:hover { 19 | filter: drop-shadow(0 0 2em rgb(0, 0, 0)); 20 | } 21 | 22 | .card { 23 | padding: 2em; 24 | } 25 | 26 | .read-the-docs { 27 | color: #888; 28 | } 29 | 30 | @media (prefers-color-scheme: dark) { 31 | .logo.jwc:hover { 32 | filter: drop-shadow(0 0 2em rgb(255, 255, 255)); 33 | } 34 | } 35 | 36 | 37 | button { 38 | border-radius: 8px; 39 | border: 1px solid transparent; 40 | padding: 0.6em 1.2em; 41 | font-size: 1em; 42 | font-weight: 500; 43 | font-family: inherit; 44 | background-color: #1a1a1a; 45 | cursor: pointer; 46 | transition: border-color 0.25s; 47 | } 48 | button:hover { 49 | border-color: #646cff; 50 | } 51 | button:focus, 52 | button:focus-visible { 53 | outline: 4px auto -webkit-focus-ring-color; 54 | } 55 | 56 | 57 | @media (prefers-color-scheme: light) { 58 | button { 59 | background-color: #f9f9f9; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /demo/src/index.css: -------------------------------------------------------------------------------- 1 | 2 | :root { 3 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 4 | font-size: 16px; 5 | line-height: 24px; 6 | font-weight: 400; 7 | 8 | color-scheme: light dark; 9 | color: rgba(255, 255, 255, 0.87); 10 | background-color: #242424; 11 | 12 | font-synthesis: none; 13 | text-rendering: optimizeLegibility; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | -webkit-text-size-adjust: 100%; 17 | } 18 | 19 | a { 20 | font-weight: 500; 21 | color: #646cff; 22 | text-decoration: inherit; 23 | } 24 | a:hover { 25 | color: #535bf2; 26 | } 27 | 28 | body { 29 | margin: 0; 30 | display: flex; 31 | place-items: center; 32 | min-width: 320px; 33 | min-height: 100vh; 34 | } 35 | 36 | 37 | h1 { 38 | font-size: 3.2em; 39 | line-height: 1.1; 40 | } 41 | 42 | 43 | @media (prefers-color-scheme: light) { 44 | :root { 45 | color: #213547; 46 | background-color: #ffffff; 47 | } 48 | a:hover { 49 | color: #747bff; 50 | } 51 | button { 52 | background-color: #f9f9f9; 53 | } 54 | } 55 | 56 | 57 | #root { 58 | max-width: 1280px; 59 | margin: 0 auto; 60 | padding: 2rem; 61 | text-align: center; 62 | } 63 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | tags: ['v*'] 4 | 5 | name: Release 6 | 7 | jobs: 8 | release: 9 | name: Create Release 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest] 13 | runs-on: ${{ matrix.os }} 14 | # outputs: 15 | # release_url: ${{ steps.create_release.outputs.upload_url }} 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v3 19 | with: 20 | fetch-depth: 0 21 | - uses: actions/setup-node@v3 22 | with: 23 | node-version: 16.x 24 | - name: Cache pnpm modules 25 | uses: actions/cache@v3 26 | env: 27 | cache-name: cache-pnpm-modules 28 | with: 29 | path: ~/.pnpm-store 30 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }} 31 | restore-keys: | 32 | ${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }} 33 | - uses: pnpm/action-setup@v2.2.4 34 | with: 35 | version: latest 36 | run_install: true 37 | 38 | - name: Build 39 | run: | 40 | npm run build 41 | 42 | - name: Create Release 43 | id: create_release 44 | run: | 45 | npx changelogithub 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /demo/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/runtime/v-dom/patch.ts: -------------------------------------------------------------------------------- 1 | import { createElement } from "../dom"; 2 | import { updateAttributes } from "../dom/attrs"; 3 | 4 | import { VNode } from "./vnode"; 5 | 6 | export function patch( 7 | host: Node, 8 | vnode: VNode | VNode[], 9 | old: VNode | VNode[], 10 | index: number 11 | ) { 12 | if (Array.isArray(vnode) && Array.isArray(old)) { 13 | vnode.forEach((node, index) => { 14 | patch(host, node, old[index], index); 15 | }); 16 | return; 17 | } 18 | vnode = vnode as VNode; 19 | old = old as VNode; 20 | if (vnode.isUpdated) { 21 | // update the attributes of the dom node 22 | updateAttributes(vnode.el, vnode.attributes); 23 | // update the children of the dom node 24 | // if the children is a string, update the textContent of the dom node 25 | if (typeof vnode.children === "string") { 26 | vnode.el.textContent = vnode.children; 27 | } 28 | host.parentNode?.replaceChild(createElement(vnode), host); 29 | } else if (vnode.isNew) { 30 | host.appendChild(createElement(vnode)); 31 | } else if (vnode.isDeleted) { 32 | host.removeChild(host.childNodes[index]); 33 | } 34 | 35 | // update the children of the dom node 36 | if (vnode.children instanceof Array) { 37 | for (let index = 0; index < vnode.children.length; index++) { 38 | // find the dom node in the host node 39 | const child = host.childNodes[index]; 40 | patch(child, vnode.children[index], old?.children[index], index); 41 | continue; 42 | } 43 | } 44 | return; 45 | } 46 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jwcjs", 3 | "version": "0.1.0-alpha.1", 4 | "description": "Jwc.js is a JavaScript framework for using JSX to write web components on the web.", 5 | "main": "./dist/index.js", 6 | "exports": { 7 | ".": "./dist/index.js" 8 | }, 9 | "publishConfig": { 10 | "access": "public" 11 | }, 12 | "types": "./dist/index.d.ts", 13 | "files": [ 14 | "dist", 15 | "package.json", 16 | "LICENSE" 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/jwcjs/core.git" 21 | }, 22 | "homepage": "https://jwc.js.org", 23 | "bugs": { 24 | "url": "https://github.com/jwcjs/core/issues" 25 | }, 26 | "readme": "https://github.com/jwcjs/core#readme", 27 | "scripts": { 28 | "prepublish": "npm run build", 29 | "build": "rimraf dist && rollup -c rollup.config.mjs" 30 | }, 31 | "keywords": [ 32 | "jsx", 33 | "web components", 34 | "framework", 35 | "jwcjs" 36 | ], 37 | "author": "JwcJS", 38 | "license": "MIT", 39 | "devDependencies": { 40 | "@rollup/plugin-node-resolve": "^15.0.1", 41 | "esbuild": "^0.17.0", 42 | "rollup": "^3.7.4", 43 | "rollup-plugin-esbuild": "^5.0.0", 44 | "vite": "^4.0.1", 45 | "@jwcjs/reactively": "workspace:^1.0.0", 46 | "@jwcjs/runtime": "workspace:^1.0.0", 47 | "@jwcjs/shared": "workspace:^1.0.0", 48 | "reflect-metadata": "^0.1.13", 49 | "rollup-plugin-ts": "^3.0.2" 50 | }, 51 | "bump": { 52 | "publish": true, 53 | "changelog": true 54 | } 55 | } -------------------------------------------------------------------------------- /packages/reactively/src/define-reactive.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PropOptions, 3 | WatcherOptions, 4 | COMPONENT_EVENT_METADATA_KEY, 5 | COMPONENT_PROP_METADATA_KEY, 6 | } from "@jwcjs/shared"; 7 | import { ReactiveEvent } from "./call-reactive"; 8 | 9 | /** 10 | * A universal function for defining props and state 11 | */ 12 | function definePropsOrState(target: any, attr: string, options: PropOptions) { 13 | const { default: v, required } = options; 14 | const keys = Reflect.getMetadata(COMPONENT_PROP_METADATA_KEY, target) || []; 15 | 16 | keys.push({ 17 | attr, 18 | default: v, 19 | required, 20 | }); 21 | Reflect.defineMetadata(COMPONENT_PROP_METADATA_KEY, keys, target); 22 | } 23 | 24 | /** 25 | * Define props for component 26 | */ 27 | export function defineProps(target: any, attr: string, options: PropOptions) { 28 | definePropsOrState(target, attr, options); 29 | } 30 | 31 | /** 32 | * Define state for component 33 | */ 34 | export function defineState(target: any, attr: string, options: PropOptions) { 35 | definePropsOrState(target, attr, options); 36 | } 37 | 38 | /** 39 | * Define event for component 40 | */ 41 | export function defineEvent(target: any, event: ReactiveEvent) { 42 | const keys = 43 | Reflect.getMetadata(COMPONENT_EVENT_METADATA_KEY, target) || []; 44 | keys.push(event); 45 | Reflect.defineMetadata(COMPONENT_EVENT_METADATA_KEY, keys, target); 46 | } 47 | 48 | /** 49 | * Define watcher for component 50 | */ 51 | export function defineWatcher(target: any, options: WatcherOptions) { 52 | const keys = 53 | Reflect.getMetadata(COMPONENT_EVENT_METADATA_KEY, target) || []; 54 | keys.push(options); 55 | Reflect.defineMetadata(COMPONENT_EVENT_METADATA_KEY, keys, target); 56 | } 57 | -------------------------------------------------------------------------------- /demo/public/jwc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Jwc.js Light Just Logo 4 | 8 | -------------------------------------------------------------------------------- /demo/public/jwc-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Jwc.js Dark Just Logo 4 | 8 | -------------------------------------------------------------------------------- /demo/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { JwcComponent, Component, Prop, h, Fragment } from "jwcjs"; 2 | import styles from "./App.css?inline"; 3 | 4 | @Component({ 5 | name: "app-element", 6 | css: styles, 7 | }) 8 | export class App extends JwcComponent { 9 | constructor() { 10 | super(); 11 | } 12 | 13 | @Prop({ default: 0, attr: "count" }) 14 | public count = 0; 15 | 16 | public onClick = () => { 17 | this.count++; 18 | }; 19 | 20 | // get media 21 | public getSystemColorScheme() { 22 | return window.matchMedia("(prefers-color-scheme: dark)").matches 23 | ? "dark" 24 | : "light"; 25 | } 26 | 27 | public override connectedCallback() { 28 | super.connectedCallback(); 29 | window 30 | .matchMedia("(prefers-color-scheme: dark)") 31 | .addEventListener("change", () => { 32 | this.updateDiff(); 33 | console.log("change"); 34 | }); 35 | } 36 | 37 | public override disconnectedCallback() { 38 | super.disconnectedCallback(); 39 | window 40 | .matchMedia("(prefers-color-scheme: dark)") 41 | .removeEventListener("change", () => { 42 | this.updateDiff(); 43 | }); 44 | } 45 | 46 | public override render() { 47 | return ( 48 | <> 49 |
50 | 51 | 52 | 53 | 54 | 63 | 64 |
65 |
66 | 69 |
70 | {Array.from({ length: this.count }).map((_, i) => ( 71 |

72 | 点击按钮,此处应随着按钮的点击次数而变化 {String(i + 1)} 73 |

74 | ))} 75 | 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /packages/shared/src/types/jwc-element.interface.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from "@jwcjs/runtime"; 2 | 3 | export interface CustomElementProps { 4 | /** 5 | * The component's name. 6 | */ 7 | name: string; 8 | 9 | /** 10 | * The component's styles. 11 | */ 12 | css?: any; 13 | 14 | /** 15 | * Options for the component. 16 | */ 17 | options?: ElementDefinitionOptions; // https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define 18 | 19 | isMounted?: boolean; 20 | } 21 | 22 | export interface PropOptions { 23 | /** 24 | * default value for the prop 25 | * @default undefined 26 | */ 27 | default?: any; 28 | 29 | /** 30 | * whether the prop is required 31 | * @default false 32 | */ 33 | required?: boolean; 34 | 35 | /** 36 | * The prop's attribute name. 37 | */ 38 | attr?: string; 39 | } 40 | 41 | export interface JwcElement { 42 | /** 43 | * Whether ths component is connected to the DOM. 44 | */ 45 | isConnected: boolean; 46 | 47 | /** 48 | * Whether the component should be updated. 49 | */ 50 | shouldUpdate: boolean; 51 | 52 | /** 53 | * The component's custom styles. 54 | */ 55 | customStyles?: string; 56 | 57 | /** 58 | * The component host element. 59 | */ 60 | host: HTMLElement; 61 | 62 | /** 63 | * The component's reactivity data. 64 | */ 65 | $data?: any; 66 | 67 | /** 68 | * The component's options. 69 | * @see CustomElementProps 70 | */ 71 | $options?: CustomElementProps; 72 | 73 | /** 74 | * The component's injected dependencies. 75 | */ 76 | $deps?: any; 77 | 78 | /** 79 | * The last time vdom was rendered. 80 | */ 81 | $lastRender?: VNode; 82 | 83 | /** 84 | * The component's attributes changed callback. 85 | */ 86 | attributeChangedCallback?: ( 87 | name: string, 88 | oldValue: string, 89 | newValue: string 90 | ) => void; 91 | 92 | /** 93 | * The component's connected callback. 94 | */ 95 | connectedCallback?: () => void; 96 | 97 | /** 98 | * The component's connected function. 99 | */ 100 | connected?: (shadowRoot: ShadowRoot) => void; 101 | 102 | /** 103 | * The component's disconnected callback. 104 | */ 105 | disconnectedCallback?: () => void; 106 | 107 | /** 108 | * The component's disconnected function. 109 | */ 110 | disconnected?: () => void; 111 | 112 | /** 113 | * The component's adopted callback. 114 | * @see https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define 115 | */ 116 | adoptedCallback?: (oldDocument: Document, newDocument: Document) => void; 117 | 118 | /** 119 | * The component's update function. 120 | */ 121 | update?: () => void; 122 | 123 | /** 124 | * The component's render function. 125 | */ 126 | render?(...args: any[]): any; 127 | } 128 | 129 | /** 130 | * The JwcElement constructor. 131 | */ 132 | export interface JwcElementConstructor { 133 | new (): JwcElement; 134 | } 135 | -------------------------------------------------------------------------------- /packages/runtime/v-dom/diff.ts: -------------------------------------------------------------------------------- 1 | import { updateDOM } from "../dom/dom"; 2 | import { removeAttrs } from "../utils/attrs"; 3 | import { patch } from "./patch"; 4 | import { VNode } from "./vnode"; 5 | 6 | /** 7 | * Diff the old vnode and the new vnode. 8 | * 9 | * 1. Mark the new vnode, 10 | * and mark the child nodes of the new vnode as new. 11 | * 2. Diff the old vnode and the new vnode. 12 | * 3. Update the dom tree. 13 | * 14 | * Note: 15 | * I can't get the type of the old vnode and the new vnode. 16 | * So I use any to replace the type. 17 | * 18 | * @param oldVNode 19 | * @param newVNode 20 | */ 21 | export function diff(oldVNode: any, newVNode: any, host?: Node) { 22 | if (!oldVNode) { 23 | newVNode = markNewVNode(newVNode); 24 | } 25 | newVNode = diffRecursive(oldVNode, newVNode); 26 | const updated = updateDOM(oldVNode, newVNode); 27 | 28 | if (host) { 29 | const hostel: Node[] = []; 30 | if (host.childNodes[0].nodeName === "STYLE") { 31 | /** 32 | * If the first child node of the host is a style node, 33 | * then the style node is not a child node of the vnode. 34 | * 35 | * So I need to remove the style node from the host. 36 | */ 37 | host.childNodes.forEach((node: any) => { 38 | if (node.nodeName !== "STYLE") hostel.push(node); 39 | }); 40 | } 41 | // transform the vnode to the dom tree 42 | if (updated.children instanceof Array) { 43 | for (let index = 0; index < updated.children.length; index++) { 44 | patch( 45 | hostel[index], 46 | updated.children[index], 47 | oldVNode.children[index], 48 | index 49 | ); 50 | } 51 | } 52 | } 53 | 54 | return removeAttrs(updated, ["isUpdated", "isNew", "isDeleted"]); 55 | } 56 | 57 | /** 58 | * Mark the new vnode, 59 | * and mark the child nodes of the new vnode as new. 60 | * 61 | * @param node the new vnode 62 | */ 63 | function markNewVNode(node: VNode) { 64 | if (node.isNew) { 65 | // For each child node of the node 66 | for (const child of node.children) { 67 | markNewVNode(child); 68 | } 69 | } 70 | node?.isNew === false && (node.isNew = true); 71 | return node; 72 | } 73 | 74 | /** 75 | * Diff the old vnode and the new vnode. 76 | * 77 | * 1. If the old vnode is marked as deleted, then return. 78 | * 2. If the new vnode is marked as new, then return. 79 | * 3. If the **tag name** of the old vnode and the new vnode are not equal, 80 | * then mark the old vnode as deleted, and mark the new vnode as new. 81 | * 4. If the attributes of the old vnode and the new vnode are not equal, 82 | * then mark the new vnode as updated. 83 | * 5. Diff the child nodes of the old vnode and the new vnode. 84 | * 85 | * @param oldVNode 86 | * @param newVNode 87 | */ 88 | function diffRecursive( 89 | oldVNode: VNode | undefined, 90 | newVNode: VNode, 91 | host?: VNode 92 | ) { 93 | if (!oldVNode) { 94 | newVNode = markNewVNode(newVNode); 95 | return newVNode; 96 | } 97 | // the type of the vnode may be VNode[] ( x.map(() => (<>)) ) 98 | if (oldVNode instanceof Array && newVNode instanceof Array) { 99 | const maxLength = Math.max(oldVNode.length, newVNode.length); 100 | for (let i = 0; i < maxLength; i++) { 101 | newVNode[i] = diffRecursive(oldVNode[i], newVNode[i], host); 102 | } 103 | return newVNode; 104 | } 105 | // just text node 106 | if (typeof oldVNode === "string" && typeof newVNode === "string") { 107 | if (oldVNode !== newVNode) { 108 | newVNode = newVNode; 109 | host!.isUpdated = true; 110 | } 111 | } 112 | 113 | if (oldVNode.isDeleted) { 114 | return oldVNode; 115 | } 116 | 117 | // if (newVNode.isNew) { 118 | // // if the new vnode is new, then return; 119 | // return newVNode; 120 | // } 121 | 122 | if (oldVNode?.tagName !== newVNode.tagName) { 123 | oldVNode.isDeleted = true; 124 | newVNode.isNew = true; 125 | } 126 | 127 | if ( 128 | JSON.stringify(oldVNode.attributes) !== 129 | JSON.stringify(newVNode.attributes) 130 | ) { 131 | /** 132 | * if the attributes of the old vnode and the new vnode are not equal, 133 | * then the new vnode is updated. 134 | */ 135 | newVNode.isUpdated = true; 136 | } 137 | // diff the child nodes of the old vnode and the new vnode 138 | if (oldVNode.children && newVNode.children) { 139 | const oldChildren = Object.values(oldVNode.children); 140 | const newChildren = Object.values(newVNode.children); 141 | if (JSON.stringify(oldChildren) !== JSON.stringify(newChildren)) { 142 | const maxLength = Math.max(oldChildren.length, newChildren.length); 143 | for (let i = 0; i < maxLength; i++) { 144 | newVNode.children[i] = diffRecursive( 145 | oldChildren[i], 146 | newChildren[i], 147 | newVNode 148 | ); 149 | } 150 | } 151 | } 152 | return newVNode; 153 | } 154 | -------------------------------------------------------------------------------- /packages/runtime/dom/dom.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from "../v-dom"; 2 | import { camelToDash } from "../utils/others"; 3 | 4 | /** 5 | * Create a dom node according to the tag name of the vnode. 6 | * 7 | * 1. Create a dom node according to the tag name of the vnode. 8 | * 2. Set the attributes of the dom node. 9 | * 3. Create the child nodes of the dom node. 10 | * 11 | * @param node the vnode 12 | */ 13 | export function createElement(node: VNode | VNode[]): Node { 14 | if (Array.isArray(node)) { 15 | const fragment = document.createDocumentFragment(); 16 | for (const child of node) { 17 | fragment.appendChild(createElement(child)); 18 | } 19 | return fragment; 20 | } 21 | // create a dom node according to the tag name of the vnode 22 | const el = 23 | node.tagName === "Fragment" 24 | ? document.createDocumentFragment() 25 | : document.createElement(node.tagName); 26 | 27 | // set the attributes of the dom node 28 | const attributes = node.attributes; 29 | for (const key in attributes) { 30 | const value = attributes[key]; 31 | if (key.startsWith("on")) { 32 | const eventName = key.slice(2).toLowerCase(); 33 | el.addEventListener(eventName, value); 34 | } else if (key === "style") { 35 | for (const styleKey of value) { 36 | const styleValue = value[styleKey]; 37 | (el as HTMLElement).style[styleKey] = styleValue; 38 | } 39 | } else { 40 | if (!(node.tagName === "Fragment")) { 41 | (el as HTMLElement).setAttribute(camelToDash(key), value); 42 | } 43 | } 44 | } 45 | 46 | // create the child nodes of the dom node 47 | if (node.children) { 48 | for (const child of node.children) { 49 | if (typeof child === "string") { 50 | el.appendChild(document.createTextNode(child)); 51 | continue; 52 | } 53 | el.appendChild(createElement(child)); 54 | } 55 | } 56 | return el; 57 | } 58 | 59 | /** 60 | * Update the attributes of the dom node. 61 | * 62 | * 1. Get the dom node of the vnode. 63 | * 2. Get the attributes of the vnode. 64 | * 3. Update the attributes of the dom node. 65 | * 4. Update the child nodes of the dom node. 66 | * 67 | * @param node the vnode 68 | */ 69 | export function updateElement(oldNode: VNode, newNode: VNode) { 70 | // get the dom node of the vnode 71 | const el = newNode.el! as HTMLElement; 72 | 73 | // get the attributes of the vnode 74 | const attributes = newNode.attributes; 75 | 76 | // update the attributes of the dom node 77 | for (const key in attributes) { 78 | if (key.startsWith("on")) { 79 | if (typeof oldNode?.attributes[key] === "function") { 80 | const eventName = key.slice(2).toLowerCase(); 81 | el.removeEventListener(eventName, oldNode.attributes[key]); 82 | el.addEventListener(eventName, attributes[key]); 83 | } 84 | } else { 85 | el.setAttribute(camelToDash(key), attributes[key]); 86 | } 87 | } 88 | 89 | for (const child of newNode.children) { 90 | if (typeof child === "string") { 91 | el.appendChild(document.createTextNode(child)); 92 | continue; 93 | } 94 | el.appendChild(createElement(child)); 95 | } 96 | 97 | // update the child nodes of the dom node 98 | if (newNode.children) { 99 | for (const child of Object.values(newNode.children)) { 100 | updateDOM(undefined, child); 101 | } 102 | } 103 | 104 | return el; 105 | } 106 | 107 | /** 108 | * Update the dom tree. 109 | * 110 | * 1. If the node is marked as deleted, then remove it from the dom tree. 111 | * 2. If the node is marked as new, then create a new dom node. 112 | * 3. If the node is marked as updated, then 113 | * update the attributes of the dom node. 114 | * 4. Update the child nodes of the dom node. 115 | * 116 | */ 117 | export function updateDOM( 118 | oldNode: VNode | undefined, 119 | newNode: VNode | VNode[] 120 | ): VNode { 121 | if (Array.isArray(newNode)) { 122 | for (const child of newNode) { 123 | newNode = updateDOM(undefined, child); 124 | } 125 | return newNode as VNode; 126 | } 127 | // if the node is marked as deleted, then remove it from the dom tree 128 | if (newNode.isDeleted) { 129 | newNode.el!.parentNode!.removeChild(newNode.el!); 130 | return newNode; 131 | } 132 | 133 | // if the node is marked as new, then create a new dom node 134 | if (newNode.isNew) { 135 | newNode.el = createElement(newNode); 136 | return newNode; 137 | } 138 | 139 | // if the node is marked as updated, then update the attributes of the dom node 140 | if (newNode.isUpdated) { 141 | const updated = updateElement(oldNode, newNode); 142 | if (updated) { 143 | newNode.el = updated; 144 | } 145 | return newNode; 146 | } 147 | 148 | // update the child nodes of the dom node 149 | if (newNode.children) { 150 | for (const child of Object.values(newNode.children)) { 151 | updateDOM(undefined, child); 152 | } 153 | } 154 | 155 | return newNode; 156 | } 157 | -------------------------------------------------------------------------------- /packages/core/src/wc-class.ts: -------------------------------------------------------------------------------- 1 | import { createCSSElement, defineProxy } from "@jwcjs/reactively"; 2 | import { createElement, diff, removeAttrs } from "@jwcjs/runtime"; 3 | import { 4 | COMPONENT_PROP_METADATA_KEY, 5 | JwcElement, 6 | PropOptions, 7 | WatcherOptions, 8 | } from "@jwcjs/shared"; 9 | 10 | /** 11 | * The map of adoptedStyleSheets. 12 | * It is used to avoid duplicate styleSheets. 13 | */ 14 | const adoptedStyleSheetsMap = new WeakMap(); 15 | 16 | export class JwcComponent extends HTMLElement implements JwcElement { 17 | public override tagName: string; 18 | public rootNode = null; 19 | 20 | public $data = null; 21 | public $options = null; 22 | public $deps = null; 23 | 24 | public $lastRender = null; 25 | public customStyles = null; 26 | public shouldUpdate = false; 27 | public props = {}; 28 | public propsList: PropOptions[] = []; 29 | public previousProps = {}; 30 | public previousVNode = null; 31 | 32 | public host: HTMLElement; 33 | 34 | public override shadowRoot: ShadowRoot; 35 | 36 | private watchersMap = new Map(); 37 | 38 | public getMetaList(key: string): Map { 39 | return Reflect.getMetadata(key, this) || new Map(); 40 | } 41 | 42 | private initWatcher() { 43 | const watchers = 44 | this.getMetaList(COMPONENT_PROP_METADATA_KEY) || 45 | ([] as WatcherOptions[]); 46 | watchers.forEach((watcher: WatcherOptions) => { 47 | const { callbackName } = watcher; 48 | const currentItem = this.watchersMap.get(callbackName); 49 | /** 50 | * if the callbackName is already exist, 51 | * add the watcher to the array. 52 | * 53 | * if not, create a new array and add the watcher to it. 54 | */ 55 | if (currentItem) { 56 | this.watchersMap.set(callbackName, [...currentItem, watcher]); 57 | } else { 58 | this.watchersMap.set(callbackName, [watcher]); 59 | } 60 | }); 61 | } 62 | 63 | constructor() { 64 | super(); 65 | this.host = this; 66 | this.$options = (this.constructor as any).$options; 67 | this.init(); 68 | } 69 | 70 | /** 71 | * init the styleSheets. 72 | * Put the styleSheets into the shadowRoot. 73 | */ 74 | private initCSS(shadowRoot: ShadowRoot) { 75 | if (adoptedStyleSheetsMap.has(this.constructor)) { 76 | /** 77 | * if the adoptedStyleSheetsMap has the constructor, 78 | * it means that the styleSheets has been created. 79 | */ 80 | shadowRoot.adoptedStyleSheets = adoptedStyleSheetsMap.get( 81 | this.constructor 82 | ); 83 | } else { 84 | /** 85 | * if the adoptedStyleSheetsMap doesn't have the constructor, 86 | * it means that the styleSheets hasn't been created. 87 | */ 88 | const styleSheets = this.$options.css; 89 | if (styleSheets) { 90 | const css = new CSSStyleSheet(); 91 | css.replaceSync(styleSheets); 92 | shadowRoot.adoptedStyleSheets = [css]; 93 | adoptedStyleSheetsMap.set(this.constructor, [css]); 94 | } 95 | } 96 | return shadowRoot; 97 | } 98 | 99 | private initShadowRoot() { 100 | let shadowRoot: ShadowRoot = 101 | this.shadowRoot || this.attachShadow({ mode: "open" }); 102 | shadowRoot = this.initCSS(this.shadowRoot); 103 | if (this.$options.css) { 104 | shadowRoot.appendChild(createCSSElement(this.$options.css)); 105 | } 106 | if (this.inlineStyles) { 107 | this.customStyles = createCSSElement(this.inlineStyles); 108 | shadowRoot.appendChild(this.customStyles); 109 | } 110 | return shadowRoot; 111 | } 112 | 113 | private attrsToProps() { 114 | const host = 115 | this.shadowRoot && this.shadowRoot.host 116 | ? this.shadowRoot.host 117 | : this; 118 | const attrs: Record = {}; 119 | for (let i = 0; i < host.attributes.length; i++) { 120 | const attr = host.attributes[i]; 121 | attrs[attr.name] = attr.value; 122 | } 123 | this.propsList.forEach((prop: PropOptions) => { 124 | const { attr: name, default: defaultValue } = prop; 125 | if (attrs[name]) { 126 | this.previousProps[name] = attrs[name]; 127 | this[name] = attrs[name]; 128 | } else { 129 | this.previousProps[name] = defaultValue; 130 | this[name] = defaultValue; 131 | } 132 | }); 133 | } 134 | 135 | private init() { 136 | this.props = this.getMetaList(COMPONENT_PROP_METADATA_KEY) || []; 137 | this.propsList = Object.values(this.props); 138 | const that = this; 139 | // define the default value of the props. 140 | this.propsList.forEach((prop: PropOptions) => { 141 | const { attr: name, default: defaultValue } = prop; 142 | this.previousProps[name] = defaultValue; 143 | // getAttribute 144 | this[name] = defaultValue; 145 | defineProxy(that, name, prop); 146 | }); 147 | this.initWatcher(); 148 | } 149 | 150 | get inlineStyles() { 151 | return super.getAttribute("style"); 152 | } 153 | 154 | public updateDiff() { 155 | const previous = this.$lastRender; 156 | const current = this.render(this.$data); 157 | if (previous) { 158 | this.$lastRender = null; 159 | this.$lastRender = diff( 160 | removeAttrs(previous), 161 | removeAttrs(current), 162 | this.shadowRoot 163 | ); 164 | } 165 | } 166 | 167 | public customEvent(name: string, detail: any) { 168 | const event = new CustomEvent(name, { 169 | detail, 170 | bubbles: true, 171 | composed: true, 172 | }); 173 | 174 | this.dispatchEvent(event); 175 | } 176 | 177 | public connectedCallback() { 178 | const shadowRoot = this.initShadowRoot(); 179 | this.attrsToProps(); 180 | /** 181 | * beforeCreate -> 182 | * created -> 183 | * afterCreate -> 184 | * beforeMount -> 185 | * mounted 186 | */ 187 | const propsList = this.props as PropOptions[]; 188 | const that = this; 189 | propsList.forEach((prop: PropOptions) => { 190 | const attr = shadowRoot.host.getAttribute(prop.attr); 191 | if (attr) { 192 | that[prop.attr] = attr; 193 | } 194 | }); 195 | const rendered = this.render(this.$data); 196 | this.rootNode = createElement(removeAttrs(rendered) as any); 197 | if (this.$options.isMounted) { 198 | this.rootNode && shadowRoot.appendChild(this.rootNode); 199 | } 200 | 201 | this.$lastRender = removeAttrs(rendered); 202 | } 203 | 204 | public disconnectedCallback() {} 205 | 206 | public attributeChangedCallback( 207 | name: string, 208 | oldValue: string, 209 | newValue: string 210 | ) { 211 | if (oldValue !== newValue) { 212 | this.props[name] = newValue; 213 | } 214 | this.updateDiff(); 215 | } 216 | 217 | public adoptedCallback() {} 218 | 219 | public render(data: {}): any {} 220 | } 221 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | # [0.1.0-alpha.1](https://github.com/jwcjs/core/compare/0.1.0-alpha.0...0.1.0-alpha.1) (2023-01-29) 4 | 5 | 6 | ### Bug Fixes 7 | 8 | * **core:** missing checking vnode type in creating, fixed [#19](https://github.com/jwcjs/core/issues/19) ([#20](https://github.com/jwcjs/core/issues/20)) ([6e25dc9](https://github.com/jwcjs/core/commit/6e25dc91606c56348d6339d23b09a0df5d086a64)) 9 | * root package, init before build packages ([#21](https://github.com/jwcjs/core/issues/21)) ([a90296f](https://github.com/jwcjs/core/commit/a90296f7bb7d725991dfac37e835368eeb27b877)) 10 | * style attribute ([#25](https://github.com/jwcjs/core/issues/25)) ([21c27a3](https://github.com/jwcjs/core/commit/21c27a3b514c2a96d64bdd2db65638dabb9bdbd1)) 11 | 12 | 13 | ### Performance Improvements 14 | 15 | * **core:** export all packages in root ([98995ee](https://github.com/jwcjs/core/commit/98995ee8b250cb58d60295d4f05f714d4db6d910)) 16 | 17 | 18 | 19 | # [0.1.0-alpha.0](https://github.com/jwcjs/core/compare/3aac67f35915f92e2a3a27b16a014dacaa662caa...0.1.0-alpha.0) (2022-12-22) 20 | 21 | 22 | ### Bug Fixes 23 | 24 | * **core:** default value of prop inoperative ([034e51f](https://github.com/jwcjs/core/commit/034e51fae9462f30da7f2ab4f3bfaf2ed9d8a457)) 25 | * **core:** missing adoptedCallback ([638f8f5](https://github.com/jwcjs/core/commit/638f8f5fcd93bdcacf4d636bc89d56a3b9ceeb7b)) 26 | * **core:** missing attributes updating ([cc6c3b2](https://github.com/jwcjs/core/commit/cc6c3b20538b67646890a159cfafef5afc57cccc)) 27 | * css type warning ([c2c0774](https://github.com/jwcjs/core/commit/c2c077439a532f1fca57d06b1856f75f8d52d78b)) 28 | * export modules ([8ae586b](https://github.com/jwcjs/core/commit/8ae586bfeead128fe64c475f965f46a952e0b54c)) 29 | * **jwc-core:** component decorators doesn't return a function ([b827d9a](https://github.com/jwcjs/core/commit/b827d9a005ec2d7392aa00cfe1a033e2bdfc0e8e)) 30 | * **jwc-core:** create dom element at first rendering ([27dcf6c](https://github.com/jwcjs/core/commit/27dcf6c18f6dca14bd2dd9d1798d82325738e68d)) 31 | * **jwc-core:** inject styles into host ([f198477](https://github.com/jwcjs/core/commit/f19847797f13b9b95b63fa9c44f4e44e94ed482c)) 32 | * **jwc-reactively:** reactive function extra props ([c97f7f5](https://github.com/jwcjs/core/commit/c97f7f524dacd1e31fc3b9cb4ee66a4ad95f805c)) 33 | * **jwc-runtime:** diff function return a vnode ([bb18358](https://github.com/jwcjs/core/commit/bb18358d32abc969ec2492e69b25711a5aa0714f)) 34 | * **jwc-runtime:** incorrectly passed arguments after using fragment ([0a7caa5](https://github.com/jwcjs/core/commit/0a7caa514c8057710fe1a4ce97122295afc5896a)) 35 | * **jwc-runtime:** vnode attrs do not be updated ([fb27f63](https://github.com/jwcjs/core/commit/fb27f63f86cc0320fffe2816c1df4b61b03a99de)) 36 | * **jwc-starter-vite-ts:** vite warning of css files ([0d70380](https://github.com/jwcjs/core/commit/0d70380782f198f28d6c3282b166dc67944422ca)) 37 | * **reactively:** circular dependency ([a324244](https://github.com/jwcjs/core/commit/a3242443cf1eee82cd569e41024f366ab442ffea)) 38 | * **reactively:** circular dependency ([#12](https://github.com/jwcjs/core/issues/12)) ([40075cc](https://github.com/jwcjs/core/commit/40075cc0de9ac11c28da434ad8171dfb7e54c569)) 39 | * **runtime:** dom functions in circular dependency ([3b2f54a](https://github.com/jwcjs/core/commit/3b2f54a280f5e0026af59ec01b75c2f16dba8218)) 40 | * type defination ([f7ae05e](https://github.com/jwcjs/core/commit/f7ae05efd5a87384884cc7cd0f4f1573d46ceb50)) 41 | 42 | 43 | ### Features 44 | 45 | * cli commands ([e22c311](https://github.com/jwcjs/core/commit/e22c311f18795ae59de89868699d322a276dbf7d)) 46 | * core bundle ([#7](https://github.com/jwcjs/core/issues/7)) ([e34655d](https://github.com/jwcjs/core/commit/e34655dd60e10ca7af0a2cd96803fbce3042c200)) 47 | * event listener ([32c5040](https://github.com/jwcjs/core/commit/32c5040f2aeabf4ca0e1e86427f8ed00b3b63211)) 48 | * JSX types support ([#2](https://github.com/jwcjs/core/issues/2)) ([f33f673](https://github.com/jwcjs/core/commit/f33f673a6e448a1767e66dd58139841188d6bc64)) 49 | * **jwc-core:** base JwcComponent class ([699acba](https://github.com/jwcjs/core/commit/699acbab580dd6af0e941667bc37fb7bcb9c604a)) 50 | * **jwc-core:** element and watcher interfaces ([896b4d1](https://github.com/jwcjs/core/commit/896b4d10bbc3c8afbe026addaf28ebb395fec785)) 51 | * **jwc-core:** init shadow root and css style ([c850cf6](https://github.com/jwcjs/core/commit/c850cf656e0d1f0272af8ef20153dc108191a284)) 52 | * **jwc-core:** init watcher in wc ([f03f9d7](https://github.com/jwcjs/core/commit/f03f9d76625387ae8aadbbfc723c7ba7c07e3f11)) 53 | * **jwc-core:** reactively decorators ([2e1e1f5](https://github.com/jwcjs/core/commit/2e1e1f534341b644a6af247161cfefac88709942)) 54 | * **jwc-core:** register custom element ([fada8a7](https://github.com/jwcjs/core/commit/fada8a7464e21153a06039c23177744dffc17930)) 55 | * **jwc-core:** transform attrs to props ([f027d79](https://github.com/jwcjs/core/commit/f027d7978718b9696e27040a62643845948de44b)) 56 | * **jwc-reactively:** base reactive data handler ([63e74c6](https://github.com/jwcjs/core/commit/63e74c68233987d8d4179432541e36e156c2c4e9)) 57 | * **jwc-reactively:** create css element with css text ([e72cb55](https://github.com/jwcjs/core/commit/e72cb555db4f6dc08d6bdbfac21fcb6aa82cb79e)) 58 | * **jwc-reactively:** define data and event by proxy ([a39e943](https://github.com/jwcjs/core/commit/a39e943ec9b8476843db8f7cc5f2ba1c00e6dd87)) 59 | * **jwc-reactively:** define reactively props datas ([d023082](https://github.com/jwcjs/core/commit/d0230826b997855d494a655306b17c4b88b0eac3)) 60 | * **jwc-runtime:** `` support ([#4](https://github.com/jwcjs/core/issues/4)) ([1edd095](https://github.com/jwcjs/core/commit/1edd095a50c9d85ba91b2ac7920985f00680f889)) 61 | * **jwc-runtime:** reactively support ([#1](https://github.com/jwcjs/core/issues/1)) ([25680d3](https://github.com/jwcjs/core/commit/25680d30aaaf28667ff1727c52956962eb50198d)) 62 | * **jwc-starter-vite-ts:** create a vite starter template ([76be0cc](https://github.com/jwcjs/core/commit/76be0cc8f5200829125dcb0d95d7154bfeed84f3)) 63 | * starter vite config ([b41a115](https://github.com/jwcjs/core/commit/b41a115db92b012e5522aafff0d39f09e871c3c4)) 64 | * use cli to create project ([9ace584](https://github.com/jwcjs/core/commit/9ace5840ce21dc117ec3bb25354b16292198f434)) 65 | * **v-dom:** diff function ([3aac67f](https://github.com/jwcjs/core/commit/3aac67f35915f92e2a3a27b16a014dacaa662caa)) 66 | * **v-dom:** h create vnode function ([852dc11](https://github.com/jwcjs/core/commit/852dc118ffb518909ed702b1b3ac6554d5a6d7db)) 67 | 68 | 69 | ### Performance Improvements 70 | 71 | * export modules in core ([#3](https://github.com/jwcjs/core/issues/3)) ([9672b8f](https://github.com/jwcjs/core/commit/9672b8f7269ad1ef57dc0072e0a49840b2e44030)) 72 | * **jwc-core:** `*.css` file types support ([105b133](https://github.com/jwcjs/core/commit/105b133de959a1d70fd64067a14ac97647f7463c)) 73 | * **jwc-starter:** import vite client env ([0e72b92](https://github.com/jwcjs/core/commit/0e72b9262779b3c939c3a1c42fb460772a103660)) 74 | * remove useless things ([8af7171](https://github.com/jwcjs/core/commit/8af7171a46b42e82446539b49b59052e6a0dd8f4)) 75 | 76 | 77 | ### Reverts 78 | 79 | * remove a exist file ([f3f5620](https://github.com/jwcjs/core/commit/f3f5620ad9b72cedf3f2d9111deed40dd458749e)) 80 | * remove a wrong usage ([15d0479](https://github.com/jwcjs/core/commit/15d0479a1db294bc44764cb3ef0ff58ce7c5a09b)) 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /packages/shared/src/types/local-jsx.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Jwc.js 2 | // Definitions by: wibus-wee 3 | // Thanks to: DefinitelyTyped 4 | // ReactJS 5 | 6 | import { h } from "@jwcjs/runtime"; 7 | import * as CSS from "csstype"; 8 | 9 | type Booleanish = boolean | "true" | "false"; 10 | type NativeAnimationEvent = AnimationEvent; 11 | type NativeClipboardEvent = ClipboardEvent; 12 | type NativeCompositionEvent = CompositionEvent; 13 | type NativeDragEvent = DragEvent; 14 | type NativeFocusEvent = FocusEvent; 15 | type NativeKeyboardEvent = KeyboardEvent; 16 | type NativeMouseEvent = MouseEvent; 17 | type NativeTouchEvent = TouchEvent; 18 | type NativePointerEvent = PointerEvent; 19 | type NativeTransitionEvent = TransitionEvent; 20 | type NativeUIEvent = UIEvent; 21 | type NativeWheelEvent = WheelEvent; 22 | 23 | export type CSSProperties = CSS.Properties; 24 | 25 | declare global { 26 | // eslint-disable-next-line @typescript-eslint/no-namespace 27 | namespace JSX { 28 | // 29 | // Event System 30 | // ---------------------------------------------------------------------- 31 | // TODO: change any to unknown when moving to TS v3 32 | interface BaseSyntheticEvent { 33 | nativeEvent: E; 34 | currentTarget: C; 35 | target: T; 36 | bubbles: boolean; 37 | cancelable: boolean; 38 | defaultPrevented: boolean; 39 | eventPhase: number; 40 | isTrusted: boolean; 41 | preventDefault(): void; 42 | isDefaultPrevented(): boolean; 43 | stopPropagation(): void; 44 | isPropagationStopped(): boolean; 45 | persist(): void; 46 | timeStamp: number; 47 | type: string; 48 | } 49 | 50 | // 51 | // Browser Interfaces 52 | // https://github.com/nikeee/2048-typescript/blob/master/2048/js/touch.d.ts 53 | // ---------------------------------------------------------------------- 54 | 55 | interface AbstractView { 56 | styleMedia: StyleMedia; 57 | document: Document; 58 | } 59 | 60 | interface Touch { 61 | identifier: number; 62 | target: EventTarget; 63 | screenX: number; 64 | screenY: number; 65 | clientX: number; 66 | clientY: number; 67 | pageX: number; 68 | pageY: number; 69 | } 70 | 71 | interface TouchList { 72 | [index: number]: Touch; 73 | length: number; 74 | item(index: number): Touch; 75 | identifiedTouch(identifier: number): Touch; 76 | } 77 | 78 | // 79 | // Error Interfaces 80 | // ---------------------------------------------------------------------- 81 | interface ErrorInfo { 82 | /** 83 | * Captures which component contained the exception, and its ancestors. 84 | */ 85 | componentStack: string; 86 | } 87 | 88 | /** 89 | * currentTarget - a reference to the element on which the event listener is registered. 90 | * 91 | * target - a reference to the element from which the event was originally dispatched. 92 | * This might be a child element to the element on which the event listener is registered. 93 | * If you thought this should be `EventTarget & T`, see https://github.com/DefinitelyTyped/DefinitelyTyped/issues/11508#issuecomment-256045682 94 | */ 95 | type SyntheticEvent = BaseSyntheticEvent< 96 | E, 97 | EventTarget & T, 98 | EventTarget 99 | >; 100 | interface ClipboardEvent 101 | extends SyntheticEvent { 102 | clipboardData: DataTransfer; 103 | } 104 | 105 | interface CompositionEvent 106 | extends SyntheticEvent { 107 | data: string; 108 | } 109 | 110 | interface DragEvent 111 | extends MouseEvent { 112 | dataTransfer: DataTransfer; 113 | } 114 | 115 | interface PointerEvent 116 | extends MouseEvent { 117 | pointerId: number; 118 | pressure: number; 119 | tangentialPressure: number; 120 | tiltX: number; 121 | tiltY: number; 122 | twist: number; 123 | width: number; 124 | height: number; 125 | pointerType: "mouse" | "pen" | "touch"; 126 | isPrimary: boolean; 127 | } 128 | 129 | interface FocusEvent 130 | extends SyntheticEvent { 131 | relatedTarget: (EventTarget & RelatedTarget) | null; 132 | target: EventTarget & Target; 133 | } 134 | 135 | type FormEvent = SyntheticEvent; 136 | 137 | interface InvalidEvent extends SyntheticEvent { 138 | target: EventTarget & T; 139 | } 140 | 141 | interface ChangeEvent extends SyntheticEvent { 142 | target: EventTarget & T; 143 | } 144 | 145 | export type ModifierKey = 146 | | "Alt" 147 | | "AltGraph" 148 | | "CapsLock" 149 | | "Control" 150 | | "Fn" 151 | | "FnLock" 152 | | "Hyper" 153 | | "Meta" 154 | | "NumLock" 155 | | "ScrollLock" 156 | | "Shift" 157 | | "Super" 158 | | "Symbol" 159 | | "SymbolLock"; 160 | 161 | interface KeyboardEvent 162 | extends UIEvent { 163 | altKey: boolean; 164 | /** @deprecated */ 165 | charCode: number; 166 | ctrlKey: boolean; 167 | code: string; 168 | /** 169 | * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. 170 | */ 171 | getModifierState(key: ModifierKey): boolean; 172 | /** 173 | * See the [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#named-key-attribute-values). for possible values 174 | */ 175 | key: string; 176 | /** @deprecated */ 177 | keyCode: number; 178 | locale: string; 179 | location: number; 180 | metaKey: boolean; 181 | repeat: boolean; 182 | shiftKey: boolean; 183 | /** @deprecated */ 184 | which: number; 185 | } 186 | 187 | interface MouseEvent 188 | extends UIEvent { 189 | altKey: boolean; 190 | button: number; 191 | buttons: number; 192 | clientX: number; 193 | clientY: number; 194 | ctrlKey: boolean; 195 | /** 196 | * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. 197 | */ 198 | getModifierState(key: ModifierKey): boolean; 199 | metaKey: boolean; 200 | movementX: number; 201 | movementY: number; 202 | pageX: number; 203 | pageY: number; 204 | relatedTarget: EventTarget | null; 205 | screenX: number; 206 | screenY: number; 207 | shiftKey: boolean; 208 | } 209 | 210 | interface TouchEvent extends UIEvent { 211 | altKey: boolean; 212 | changedTouches: TouchList; 213 | ctrlKey: boolean; 214 | /** 215 | * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. 216 | */ 217 | getModifierState(key: ModifierKey): boolean; 218 | metaKey: boolean; 219 | shiftKey: boolean; 220 | targetTouches: TouchList; 221 | touches: TouchList; 222 | } 223 | 224 | interface UIEvent 225 | extends SyntheticEvent { 226 | detail: number; 227 | view: AbstractView; 228 | } 229 | 230 | interface WheelEvent 231 | extends MouseEvent { 232 | deltaMode: number; 233 | deltaX: number; 234 | deltaY: number; 235 | deltaZ: number; 236 | } 237 | 238 | interface AnimationEvent 239 | extends SyntheticEvent { 240 | animationName: string; 241 | elapsedTime: number; 242 | pseudoElement: string; 243 | } 244 | 245 | interface TransitionEvent 246 | extends SyntheticEvent { 247 | elapsedTime: number; 248 | propertyName: string; 249 | pseudoElement: string; 250 | } 251 | 252 | type EventHandler> = { 253 | bivarianceHack(event: E): void; 254 | }["bivarianceHack"]; 255 | type JwcEventHandler = EventHandler>; 256 | 257 | type ClipboardEventHandler = EventHandler< 258 | ClipboardEvent 259 | >; 260 | type CompositionEventHandler = EventHandler< 261 | CompositionEvent 262 | >; 263 | type DragEventHandler = EventHandler>; 264 | type FocusEventHandler = EventHandler>; 265 | type FormEventHandler = EventHandler>; 266 | type ChangeEventHandler = EventHandler>; 267 | type KeyboardEventHandler = EventHandler>; 268 | type MouseEventHandler = EventHandler>; 269 | type TouchEventHandler = EventHandler>; 270 | type PointerEventHandler = EventHandler>; 271 | type UIEventHandler = EventHandler>; 272 | type WheelEventHandler = EventHandler>; 273 | type AnimationEventHandler = EventHandler< 274 | AnimationEvent 275 | >; 276 | type TransitionEventHandler = EventHandler< 277 | TransitionEvent 278 | >; 279 | 280 | // All the WAI-ARIA 1.1 role attribute values from https://www.w3.org/TR/wai-aria-1.1/#role_definitions 281 | type AriaRole = 282 | | "alert" 283 | | "alertdialog" 284 | | "application" 285 | | "article" 286 | | "banner" 287 | | "button" 288 | | "cell" 289 | | "checkbox" 290 | | "columnheader" 291 | | "combobox" 292 | | "complementary" 293 | | "contentinfo" 294 | | "definition" 295 | | "dialog" 296 | | "directory" 297 | | "document" 298 | | "feed" 299 | | "figure" 300 | | "form" 301 | | "grid" 302 | | "gridcell" 303 | | "group" 304 | | "heading" 305 | | "img" 306 | | "link" 307 | | "list" 308 | | "listbox" 309 | | "listitem" 310 | | "log" 311 | | "main" 312 | | "marquee" 313 | | "math" 314 | | "menu" 315 | | "menubar" 316 | | "menuitem" 317 | | "menuitemcheckbox" 318 | | "menuitemradio" 319 | | "navigation" 320 | | "none" 321 | | "note" 322 | | "option" 323 | | "presentation" 324 | | "progressbar" 325 | | "radio" 326 | | "radiogroup" 327 | | "region" 328 | | "row" 329 | | "rowgroup" 330 | | "rowheader" 331 | | "scrollbar" 332 | | "search" 333 | | "searchbox" 334 | | "separator" 335 | | "slider" 336 | | "spinbutton" 337 | | "status" 338 | | "switch" 339 | | "tab" 340 | | "table" 341 | | "tablist" 342 | | "tabpanel" 343 | | "term" 344 | | "textbox" 345 | | "timer" 346 | | "toolbar" 347 | | "tooltip" 348 | | "tree" 349 | | "treegrid" 350 | | "treeitem" 351 | | (string & {}); 352 | 353 | // All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/ 354 | interface AriaAttributes { 355 | /** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */ 356 | "aria-activedescendant"?: string | undefined; 357 | /** Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. */ 358 | "aria-atomic"?: Booleanish | undefined; 359 | /** 360 | * Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be 361 | * presented if they are made. 362 | */ 363 | "aria-autocomplete"?: 364 | | "none" 365 | | "inline" 366 | | "list" 367 | | "both" 368 | | undefined; 369 | /** Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user. */ 370 | "aria-busy"?: Booleanish | undefined; 371 | /** 372 | * Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. 373 | * @see aria-pressed @see aria-selected. 374 | */ 375 | "aria-checked"?: boolean | "false" | "mixed" | "true" | undefined; 376 | /** 377 | * Defines the total number of columns in a table, grid, or treegrid. 378 | * @see aria-colindex. 379 | */ 380 | "aria-colcount"?: number | undefined; 381 | /** 382 | * Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. 383 | * @see aria-colcount @see aria-colspan. 384 | */ 385 | "aria-colindex"?: number | undefined; 386 | /** 387 | * Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. 388 | * @see aria-colindex @see aria-rowspan. 389 | */ 390 | "aria-colspan"?: number | undefined; 391 | /** 392 | * Identifies the element (or elements) whose contents or presence are controlled by the current element. 393 | * @see aria-owns. 394 | */ 395 | "aria-controls"?: string | undefined; 396 | /** Indicates the element that represents the current item within a container or set of related elements. */ 397 | "aria-current"?: 398 | | boolean 399 | | "false" 400 | | "true" 401 | | "page" 402 | | "step" 403 | | "location" 404 | | "date" 405 | | "time" 406 | | undefined; 407 | /** 408 | * Identifies the element (or elements) that describes the object. 409 | * @see aria-labelledby 410 | */ 411 | "aria-describedby"?: string | undefined; 412 | /** 413 | * Identifies the element that provides a detailed, extended description for the object. 414 | * @see aria-describedby. 415 | */ 416 | "aria-details"?: string | undefined; 417 | /** 418 | * Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable. 419 | * @see aria-hidden @see aria-readonly. 420 | */ 421 | "aria-disabled"?: Booleanish | undefined; 422 | /** 423 | * Indicates what functions can be performed when a dragged object is released on the drop target. 424 | * @deprecated in ARIA 1.1 425 | */ 426 | "aria-dropeffect"?: 427 | | "none" 428 | | "copy" 429 | | "execute" 430 | | "link" 431 | | "move" 432 | | "popup" 433 | | undefined; 434 | /** 435 | * Identifies the element that provides an error message for the object. 436 | * @see aria-invalid @see aria-describedby. 437 | */ 438 | "aria-errormessage"?: string | undefined; 439 | /** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */ 440 | "aria-expanded"?: Booleanish | undefined; 441 | /** 442 | * Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, 443 | * allows assistive technology to override the general default of reading in document source order. 444 | */ 445 | "aria-flowto"?: string | undefined; 446 | /** 447 | * Indicates an element's "grabbed" state in a drag-and-drop operation. 448 | * @deprecated in ARIA 1.1 449 | */ 450 | "aria-grabbed"?: Booleanish | undefined; 451 | /** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */ 452 | "aria-haspopup"?: 453 | | boolean 454 | | "false" 455 | | "true" 456 | | "menu" 457 | | "listbox" 458 | | "tree" 459 | | "grid" 460 | | "dialog" 461 | | undefined; 462 | /** 463 | * Indicates whether the element is exposed to an accessibility API. 464 | * @see aria-disabled. 465 | */ 466 | "aria-hidden"?: Booleanish | undefined; 467 | /** 468 | * Indicates the entered value does not conform to the format expected by the application. 469 | * @see aria-errormessage. 470 | */ 471 | "aria-invalid"?: 472 | | boolean 473 | | "false" 474 | | "true" 475 | | "grammar" 476 | | "spelling" 477 | | undefined; 478 | /** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */ 479 | "aria-keyshortcuts"?: string | undefined; 480 | /** 481 | * Defines a string value that labels the current element. 482 | * @see aria-labelledby. 483 | */ 484 | "aria-label"?: string | undefined; 485 | /** 486 | * Identifies the element (or elements) that labels the current element. 487 | * @see aria-describedby. 488 | */ 489 | "aria-labelledby"?: string | undefined; 490 | /** Defines the hierarchical level of an element within a structure. */ 491 | "aria-level"?: number | undefined; 492 | /** Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. */ 493 | "aria-live"?: "off" | "assertive" | "polite" | undefined; 494 | /** Indicates whether an element is modal when displayed. */ 495 | "aria-modal"?: Booleanish | undefined; 496 | /** Indicates whether a text box accepts multiple lines of input or only a single line. */ 497 | "aria-multiline"?: Booleanish | undefined; 498 | /** Indicates that the user may select more than one item from the current selectable descendants. */ 499 | "aria-multiselectable"?: Booleanish | undefined; 500 | /** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */ 501 | "aria-orientation"?: "horizontal" | "vertical" | undefined; 502 | /** 503 | * Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship 504 | * between DOM elements where the DOM hierarchy cannot be used to represent the relationship. 505 | * @see aria-controls. 506 | */ 507 | "aria-owns"?: string | undefined; 508 | /** 509 | * Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. 510 | * A hint could be a sample value or a brief description of the expected format. 511 | */ 512 | "aria-placeholder"?: string | undefined; 513 | /** 514 | * Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. 515 | * @see aria-setsize. 516 | */ 517 | "aria-posinset"?: number | undefined; 518 | /** 519 | * Indicates the current "pressed" state of toggle buttons. 520 | * @see aria-checked @see aria-selected. 521 | */ 522 | "aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined; 523 | /** 524 | * Indicates that the element is not editable, but is otherwise operable. 525 | * @see aria-disabled. 526 | */ 527 | "aria-readonly"?: Booleanish | undefined; 528 | /** 529 | * Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. 530 | * @see aria-atomic. 531 | */ 532 | "aria-relevant"?: 533 | | "additions" 534 | | "additions removals" 535 | | "additions text" 536 | | "all" 537 | | "removals" 538 | | "removals additions" 539 | | "removals text" 540 | | "text" 541 | | "text additions" 542 | | "text removals" 543 | | undefined; 544 | /** Indicates that user input is required on the element before a form may be submitted. */ 545 | "aria-required"?: Booleanish | undefined; 546 | /** Defines a human-readable, author-localized description for the role of an element. */ 547 | "aria-roledescription"?: string | undefined; 548 | /** 549 | * Defines the total number of rows in a table, grid, or treegrid. 550 | * @see aria-rowindex. 551 | */ 552 | "aria-rowcount"?: number | undefined; 553 | /** 554 | * Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. 555 | * @see aria-rowcount @see aria-rowspan. 556 | */ 557 | "aria-rowindex"?: number | undefined; 558 | /** 559 | * Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. 560 | * @see aria-rowindex @see aria-colspan. 561 | */ 562 | "aria-rowspan"?: number | undefined; 563 | /** 564 | * Indicates the current "selected" state of various widgets. 565 | * @see aria-checked @see aria-pressed. 566 | */ 567 | "aria-selected"?: Booleanish | undefined; 568 | /** 569 | * Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. 570 | * @see aria-posinset. 571 | */ 572 | "aria-setsize"?: number | undefined; 573 | /** Indicates if items in a table or grid are sorted in ascending or descending order. */ 574 | "aria-sort"?: 575 | | "none" 576 | | "ascending" 577 | | "descending" 578 | | "other" 579 | | undefined; 580 | /** Defines the maximum allowed value for a range widget. */ 581 | "aria-valuemax"?: number | undefined; 582 | /** Defines the minimum allowed value for a range widget. */ 583 | "aria-valuemin"?: number | undefined; 584 | /** 585 | * Defines the current value for a range widget. 586 | * @see aria-valuetext. 587 | */ 588 | "aria-valuenow"?: number | undefined; 589 | /** Defines the human readable text alternative of aria-valuenow for a range widget. */ 590 | "aria-valuetext"?: string | undefined; 591 | } 592 | 593 | interface DOMAttributes { 594 | children?: typeof h | string | number | boolean | null | undefined; 595 | dangerouslySetInnerHTML?: 596 | | { 597 | __html: string; 598 | } 599 | | undefined; 600 | 601 | // Clipboard Events 602 | onCopy?: ClipboardEventHandler | undefined; 603 | onCopyCapture?: ClipboardEventHandler | undefined; 604 | onCut?: ClipboardEventHandler | undefined; 605 | onCutCapture?: ClipboardEventHandler | undefined; 606 | onPaste?: ClipboardEventHandler | undefined; 607 | onPasteCapture?: ClipboardEventHandler | undefined; 608 | 609 | // Composition Events 610 | onCompositionEnd?: CompositionEventHandler | undefined; 611 | onCompositionEndCapture?: CompositionEventHandler | undefined; 612 | onCompositionStart?: CompositionEventHandler | undefined; 613 | onCompositionStartCapture?: CompositionEventHandler | undefined; 614 | onCompositionUpdate?: CompositionEventHandler | undefined; 615 | onCompositionUpdateCapture?: CompositionEventHandler | undefined; 616 | 617 | // Focus Events 618 | onFocus?: FocusEventHandler | undefined; 619 | onFocusCapture?: FocusEventHandler | undefined; 620 | onBlur?: FocusEventHandler | undefined; 621 | onBlurCapture?: FocusEventHandler | undefined; 622 | 623 | // Form Events 624 | onChange?: FormEventHandler | undefined; 625 | onChangeCapture?: FormEventHandler | undefined; 626 | onBeforeInput?: FormEventHandler | undefined; 627 | onBeforeInputCapture?: FormEventHandler | undefined; 628 | onInput?: FormEventHandler | undefined; 629 | onInputCapture?: FormEventHandler | undefined; 630 | onReset?: FormEventHandler | undefined; 631 | onResetCapture?: FormEventHandler | undefined; 632 | onSubmit?: FormEventHandler | undefined; 633 | onSubmitCapture?: FormEventHandler | undefined; 634 | onInvalid?: FormEventHandler | undefined; 635 | onInvalidCapture?: FormEventHandler | undefined; 636 | 637 | // Image Events 638 | onLoad?: JwcEventHandler | undefined; 639 | onLoadCapture?: JwcEventHandler | undefined; 640 | onError?: JwcEventHandler | undefined; // also a Media Event 641 | onErrorCapture?: JwcEventHandler | undefined; // also a Media Event 642 | 643 | // Keyboard Events 644 | onKeyDown?: KeyboardEventHandler | undefined; 645 | onKeyDownCapture?: KeyboardEventHandler | undefined; 646 | /** @deprecated */ 647 | onKeyPress?: KeyboardEventHandler | undefined; 648 | /** @deprecated */ 649 | onKeyPressCapture?: KeyboardEventHandler | undefined; 650 | onKeyUp?: KeyboardEventHandler | undefined; 651 | onKeyUpCapture?: KeyboardEventHandler | undefined; 652 | 653 | // Media Events 654 | onAbort?: JwcEventHandler | undefined; 655 | onAbortCapture?: JwcEventHandler | undefined; 656 | onCanPlay?: JwcEventHandler | undefined; 657 | onCanPlayCapture?: JwcEventHandler | undefined; 658 | onCanPlayThrough?: JwcEventHandler | undefined; 659 | onCanPlayThroughCapture?: JwcEventHandler | undefined; 660 | onDurationChange?: JwcEventHandler | undefined; 661 | onDurationChangeCapture?: JwcEventHandler | undefined; 662 | onEmptied?: JwcEventHandler | undefined; 663 | onEmptiedCapture?: JwcEventHandler | undefined; 664 | onEncrypted?: JwcEventHandler | undefined; 665 | onEncryptedCapture?: JwcEventHandler | undefined; 666 | onEnded?: JwcEventHandler | undefined; 667 | onEndedCapture?: JwcEventHandler | undefined; 668 | onLoadedData?: JwcEventHandler | undefined; 669 | onLoadedDataCapture?: JwcEventHandler | undefined; 670 | onLoadedMetadata?: JwcEventHandler | undefined; 671 | onLoadedMetadataCapture?: JwcEventHandler | undefined; 672 | onLoadStart?: JwcEventHandler | undefined; 673 | onLoadStartCapture?: JwcEventHandler | undefined; 674 | onPause?: JwcEventHandler | undefined; 675 | onPauseCapture?: JwcEventHandler | undefined; 676 | onPlay?: JwcEventHandler | undefined; 677 | onPlayCapture?: JwcEventHandler | undefined; 678 | onPlaying?: JwcEventHandler | undefined; 679 | onPlayingCapture?: JwcEventHandler | undefined; 680 | onProgress?: JwcEventHandler | undefined; 681 | onProgressCapture?: JwcEventHandler | undefined; 682 | onRateChange?: JwcEventHandler | undefined; 683 | onRateChangeCapture?: JwcEventHandler | undefined; 684 | onResize?: JwcEventHandler | undefined; 685 | onResizeCapture?: JwcEventHandler | undefined; 686 | onSeeked?: JwcEventHandler | undefined; 687 | onSeekedCapture?: JwcEventHandler | undefined; 688 | onSeeking?: JwcEventHandler | undefined; 689 | onSeekingCapture?: JwcEventHandler | undefined; 690 | onStalled?: JwcEventHandler | undefined; 691 | onStalledCapture?: JwcEventHandler | undefined; 692 | onSuspend?: JwcEventHandler | undefined; 693 | onSuspendCapture?: JwcEventHandler | undefined; 694 | onTimeUpdate?: JwcEventHandler | undefined; 695 | onTimeUpdateCapture?: JwcEventHandler | undefined; 696 | onVolumeChange?: JwcEventHandler | undefined; 697 | onVolumeChangeCapture?: JwcEventHandler | undefined; 698 | onWaiting?: JwcEventHandler | undefined; 699 | onWaitingCapture?: JwcEventHandler | undefined; 700 | 701 | // MouseEvents 702 | onAuxClick?: MouseEventHandler | undefined; 703 | onAuxClickCapture?: MouseEventHandler | undefined; 704 | onClick?: MouseEventHandler | undefined; 705 | onClickCapture?: MouseEventHandler | undefined; 706 | onContextMenu?: MouseEventHandler | undefined; 707 | onContextMenuCapture?: MouseEventHandler | undefined; 708 | onDoubleClick?: MouseEventHandler | undefined; 709 | onDoubleClickCapture?: MouseEventHandler | undefined; 710 | onDrag?: DragEventHandler | undefined; 711 | onDragCapture?: DragEventHandler | undefined; 712 | onDragEnd?: DragEventHandler | undefined; 713 | onDragEndCapture?: DragEventHandler | undefined; 714 | onDragEnter?: DragEventHandler | undefined; 715 | onDragEnterCapture?: DragEventHandler | undefined; 716 | onDragExit?: DragEventHandler | undefined; 717 | onDragExitCapture?: DragEventHandler | undefined; 718 | onDragLeave?: DragEventHandler | undefined; 719 | onDragLeaveCapture?: DragEventHandler | undefined; 720 | onDragOver?: DragEventHandler | undefined; 721 | onDragOverCapture?: DragEventHandler | undefined; 722 | onDragStart?: DragEventHandler | undefined; 723 | onDragStartCapture?: DragEventHandler | undefined; 724 | onDrop?: DragEventHandler | undefined; 725 | onDropCapture?: DragEventHandler | undefined; 726 | onMouseDown?: MouseEventHandler | undefined; 727 | onMouseDownCapture?: MouseEventHandler | undefined; 728 | onMouseEnter?: MouseEventHandler | undefined; 729 | onMouseLeave?: MouseEventHandler | undefined; 730 | onMouseMove?: MouseEventHandler | undefined; 731 | onMouseMoveCapture?: MouseEventHandler | undefined; 732 | onMouseOut?: MouseEventHandler | undefined; 733 | onMouseOutCapture?: MouseEventHandler | undefined; 734 | onMouseOver?: MouseEventHandler | undefined; 735 | onMouseOverCapture?: MouseEventHandler | undefined; 736 | onMouseUp?: MouseEventHandler | undefined; 737 | onMouseUpCapture?: MouseEventHandler | undefined; 738 | 739 | // Selection Events 740 | onSelect?: JwcEventHandler | undefined; 741 | onSelectCapture?: JwcEventHandler | undefined; 742 | 743 | // Touch Events 744 | onTouchCancel?: TouchEventHandler | undefined; 745 | onTouchCancelCapture?: TouchEventHandler | undefined; 746 | onTouchEnd?: TouchEventHandler | undefined; 747 | onTouchEndCapture?: TouchEventHandler | undefined; 748 | onTouchMove?: TouchEventHandler | undefined; 749 | onTouchMoveCapture?: TouchEventHandler | undefined; 750 | onTouchStart?: TouchEventHandler | undefined; 751 | onTouchStartCapture?: TouchEventHandler | undefined; 752 | 753 | // Pointer Events 754 | onPointerDown?: PointerEventHandler | undefined; 755 | onPointerDownCapture?: PointerEventHandler | undefined; 756 | onPointerMove?: PointerEventHandler | undefined; 757 | onPointerMoveCapture?: PointerEventHandler | undefined; 758 | onPointerUp?: PointerEventHandler | undefined; 759 | onPointerUpCapture?: PointerEventHandler | undefined; 760 | onPointerCancel?: PointerEventHandler | undefined; 761 | onPointerCancelCapture?: PointerEventHandler | undefined; 762 | onPointerEnter?: PointerEventHandler | undefined; 763 | onPointerEnterCapture?: PointerEventHandler | undefined; 764 | onPointerLeave?: PointerEventHandler | undefined; 765 | onPointerLeaveCapture?: PointerEventHandler | undefined; 766 | onPointerOver?: PointerEventHandler | undefined; 767 | onPointerOverCapture?: PointerEventHandler | undefined; 768 | onPointerOut?: PointerEventHandler | undefined; 769 | onPointerOutCapture?: PointerEventHandler | undefined; 770 | onGotPointerCapture?: PointerEventHandler | undefined; 771 | onGotPointerCaptureCapture?: PointerEventHandler | undefined; 772 | onLostPointerCapture?: PointerEventHandler | undefined; 773 | onLostPointerCaptureCapture?: PointerEventHandler | undefined; 774 | 775 | // UI Events 776 | onScroll?: UIEventHandler | undefined; 777 | onScrollCapture?: UIEventHandler | undefined; 778 | 779 | // Wheel Events 780 | onWheel?: WheelEventHandler | undefined; 781 | onWheelCapture?: WheelEventHandler | undefined; 782 | 783 | // Animation Events 784 | onAnimationStart?: AnimationEventHandler | undefined; 785 | onAnimationStartCapture?: AnimationEventHandler | undefined; 786 | onAnimationEnd?: AnimationEventHandler | undefined; 787 | onAnimationEndCapture?: AnimationEventHandler | undefined; 788 | onAnimationIteration?: AnimationEventHandler | undefined; 789 | onAnimationIterationCapture?: AnimationEventHandler | undefined; 790 | 791 | // Transition Events 792 | onTransitionEnd?: TransitionEventHandler | undefined; 793 | onTransitionEndCapture?: TransitionEventHandler | undefined; 794 | } 795 | 796 | interface HTMLAttributes extends AriaAttributes, DOMAttributes { 797 | // React-specific Attributes 798 | defaultChecked?: boolean | undefined; 799 | defaultValue?: string | number | ReadonlyArray | undefined; 800 | suppressContentEditableWarning?: boolean | undefined; 801 | suppressHydrationWarning?: boolean | undefined; 802 | 803 | // Standard HTML Attributes 804 | accessKey?: string | undefined; 805 | class?: string | undefined; 806 | contentEditable?: Booleanish | "inherit" | undefined; 807 | contextMenu?: string | undefined; 808 | dir?: string | undefined; 809 | draggable?: Booleanish | undefined; 810 | hidden?: boolean | undefined; 811 | id?: string | undefined; 812 | lang?: string | undefined; 813 | nonce?: string | undefined; 814 | placeholder?: string | undefined; 815 | slot?: string | undefined; 816 | spellCheck?: Booleanish | undefined; 817 | style?: CSSProperties | undefined; 818 | tabIndex?: number | undefined; 819 | title?: string | undefined; 820 | translate?: "yes" | "no" | undefined; 821 | 822 | // Unknown 823 | radioGroup?: string | undefined; // , 824 | 825 | // WAI-ARIA 826 | role?: AriaRole | undefined; 827 | 828 | // RDFa Attributes 829 | about?: string | undefined; 830 | datatype?: string | undefined; 831 | inlist?: any; 832 | prefix?: string | undefined; 833 | property?: string | undefined; 834 | resource?: string | undefined; 835 | typeof?: string | undefined; 836 | vocab?: string | undefined; 837 | 838 | // Non-standard Attributes 839 | autoCapitalize?: string | undefined; 840 | autoCorrect?: string | undefined; 841 | autoSave?: string | undefined; 842 | color?: string | undefined; 843 | itemProp?: string | undefined; 844 | itemScope?: boolean | undefined; 845 | itemType?: string | undefined; 846 | itemID?: string | undefined; 847 | itemRef?: string | undefined; 848 | results?: number | undefined; 849 | security?: string | undefined; 850 | unselectable?: "on" | "off" | undefined; 851 | 852 | // Living Standard 853 | /** 854 | * Hints at the type of data that might be entered by the user while editing the element or its contents 855 | * @see https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute 856 | */ 857 | inputMode?: 858 | | "none" 859 | | "text" 860 | | "tel" 861 | | "url" 862 | | "email" 863 | | "numeric" 864 | | "decimal" 865 | | "search" 866 | | undefined; 867 | /** 868 | * Specify that a standard HTML element should behave like a defined custom built-in element 869 | * @see https://html.spec.whatwg.org/multipage/custom-elements.html#attr-is 870 | */ 871 | is?: string | undefined; 872 | } 873 | 874 | type HTMLAttributeAnchorTarget = 875 | | "_self" 876 | | "_blank" 877 | | "_parent" 878 | | "_top" 879 | | (string & {}); 880 | 881 | export interface AnchorHTMLAttributes extends HTMLAttributes { 882 | download?: any; 883 | href?: string | undefined; 884 | hrefLang?: string | undefined; 885 | media?: string | undefined; 886 | rel?: string | undefined; 887 | target?: HTMLAttributeAnchorTarget | undefined; 888 | type?: string | undefined; 889 | referrePolicy?: ReferrerPolicy | undefined; 890 | } 891 | 892 | type AudioHTMLAttributes = MediaHTMLAttributes; 893 | 894 | interface AreaHTMLAttributes extends HTMLAttributes { 895 | alt?: string | undefined; 896 | coords?: string | undefined; 897 | download?: any; 898 | href?: string | undefined; 899 | hrefLang?: string | undefined; 900 | media?: string | undefined; 901 | referrerPolicy?: ReferrerPolicy | undefined; 902 | rel?: string | undefined; 903 | shape?: string | undefined; 904 | target?: string | undefined; 905 | } 906 | 907 | interface BaseHTMLAttributes extends HTMLAttributes { 908 | href?: string | undefined; 909 | target?: string | undefined; 910 | } 911 | 912 | interface BlockquoteHTMLAttributes extends HTMLAttributes { 913 | cite?: string | undefined; 914 | } 915 | 916 | interface ButtonHTMLAttributes extends HTMLAttributes { 917 | autoFocus?: boolean | undefined; 918 | disabled?: boolean | undefined; 919 | form?: string | undefined; 920 | formAction?: string | undefined; 921 | formEncType?: string | undefined; 922 | formMethod?: string | undefined; 923 | formNoValidate?: boolean | undefined; 924 | formTarget?: string | undefined; 925 | name?: string | undefined; 926 | type?: "submit" | "reset" | "button" | undefined; 927 | value?: string | ReadonlyArray | number | undefined; 928 | } 929 | 930 | interface CanvasHTMLAttributes extends HTMLAttributes { 931 | height?: number | string | undefined; 932 | width?: number | string | undefined; 933 | } 934 | 935 | interface ColHTMLAttributes extends HTMLAttributes { 936 | span?: number | undefined; 937 | width?: number | string | undefined; 938 | } 939 | 940 | interface ColgroupHTMLAttributes extends HTMLAttributes { 941 | span?: number | undefined; 942 | } 943 | 944 | interface DataHTMLAttributes extends HTMLAttributes { 945 | value?: string | ReadonlyArray | number | undefined; 946 | } 947 | 948 | interface DetailsHTMLAttributes extends HTMLAttributes { 949 | open?: boolean | undefined; 950 | onToggle?: JwcEventHandler | undefined; 951 | } 952 | 953 | interface DelHTMLAttributes extends HTMLAttributes { 954 | cite?: string | undefined; 955 | dateTime?: string | undefined; 956 | } 957 | 958 | interface DialogHTMLAttributes extends HTMLAttributes { 959 | onCancel?: JwcEventHandler | undefined; 960 | onClose?: JwcEventHandler | undefined; 961 | open?: boolean | undefined; 962 | } 963 | 964 | interface EmbedHTMLAttributes extends HTMLAttributes { 965 | height?: number | string | undefined; 966 | src?: string | undefined; 967 | type?: string | undefined; 968 | width?: number | string | undefined; 969 | } 970 | 971 | interface FieldsetHTMLAttributes extends HTMLAttributes { 972 | disabled?: boolean | undefined; 973 | form?: string | undefined; 974 | name?: string | undefined; 975 | } 976 | 977 | interface FormHTMLAttributes extends HTMLAttributes { 978 | acceptCharset?: string | undefined; 979 | action?: string | undefined; 980 | autoComplete?: string | undefined; 981 | encType?: string | undefined; 982 | method?: string | undefined; 983 | name?: string | undefined; 984 | noValidate?: boolean | undefined; 985 | target?: string | undefined; 986 | rel?: string | undefined; 987 | } 988 | 989 | interface HtmlHTMLAttributes extends HTMLAttributes { 990 | manifest?: string | undefined; 991 | } 992 | 993 | interface IframeHTMLAttributes extends HTMLAttributes { 994 | allow?: string | undefined; 995 | allowFullScreen?: boolean | undefined; 996 | allowTransparency?: boolean | undefined; 997 | /** @deprecated */ 998 | frameBorder?: number | string | undefined; 999 | height?: number | string | undefined; 1000 | loading?: "eager" | "lazy" | undefined; 1001 | /** @deprecated */ 1002 | marginHeight?: number | undefined; 1003 | /** @deprecated */ 1004 | marginWidth?: number | undefined; 1005 | name?: string | undefined; 1006 | referrerPolicy?: ReferrerPolicy | undefined; 1007 | sandbox?: string | undefined; 1008 | /** @deprecated */ 1009 | scrolling?: string | undefined; 1010 | seamless?: boolean | undefined; 1011 | src?: string | undefined; 1012 | srcDoc?: string | undefined; 1013 | width?: number | string | undefined; 1014 | } 1015 | 1016 | interface ImgHTMLAttributes extends HTMLAttributes { 1017 | alt?: string | undefined; 1018 | crossOrigin?: "anonymous" | "use-credentials" | "" | undefined; 1019 | decoding?: "async" | "auto" | "sync" | undefined; 1020 | height?: number | string | undefined; 1021 | loading?: "eager" | "lazy" | undefined; 1022 | referrerPolicy?: ReferrerPolicy | undefined; 1023 | sizes?: string | undefined; 1024 | src?: string | undefined; 1025 | srcSet?: string | undefined; 1026 | useMap?: string | undefined; 1027 | width?: number | string | undefined; 1028 | } 1029 | 1030 | interface InsHTMLAttributes extends HTMLAttributes { 1031 | cite?: string | undefined; 1032 | dateTime?: string | undefined; 1033 | } 1034 | 1035 | type HTMLInputTypeAttribute = 1036 | | "button" 1037 | | "checkbox" 1038 | | "color" 1039 | | "date" 1040 | | "datetime-local" 1041 | | "email" 1042 | | "file" 1043 | | "hidden" 1044 | | "image" 1045 | | "month" 1046 | | "number" 1047 | | "password" 1048 | | "radio" 1049 | | "range" 1050 | | "reset" 1051 | | "search" 1052 | | "submit" 1053 | | "tel" 1054 | | "text" 1055 | | "time" 1056 | | "url" 1057 | | "week" 1058 | | (string & {}); 1059 | 1060 | interface InputHTMLAttributes extends HTMLAttributes { 1061 | accept?: string | undefined; 1062 | alt?: string | undefined; 1063 | autoComplete?: string | undefined; 1064 | autoFocus?: boolean | undefined; 1065 | capture?: boolean | "user" | "environment" | undefined; // https://www.w3.org/TR/html-media-capture/#the-capture-attribute 1066 | checked?: boolean | undefined; 1067 | crossOrigin?: string | undefined; 1068 | disabled?: boolean | undefined; 1069 | enterKeyHint?: 1070 | | "enter" 1071 | | "done" 1072 | | "go" 1073 | | "next" 1074 | | "previous" 1075 | | "search" 1076 | | "send" 1077 | | undefined; 1078 | form?: string | undefined; 1079 | formAction?: string | undefined; 1080 | formEncType?: string | undefined; 1081 | formMethod?: string | undefined; 1082 | formNoValidate?: boolean | undefined; 1083 | formTarget?: string | undefined; 1084 | height?: number | string | undefined; 1085 | list?: string | undefined; 1086 | max?: number | string | undefined; 1087 | maxLength?: number | undefined; 1088 | min?: number | string | undefined; 1089 | minLength?: number | undefined; 1090 | multiple?: boolean | undefined; 1091 | name?: string | undefined; 1092 | pattern?: string | undefined; 1093 | placeholder?: string | undefined; 1094 | readOnly?: boolean | undefined; 1095 | required?: boolean | undefined; 1096 | size?: number | undefined; 1097 | src?: string | undefined; 1098 | step?: number | string | undefined; 1099 | type?: HTMLInputTypeAttribute | undefined; 1100 | value?: string | ReadonlyArray | number | undefined; 1101 | width?: number | string | undefined; 1102 | 1103 | onChange?: ChangeEventHandler | undefined; 1104 | } 1105 | 1106 | interface KeygenHTMLAttributes extends HTMLAttributes { 1107 | autoFocus?: boolean | undefined; 1108 | challenge?: string | undefined; 1109 | disabled?: boolean | undefined; 1110 | form?: string | undefined; 1111 | keyType?: string | undefined; 1112 | keyParams?: string | undefined; 1113 | name?: string | undefined; 1114 | } 1115 | 1116 | interface LabelHTMLAttributes extends HTMLAttributes { 1117 | form?: string | undefined; 1118 | htmlFor?: string | undefined; 1119 | } 1120 | 1121 | interface LiHTMLAttributes extends HTMLAttributes { 1122 | value?: string | ReadonlyArray | number | undefined; 1123 | } 1124 | 1125 | interface LinkHTMLAttributes extends HTMLAttributes { 1126 | as?: string | undefined; 1127 | crossOrigin?: string | undefined; 1128 | href?: string | undefined; 1129 | hrefLang?: string | undefined; 1130 | integrity?: string | undefined; 1131 | media?: string | undefined; 1132 | imageSrcSet?: string | undefined; 1133 | imageSizes?: string | undefined; 1134 | referrerPolicy?: ReferrerPolicy | undefined; 1135 | rel?: string | undefined; 1136 | sizes?: string | undefined; 1137 | type?: string | undefined; 1138 | charSet?: string | undefined; 1139 | } 1140 | 1141 | interface MapHTMLAttributes extends HTMLAttributes { 1142 | name?: string | undefined; 1143 | } 1144 | 1145 | interface MenuHTMLAttributes extends HTMLAttributes { 1146 | type?: string | undefined; 1147 | } 1148 | 1149 | interface MediaHTMLAttributes extends HTMLAttributes { 1150 | autoPlay?: boolean | undefined; 1151 | controls?: boolean | undefined; 1152 | controlsList?: string | undefined; 1153 | crossOrigin?: string | undefined; 1154 | loop?: boolean | undefined; 1155 | mediaGroup?: string | undefined; 1156 | muted?: boolean | undefined; 1157 | playsInline?: boolean | undefined; 1158 | preload?: string | undefined; 1159 | src?: string | undefined; 1160 | } 1161 | 1162 | interface MetaHTMLAttributes extends HTMLAttributes { 1163 | charSet?: string | undefined; 1164 | content?: string | undefined; 1165 | httpEquiv?: string | undefined; 1166 | name?: string | undefined; 1167 | media?: string | undefined; 1168 | } 1169 | 1170 | interface MeterHTMLAttributes extends HTMLAttributes { 1171 | form?: string | undefined; 1172 | high?: number | undefined; 1173 | low?: number | undefined; 1174 | max?: number | string | undefined; 1175 | min?: number | string | undefined; 1176 | optimum?: number | undefined; 1177 | value?: string | ReadonlyArray | number | undefined; 1178 | } 1179 | 1180 | interface QuoteHTMLAttributes extends HTMLAttributes { 1181 | cite?: string | undefined; 1182 | } 1183 | 1184 | interface ObjectHTMLAttributes extends HTMLAttributes { 1185 | classID?: string | undefined; 1186 | data?: string | undefined; 1187 | form?: string | undefined; 1188 | height?: number | string | undefined; 1189 | name?: string | undefined; 1190 | type?: string | undefined; 1191 | useMap?: string | undefined; 1192 | width?: number | string | undefined; 1193 | wmode?: string | undefined; 1194 | } 1195 | 1196 | interface OlHTMLAttributes extends HTMLAttributes { 1197 | reversed?: boolean | undefined; 1198 | start?: number | undefined; 1199 | type?: "1" | "a" | "A" | "i" | "I" | undefined; 1200 | } 1201 | 1202 | interface OptgroupHTMLAttributes extends HTMLAttributes { 1203 | disabled?: boolean | undefined; 1204 | label?: string | undefined; 1205 | } 1206 | 1207 | interface OptionHTMLAttributes extends HTMLAttributes { 1208 | disabled?: boolean | undefined; 1209 | label?: string | undefined; 1210 | selected?: boolean | undefined; 1211 | value?: string | ReadonlyArray | number | undefined; 1212 | } 1213 | 1214 | interface OutputHTMLAttributes extends HTMLAttributes { 1215 | form?: string | undefined; 1216 | htmlFor?: string | undefined; 1217 | name?: string | undefined; 1218 | } 1219 | 1220 | interface ParamHTMLAttributes extends HTMLAttributes { 1221 | name?: string | undefined; 1222 | value?: string | ReadonlyArray | number | undefined; 1223 | } 1224 | 1225 | interface ProgressHTMLAttributes extends HTMLAttributes { 1226 | max?: number | string | undefined; 1227 | value?: string | ReadonlyArray | number | undefined; 1228 | } 1229 | 1230 | interface SlotHTMLAttributes extends HTMLAttributes { 1231 | name?: string | undefined; 1232 | } 1233 | 1234 | interface ScriptHTMLAttributes extends HTMLAttributes { 1235 | async?: boolean | undefined; 1236 | /** @deprecated */ 1237 | charSet?: string | undefined; 1238 | crossOrigin?: string | undefined; 1239 | defer?: boolean | undefined; 1240 | integrity?: string | undefined; 1241 | noModule?: boolean | undefined; 1242 | referrerPolicy?: ReferrerPolicy | undefined; 1243 | src?: string | undefined; 1244 | type?: string | undefined; 1245 | } 1246 | 1247 | interface SelectHTMLAttributes extends HTMLAttributes { 1248 | autoComplete?: string | undefined; 1249 | autoFocus?: boolean | undefined; 1250 | disabled?: boolean | undefined; 1251 | form?: string | undefined; 1252 | multiple?: boolean | undefined; 1253 | name?: string | undefined; 1254 | required?: boolean | undefined; 1255 | size?: number | undefined; 1256 | value?: string | ReadonlyArray | number | undefined; 1257 | onChange?: ChangeEventHandler | undefined; 1258 | } 1259 | 1260 | interface SourceHTMLAttributes extends HTMLAttributes { 1261 | height?: number | string | undefined; 1262 | media?: string | undefined; 1263 | sizes?: string | undefined; 1264 | src?: string | undefined; 1265 | srcSet?: string | undefined; 1266 | type?: string | undefined; 1267 | width?: number | string | undefined; 1268 | } 1269 | 1270 | interface StyleHTMLAttributes extends HTMLAttributes { 1271 | media?: string | undefined; 1272 | scoped?: boolean | undefined; 1273 | type?: string | undefined; 1274 | } 1275 | 1276 | interface TableHTMLAttributes extends HTMLAttributes { 1277 | align?: "left" | "center" | "right" | undefined; 1278 | bgcolor?: string | undefined; 1279 | border?: number | undefined; 1280 | cellPadding?: number | string | undefined; 1281 | cellSpacing?: number | string | undefined; 1282 | frame?: boolean | undefined; 1283 | rules?: "none" | "groups" | "rows" | "columns" | "all" | undefined; 1284 | summary?: string | undefined; 1285 | width?: number | string | undefined; 1286 | } 1287 | 1288 | interface TextareaHTMLAttributes extends HTMLAttributes { 1289 | autoComplete?: string | undefined; 1290 | autoFocus?: boolean | undefined; 1291 | cols?: number | undefined; 1292 | dirName?: string | undefined; 1293 | disabled?: boolean | undefined; 1294 | form?: string | undefined; 1295 | maxLength?: number | undefined; 1296 | minLength?: number | undefined; 1297 | name?: string | undefined; 1298 | placeholder?: string | undefined; 1299 | readOnly?: boolean | undefined; 1300 | required?: boolean | undefined; 1301 | rows?: number | undefined; 1302 | value?: string | ReadonlyArray | number | undefined; 1303 | wrap?: string | undefined; 1304 | 1305 | onChange?: ChangeEventHandler | undefined; 1306 | } 1307 | 1308 | interface TdHTMLAttributes extends HTMLAttributes { 1309 | align?: 1310 | | "left" 1311 | | "center" 1312 | | "right" 1313 | | "justify" 1314 | | "char" 1315 | | undefined; 1316 | colSpan?: number | undefined; 1317 | headers?: string | undefined; 1318 | rowSpan?: number | undefined; 1319 | scope?: string | undefined; 1320 | abbr?: string | undefined; 1321 | height?: number | string | undefined; 1322 | width?: number | string | undefined; 1323 | valign?: "top" | "middle" | "bottom" | "baseline" | undefined; 1324 | } 1325 | 1326 | interface ThHTMLAttributes extends HTMLAttributes { 1327 | align?: 1328 | | "left" 1329 | | "center" 1330 | | "right" 1331 | | "justify" 1332 | | "char" 1333 | | undefined; 1334 | colSpan?: number | undefined; 1335 | headers?: string | undefined; 1336 | rowSpan?: number | undefined; 1337 | scope?: string | undefined; 1338 | abbr?: string | undefined; 1339 | } 1340 | 1341 | interface TimeHTMLAttributes extends HTMLAttributes { 1342 | dateTime?: string | undefined; 1343 | } 1344 | 1345 | interface TrackHTMLAttributes extends HTMLAttributes { 1346 | default?: boolean | undefined; 1347 | kind?: string | undefined; 1348 | label?: string | undefined; 1349 | src?: string | undefined; 1350 | srcLang?: string | undefined; 1351 | } 1352 | 1353 | interface VideoHTMLAttributes extends MediaHTMLAttributes { 1354 | height?: number | string | undefined; 1355 | playsInline?: boolean | undefined; 1356 | poster?: string | undefined; 1357 | width?: number | string | undefined; 1358 | disablePictureInPicture?: boolean | undefined; 1359 | disableRemotePlayback?: boolean | undefined; 1360 | } 1361 | 1362 | // this list is "complete" in that it contains every SVG attribute 1363 | // that React supports, but the types can be improved. 1364 | // Full list here: https://facebook.github.io/react/docs/dom-elements.html 1365 | // 1366 | // The three broad type categories are (in order of restrictiveness): 1367 | // - "number | string" 1368 | // - "string" 1369 | // - union of string literals 1370 | interface SVGAttributes extends AriaAttributes, DOMAttributes { 1371 | // Attributes which also defined in HTMLAttributes 1372 | // See comment in SVGDOMPropertyConfig.js 1373 | className?: string | undefined; 1374 | color?: string | undefined; 1375 | height?: number | string | undefined; 1376 | id?: string | undefined; 1377 | lang?: string | undefined; 1378 | max?: number | string | undefined; 1379 | media?: string | undefined; 1380 | method?: string | undefined; 1381 | min?: number | string | undefined; 1382 | name?: string | undefined; 1383 | style?: CSSProperties | undefined; 1384 | target?: string | undefined; 1385 | type?: string | undefined; 1386 | width?: number | string | undefined; 1387 | 1388 | // Other HTML properties supported by SVG elements in browsers 1389 | role?: AriaRole | undefined; 1390 | tabIndex?: number | undefined; 1391 | crossOrigin?: "anonymous" | "use-credentials" | "" | undefined; 1392 | 1393 | // SVG Specific attributes 1394 | accentHeight?: number | string | undefined; 1395 | accumulate?: "none" | "sum" | undefined; 1396 | additive?: "replace" | "sum" | undefined; 1397 | alignmentBaseline?: 1398 | | "auto" 1399 | | "baseline" 1400 | | "before-edge" 1401 | | "text-before-edge" 1402 | | "middle" 1403 | | "central" 1404 | | "after-edge" 1405 | | "text-after-edge" 1406 | | "ideographic" 1407 | | "alphabetic" 1408 | | "hanging" 1409 | | "mathematical" 1410 | | "inherit" 1411 | | undefined; 1412 | allowReorder?: "no" | "yes" | undefined; 1413 | alphabetic?: number | string | undefined; 1414 | amplitude?: number | string | undefined; 1415 | arabicForm?: 1416 | | "initial" 1417 | | "medial" 1418 | | "terminal" 1419 | | "isolated" 1420 | | undefined; 1421 | ascent?: number | string | undefined; 1422 | attributeName?: string | undefined; 1423 | attributeType?: string | undefined; 1424 | autoReverse?: Booleanish | undefined; 1425 | azimuth?: number | string | undefined; 1426 | baseFrequency?: number | string | undefined; 1427 | baselineShift?: number | string | undefined; 1428 | baseProfile?: number | string | undefined; 1429 | bbox?: number | string | undefined; 1430 | begin?: number | string | undefined; 1431 | bias?: number | string | undefined; 1432 | by?: number | string | undefined; 1433 | calcMode?: number | string | undefined; 1434 | capHeight?: number | string | undefined; 1435 | clip?: number | string | undefined; 1436 | clipPath?: string | undefined; 1437 | clipPathUnits?: number | string | undefined; 1438 | clipRule?: number | string | undefined; 1439 | colorInterpolation?: number | string | undefined; 1440 | colorInterpolationFilters?: 1441 | | "auto" 1442 | | "sRGB" 1443 | | "linearRGB" 1444 | | "inherit" 1445 | | undefined; 1446 | colorProfile?: number | string | undefined; 1447 | colorRendering?: number | string | undefined; 1448 | contentScriptType?: number | string | undefined; 1449 | contentStyleType?: number | string | undefined; 1450 | cursor?: number | string | undefined; 1451 | cx?: number | string | undefined; 1452 | cy?: number | string | undefined; 1453 | d?: string | undefined; 1454 | decelerate?: number | string | undefined; 1455 | descent?: number | string | undefined; 1456 | diffuseConstant?: number | string | undefined; 1457 | direction?: number | string | undefined; 1458 | display?: number | string | undefined; 1459 | divisor?: number | string | undefined; 1460 | dominantBaseline?: number | string | undefined; 1461 | dur?: number | string | undefined; 1462 | dx?: number | string | undefined; 1463 | dy?: number | string | undefined; 1464 | edgeMode?: number | string | undefined; 1465 | elevation?: number | string | undefined; 1466 | enableBackground?: number | string | undefined; 1467 | end?: number | string | undefined; 1468 | exponent?: number | string | undefined; 1469 | externalResourcesRequired?: Booleanish | undefined; 1470 | fill?: string | undefined; 1471 | fillOpacity?: number | string | undefined; 1472 | fillRule?: "nonzero" | "evenodd" | "inherit" | undefined; 1473 | filter?: string | undefined; 1474 | filterRes?: number | string | undefined; 1475 | filterUnits?: number | string | undefined; 1476 | floodColor?: number | string | undefined; 1477 | floodOpacity?: number | string | undefined; 1478 | focusable?: Booleanish | "auto" | undefined; 1479 | fontFamily?: string | undefined; 1480 | fontSize?: number | string | undefined; 1481 | fontSizeAdjust?: number | string | undefined; 1482 | fontStretch?: number | string | undefined; 1483 | fontStyle?: number | string | undefined; 1484 | fontVariant?: number | string | undefined; 1485 | fontWeight?: number | string | undefined; 1486 | format?: number | string | undefined; 1487 | fr?: number | string | undefined; 1488 | from?: number | string | undefined; 1489 | fx?: number | string | undefined; 1490 | fy?: number | string | undefined; 1491 | g1?: number | string | undefined; 1492 | g2?: number | string | undefined; 1493 | glyphName?: number | string | undefined; 1494 | glyphOrientationHorizontal?: number | string | undefined; 1495 | glyphOrientationVertical?: number | string | undefined; 1496 | glyphRef?: number | string | undefined; 1497 | gradientTransform?: string | undefined; 1498 | gradientUnits?: string | undefined; 1499 | hanging?: number | string | undefined; 1500 | horizAdvX?: number | string | undefined; 1501 | horizOriginX?: number | string | undefined; 1502 | href?: string | undefined; 1503 | ideographic?: number | string | undefined; 1504 | imageRendering?: number | string | undefined; 1505 | in2?: number | string | undefined; 1506 | in?: string | undefined; 1507 | intercept?: number | string | undefined; 1508 | k1?: number | string | undefined; 1509 | k2?: number | string | undefined; 1510 | k3?: number | string | undefined; 1511 | k4?: number | string | undefined; 1512 | k?: number | string | undefined; 1513 | kernelMatrix?: number | string | undefined; 1514 | kernelUnitLength?: number | string | undefined; 1515 | kerning?: number | string | undefined; 1516 | keyPoints?: number | string | undefined; 1517 | keySplines?: number | string | undefined; 1518 | keyTimes?: number | string | undefined; 1519 | lengthAdjust?: number | string | undefined; 1520 | letterSpacing?: number | string | undefined; 1521 | lightingColor?: number | string | undefined; 1522 | limitingConeAngle?: number | string | undefined; 1523 | local?: number | string | undefined; 1524 | markerEnd?: string | undefined; 1525 | markerHeight?: number | string | undefined; 1526 | markerMid?: string | undefined; 1527 | markerStart?: string | undefined; 1528 | markerUnits?: number | string | undefined; 1529 | markerWidth?: number | string | undefined; 1530 | mask?: string | undefined; 1531 | maskContentUnits?: number | string | undefined; 1532 | maskUnits?: number | string | undefined; 1533 | mathematical?: number | string | undefined; 1534 | mode?: number | string | undefined; 1535 | numOctaves?: number | string | undefined; 1536 | offset?: number | string | undefined; 1537 | opacity?: number | string | undefined; 1538 | operator?: number | string | undefined; 1539 | order?: number | string | undefined; 1540 | orient?: number | string | undefined; 1541 | orientation?: number | string | undefined; 1542 | origin?: number | string | undefined; 1543 | overflow?: number | string | undefined; 1544 | overlinePosition?: number | string | undefined; 1545 | overlineThickness?: number | string | undefined; 1546 | paintOrder?: number | string | undefined; 1547 | panose1?: number | string | undefined; 1548 | path?: string | undefined; 1549 | pathLength?: number | string | undefined; 1550 | patternContentUnits?: string | undefined; 1551 | patternTransform?: number | string | undefined; 1552 | patternUnits?: string | undefined; 1553 | pointerEvents?: number | string | undefined; 1554 | points?: string | undefined; 1555 | pointsAtX?: number | string | undefined; 1556 | pointsAtY?: number | string | undefined; 1557 | pointsAtZ?: number | string | undefined; 1558 | preserveAlpha?: Booleanish | undefined; 1559 | preserveAspectRatio?: string | undefined; 1560 | primitiveUnits?: number | string | undefined; 1561 | r?: number | string | undefined; 1562 | radius?: number | string | undefined; 1563 | refX?: number | string | undefined; 1564 | refY?: number | string | undefined; 1565 | renderingIntent?: number | string | undefined; 1566 | repeatCount?: number | string | undefined; 1567 | repeatDur?: number | string | undefined; 1568 | requiredExtensions?: number | string | undefined; 1569 | requiredFeatures?: number | string | undefined; 1570 | restart?: number | string | undefined; 1571 | result?: string | undefined; 1572 | rotate?: number | string | undefined; 1573 | rx?: number | string | undefined; 1574 | ry?: number | string | undefined; 1575 | scale?: number | string | undefined; 1576 | seed?: number | string | undefined; 1577 | shapeRendering?: number | string | undefined; 1578 | slope?: number | string | undefined; 1579 | spacing?: number | string | undefined; 1580 | specularConstant?: number | string | undefined; 1581 | specularExponent?: number | string | undefined; 1582 | speed?: number | string | undefined; 1583 | spreadMethod?: string | undefined; 1584 | startOffset?: number | string | undefined; 1585 | stdDeviation?: number | string | undefined; 1586 | stemh?: number | string | undefined; 1587 | stemv?: number | string | undefined; 1588 | stitchTiles?: number | string | undefined; 1589 | stopColor?: string | undefined; 1590 | stopOpacity?: number | string | undefined; 1591 | strikethroughPosition?: number | string | undefined; 1592 | strikethroughThickness?: number | string | undefined; 1593 | string?: number | string | undefined; 1594 | stroke?: string | undefined; 1595 | strokeDasharray?: string | number | undefined; 1596 | strokeDashoffset?: string | number | undefined; 1597 | strokeLinecap?: "butt" | "round" | "square" | "inherit" | undefined; 1598 | strokeLinejoin?: 1599 | | "miter" 1600 | | "round" 1601 | | "bevel" 1602 | | "inherit" 1603 | | undefined; 1604 | strokeMiterlimit?: number | string | undefined; 1605 | strokeOpacity?: number | string | undefined; 1606 | strokeWidth?: number | string | undefined; 1607 | surfaceScale?: number | string | undefined; 1608 | systemLanguage?: number | string | undefined; 1609 | tableValues?: number | string | undefined; 1610 | targetX?: number | string | undefined; 1611 | targetY?: number | string | undefined; 1612 | textAnchor?: string | undefined; 1613 | textDecoration?: number | string | undefined; 1614 | textLength?: number | string | undefined; 1615 | textRendering?: number | string | undefined; 1616 | to?: number | string | undefined; 1617 | transform?: string | undefined; 1618 | u1?: number | string | undefined; 1619 | u2?: number | string | undefined; 1620 | underlinePosition?: number | string | undefined; 1621 | underlineThickness?: number | string | undefined; 1622 | unicode?: number | string | undefined; 1623 | unicodeBidi?: number | string | undefined; 1624 | unicodeRange?: number | string | undefined; 1625 | unitsPerEm?: number | string | undefined; 1626 | vAlphabetic?: number | string | undefined; 1627 | values?: string | undefined; 1628 | vectorEffect?: number | string | undefined; 1629 | version?: string | undefined; 1630 | vertAdvY?: number | string | undefined; 1631 | vertOriginX?: number | string | undefined; 1632 | vertOriginY?: number | string | undefined; 1633 | vHanging?: number | string | undefined; 1634 | vIdeographic?: number | string | undefined; 1635 | viewBox?: string | undefined; 1636 | viewTarget?: number | string | undefined; 1637 | visibility?: number | string | undefined; 1638 | vMathematical?: number | string | undefined; 1639 | widths?: number | string | undefined; 1640 | wordSpacing?: number | string | undefined; 1641 | writingMode?: number | string | undefined; 1642 | x1?: number | string | undefined; 1643 | x2?: number | string | undefined; 1644 | x?: number | string | undefined; 1645 | xChannelSelector?: string | undefined; 1646 | xHeight?: number | string | undefined; 1647 | xlinkActuate?: string | undefined; 1648 | xlinkArcrole?: string | undefined; 1649 | xlinkHref?: string | undefined; 1650 | xlinkRole?: string | undefined; 1651 | xlinkShow?: string | undefined; 1652 | xlinkTitle?: string | undefined; 1653 | xlinkType?: string | undefined; 1654 | xmlBase?: string | undefined; 1655 | xmlLang?: string | undefined; 1656 | xmlns?: string | undefined; 1657 | xmlnsXlink?: string | undefined; 1658 | xmlSpace?: string | undefined; 1659 | y1?: number | string | undefined; 1660 | y2?: number | string | undefined; 1661 | y?: number | string | undefined; 1662 | yChannelSelector?: string | undefined; 1663 | z?: number | string | undefined; 1664 | zoomAndPan?: string | undefined; 1665 | } 1666 | 1667 | interface WebViewHTMLAttributes extends HTMLAttributes { 1668 | allowFullScreen?: boolean | undefined; 1669 | allowpopups?: boolean | undefined; 1670 | autoFocus?: boolean | undefined; 1671 | autosize?: boolean | undefined; 1672 | blinkfeatures?: string | undefined; 1673 | disableblinkfeatures?: string | undefined; 1674 | disableguestresize?: boolean | undefined; 1675 | disablewebsecurity?: boolean | undefined; 1676 | guestinstance?: string | undefined; 1677 | httpreferrer?: string | undefined; 1678 | nodeintegration?: boolean | undefined; 1679 | partition?: string | undefined; 1680 | plugins?: boolean | undefined; 1681 | preload?: string | undefined; 1682 | src?: string | undefined; 1683 | useragent?: string | undefined; 1684 | webpreferences?: string | undefined; 1685 | } 1686 | 1687 | interface IntrinsicElements { 1688 | [elemName: string]: any; 1689 | a: AnchorHTMLAttributes; 1690 | abbr: HTMLAttributes; 1691 | address: HTMLAttributes; 1692 | area: AreaHTMLAttributes; 1693 | article: HTMLAttributes; 1694 | aside: HTMLAttributes; 1695 | audio: AudioHTMLAttributes; 1696 | b: HTMLAttributes; 1697 | base: BaseHTMLAttributes; 1698 | bdi: HTMLAttributes; 1699 | bdo: HTMLAttributes; 1700 | big: HTMLAttributes; 1701 | blockquote: BlockquoteHTMLAttributes; 1702 | body: HTMLAttributes; 1703 | br: HTMLAttributes; 1704 | button: ButtonHTMLAttributes; 1705 | canvas: CanvasHTMLAttributes; 1706 | caption: HTMLAttributes; 1707 | cite: HTMLAttributes; 1708 | code: HTMLAttributes; 1709 | col: ColHTMLAttributes; 1710 | colgroup: ColgroupHTMLAttributes; 1711 | data: HTMLAttributes; 1712 | datalist: HTMLAttributes; 1713 | dd: HTMLAttributes; 1714 | del: DelHTMLAttributes; 1715 | details: DetailsHTMLAttributes; 1716 | dfn: HTMLAttributes; 1717 | dialog: DialogHTMLAttributes; 1718 | div: HTMLAttributes; 1719 | dl: HTMLAttributes; 1720 | dt: HTMLAttributes; 1721 | em: HTMLAttributes; 1722 | embed: EmbedHTMLAttributes; 1723 | fieldset: FieldsetHTMLAttributes; 1724 | figcaption: HTMLAttributes; 1725 | figure: HTMLAttributes; 1726 | footer: HTMLAttributes; 1727 | form: FormHTMLAttributes; 1728 | h1: HTMLAttributes; 1729 | h2: HTMLAttributes; 1730 | h3: HTMLAttributes; 1731 | h4: HTMLAttributes; 1732 | h5: HTMLAttributes; 1733 | h6: HTMLAttributes; 1734 | head: HTMLAttributes; 1735 | header: HTMLAttributes; 1736 | hgroup: HTMLAttributes; 1737 | hr: HTMLAttributes; 1738 | html: HtmlHTMLAttributes; 1739 | i: HTMLAttributes; 1740 | iframe: IframeHTMLAttributes; 1741 | img: ImgHTMLAttributes; 1742 | input: InputHTMLAttributes; 1743 | ins: InsHTMLAttributes; 1744 | kbd: HTMLAttributes; 1745 | keygen: KeygenHTMLAttributes; 1746 | label: LabelHTMLAttributes; 1747 | legend: HTMLAttributes; 1748 | li: LiHTMLAttributes; 1749 | link: LinkHTMLAttributes; 1750 | main: HTMLAttributes; 1751 | map: MapHTMLAttributes; 1752 | mark: HTMLAttributes; 1753 | menu: MenuHTMLAttributes; 1754 | menuitem: HTMLAttributes; 1755 | meta: MetaHTMLAttributes; 1756 | meter: MeterHTMLAttributes; 1757 | nav: HTMLAttributes; 1758 | noindex: HTMLAttributes; 1759 | noscript: HTMLAttributes; 1760 | object: ObjectHTMLAttributes; 1761 | ol: OlHTMLAttributes; 1762 | optgroup: OptgroupHTMLAttributes; 1763 | option: OptionHTMLAttributes; 1764 | output: OutputHTMLAttributes; 1765 | p: HTMLAttributes; 1766 | param: ParamHTMLAttributes; 1767 | picture: HTMLAttributes; 1768 | pre: HTMLAttributes; 1769 | progress: ProgressHTMLAttributes; 1770 | q: QuoteHTMLAttributes; 1771 | rp: HTMLAttributes; 1772 | rt: HTMLAttributes; 1773 | ruby: HTMLAttributes; 1774 | s: HTMLAttributes; 1775 | samp: HTMLAttributes; 1776 | script: ScriptHTMLAttributes; 1777 | section: HTMLAttributes; 1778 | select: SelectHTMLAttributes; 1779 | small: HTMLAttributes; 1780 | source: SourceHTMLAttributes; 1781 | span: HTMLAttributes; 1782 | strong: HTMLAttributes; 1783 | style: StyleHTMLAttributes; 1784 | sub: HTMLAttributes; 1785 | summary: HTMLAttributes; 1786 | sup: HTMLAttributes; 1787 | table: TableHTMLAttributes; 1788 | tbody: HTMLAttributes; 1789 | td: TdHTMLAttributes; 1790 | textarea: TextareaHTMLAttributes; 1791 | tfoot: HTMLAttributes; 1792 | th: ThHTMLAttributes; 1793 | thead: HTMLAttributes; 1794 | time: TimeHTMLAttributes; 1795 | title: HTMLAttributes; 1796 | tr: HTMLAttributes; 1797 | track: TrackHTMLAttributes; 1798 | u: HTMLAttributes; 1799 | ul: HTMLAttributes; 1800 | var: HTMLAttributes; 1801 | video: VideoHTMLAttributes; 1802 | wbr: HTMLAttributes; 1803 | webview: WebViewHTMLAttributes; 1804 | 1805 | // SVG 1806 | svg: SVGAttributes; 1807 | 1808 | animate: SVGAttributes; // TODO: It is SVGAnimateElement but is not in TypeScript's lib.dom.d.ts for now. 1809 | animateTransform: SVGAttributes; // TODO: It is SVGAnimateTransformElement but is not in TypeScript's lib.dom.d.ts for now. 1810 | circle: SVGAttributes; 1811 | clipPath: SVGAttributes; 1812 | defs: SVGAttributes; 1813 | desc: SVGAttributes; 1814 | ellipse: SVGAttributes; 1815 | feBlend: SVGAttributes; 1816 | 1817 | feColorMatrix: SVGAttributes; 1818 | feComponentTransfer: SVGAttributes; 1819 | feComposite: SVGAttributes; 1820 | feConvolveMatrix: SVGAttributes; 1821 | feDiffuseLighting: SVGAttributes; 1822 | feDisplacementMap: SVGAttributes; 1823 | feDistantLight: SVGAttributes; 1824 | feDropShadow: SVGAttributes; 1825 | feFlood: SVGAttributes; 1826 | feFuncA: SVGAttributes; 1827 | feFuncB: SVGAttributes; 1828 | feFuncG: SVGAttributes; 1829 | feFuncR: SVGAttributes; 1830 | feGaussianBlur: SVGAttributes; 1831 | feImage: SVGAttributes; 1832 | feMerge: SVGAttributes; 1833 | feMergeNode: SVGAttributes; 1834 | feMorphology: SVGAttributes; 1835 | feOffset: SVGAttributes; 1836 | fePointLight: SVGAttributes; 1837 | feSpecularLighting: SVGAttributes; 1838 | feSpotLight: SVGAttributes; 1839 | feTile: SVGAttributes; 1840 | feTurbulence: SVGAttributes; 1841 | filter: SVGAttributes; 1842 | foreignObject: SVGAttributes; 1843 | g: SVGAttributes; 1844 | image: SVGAttributes; 1845 | line: SVGAttributes; 1846 | linearGradient: SVGAttributes; 1847 | marker: SVGAttributes; 1848 | mask: SVGAttributes; 1849 | metadata: SVGAttributes; 1850 | path: SVGAttributes; 1851 | pattern: SVGAttributes; 1852 | polygon: SVGAttributes; 1853 | polyline: SVGAttributes; 1854 | radialGradient: SVGAttributes; 1855 | rect: SVGAttributes; 1856 | stop: SVGAttributes; 1857 | switch: SVGAttributes; 1858 | symbol: SVGAttributes; 1859 | text: SVGAttributes; 1860 | textPath: SVGAttributes; 1861 | tspan: SVGAttributes; 1862 | use: SVGAttributes; 1863 | view: SVGAttributes; 1864 | } 1865 | } 1866 | } 1867 | --------------------------------------------------------------------------------