omi-native

This commit is contained in:
dntzhang 2018-11-01 09:10:48 +08:00
parent 2dd0b41933
commit b13bec1c5d
50 changed files with 9427 additions and 0 deletions

View File

@ -0,0 +1,18 @@
{
"presets": [
[
"env",
{
"loose": true,
"exclude": ["transform-es2015-typeof-symbol"],
"targets": {
"browsers": ["last 2 versions", "IE >= 9"]
}
}
]
],
"plugins": [
"transform-class-properties",
["transform-react-jsx", { "pragma": "Omi.h" }]
]
}

View File

@ -0,0 +1,15 @@
root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{package.json,.*rc,*.yml}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false

View File

@ -0,0 +1 @@
test/ts/

View File

@ -0,0 +1,14 @@
{
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"semi": 2,
"indent": ["error", 2]
}
}

View File

@ -0,0 +1,10 @@
[ignore]
<PROJECT_ROOT>/dist/.*
[include]
[libs]
[lints]
[options]

View File

@ -0,0 +1,60 @@
<h2 align="center">Omi: Next Generation Web Framework in 4kb JavaScript</h2>
<p align="center"><b>Merge JSX, Web Components, Proxy, Store, Path Updating together</b></p>
## Why Omi?
- Tiny size. _(**4kb** gzipped)_
- Supports TypeScript.
- Reactive data-binding
- [Based on Shadow DOM](https://developers.google.com/web/fundamentals/web-components/shadowdom)
- Easy to debug via [Omi DevTools Extension](https://github.com/f/omi-devtools) [[Install from Chrome WebStore](https://chrome.google.com/webstore/detail/omijs-devtools/pjgglfliglbhpcpalbpeloghnbceocmd)]
- Compliance with browser trend and API design.
- Merge [**Web Components**](https://developers.google.com/web/fundamentals/web-components/) and [**JSX**](https://reactjs.org/docs/introducing-jsx.html) into one framework.
- Work well with mobx by omi-mobx (No need to call `this.update()`).
- Web Components can also be a data-driven view, **`UI = fn(data)`**.
- JSX is the best development experience (code intelligent completion and tip) UI Expression with least [grammatical noise](https://github.com/facebook/jsx#why-not-template-literals).
- The original **Path Updating** system. Proxy-based automatic **accurate** update, **low power consumption**, high degree of freedom, excellent performance, easy integration of `requestIdleCallback`
- Say goodbye to `this.update` method when using **store system**! It will automatically update UI partially when data is changed.
- Look at [Facebook React vs Web Components](https://softwareengineering.stackexchange.com/questions/225400/pros-and-cons-of-facebooks-react-vs-web-components-polymer)Omi **combines their advantages** and gives developers the **freedom to choose the way they like**.
- **Shadow DOM merges with Virtual DOM**, Omi uses both virtual DOM and real Shadow DOM to make view updates more accurate and faster.
- With a Store system, 99.9% of projects don't need time travel, and not only Redux can travel, please don't come up on Redux, Omi store system can meet all projects
- **Scoped CSS**'s best solution is **Shadow DOM**, the community churning out frameworks and libraries for Scoped CSS (using JS or JSON writing styles such as Radium, jsxstyle, react-style; binding to webpack using generated unique `className` `filename-classname-hash`, such as CSS Modules, Vue), are hack technologies; _and Shadow DOM Style is the perfect solution_.
---
## Ecosystem of Omi
| **Project** | **Description** |
| ------------------------------- | ----------------------------------- |
| [omi-docs](https://github.com/Tencent/omi/blob/master/docs/main-concepts.md)| Omi official documents |
| [omi-devtools](https://github.com/f/omi-devtools)| Browser DevTools extension |
| [omi-cli](https://github.com/Tencent/omi/tree/master/packages/omi-cli)| Project scaffolding |
|[omi-i18n](https://github.com/i18next/omi-i18n)| Internationalization solution for omi.js using i18next ecosystem |
| [omi-transform](https://github.com/Tencent/omi/tree/master/packages/omi-transform)|Omi / [css3transform](https://tencent.github.io/omi/packages/omi-transform/css3transform/) integration. Made css3 transform super easy in your Omi project.|
| [omi-page](https://github.com/Tencent/omi/tree/master/packages/omi-page) |Tiny client-side router by [page](https://github.com/visionmedia/page.js)|
| [omi-tap](https://github.com/Tencent/omi/tree/master/packages/omi-tap)|Support tap event in your omi project|
| [omi-mobx](https://github.com/Tencent/omi/tree/master/packages/omi-mobx)|Omi Mobx Adapter|
|[omi element ui(working)](https://github.com/Tencent/omi/tree/master/packages/omi-element-ui)|Omi version of element-ui|
Other:
- [https://www.webcomponents.org/](https://www.webcomponents.org/)
- [https://www.webcomponents.org/elements](https://www.webcomponents.org/elements)
## Contribution
1. Fork it (https://github.com/Tencent/omi/fork)
2. Create your branch (`git checkout -b my-urgent-hotfix`)
3. Commit your changes (`git commit -am 'Fixed something'`)
4. Push to the branch (`git push origin my-urgent-hotfix`)
5. Create a new Pull Request
Please contact us for any questions:
- [@f](https://github.com/f)
- [@dntzhang](https://github.com/dntzhang)
- [@xcatliu](https://github.com/xcatliu)
## License
MIT © Tencent

View File

@ -0,0 +1,43 @@
/* eslint no-console:0 */
/** Find constants (identified by ALL_CAPS_DECLARATIONS), and inline them globally.
* This is safe because Omi *only* uses global constants.
*/
export default (file, api) => {
let j = api.jscodeshift,
code = j(file.source),
constants = {},
found = 0;
code
.find(j.VariableDeclaration)
.filter(decl => {
for (let i = decl.value.declarations.length; i--; ) {
let node = decl.value.declarations[i],
name = node.id && node.id.name,
init = node.init;
if (name && init && name.match(/^[A-Z0-9_$]+$/g) && !init.regex) {
if (init.type === "Literal") {
// console.log(`Inlining constant: ${name}=${init.raw}`);
found++;
constants[name] = init;
// remove declaration
decl.value.declarations.splice(i, 1);
// if it's the last, we'll remove the whole statement
return !decl.value.declarations.length;
}
}
}
return false;
})
.remove();
code
.find(j.Identifier)
.filter(
path => path.value.name && constants.hasOwnProperty(path.value.name)
)
.replaceWith(path => (found++, constants[path.value.name]));
return found ? code.toSource({ quote: "single" }) : null;
};

View File

@ -0,0 +1,16 @@
/**
* Restores var names transformed by babel's let block scoping
*/
export default (file, api) => {
let j = api.jscodeshift;
let code = j(file.source);
// @TODO unsafe, but without it we gain 20b gzipped: https://www.diffchecker.com/bVrOJWTO
code
.findVariableDeclarators()
.filter(d => /^_i/.test(d.value.id.name))
.renameTo("i");
code.findVariableDeclarators("_key").renameTo("key");
return code.toSource({ quote: "single" });
};

View File

@ -0,0 +1,62 @@
/* eslint no-console:0 */
// parent node types that we don't want to remove pointless initializations from (because it breaks hoisting)
const BLOCKED = ["ForStatement", "WhileStatement"]; // 'IfStatement', 'SwitchStatement'
/** Removes var initialization to `void 0`, which Babel adds for TDZ strictness. */
export default (file, api) => {
let { jscodeshift } = api,
found = 0;
let code = jscodeshift(file.source)
.find(jscodeshift.VariableDeclaration)
.forEach(handleDeclaration);
function handleDeclaration(decl) {
let p = decl,
remove = true;
while ((p = p.parentPath)) {
if (~BLOCKED.indexOf(p.value.type)) {
remove = false;
break;
}
}
decl.value.declarations.filter(isPointless).forEach(node => {
if (remove === false) {
console.log(
`> Skipping removal of undefined init for "${node.id.name}": within ${
p.value.type
}`
);
} else {
removeNodeInitialization(node);
}
});
}
function removeNodeInitialization(node) {
node.init = null;
found++;
}
function isPointless(node) {
let { init } = node;
if (init) {
if (
init.type === "UnaryExpression" &&
init.operator === "void" &&
init.argument.value == 0
) {
return true;
}
if (init.type === "Identifier" && init.name === "undefined") {
return true;
}
}
return false;
}
return found ? code.toSource({ quote: "single" }) : null;
};

View File

@ -0,0 +1,68 @@
module.exports = {
parser: "babel-eslint",
// extends: "eslint:recommended",
// plugins: ["react"],
"extends": ["prettier"],
"plugins": ["prettier"],
env: {
browser: true,
mocha: true,
node: true,
es6: true
},
parserOptions: {
ecmaFeatures: {
modules: true,
jsx: true
}
},
globals: {
sinon: true,
expect: true
},
rules: {
"prettier/prettier": "error",
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2,
"no-unused-vars": [1, { varsIgnorePattern: "^h$" }],
"no-cond-assign": 1,
"no-empty": 0,
"no-console": 1,
semi: [1, "never"],
camelcase: 0,
"comma-style": 2,
"comma-dangle": [2, "never"],
indent: ["error", 2],
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
"no-trailing-spaces": [2, { skipBlankLines: true }],
"max-nested-callbacks": [2, 3],
"no-eval": 2,
"no-implied-eval": 2,
"no-new-func": 2,
"guard-for-in": 0,
eqeqeq: 0,
"no-else-return": 2,
"no-redeclare": 2,
"no-dupe-keys": 2,
radix: 2,
strict: [2, "never"],
"no-shadow": 0,
"callback-return": [1, ["callback", "cb", "next", "done"]],
"no-delete-var": 2,
"no-undef-init": 2,
"no-shadow-restricted-names": 2,
"handle-callback-err": 0,
"no-lonely-if": 2,
"keyword-spacing": 2,
"constructor-super": 2,
"no-this-before-super": 2,
"no-dupe-class-members": 2,
"no-const-assign": 2,
"prefer-spread": 2,
"no-useless-concat": 2,
"no-var": 2,
"object-shorthand": 2,
"prefer-arrow-callback": 2,
"quotes": [1, "single"]
}
};

View File

@ -0,0 +1,39 @@
{
"props": {
"cname": 29,
"props": {
"$_dirty": "__d",
"$_disable": "__x",
"$_listeners": "__l",
"$_renderCallbacks": "__h",
"$__key": "__k",
"$__ref": "__r",
"$normalizedNodeName": "__n",
"$nextBase": "__b",
"$prevContext": "__c",
"$prevProps": "__p",
"$prevState": "__s",
"$_parentComponent": "__u",
"$_componentConstructor": "_componentConstructor",
"$__html": "__html",
"$_component": "_component",
"$__omiattr_": "__omiattr_",
"$_preStyle": "r",
"$_id": "s",
"$__preactattr_": "t",
"$__config__": "v",
"$_isMockDocument": "w",
"$__omiSsrData": "x",
"$_vd": "y",
"$_css": "z",
"$_proxifyObjectTreeRecursively": "A",
"$_isInstalled": "B",
"$_useId": "C",
"$_useMap": "D"
}
},
"vars": {
"cname": -1,
"props": {}
}
}

View File

@ -0,0 +1,10 @@
import config from "./rollup.config";
// ES output
config.output.format = "es";
config.output.file = "dist/omi.esm.js";
// remove memory() plugin
config.plugins.splice(0, 1);
export default config;

View File

@ -0,0 +1,58 @@
import nodeResolve from "rollup-plugin-node-resolve";
import babel from "rollup-plugin-babel";
import memory from "rollup-plugin-memory";
const license = require("rollup-plugin-license");
const pkg = require("../package.json");
const licensePlugin = license({
banner:
" omi v" +
pkg.version +
" http://omijs.org\r\nOmi === Preact + Scoped CSS + Store System + Native Support in 3kb javascript.\r\nBy dntzhang https://github.com/dntzhang \r\n Github: https://github.com/Tencent/omi\r\n MIT Licensed."
});
export default {
input: "src/omi.js",
output: {
format: "iife",
file: "dist/omi.dev.js",
name: "omi",
sourcemap: true,
strict: true
},
plugins: [
memory({
path: "src/omi.js",
contents: `
import Omi from './omi';
if (typeof module!='undefined') module.exports = Omi;
else self.Omi = Omi;
`
}),
nodeResolve({
main: true
}),
babel({
sourceMap: true,
exclude: "node_modules/**",
babelrc: false,
presets: [
[
"env",
{
modules: false,
loose: true,
exclude: ["transform-es2015-typeof-symbol"],
targets: {
browsers: ["last 2 versions", "IE >= 9"]
}
}
]
],
plugins: [
"transform-class-properties"
]
}),
licensePlugin
]
};

View File

@ -0,0 +1,52 @@
import nodeResolve from "rollup-plugin-node-resolve";
import babel from "rollup-plugin-babel";
import memory from "rollup-plugin-memory";
var ENV = process.env.npm_lifecycle_event;
export default {
input: "examples/" + ENV + "/main.js",
output: {
format: "iife",
file: "examples/" + ENV + "/b.js",
name: "omi",
sourcemap: true,
strict: true
},
plugins: [
memory({
path: "src/omi.js",
contents: `
import Omi from './omi';
if (typeof module!='undefined') module.exports = Omi;
else self.Omi = Omi;
`
}),
nodeResolve({
main: true
}),
babel({
sourceMap: true,
exclude: "node_modules/**",
babelrc: false,
presets: [
[
"env",
{
modules: false,
loose: true,
exclude: ["transform-es2015-typeof-symbol"],
targets: {
browsers: ["last 2 versions", "IE >= 9"]
}
}
]
],
plugins: [
"transform-decorators-legacy",
"transform-class-properties",
["transform-react-jsx", { pragma: "Omi.h" }]
]
})
]
};

891
packages/omi-native/dist/omi.d.ts vendored Normal file
View File

@ -0,0 +1,891 @@
export = Omi;
export as namespace Omi;
declare namespace Omi {
type Key = string | number;
type Ref<T> = (instance: T) => void;
type ComponentChild = VNode<any> | object | string | number | boolean | null;
type ComponentChildren = ComponentChild[] | ComponentChild;
interface Attributes {
key?: string | number | any;
}
interface ClassAttributes<T> extends Attributes {
ref?: Ref<T>;
}
interface OmiDOMAttributes {
children?: ComponentChildren;
dangerouslySetInnerHTML?: {
__html: string;
};
}
/**
* Use this to manually set the attributes of a custom element
*
* declare global {
* namespace JSX {
* interface IntrinsicElements {
* 'hello-element': CustomElementBaseAttributes & {
* 'prop-from-parent': string;
* }
* }
* }
* }
*/
interface CustomElementBaseAttributes extends ClassAttributes<any>, OmiDOMAttributes {}
/**
* Define the contract for a virtual node in omi.
*
* A virtual node has a name, a map of attributes, an array
* of child {VNode}s and a key. The key is used by omi for
* internal purposes.
*/
interface VNode<P = any> {
nodeName: string;
attributes: P;
children: Array<VNode<any> | string>;
key?: Key | null;
}
type RenderableProps<P, RefType = any> = Readonly<
P & Attributes & { children?: ComponentChildren; ref?: Ref<RefType> }
>;
interface WeElement<P, D> {
install?(): void;
installed?(): void;
uninstall?(): void;
beforeUpdate?(): void;
afterUpdate?(): void;
beforeRender?(): void;
}
abstract class WeElement<P = {}, D = {}> {
constructor();
// Allow static members to reference class type parameters
// https://github.com/Microsoft/TypeScript/issues/24018
static props: object;
static data: object;
props: RenderableProps<P>;
data: D;
host: HTMLElement;
css(): void;
update(): void;
fire(name: string, data?: object): void;
// Abstract methods don't infer argument types
// https://github.com/Microsoft/TypeScript/issues/14887
abstract render(props: RenderableProps<P>, data: D): void;
}
function h<P>(
node: string,
params: Attributes & P | null,
...children: ComponentChildren[]
): VNode<any>;
function h(
node: string,
params: JSX.HTMLAttributes & JSX.SVGAttributes & Record<string, any> | null,
...children: ComponentChildren[]
): VNode<any>;
function render(vnode: ComponentChild, parent: string | Element | Document | ShadowRoot | DocumentFragment, store?: object): void;
function define(name: string, ctor: any): void;
function tag(name: string, pure?: boolean): (ctor: any) => void;
var options: {
vnode?: (vnode: VNode<any>) => void;
event?: (event: Event) => Event;
};
}
type Defaultize<Props, Defaults> =
// Distribute over unions
Props extends any
? // Make any properties included in Default optional
& Partial<Pick<Props, Extract<keyof Props, keyof Defaults>>>
// Include the remaining properties from Props
& Pick<Props, Exclude<keyof Props, keyof Defaults>>
: never;
declare global {
namespace JSX {
interface Element extends Omi.VNode<any> {
}
interface ElementClass extends Omi.WeElement<any, any> {
}
interface ElementAttributesProperty {
props: any;
}
interface ElementChildrenAttribute {
children: any;
}
type LibraryManagedAttributes<Component, Props> =
Component extends { defaultProps: infer Defaults }
? Defaultize<Props, Defaults>
: Props;
interface SVGAttributes extends HTMLAttributes {
accentHeight?: number | string;
accumulate?: "none" | "sum";
additive?: "replace" | "sum";
alignmentBaseline?: "auto" | "baseline" | "before-edge" | "text-before-edge" | "middle" | "central" | "after-edge" | "text-after-edge" | "ideographic" | "alphabetic" | "hanging" | "mathematical" | "inherit";
allowReorder?: "no" | "yes";
alphabetic?: number | string;
amplitude?: number | string;
arabicForm?: "initial" | "medial" | "terminal" | "isolated";
ascent?: number | string;
attributeName?: string;
attributeType?: string;
autoReverse?: number | string;
azimuth?: number | string;
baseFrequency?: number | string;
baselineShift?: number | string;
baseProfile?: number | string;
bbox?: number | string;
begin?: number | string;
bias?: number | string;
by?: number | string;
calcMode?: number | string;
capHeight?: number | string;
clip?: number | string;
clipPath?: string;
clipPathUnits?: number | string;
clipRule?: number | string;
colorInterpolation?: number | string;
colorInterpolationFilters?: "auto" | "sRGB" | "linearRGB" | "inherit";
colorProfile?: number | string;
colorRendering?: number | string;
contentScriptType?: number | string;
contentStyleType?: number | string;
cursor?: number | string;
cx?: number | string;
cy?: number | string;
d?: string;
decelerate?: number | string;
descent?: number | string;
diffuseConstant?: number | string;
direction?: number | string;
display?: number | string;
divisor?: number | string;
dominantBaseline?: number | string;
dur?: number | string;
dx?: number | string;
dy?: number | string;
edgeMode?: number | string;
elevation?: number | string;
enableBackground?: number | string;
end?: number | string;
exponent?: number | string;
externalResourcesRequired?: number | string;
fill?: string;
fillOpacity?: number | string;
fillRule?: "nonzero" | "evenodd" | "inherit";
filter?: string;
filterRes?: number | string;
filterUnits?: number | string;
floodColor?: number | string;
floodOpacity?: number | string;
focusable?: number | string;
fontFamily?: string;
fontSize?: number | string;
fontSizeAdjust?: number | string;
fontStretch?: number | string;
fontStyle?: number | string;
fontVariant?: number | string;
fontWeight?: number | string;
format?: number | string;
from?: number | string;
fx?: number | string;
fy?: number | string;
g1?: number | string;
g2?: number | string;
glyphName?: number | string;
glyphOrientationHorizontal?: number | string;
glyphOrientationVertical?: number | string;
glyphRef?: number | string;
gradientTransform?: string;
gradientUnits?: string;
hanging?: number | string;
horizAdvX?: number | string;
horizOriginX?: number | string;
ideographic?: number | string;
imageRendering?: number | string;
in2?: number | string;
in?: string;
intercept?: number | string;
k1?: number | string;
k2?: number | string;
k3?: number | string;
k4?: number | string;
k?: number | string;
kernelMatrix?: number | string;
kernelUnitLength?: number | string;
kerning?: number | string;
keyPoints?: number | string;
keySplines?: number | string;
keyTimes?: number | string;
lengthAdjust?: number | string;
letterSpacing?: number | string;
lightingColor?: number | string;
limitingConeAngle?: number | string;
local?: number | string;
markerEnd?: string;
markerHeight?: number | string;
markerMid?: string;
markerStart?: string;
markerUnits?: number | string;
markerWidth?: number | string;
mask?: string;
maskContentUnits?: number | string;
maskUnits?: number | string;
mathematical?: number | string;
mode?: number | string;
numOctaves?: number | string;
offset?: number | string;
opacity?: number | string;
operator?: number | string;
order?: number | string;
orient?: number | string;
orientation?: number | string;
origin?: number | string;
overflow?: number | string;
overlinePosition?: number | string;
overlineThickness?: number | string;
paintOrder?: number | string;
panose1?: number | string;
pathLength?: number | string;
patternContentUnits?: string;
patternTransform?: number | string;
patternUnits?: string;
pointerEvents?: number | string;
points?: string;
pointsAtX?: number | string;
pointsAtY?: number | string;
pointsAtZ?: number | string;
preserveAlpha?: number | string;
preserveAspectRatio?: string;
primitiveUnits?: number | string;
r?: number | string;
radius?: number | string;
refX?: number | string;
refY?: number | string;
renderingIntent?: number | string;
repeatCount?: number | string;
repeatDur?: number | string;
requiredExtensions?: number | string;
requiredFeatures?: number | string;
restart?: number | string;
result?: string;
rotate?: number | string;
rx?: number | string;
ry?: number | string;
scale?: number | string;
seed?: number | string;
shapeRendering?: number | string;
slope?: number | string;
spacing?: number | string;
specularConstant?: number | string;
specularExponent?: number | string;
speed?: number | string;
spreadMethod?: string;
startOffset?: number | string;
stdDeviation?: number | string;
stemh?: number | string;
stemv?: number | string;
stitchTiles?: number | string;
stopColor?: string;
stopOpacity?: number | string;
strikethroughPosition?: number | string;
strikethroughThickness?: number | string;
string?: number | string;
stroke?: string;
strokeDasharray?: string | number;
strokeDashoffset?: string | number;
strokeLinecap?: "butt" | "round" | "square" | "inherit";
strokeLinejoin?: "miter" | "round" | "bevel" | "inherit";
strokeMiterlimit?: string;
strokeOpacity?: number | string;
strokeWidth?: number | string;
surfaceScale?: number | string;
systemLanguage?: number | string;
tableValues?: number | string;
targetX?: number | string;
targetY?: number | string;
textAnchor?: string;
textDecoration?: number | string;
textLength?: number | string;
textRendering?: number | string;
to?: number | string;
transform?: string;
u1?: number | string;
u2?: number | string;
underlinePosition?: number | string;
underlineThickness?: number | string;
unicode?: number | string;
unicodeBidi?: number | string;
unicodeRange?: number | string;
unitsPerEm?: number | string;
vAlphabetic?: number | string;
values?: string;
vectorEffect?: number | string;
version?: string;
vertAdvY?: number | string;
vertOriginX?: number | string;
vertOriginY?: number | string;
vHanging?: number | string;
vIdeographic?: number | string;
viewBox?: string;
viewTarget?: number | string;
visibility?: number | string;
vMathematical?: number | string;
widths?: number | string;
wordSpacing?: number | string;
writingMode?: number | string;
x1?: number | string;
x2?: number | string;
x?: number | string;
xChannelSelector?: string;
xHeight?: number | string;
xlinkActuate?: string;
xlinkArcrole?: string;
xlinkHref?: string;
xlinkRole?: string;
xlinkShow?: string;
xlinkTitle?: string;
xlinkType?: string;
xmlBase?: string;
xmlLang?: string;
xmlns?: string;
xmlnsXlink?: string;
xmlSpace?: string;
y1?: number | string;
y2?: number | string;
y?: number | string;
yChannelSelector?: string;
z?: number | string;
zoomAndPan?: string;
}
interface PathAttributes {
d: string;
}
interface EventHandler<E extends Event> {
(event: E): void;
}
type ClipboardEventHandler = EventHandler<ClipboardEvent>;
type CompositionEventHandler = EventHandler<CompositionEvent>;
type DragEventHandler = EventHandler<DragEvent>;
type FocusEventHandler = EventHandler<FocusEvent>;
type KeyboardEventHandler = EventHandler<KeyboardEvent>;
type MouseEventHandler = EventHandler<MouseEvent>;
type TouchEventHandler = EventHandler<TouchEvent>;
type UIEventHandler = EventHandler<UIEvent>;
type WheelEventHandler = EventHandler<WheelEvent>;
type AnimationEventHandler = EventHandler<AnimationEvent>;
type TransitionEventHandler = EventHandler<TransitionEvent>;
type GenericEventHandler = EventHandler<Event>;
type PointerEventHandler = EventHandler<PointerEvent>;
interface DOMAttributes extends Omi.OmiDOMAttributes {
// Image Events
onLoad?: GenericEventHandler;
onError?: GenericEventHandler;
onLoadCapture?: GenericEventHandler;
// Clipboard Events
onCopy?: ClipboardEventHandler;
onCopyCapture?: ClipboardEventHandler;
onCut?: ClipboardEventHandler;
onCutCapture?: ClipboardEventHandler;
onPaste?: ClipboardEventHandler;
onPasteCapture?: ClipboardEventHandler;
// Composition Events
onCompositionEnd?: CompositionEventHandler;
onCompositionEndCapture?: CompositionEventHandler;
onCompositionStart?: CompositionEventHandler;
onCompositionStartCapture?: CompositionEventHandler;
onCompositionUpdate?: CompositionEventHandler;
onCompositionUpdateCapture?: CompositionEventHandler;
// Focus Events
onFocus?: FocusEventHandler;
onFocusCapture?: FocusEventHandler;
onBlur?: FocusEventHandler;
onBlurCapture?: FocusEventHandler;
// Form Events
onChange?: GenericEventHandler;
onChangeCapture?: GenericEventHandler;
onInput?: GenericEventHandler;
onInputCapture?: GenericEventHandler;
onSearch?: GenericEventHandler;
onSearchCapture?: GenericEventHandler;
onSubmit?: GenericEventHandler;
onSubmitCapture?: GenericEventHandler;
// Keyboard Events
onKeyDown?: KeyboardEventHandler;
onKeyDownCapture?: KeyboardEventHandler;
onKeyPress?: KeyboardEventHandler;
onKeyPressCapture?: KeyboardEventHandler;
onKeyUp?: KeyboardEventHandler;
onKeyUpCapture?: KeyboardEventHandler;
// Media Events
onAbort?: GenericEventHandler;
onAbortCapture?: GenericEventHandler;
onCanPlay?: GenericEventHandler;
onCanPlayCapture?: GenericEventHandler;
onCanPlayThrough?: GenericEventHandler;
onCanPlayThroughCapture?: GenericEventHandler;
onDurationChange?: GenericEventHandler;
onDurationChangeCapture?: GenericEventHandler;
onEmptied?: GenericEventHandler;
onEmptiedCapture?: GenericEventHandler;
onEncrypted?: GenericEventHandler;
onEncryptedCapture?: GenericEventHandler;
onEnded?: GenericEventHandler;
onEndedCapture?: GenericEventHandler;
onLoadedData?: GenericEventHandler;
onLoadedDataCapture?: GenericEventHandler;
onLoadedMetadata?: GenericEventHandler;
onLoadedMetadataCapture?: GenericEventHandler;
onLoadStart?: GenericEventHandler;
onLoadStartCapture?: GenericEventHandler;
onPause?: GenericEventHandler;
onPauseCapture?: GenericEventHandler;
onPlay?: GenericEventHandler;
onPlayCapture?: GenericEventHandler;
onPlaying?: GenericEventHandler;
onPlayingCapture?: GenericEventHandler;
onProgress?: GenericEventHandler;
onProgressCapture?: GenericEventHandler;
onRateChange?: GenericEventHandler;
onRateChangeCapture?: GenericEventHandler;
onSeeked?: GenericEventHandler;
onSeekedCapture?: GenericEventHandler;
onSeeking?: GenericEventHandler;
onSeekingCapture?: GenericEventHandler;
onStalled?: GenericEventHandler;
onStalledCapture?: GenericEventHandler;
onSuspend?: GenericEventHandler;
onSuspendCapture?: GenericEventHandler;
onTimeUpdate?: GenericEventHandler;
onTimeUpdateCapture?: GenericEventHandler;
onVolumeChange?: GenericEventHandler;
onVolumeChangeCapture?: GenericEventHandler;
onWaiting?: GenericEventHandler;
onWaitingCapture?: GenericEventHandler;
// MouseEvents
onClick?: MouseEventHandler;
onClickCapture?: MouseEventHandler;
onContextMenu?: MouseEventHandler;
onContextMenuCapture?: MouseEventHandler;
onDblClick?: MouseEventHandler;
onDblClickCapture?: MouseEventHandler;
onDrag?: DragEventHandler;
onDragCapture?: DragEventHandler;
onDragEnd?: DragEventHandler;
onDragEndCapture?: DragEventHandler;
onDragEnter?: DragEventHandler;
onDragEnterCapture?: DragEventHandler;
onDragExit?: DragEventHandler;
onDragExitCapture?: DragEventHandler;
onDragLeave?: DragEventHandler;
onDragLeaveCapture?: DragEventHandler;
onDragOver?: DragEventHandler;
onDragOverCapture?: DragEventHandler;
onDragStart?: DragEventHandler;
onDragStartCapture?: DragEventHandler;
onDrop?: DragEventHandler;
onDropCapture?: DragEventHandler;
onMouseDown?: MouseEventHandler;
onMouseDownCapture?: MouseEventHandler;
onMouseEnter?: MouseEventHandler;
onMouseEnterCapture?: MouseEventHandler;
onMouseLeave?: MouseEventHandler;
onMouseLeaveCapture?: MouseEventHandler;
onMouseMove?: MouseEventHandler;
onMouseMoveCapture?: MouseEventHandler;
onMouseOut?: MouseEventHandler;
onMouseOutCapture?: MouseEventHandler;
onMouseOver?: MouseEventHandler;
onMouseOverCapture?: MouseEventHandler;
onMouseUp?: MouseEventHandler;
onMouseUpCapture?: MouseEventHandler;
// Selection Events
onSelect?: GenericEventHandler;
onSelectCapture?: GenericEventHandler;
// Touch Events
onTouchCancel?: TouchEventHandler;
onTouchCancelCapture?: TouchEventHandler;
onTouchEnd?: TouchEventHandler;
onTouchEndCapture?: TouchEventHandler;
onTouchMove?: TouchEventHandler;
onTouchMoveCapture?: TouchEventHandler;
onTouchStart?: TouchEventHandler;
onTouchStartCapture?: TouchEventHandler;
// Pointer Events
onPointerOver?: PointerEventHandler;
onPointerOverCapture?: PointerEventHandler;
onPointerEnter?: PointerEventHandler;
onPointerEnterCapture?: PointerEventHandler;
onPointerDown?: PointerEventHandler;
onPointerDownCapture?: PointerEventHandler;
onPointerMove?: PointerEventHandler;
onPointerMoveCapture?: PointerEventHandler;
onPointerUp?: PointerEventHandler;
onPointerUpCapture?: PointerEventHandler;
onPointerCancel?: PointerEventHandler;
onPointerCancelCapture?: PointerEventHandler;
onPointerOut?: PointerEventHandler;
onPointerOutCapture?: PointerEventHandler;
onPointerLeave?: PointerEventHandler;
onPointerLeaveCapture?: PointerEventHandler;
onGotPointerCapture?: PointerEventHandler;
onGotPointerCaptureCapture?: PointerEventHandler;
onLostPointerCapture?: PointerEventHandler;
onLostPointerCaptureCapture?: PointerEventHandler;
// UI Events
onScroll?: UIEventHandler;
onScrollCapture?: UIEventHandler;
// Wheel Events
onWheel?: WheelEventHandler;
onWheelCapture?: WheelEventHandler;
// Animation Events
onAnimationStart?: AnimationEventHandler;
onAnimationStartCapture?: AnimationEventHandler;
onAnimationEnd?: AnimationEventHandler;
onAnimationEndCapture?: AnimationEventHandler;
onAnimationIteration?: AnimationEventHandler;
onAnimationIterationCapture?: AnimationEventHandler;
// Transition Events
onTransitionEnd?: TransitionEventHandler;
onTransitionEndCapture?: TransitionEventHandler;
}
interface HTMLAttributes extends Omi.ClassAttributes<any>, DOMAttributes {
// Standard HTML Attributes
accept?: string;
acceptCharset?: string;
accessKey?: string;
action?: string;
allowFullScreen?: boolean;
allowTransparency?: boolean;
alt?: string;
async?: boolean;
autocomplete?: string;
autofocus?: boolean;
autoPlay?: boolean;
capture?: boolean;
cellPadding?: number | string;
cellSpacing?: number | string;
charSet?: string;
challenge?: string;
checked?: boolean;
class?: string;
className?: string;
cols?: number;
colSpan?: number;
content?: string;
contentEditable?: boolean;
contextMenu?: string;
controls?: boolean;
controlsList?: string;
coords?: string;
crossOrigin?: string;
data?: string;
dateTime?: string;
default?: boolean;
defer?: boolean;
dir?: string;
disabled?: boolean;
download?: any;
draggable?: boolean;
encType?: string;
form?: string;
formAction?: string;
formEncType?: string;
formMethod?: string;
formNoValidate?: boolean;
formTarget?: string;
frameBorder?: number | string;
headers?: string;
height?: number | string;
hidden?: boolean;
high?: number;
href?: string;
hrefLang?: string;
for?: string;
httpEquiv?: string;
icon?: string;
id?: string;
inputMode?: string;
integrity?: string;
is?: string;
keyParams?: string;
keyType?: string;
kind?: string;
label?: string;
lang?: string;
list?: string;
loop?: boolean;
low?: number;
manifest?: string;
marginHeight?: number;
marginWidth?: number;
max?: number | string;
maxLength?: number;
media?: string;
mediaGroup?: string;
method?: string;
min?: number | string;
minLength?: number;
multiple?: boolean;
muted?: boolean;
name?: string;
noValidate?: boolean;
open?: boolean;
optimum?: number;
pattern?: string;
placeholder?: string;
playsInline?: boolean;
poster?: string;
preload?: string;
radioGroup?: string;
readOnly?: boolean;
rel?: string;
required?: boolean;
role?: string;
rows?: number;
rowSpan?: number;
sandbox?: string;
scope?: string;
scoped?: boolean;
scrolling?: string;
seamless?: boolean;
selected?: boolean;
shape?: string;
size?: number;
sizes?: string;
slot?: string;
span?: number;
spellcheck?: boolean;
src?: string;
srcset?: string;
srcDoc?: string;
srcLang?: string;
srcSet?: string;
start?: number;
step?: number | string;
style?: any;
summary?: string;
tabIndex?: number;
target?: string;
title?: string;
type?: string;
useMap?: string;
value?: string | string[] | number;
width?: number | string;
wmode?: string;
wrap?: string;
// RDFa Attributes
about?: string;
datatype?: string;
inlist?: any;
prefix?: string;
property?: string;
resource?: string;
typeof?: string;
vocab?: string;
}
interface IntrinsicElements {
// HTML
a: HTMLAttributes;
abbr: HTMLAttributes;
address: HTMLAttributes;
area: HTMLAttributes;
article: HTMLAttributes;
aside: HTMLAttributes;
audio: HTMLAttributes;
b: HTMLAttributes;
base: HTMLAttributes;
bdi: HTMLAttributes;
bdo: HTMLAttributes;
big: HTMLAttributes;
blockquote: HTMLAttributes;
body: HTMLAttributes;
br: HTMLAttributes;
button: HTMLAttributes;
canvas: HTMLAttributes;
caption: HTMLAttributes;
cite: HTMLAttributes;
code: HTMLAttributes;
col: HTMLAttributes;
colgroup: HTMLAttributes;
data: HTMLAttributes;
datalist: HTMLAttributes;
dd: HTMLAttributes;
del: HTMLAttributes;
details: HTMLAttributes;
dfn: HTMLAttributes;
dialog: HTMLAttributes;
div: HTMLAttributes;
dl: HTMLAttributes;
dt: HTMLAttributes;
em: HTMLAttributes;
embed: HTMLAttributes;
fieldset: HTMLAttributes;
figcaption: HTMLAttributes;
figure: HTMLAttributes;
footer: HTMLAttributes;
form: HTMLAttributes;
h1: HTMLAttributes;
h2: HTMLAttributes;
h3: HTMLAttributes;
h4: HTMLAttributes;
h5: HTMLAttributes;
h6: HTMLAttributes;
head: HTMLAttributes;
header: HTMLAttributes;
hr: HTMLAttributes;
html: HTMLAttributes;
i: HTMLAttributes;
iframe: HTMLAttributes;
img: HTMLAttributes;
input: HTMLAttributes;
ins: HTMLAttributes;
kbd: HTMLAttributes;
keygen: HTMLAttributes;
label: HTMLAttributes;
legend: HTMLAttributes;
li: HTMLAttributes;
link: HTMLAttributes;
main: HTMLAttributes;
map: HTMLAttributes;
mark: HTMLAttributes;
menu: HTMLAttributes;
menuitem: HTMLAttributes;
meta: HTMLAttributes;
meter: HTMLAttributes;
nav: HTMLAttributes;
noscript: HTMLAttributes;
object: HTMLAttributes;
ol: HTMLAttributes;
optgroup: HTMLAttributes;
option: HTMLAttributes;
output: HTMLAttributes;
p: HTMLAttributes;
param: HTMLAttributes;
picture: HTMLAttributes;
pre: HTMLAttributes;
progress: HTMLAttributes;
q: HTMLAttributes;
rp: HTMLAttributes;
rt: HTMLAttributes;
ruby: HTMLAttributes;
s: HTMLAttributes;
samp: HTMLAttributes;
script: HTMLAttributes;
section: HTMLAttributes;
select: HTMLAttributes;
slot: HTMLAttributes;
small: HTMLAttributes;
source: HTMLAttributes;
span: HTMLAttributes;
strong: HTMLAttributes;
style: HTMLAttributes;
sub: HTMLAttributes;
summary: HTMLAttributes;
sup: HTMLAttributes;
table: HTMLAttributes;
tbody: HTMLAttributes;
td: HTMLAttributes;
textarea: HTMLAttributes;
tfoot: HTMLAttributes;
th: HTMLAttributes;
thead: HTMLAttributes;
time: HTMLAttributes;
title: HTMLAttributes;
tr: HTMLAttributes;
track: HTMLAttributes;
u: HTMLAttributes;
ul: HTMLAttributes;
"var": HTMLAttributes;
video: HTMLAttributes;
wbr: HTMLAttributes;
//SVG
svg: SVGAttributes;
animate: SVGAttributes;
circle: SVGAttributes;
clipPath: SVGAttributes;
defs: SVGAttributes;
ellipse: SVGAttributes;
feBlend: SVGAttributes;
feColorMatrix: SVGAttributes;
feComponentTransfer: SVGAttributes;
feComposite: SVGAttributes;
feConvolveMatrix: SVGAttributes;
feDiffuseLighting: SVGAttributes;
feDisplacementMap: SVGAttributes;
feFlood: SVGAttributes;
feGaussianBlur: SVGAttributes;
feImage: SVGAttributes;
feMerge: SVGAttributes;
feMergeNode: SVGAttributes;
feMorphology: SVGAttributes;
feOffset: SVGAttributes;
feSpecularLighting: SVGAttributes;
feTile: SVGAttributes;
feTurbulence: SVGAttributes;
filter: SVGAttributes;
foreignObject: SVGAttributes;
g: SVGAttributes;
image: SVGAttributes;
line: SVGAttributes;
linearGradient: SVGAttributes;
marker: SVGAttributes;
mask: SVGAttributes;
path: SVGAttributes;
pattern: SVGAttributes;
polygon: SVGAttributes;
polyline: SVGAttributes;
radialGradient: SVGAttributes;
rect: SVGAttributes;
stop: SVGAttributes;
symbol: SVGAttributes;
text: SVGAttributes;
tspan: SVGAttributes;
use: SVGAttributes;
[tagName: string]: any;
}
}
}

1396
packages/omi-native/dist/omi.dev.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1393
packages/omi-native/dist/omi.esm.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

770
packages/omi-native/dist/omi.js vendored Normal file
View File

@ -0,0 +1,770 @@
!function() {
'use strict';
function VNode() {}
function h(nodeName, attributes) {
var lastSimple, child, simple, i, children = EMPTY_CHILDREN;
for (i = arguments.length; i-- > 2; ) stack.push(arguments[i]);
if (attributes && null != attributes.children) {
if (!stack.length) stack.push(attributes.children);
delete attributes.children;
}
while (stack.length) if ((child = stack.pop()) && void 0 !== child.pop) for (i = child.length; i--; ) stack.push(child[i]); else {
if ('boolean' == typeof child) child = null;
if (simple = 'function' != typeof nodeName) if (null == child) child = ''; else if ('number' == typeof child) child = String(child); else if ('string' != typeof child) simple = !1;
if (simple && lastSimple) children[children.length - 1] += child; else if (children === EMPTY_CHILDREN) children = [ child ]; else children.push(child);
lastSimple = simple;
}
var p = new VNode();
p.nodeName = nodeName;
p.children = children;
p.attributes = null == attributes ? void 0 : attributes;
p.key = null == attributes ? void 0 : attributes.key;
if (void 0 !== options.vnode) options.vnode(p);
return p;
}
function cssToDom(css) {
var node = document.createElement('style');
node.textContent = css;
return node;
}
function npn(str) {
return str.replace(/-(\w)/g, function($, $1) {
return $1.toUpperCase();
});
}
function extend(obj, props) {
for (var i in props) obj[i] = props[i];
return obj;
}
function applyRef(ref, value) {
if (null != ref) if ('function' == typeof ref) ref(value); else ref.current = value;
}
function isArray(obj) {
return '[object Array]' === Object.prototype.toString.call(obj);
}
function nProps(props) {
if (!props || isArray(props)) return {};
var result = {};
Object.keys(props).forEach(function(key) {
result[key] = props[key].value;
});
return result;
}
function isSameNodeType(node, vnode, hydrating) {
if ('string' == typeof vnode || 'number' == typeof vnode) return void 0 !== node.splitText;
if ('string' == typeof vnode.nodeName) return !node._componentConstructor && isNamedNode(node, vnode.nodeName); else return hydrating || node._componentConstructor === vnode.nodeName;
}
function isNamedNode(node, nodeName) {
return node.__n === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase();
}
function createNode(nodeName, isSvg) {
var node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);
node.__n = nodeName;
return node;
}
function removeNode(node) {
var parentNode = node.parentNode;
if (parentNode) parentNode.removeChild(node);
}
function setAccessor(node, name, old, value, isSvg) {
if ('className' === name) name = 'class';
if ('key' === name) ; else if ('ref' === name) {
applyRef(old, null);
applyRef(value, node);
} else if ('class' === name && !isSvg) node.className = value || ''; else if ('style' === name) {
if (!value || 'string' == typeof value || 'string' == typeof old) node.style.cssText = value || '';
if (value && 'object' == typeof value) {
if ('string' != typeof old) for (var i in old) if (!(i in value)) node.style[i] = '';
for (var i in value) node.style[i] = 'number' == typeof value[i] && !1 === IS_NON_DIMENSIONAL.test(i) ? value[i] + 'px' : value[i];
}
} else if ('dangerouslySetInnerHTML' === name) {
if (value) node.innerHTML = value.__html || '';
} else if ('o' == name[0] && 'n' == name[1]) {
var useCapture = name !== (name = name.replace(/Capture$/, ''));
name = name.toLowerCase().substring(2);
if (value) {
if (!old) node.addEventListener(name, eventProxy, useCapture);
} else node.removeEventListener(name, eventProxy, useCapture);
(node.__l || (node.__l = {}))[name] = value;
} else if ('list' !== name && 'type' !== name && !isSvg && name in node) {
try {
node[name] = null == value ? '' : value;
} catch (e) {}
if ((null == value || !1 === value) && 'spellcheck' != name) node.removeAttribute(name);
} else {
var ns = isSvg && name !== (name = name.replace(/^xlink:?/, ''));
if (null == value || !1 === value) if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase()); else node.removeAttribute(name); else if ('string' == typeof value) if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value); else node.setAttribute(name, value);
}
}
function eventProxy(e) {
return this.__l[e.type](options.event && options.event(e) || e);
}
function diff(dom, vnode, context, mountAll, parent, componentRoot) {
var ret;
if (!diffLevel++) {
isSvgMode = null != parent && void 0 !== parent.ownerSVGElement;
hydrating = null != dom && !('__preactattr_' in dom);
}
if (isArray(vnode)) {
ret = [];
var parentNode = null;
if (isArray(dom)) {
parentNode = dom[0].parentNode;
dom.forEach(function(item, index) {
ret.push(idiff(item, vnode[index], context, mountAll, componentRoot));
});
} else vnode.forEach(function(item) {
ret.push(idiff(dom, item, context, mountAll, componentRoot));
});
if (parent) ret.forEach(function(vnode) {
parent.appendChild(vnode);
}); else if (isArray(dom)) dom.forEach(function(node) {
parentNode.appendChild(node);
});
} else {
ret = idiff(dom, vnode, context, mountAll, componentRoot);
if (parent && ret.parentNode !== parent) parent.appendChild(ret);
}
if (!--diffLevel) hydrating = !1;
return ret;
}
function idiff(dom, vnode, context, mountAll, componentRoot) {
if (dom && dom.props) dom.props.children = vnode.children;
var out = dom, prevSvgMode = isSvgMode;
if (null == vnode || 'boolean' == typeof vnode) vnode = '';
if ('string' == typeof vnode || 'number' == typeof vnode) {
if (dom && void 0 !== dom.splitText && dom.parentNode && (!dom._component || componentRoot)) {
if (dom.nodeValue != vnode) dom.nodeValue = vnode;
} else {
out = document.createTextNode(vnode);
if (dom) {
if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
recollectNodeTree(dom, !0);
}
}
out.t = !0;
return out;
}
var vnodeName = vnode.nodeName;
isSvgMode = 'svg' === vnodeName ? !0 : 'foreignObject' === vnodeName ? !1 : isSvgMode;
vnodeName = String(vnodeName);
if (!dom || !isNamedNode(dom, vnodeName)) {
out = createNode(vnodeName, isSvgMode);
if (dom) {
while (dom.firstChild) out.appendChild(dom.firstChild);
if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
recollectNodeTree(dom, !0);
}
}
var fc = out.firstChild, props = out.t, vchildren = vnode.children;
if (null == props) {
props = out.t = {};
for (var a = out.attributes, i = a.length; i--; ) props[a[i].name] = a[i].value;
}
if (!hydrating && vchildren && 1 === vchildren.length && 'string' == typeof vchildren[0] && null != fc && void 0 !== fc.splitText && null == fc.nextSibling) {
if (fc.nodeValue != vchildren[0]) fc.nodeValue = vchildren[0];
} else if (vchildren && vchildren.length || null != fc) innerDiffNode(out, vchildren, context, mountAll, hydrating || null != props.dangerouslySetInnerHTML);
diffAttributes(out, vnode.attributes, props);
if (out.props) out.props.children = vnode.children;
isSvgMode = prevSvgMode;
return out;
}
function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {
var j, c, f, vchild, child, originalChildren = dom.childNodes, children = [], keyed = {}, keyedLen = 0, min = 0, len = originalChildren.length, childrenLen = 0, vlen = vchildren ? vchildren.length : 0;
if (0 !== len) for (var i = 0; i < len; i++) {
var _child = originalChildren[i], props = _child.t, key = vlen && props ? _child._component ? _child._component.__k : props.key : null;
if (null != key) {
keyedLen++;
keyed[key] = _child;
} else if (props || (void 0 !== _child.splitText ? isHydrating ? _child.nodeValue.trim() : !0 : isHydrating)) children[childrenLen++] = _child;
}
if (0 !== vlen) for (var i = 0; i < vlen; i++) {
vchild = vchildren[i];
child = null;
var key = vchild.key;
if (null != key) {
if (keyedLen && void 0 !== keyed[key]) {
child = keyed[key];
keyed[key] = void 0;
keyedLen--;
}
} else if (!child && min < childrenLen) for (j = min; j < childrenLen; j++) if (void 0 !== children[j] && isSameNodeType(c = children[j], vchild, isHydrating)) {
child = c;
children[j] = void 0;
if (j === childrenLen - 1) childrenLen--;
if (j === min) min++;
break;
}
child = idiff(child, vchild, context, mountAll);
f = originalChildren[i];
if (child && child !== dom && child !== f) if (null == f) dom.appendChild(child); else if (child === f.nextSibling) removeNode(f); else dom.insertBefore(child, f);
}
if (keyedLen) for (var i in keyed) if (void 0 !== keyed[i]) recollectNodeTree(keyed[i], !1);
while (min <= childrenLen) if (void 0 !== (child = children[childrenLen--])) recollectNodeTree(child, !1);
}
function recollectNodeTree(node, unmountOnly) {
if (null != node.t && node.t.ref) node.t.ref(null);
if (!1 === unmountOnly || null == node.t) removeNode(node);
removeChildren(node);
}
function removeChildren(node) {
node = node.lastChild;
while (node) {
var next = node.previousSibling;
recollectNodeTree(node, !0);
node = next;
}
}
function diffAttributes(dom, attrs, old) {
var name;
var update = !1;
var isWeElement = dom.update;
for (name in old) if ((!attrs || null == attrs[name]) && null != old[name]) {
setAccessor(dom, name, old[name], old[name] = void 0, isSvgMode);
if (isWeElement) {
delete dom.props[name];
update = !0;
}
}
for (name in attrs) if (isWeElement && 'object' == typeof attrs[name]) {
dom.props[npn(name)] = attrs[name];
update = !0;
} else if (!('children' === name || 'innerHTML' === name || name in old && attrs[name] === ('value' === name || 'checked' === name ? dom[name] : old[name]))) {
setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode);
if (isWeElement) {
dom.props[npn(name)] = attrs[name];
update = !0;
}
}
dom.parentNode && update && isWeElement && dom.update();
}
function observe(target) {
target.observe = !0;
}
function proxyUpdate(ele) {
var timeout = null;
ele.data = new JSONPatcherProxy(ele.data).observe(!1, function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
ele.update();
}, 16.6);
});
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
}
function _possibleConstructorReturn(self, call) {
if (!self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return call && ("object" == typeof call || "function" == typeof call) ? call : self;
}
function _inherits(subClass, superClass) {
if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: !1,
writable: !0,
configurable: !0
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
function render(vnode, parent, store) {
parent = 'string' == typeof parent ? document.querySelector(parent) : parent;
if (store) {
store.instances = [];
extendStoreUpate(store);
var timeout = null;
var patchs = {};
store.data = new JSONPatcherProxy(store.data).observe(!1, function(patch) {
clearTimeout(timeout);
if ('remove' === patch.op) {
var kv = getArrayPatch(patch.path, store);
patchs[kv.k] = kv.v;
timeout = setTimeout(function() {
update(patchs, store);
patchs = {};
}, 16.6);
} else {
var key = fixPath(patch.path);
patchs[key] = patch.value;
timeout = setTimeout(function() {
update(patchs, store);
patchs = {};
}, 16.6);
}
});
parent.store = store;
}
diff(null, vnode, {}, !1, parent, !1);
}
function update(patch, store) {
store.update(patch);
}
function extendStoreUpate(store) {
store.update = function(patch) {
var _this = this;
var updateAll = matchGlobalData(this.globalData, patch);
if (Object.keys(patch).length > 0) {
this.instances.forEach(function(instance) {
if (updateAll || _this.updateAll || instance.constructor.updatePath && needUpdate(patch, instance.constructor.updatePath)) instance.update();
});
this.onChange && this.onChange(patch);
}
};
}
function matchGlobalData(globalData, diffResult) {
if (!globalData) return !1;
for (var keyA in diffResult) {
if (globalData.indexOf(keyA) > -1) return !0;
for (var i = 0, len = globalData.length; i < len; i++) if (includePath(keyA, globalData[i])) return !0;
}
return !1;
}
function needUpdate(diffResult, updatePath) {
for (var keyA in diffResult) {
if (updatePath[keyA]) return !0;
for (var keyB in updatePath) if (includePath(keyA, keyB)) return !0;
}
return !1;
}
function includePath(pathA, pathB) {
if (0 === pathA.indexOf(pathB)) {
var next = pathA.substr(pathB.length, 1);
if ('[' === next || '.' === next) return !0;
}
return !1;
}
function fixPath(path) {
var mpPath = '';
var arr = path.replace('/', '').split('/');
arr.forEach(function(item, index) {
if (index) if (isNaN(Number(item))) mpPath += '.' + item; else mpPath += '[' + item + ']'; else mpPath += item;
});
return mpPath;
}
function getArrayPatch(path, store) {
var arr = path.replace('/', '').split('/');
var current = store.data[arr[0]];
for (var i = 1, len = arr.length; i < len - 1; i++) current = current[arr[i]];
return {
k: fixArrPath(path),
v: current
};
}
function fixArrPath(path) {
var mpPath = '';
var arr = path.replace('/', '').split('/');
var len = arr.length;
arr.forEach(function(item, index) {
if (index < len - 1) if (index) if (isNaN(Number(item))) mpPath += '.' + item; else mpPath += '[' + item + ']'; else mpPath += item;
});
return mpPath;
}
function _classCallCheck$1(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
}
function _possibleConstructorReturn$1(self, call) {
if (!self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return call && ("object" == typeof call || "function" == typeof call) ? call : self;
}
function _inherits$1(subClass, superClass) {
if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: !1,
writable: !0,
configurable: !0
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
function define(name, ctor) {
if ('WeElement' === ctor.is) {
customElements.define(name, ctor);
if (ctor.data && !ctor.pure) ctor.updatePath = getUpdatePath(ctor.data);
} else {
var Element = function(_WeElement) {
function Element() {
var _temp, _this, _ret;
_classCallCheck$1(this, Element);
for (var _len = arguments.length, args = Array(_len), key = 0; key < _len; key++) args[key] = arguments[key];
return _ret = (_temp = _this = _possibleConstructorReturn$1(this, _WeElement.call.apply(_WeElement, [ this ].concat(args))),
_this.C = 0, _this.D = {}, _temp), _possibleConstructorReturn$1(_this, _ret);
}
_inherits$1(Element, _WeElement);
Element.prototype.render = function() {
return ctor.call(this);
};
Element.prototype.beforeRender = function() {
this.C = 0;
};
Element.prototype.useData = function(data) {
return this.use({
data: data
});
};
Element.prototype.use = function(option) {
var _this2 = this;
this.C++;
var updater = function updater(newValue) {
var item = _this2.D[updater.id];
item.data = newValue;
_this2.update();
item.effect && item.effect();
};
updater.id = this.C;
if (!this.B) {
this.D[this.C] = option;
return [ option.data, updater ];
}
return [ this.D[this.C].data, updater ];
};
Element.prototype.installed = function() {
this.B = !0;
};
return Element;
}(WeElement);
customElements.define(name, Element);
}
}
function getUpdatePath(data) {
var result = {};
dataToPath(data, result);
return result;
}
function dataToPath(data, result) {
Object.keys(data).forEach(function(key) {
result[key] = !0;
var type = Object.prototype.toString.call(data[key]);
if ('[object Object]' === type) _objToPath(data[key], key, result); else if ('[object Array]' === type) _arrayToPath(data[key], key, result);
});
}
function _objToPath(data, path, result) {
Object.keys(data).forEach(function(key) {
result[path + '.' + key] = !0;
delete result[path];
var type = Object.prototype.toString.call(data[key]);
if ('[object Object]' === type) _objToPath(data[key], path + '.' + key, result); else if ('[object Array]' === type) _arrayToPath(data[key], path + '.' + key, result);
});
}
function _arrayToPath(data, path, result) {
data.forEach(function(item, index) {
result[path + '[' + index + ']'] = !0;
delete result[path];
var type = Object.prototype.toString.call(item);
if ('[object Object]' === type) _objToPath(item, path + '[' + index + ']', result); else if ('[object Array]' === type) _arrayToPath(item, path + '[' + index + ']', result);
});
}
function tag(name, pure) {
return function(target) {
target.pure = pure;
define(name, target);
};
}
function cloneElement(vnode, props) {
return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);
}
function getHost(ele) {
var p = ele.parentNode;
while (p) if (p.host) return p.host; else p = p.parentNode;
}
var options = {
store: null,
root: function() {
if ('object' != typeof global || !global || global.Math !== Math || global.Array !== Array) return self || window || global || function() {
return this;
}(); else return global;
}()
};
var stack = [];
var EMPTY_CHILDREN = [];
!function() {
if (void 0 !== window.Reflect && void 0 !== window.customElements && !window.customElements.hasOwnProperty('polyfillWrapFlushCallback')) {
var BuiltInHTMLElement = HTMLElement;
window.HTMLElement = function() {
return Reflect.construct(BuiltInHTMLElement, [], this.constructor);
};
HTMLElement.prototype = BuiltInHTMLElement.prototype;
HTMLElement.prototype.constructor = HTMLElement;
Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement);
}
}();
'function' == typeof Promise ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout;
var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;
var diffLevel = 0;
var isSvgMode = !1;
var hydrating = !1;
var JSONPatcherProxy = function() {
function deepClone(obj) {
switch (typeof obj) {
case 'object':
return JSON.parse(JSON.stringify(obj));
case 'undefined':
return null;
default:
return obj;
}
}
function escapePathComponent(str) {
if (-1 == str.indexOf('/') && -1 == str.indexOf('~')) return str; else return str.replace(/~/g, '~0').replace(/\//g, '~1');
}
function findObjectPath(instance, obj) {
var pathComponents = [];
var parentAndPath = instance.parenthoodMap.get(obj);
while (parentAndPath && parentAndPath.path) {
pathComponents.unshift(parentAndPath.path);
parentAndPath = instance.parenthoodMap.get(parentAndPath.parent);
}
if (pathComponents.length) {
var path = pathComponents.join('/');
return '/' + path;
}
return '';
}
function setTrap(instance, target, key, newValue) {
var parentPath = findObjectPath(instance, target);
var destinationPropKey = parentPath + '/' + escapePathComponent(key);
if (instance.proxifiedObjectsMap.has(newValue)) {
var newValueOriginalObject = instance.proxifiedObjectsMap.get(newValue);
instance.parenthoodMap.set(newValueOriginalObject.originalObject, {
parent: target,
path: key
});
}
var revokableInstance = instance.proxifiedObjectsMap.get(newValue);
if (revokableInstance && !instance.isProxifyingTreeNow) revokableInstance.inherited = !0;
if (newValue && 'object' == typeof newValue && !instance.proxifiedObjectsMap.has(newValue)) {
instance.parenthoodMap.set(newValue, {
parent: target,
path: key
});
newValue = instance.A(target, newValue, key);
}
var operation = {
op: 'remove',
path: destinationPropKey
};
if (void 0 === newValue) {
if (!Array.isArray(target) && !target.hasOwnProperty(key)) return Reflect.set(target, key, newValue);
if (Array.isArray(target)) operation.op = 'replace', operation.value = null;
var oldValue = instance.proxifiedObjectsMap.get(target[key]);
if (oldValue) {
instance.parenthoodMap.delete(target[key]);
instance.disableTrapsForProxy(oldValue);
instance.proxifiedObjectsMap.delete(oldValue);
}
} else {
if (Array.isArray(target) && !Number.isInteger(+key.toString())) {
if ('length' != key) console.warn('JSONPatcherProxy noticed a non-integer prop was set for an array. This will not emit a patch');
return Reflect.set(target, key, newValue);
}
operation.op = 'add';
if (target.hasOwnProperty(key)) if (void 0 !== target[key] || Array.isArray(target)) operation.op = 'replace';
operation.value = newValue;
}
var reflectionResult = Reflect.set(target, key, newValue);
instance.defaultCallback(operation);
return reflectionResult;
}
function deleteTrap(instance, target, key) {
if (void 0 !== target[key]) {
var parentPath = findObjectPath(instance, target);
var destinationPropKey = parentPath + '/' + escapePathComponent(key);
var revokableProxyInstance = instance.proxifiedObjectsMap.get(target[key]);
if (revokableProxyInstance) if (revokableProxyInstance.inherited) revokableProxyInstance.inherited = !1; else {
instance.parenthoodMap.delete(revokableProxyInstance.originalObject);
instance.disableTrapsForProxy(revokableProxyInstance);
instance.proxifiedObjectsMap.delete(target[key]);
}
var reflectionResult = Reflect.deleteProperty(target, key);
instance.defaultCallback({
op: 'remove',
path: destinationPropKey
});
return reflectionResult;
}
}
function resume() {
var _this = this;
this.defaultCallback = function(operation) {
_this.isRecording && _this.patches.push(operation);
_this.userCallback && _this.userCallback(operation);
};
this.isObserving = !0;
}
function pause() {
this.defaultCallback = function() {};
this.isObserving = !1;
}
function JSONPatcherProxy(root, showDetachedWarning) {
this.isProxifyingTreeNow = !1;
this.isObserving = !1;
this.proxifiedObjectsMap = new Map();
this.parenthoodMap = new Map();
if ('boolean' != typeof showDetachedWarning) showDetachedWarning = !0;
this.showDetachedWarning = showDetachedWarning;
this.originalObject = root;
this.cachedProxy = null;
this.isRecording = !1;
this.userCallback;
this.resume = resume.bind(this);
this.pause = pause.bind(this);
}
JSONPatcherProxy.deepClone = deepClone;
JSONPatcherProxy.escapePathComponent = escapePathComponent;
JSONPatcherProxy.prototype.generateProxyAtPath = function(parent, obj, path) {
var _this2 = this;
if (!obj) return obj;
var traps = {
set: function(target, key, value, receiver) {
return setTrap(_this2, target, key, value);
},
deleteProperty: function(target, key) {
return deleteTrap(_this2, target, key);
}
};
var revocableInstance = Proxy.revocable(obj, traps);
revocableInstance.trapsInstance = traps;
revocableInstance.originalObject = obj;
this.parenthoodMap.set(obj, {
parent: parent,
path: path
});
this.proxifiedObjectsMap.set(revocableInstance.proxy, revocableInstance);
return revocableInstance.proxy;
};
JSONPatcherProxy.prototype.A = function(parent, root, path) {
for (var key in root) if (root.hasOwnProperty(key)) if (root[key] instanceof Object) root[key] = this.A(root, root[key], escapePathComponent(key));
return this.generateProxyAtPath(parent, root, path);
};
JSONPatcherProxy.prototype.proxifyObjectTree = function(root) {
this.pause();
this.isProxifyingTreeNow = !0;
var proxifiedObject = this.A(void 0, root, '');
this.isProxifyingTreeNow = !1;
this.resume();
return proxifiedObject;
};
JSONPatcherProxy.prototype.disableTrapsForProxy = function(revokableProxyInstance) {
if (this.showDetachedWarning) {
var message = "You're accessing an object that is detached from the observedObject tree, see https://github.com/Palindrom/JSONPatcherProxy#detached-objects";
revokableProxyInstance.trapsInstance.set = function(targetObject, propKey, newValue) {
console.warn(message);
return Reflect.set(targetObject, propKey, newValue);
};
revokableProxyInstance.trapsInstance.set = function(targetObject, propKey, newValue) {
console.warn(message);
return Reflect.set(targetObject, propKey, newValue);
};
revokableProxyInstance.trapsInstance.deleteProperty = function(targetObject, propKey) {
return Reflect.deleteProperty(targetObject, propKey);
};
} else {
delete revokableProxyInstance.trapsInstance.set;
delete revokableProxyInstance.trapsInstance.get;
delete revokableProxyInstance.trapsInstance.deleteProperty;
}
};
JSONPatcherProxy.prototype.observe = function(record, callback) {
if (!record && !callback) throw new Error('You need to either record changes or pass a callback');
this.isRecording = record;
this.userCallback = callback;
if (record) this.patches = [];
this.cachedProxy = this.proxifyObjectTree(this.originalObject);
return this.cachedProxy;
};
JSONPatcherProxy.prototype.generate = function() {
if (!this.isRecording) throw new Error('You should set record to true to get patches later');
return this.patches.splice(0, this.patches.length);
};
JSONPatcherProxy.prototype.revoke = function() {
this.proxifiedObjectsMap.forEach(function(el) {
el.revoke();
});
};
JSONPatcherProxy.prototype.disableTraps = function() {
this.proxifiedObjectsMap.forEach(this.disableTrapsForProxy, this);
};
return JSONPatcherProxy;
}();
var WeElement = function(_HTMLElement) {
function WeElement() {
_classCallCheck(this, WeElement);
var _this = _possibleConstructorReturn(this, _HTMLElement.call(this));
_this.props = nProps(_this.constructor.props);
_this.data = _this.constructor.data || {};
return _this;
}
_inherits(WeElement, _HTMLElement);
WeElement.prototype.connectedCallback = function() {
if (!this.constructor.pure) {
var p = this.parentNode;
while (p && !this.store) {
this.store = p.store;
p = p.parentNode || p.host;
}
if (this.store) this.store.instances.push(this);
}
this.install();
var shadowRoot = this.attachShadow({
mode: 'open'
});
this.css && shadowRoot.appendChild(cssToDom(this.css()));
this.beforeRender();
options.afterInstall && options.afterInstall(this);
if (this.constructor.observe) proxyUpdate(this);
this.host = diff(null, this.render(this.props, !this.constructor.pure && this.store ? this.store.data : this.data), {}, !1, null, !1);
if (isArray(this.host)) this.host.forEach(function(item) {
shadowRoot.appendChild(item);
}); else shadowRoot.appendChild(this.host);
this.installed();
this.B = !0;
};
WeElement.prototype.disconnectedCallback = function() {
this.uninstall();
if (this.store) for (var i = 0, len = this.store.instances.length; i < len; i++) if (this.store.instances[i] === this) {
this.store.instances.splice(i, 1);
break;
}
};
WeElement.prototype.update = function() {
this.beforeUpdate();
this.beforeRender();
diff(this.host, this.render(this.props, !this.constructor.pure && this.store ? this.store.data : this.data));
this.afterUpdate();
};
WeElement.prototype.fire = function(name, data) {
this.dispatchEvent(new CustomEvent(name, {
detail: data
}));
};
WeElement.prototype.install = function() {};
WeElement.prototype.installed = function() {};
WeElement.prototype.uninstall = function() {};
WeElement.prototype.beforeUpdate = function() {};
WeElement.prototype.afterUpdate = function() {};
WeElement.prototype.beforeRender = function() {};
return WeElement;
}(HTMLElement);
WeElement.is = 'WeElement';
var omi = {
tag: tag,
WeElement: WeElement,
render: render,
h: h,
createElement: h,
options: options,
define: define,
observe: observe,
cloneElement: cloneElement,
getHost: getHost
};
options.root.Omi = omi;
options.root.Omi.version = '4.0.15';
if ('undefined' != typeof module) module.exports = omi; else self.Omi = omi;
}();
//# sourceMappingURL=omi.js.map

1
packages/omi-native/dist/omi.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
packages/omi-native/dist/omi.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
<html>
<head></head>
<body>
<script src="b.js"></script>
</body>
</html>

View File

@ -0,0 +1,32 @@
import { define, render } from '../../src/omi'
define('my-counter', function() {
const [count, setCount] = this.useData(0)
const [items, setItems] = this.use({
data: [{ text: 'Omi' }],
effect: function() {
console.log(`The items count is ${this.data.length}.`)
}
})
return (
<div>
<button onClick={() => setCount(count - 1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
<ul>
{items.map(item => {
return <li>{item.text}</li>
})}
</ul>
<button onClick={() => setItems([...items, { text: 'new item' }])}>
add
</button>
<button onClick={() => setItems([])}>empty</button>
</div>
)
})
render(<my-counter />, 'body')

View File

@ -0,0 +1,16 @@
import { extend } from './util'
import { h } from './h'
/**
* Clones the given VNode, optionally adding attributes/props and replacing its children.
* @param {VNode} vnode The virtual DOM element to clone
* @param {Object} props Attributes/props to add when cloning
* @param {VNode} rest Any additional arguments will be used as replacement children.
*/
export function cloneElement(vnode, props) {
return h(
vnode.nodeName,
extend(extend({}, vnode.attributes), props),
arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children
)
}

View File

@ -0,0 +1,11 @@
// render modes
export const NO_RENDER = 0
export const SYNC_RENDER = 1
export const FORCE_RENDER = 2
export const ASYNC_RENDER = 3
export const ATTR_KEY = '__preactattr_'
// DOM properties that should NOT have "px" added when numeric
export const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i

View File

@ -0,0 +1,100 @@
import WeElement from './we-element'
const OBJECTTYPE = '[object Object]'
const ARRAYTYPE = '[object Array]'
export function define(name, ctor) {
if (ctor.is === 'WeElement') {
customElements.define(name, ctor)
if (ctor.data && !ctor.pure) {
ctor.updatePath = getUpdatePath(ctor.data)
}
} else {
class Element extends WeElement {
_useId = 0
_useMap = {}
render() {
return ctor.call(this)
}
beforeRender() {
this._useId = 0
}
useData(data) {
return this.use({ data: data })
}
use(option) {
this._useId++
const updater = newValue => {
const item = this._useMap[updater.id]
item.data = newValue
this.update()
item.effect && item.effect()
}
updater.id = this._useId
if (!this._isInstalled) {
this._useMap[this._useId] = option
return [option.data, updater]
}
return [this._useMap[this._useId].data, updater]
}
installed() {
this._isInstalled = true
}
}
customElements.define(name, Element)
}
}
export function getUpdatePath(data) {
const result = {}
dataToPath(data, result)
return result
}
function dataToPath(data, result) {
Object.keys(data).forEach(key => {
result[key] = true
const type = Object.prototype.toString.call(data[key])
if (type === OBJECTTYPE) {
_objToPath(data[key], key, result)
} else if (type === ARRAYTYPE) {
_arrayToPath(data[key], key, result)
}
})
}
function _objToPath(data, path, result) {
Object.keys(data).forEach(key => {
result[path + '.' + key] = true
delete result[path]
const type = Object.prototype.toString.call(data[key])
if (type === OBJECTTYPE) {
_objToPath(data[key], path + '.' + key, result)
} else if (type === ARRAYTYPE) {
_arrayToPath(data[key], path + '.' + key, result)
}
})
}
function _arrayToPath(data, path, result) {
data.forEach((item, index) => {
result[path + '[' + index + ']'] = true
delete result[path]
const type = Object.prototype.toString.call(item)
if (type === OBJECTTYPE) {
_objToPath(item, path + '[' + index + ']', result)
} else if (type === ARRAYTYPE) {
_arrayToPath(item, path + '[' + index + ']', result)
}
})
}

View File

@ -0,0 +1,143 @@
import { IS_NON_DIMENSIONAL } from '../constants'
import { applyRef } from '../util'
import options from '../options'
/**
* A DOM event listener
* @typedef {(e: Event) => void} EventListner
*/
/**
* A mapping of event types to event listeners
* @typedef {Object.<string, EventListener>} EventListenerMap
*/
/**
* Properties Preact adds to elements it creates
* @typedef PreactElementExtensions
* @property {string} [normalizedNodeName] A normalized node name to use in diffing
* @property {EventListenerMap} [_listeners] A map of event listeners added by components to this DOM node
* @property {import('../component').Component} [_component] The component that rendered this DOM node
* @property {function} [_componentConstructor] The constructor of the component that rendered this DOM node
*/
/**
* A DOM element that has been extended with Preact properties
* @typedef {Element & ElementCSSInlineStyle & PreactElementExtensions} PreactElement
*/
/**
* Create an element with the given nodeName.
* @param {string} nodeName The DOM node to create
* @param {boolean} [isSvg=false] If `true`, creates an element within the SVG
* namespace.
* @returns {PreactElement} The created DOM node
*/
export function createNode(nodeName, isSvg) {
/** @type {PreactElement} */
let node = isSvg
? document.createElementNS('http://www.w3.org/2000/svg', nodeName)
: document.createElement(nodeName)
node.normalizedNodeName = nodeName
return node
}
/**
* Remove a child node from its parent if attached.
* @param {Node} node The node to remove
*/
export function removeNode(node) {
let parentNode = node.parentNode
if (parentNode) parentNode.removeChild(node)
}
/**
* Set a named attribute on the given Node, with special behavior for some names
* and event handlers. If `value` is `null`, the attribute/handler will be
* removed.
* @param {PreactElement} node An element to mutate
* @param {string} name The name/key to set, such as an event or attribute name
* @param {*} old The last value that was set for this name/node pair
* @param {*} value An attribute value, such as a function to be used as an
* event handler
* @param {boolean} isSvg Are we currently diffing inside an svg?
* @private
*/
export function setAccessor(node, name, old, value, isSvg) {
if (name === 'className') name = 'class'
if (name === 'key') {
// ignore
} else if (name === 'ref') {
applyRef(old, null)
applyRef(value, node)
} else if (name === 'class' && !isSvg) {
node.className = value || ''
} else if (name === 'style') {
if (!value || typeof value === 'string' || typeof old === 'string') {
node.style.cssText = value || ''
}
if (value && typeof value === 'object') {
if (typeof old !== 'string') {
for (let i in old) if (!(i in value)) node.style[i] = ''
}
for (let i in value) {
node.style[i] =
typeof value[i] === 'number' && IS_NON_DIMENSIONAL.test(i) === false
? value[i] + 'px'
: value[i]
}
}
} else if (name === 'dangerouslySetInnerHTML') {
if (value) node.innerHTML = value.__html || ''
} else if (name[0] == 'o' && name[1] == 'n') {
let useCapture = name !== (name = name.replace(/Capture$/, ''))
name = name.toLowerCase().substring(2)
if (value) {
if (!old) node.addEventListener(name, eventProxy, useCapture)
} else {
node.removeEventListener(name, eventProxy, useCapture)
}
;(node._listeners || (node._listeners = {}))[name] = value
} else if (name !== 'list' && name !== 'type' && !isSvg && name in node) {
// Attempt to set a DOM property to the given value.
// IE & FF throw for certain property-value combinations.
try {
node[name] = value == null ? '' : value
} catch (e) {}
if ((value == null || value === false) && name != 'spellcheck')
node.removeAttribute(name)
} else {
let ns = isSvg && name !== (name = name.replace(/^xlink:?/, ''))
// spellcheck is treated differently than all other boolean values and
// should not be removed when the value is `false`. See:
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-spellcheck
if (value == null || value === false) {
if (ns)
node.removeAttributeNS(
'http://www.w3.org/1999/xlink',
name.toLowerCase()
)
else node.removeAttribute(name)
} else if (typeof value === 'string') {
if (ns) {
node.setAttributeNS(
'http://www.w3.org/1999/xlink',
name.toLowerCase(),
value
)
} else {
node.setAttribute(name, value)
}
}
}
}
/**
* Proxy an event to hooked event handlers
* @param {Event} e The event object from the browser
* @private
*/
function eventProxy(e) {
return this._listeners[e.type]((options.event && options.event(e)) || e)
}

View File

@ -0,0 +1,10 @@
export function getHost(ele) {
let p = ele.parentNode
while (p) {
if (p.host) {
return p.host
} else {
p = p.parentNode
}
}
}

View File

@ -0,0 +1,54 @@
import { VNode } from './vnode'
import options from './options'
const stack = []
const EMPTY_CHILDREN = []
export function h(nodeName, attributes) {
let children = EMPTY_CHILDREN,
lastSimple,
child,
simple,
i
for (i = arguments.length; i-- > 2; ) {
stack.push(arguments[i])
}
if (attributes && attributes.children != null) {
if (!stack.length) stack.push(attributes.children)
delete attributes.children
}
while (stack.length) {
if ((child = stack.pop()) && child.pop !== undefined) {
for (i = child.length; i--; ) stack.push(child[i])
} else {
if (typeof child === 'boolean') child = null
if ((simple = typeof nodeName !== 'function')) {
if (child == null) child = ''
else if (typeof child === 'number') child = String(child)
else if (typeof child !== 'string') simple = false
}
if (simple && lastSimple) {
children[children.length - 1] += child
} else if (children === EMPTY_CHILDREN) {
children = [child]
} else {
children.push(child)
}
lastSimple = simple
}
}
let p = new VNode()
p.nodeName = nodeName
p.children = children
p.attributes = attributes == null ? undefined : attributes
p.key = attributes == null ? undefined : attributes.key
// if a "vnode hook" is defined, pass every created VNode to it
if (options.vnode !== undefined) options.vnode(p)
return p
}

View File

@ -0,0 +1,11 @@
## document.js
Implement this web Document for native rendering, send instructions to the client through it.
## element.js
Implement this web Element for native rendering. It has the same API as dom elment.
## html-element.js
Implement this web HTMLElement for native rendering.

View File

@ -0,0 +1,98 @@
import Element from './element';
import { addDoc, removeDoc } from './util';
//get document module from global bridge
const { document } = global.bridge;
export default class Document {
constructor(id) {
this.id = id;
addDoc(id, this);
this.nodeMap = {};
this._isMockDocument = true;
this.keyframes = {};
}
createBody(type, props) {
if (!this.body) {
const el = new Element(type, props);
el.didMount = true;
el.ownerDocument = this;
el.docId = this.id;
el.style.alignItems = 'flex-start';
this.body = el;
}
return this.body;
}
createElement(tagName, props) {
let el = new Element(tagName, props);
el.ownerDocument = this;
el.docId = this.id;
return el;
}
destroy() {
delete this.listener;
delete this.nodeMap;
removeDoc(this.id);
}
createFinish() {
document.createFinish(this.id, this.body.toJSON());
}
updateFinish() {
document.updateFinish(this.id);
}
addElement(ref, element, index) {
document.addElement(this.id, ref, element, index);
}
moveElement(ref, parentRef, index) {
document.moveElement(this.id, ref, parentRef, index);
}
removeElement(ref) {
document.removeElement(this.id, ref);
}
setStyles(ref, result) {
document.setStyles(this.id, ref, result);
}
setAttr(ref, result) {
document.setAttr(this.id, ref, result);
}
removeAttr(ref, key) {
document.removeAttr(this.id, ref, key);
}
addEvent(ref, type) {
document.addEvent(this.id, ref, type);
}
removeEvent(ref, type) {
document.removeEvent(this.id, ref, type);
}
addKeyframe(frame) {
document.addKeyframe(this.id, frame);
}
addKeyframeMap(frames) {
document.addKeyframeMap(this.id, frames);
}
scrollTo(ref, x, y, animated) {
document.scrollTo(this.id, ref, x, y, animated);
}
getComputedStyle(ref, func) {
document.getComputedStyle(this.id, ref, func);
}
}

View File

@ -0,0 +1,286 @@
import {
getDoc,
uniqueId,
linkParent,
insertIndex,
moveIndex,
removeIndex
} from './util';
import { getSendBridgeFlag } from './util';
const sendBridgeFlag = getSendBridgeFlag();
function registerNode(docId, node) {
const doc = getDoc(docId);
doc.nodeMap[node.nodeId] = node;
}
export default class Element {
constructor(type) {
this.nodeType = 1;
this.nodeId = uniqueId();
this.ref = this.nodeId;
this.type = type;
this.attributes = {};
this.style = {};
this.classStyle = {};
this.event = {};
this.childNodes = [];
this.nodeName = this.type;
this.didMount = false;
this.parentNode = null;
this.nextSibling = null;
this.previousSibling = null;
this.firstChild = null;
}
appendChild(node) {
if (!node.parentNode) {
linkParent(node, this);
insertIndex(node, this.childNodes, this.childNodes.length, true);
if (this.docId != undefined) {
registerNode(this.docId, node);
}
if (this.didMount && sendBridgeFlag[this.docId]) {
this.ownerDocument.addElement(this.ref, node.toJSON(), -1);
}
}
else {
node.parentNode.removeChild(node);
this.appendChild(node);
return;
}
this.firstChild = this.childNodes[0];
if (this.didMount) {
this._setDidMount(node, true);
}
}
_setDidMount(node, mount) {
node.didMount = mount;
node.childNodes.forEach(child => {
this._setDidMount(child, mount);
});
}
insertBefore(node, before) {
if (!node.parentNode) {
linkParent(node, this);
const index = insertIndex(node, this.childNodes, this.childNodes.indexOf(before), true);
if (this.docId != undefined) {
registerNode(this.docId, node);
}
if (this.didMount && sendBridgeFlag[this.docId]) {
this.ownerDocument.addElement(this.ref, node.toJSON(), index);
}
}
else {
node.parentNode.removeChild(node);
this.insertBefore(node, before);
return;
}
if (this.didMount) {
this._setDidMount(node, true);
}
this.firstChild = this.childNodes[0];
}
insertAfter(node, after) {
if (node.parentNode && node.parentNode !== this) {
return;
}
if (node === after || (node.previousSibling && node.previousSibling === after)) {
return;
}
if (!node.parentNode) {
linkParent(node, this);
const index = insertIndex(node, this.childNodes, this.childNodes.indexOf(after) + 1, true);
if (this.docId != undefined) {
registerNode(this.docId, node);
}
if (this.didMount && sendBridgeFlag[this.docId]) {
this.ownerDocument.addElement(this.ref, node.toJSON(), index);
}
}
else {
const index = moveIndex(node, this.childNodes, this.childNodes.indexOf(after) + 1);
if (this.didMount) {
this.ownerDocument.moveElement(node.ref, this.ref, index);
}
}
if (this.didMount) {
this._setDidMount(node, true);
}
this.firstChild = this.childNodes[0];
}
removeChild(node) {
if (node.parentNode) {
removeIndex(node, this.childNodes, true);
if (this.didMount && sendBridgeFlag[this.docId]) {
this.ownerDocument.removeElement(node.ref);
}
}
node.parentNode = null;
this._setDidMount(node, false);
this.firstChild = this.childNodes[0];
}
setAttribute(key, value, silent) {
if (this.attributes[key] === value && silent !== false) {
return;
}
this.attributes[key] = value;
if (!silent) {
const result = {};
result[key] = value;
if (this.didMount && sendBridgeFlag[this.docId]) {
this.ownerDocument.setAttr(this.ref, result);
}
}
}
removeAttribute(key) {
if (this.attributes[key]) {
delete this.attributes[key];
}
}
setStyle(key, value, silent) {
if (this.style[key] === value && silent !== false) {
return;
}
this.style[key] = value;
if (!silent && this.ownerDocument) {
const result = {};
result[key] = value;
if (this.didMount && sendBridgeFlag[this.docId]) {
this.ownerDocument.setStyles(this.ref, result);
}
}
}
setStyles(styles) {
Object.assign(this.style, styles);
if (this.ownerDocument) {
if (this.didMount && sendBridgeFlag[this.docId]) {
this.ownerDocument.setStyles(this.ref, styles);
}
}
}
setClassStyle(classStyle) {
for (const key in this.classStyle) {
this.classStyle[key] = '';
}
Object.assign(this.classStyle, classStyle);
if (this.didMount && sendBridgeFlag[this.docId]) {
this.ownerDocument.setStyles(this.ref, this.toStyle());
}
}
addEventListener(type, handler) {
if (!this.event[type]) {
this.event[type] = handler;
sendBridgeFlag[this.docId] && this.didMount && this.ownerDocument.addEvent(this.ref, type);
}
}
removeEventListener(type) {
if (this.event[type]) {
delete this.event[type];
let doc = getDoc(this.docId);
doc.nodeMap[this.ref] && doc.nodeMap[this.ref].event && doc.nodeMap[this.ref].event[type] ? doc.nodeMap[this.ref].event[type] = null : '';
sendBridgeFlag[this.docId] && this.didMount && this.ownerDocument.removeEvent(this.ref, type);
}
}
fireEvent(type, e) {
const handler = this.event[type];
if (handler) {
return handler.call(this, e);
}
}
toStyle() {
return Object.assign({}, this.classStyle, this.style);
}
getComputedStyle() {
}
toJSON() {
let result = {
id: this.ref,
type: this.type,
docId: this.docId || -10000,
attributes: this.attributes ? this.attributes : {}
};
result.attributes.style = this.toStyle();
const event = Object.keys(this.event);
if (event.length) {
result.event = event;
}
if (this.childNodes.length) {
result.children = this.childNodes.map((child) => child.toJSON());
}
return result;
}
replaceChild(newChild, oldChild) {
this.insertBefore(newChild, oldChild);
this.removeChild(oldChild);
}
destroy() {
const doc = getDoc(this.docId);
if (doc) {
delete doc.nodeMap[this.nodeId];
}
this.parentNode = null;
this.childNodes.forEach(child => {
child.destroy();
});
}
}

View File

@ -0,0 +1,7 @@
import Element from './element'
export default class HTMLElement extends Element {
constructor( ) {
}
}

View File

@ -0,0 +1,144 @@
let nodeId = 1;
export function uniqueId() {
return nodeId++;
}
let docMap = {};
export function addDoc(id, doc) {
docMap[id] = doc;
}
export function getDoc(id) {
return docMap[id];
}
export function removeDoc(id) {
delete docMap[id];
}
let sendBridgeFlag = {};
export function getSendBridgeFlag(){
return sendBridgeFlag;
}
export function setSendBridgeFlag(docId, flag){
return sendBridgeFlag[docId] = flag;
}
export function insertIndex(target, list, newIndex) {
if (newIndex < 0) {
newIndex = 0;
}
const before = list[newIndex - 1];
const after = list[newIndex];
list.splice(newIndex, 0, target);
before && (before.nextSibling = target);
target.previousSibling = before;
target.nextSibling = after;
after && (after.previousSibling = target);
return newIndex;
}
export function moveIndex(target, list, newIndex) {
const index = list.indexOf(target);
if (index < 0) {
return -1;
}
const before = list[index - 1];
const after = list[index + 1];
before && (before.nextSibling = after);
after && (after.previousSibling = before);
list.splice(index, 1);
let newIndexAfter = newIndex;
if (index <= newIndex) {
newIndexAfter = newIndex - 1;
}
const beforeNew = list[newIndexAfter - 1];
const afterNew = list[newIndexAfter];
list.splice(newIndexAfter, 0, target);
beforeNew && (beforeNew.nextSibling = target);
target.previousSibling = beforeNew;
target.nextSibling = afterNew;
afterNew && (afterNew.previousSibling = target);
if (index === newIndexAfter) {
return -1;
}
return newIndex;
}
export function removeIndex(target, list, changeSibling) {
const index = list.indexOf(target);
if (index < 0) {
return;
}
if (changeSibling) {
const before = list[index - 1];
const after = list[index + 1];
before && (before.nextSibling = after);
after && (after.previousSibling = before);
}
list.splice(index, 1);
}
export function remove(target, list) {
const index = list.indexOf(target);
if (index < 0) {
return;
}
const before = list[index - 1];
const after = list[index + 1];
before && (before.nextSibling = after);
after && (after.previousSibling = before);
list.splice(index, 1);
}
export function linkParent(node, parent) {
node.parentNode = parent;
if (parent.docId) {
node.docId = parent.docId;
node.ownerDocument = parent.ownerDocument;
node.ownerDocument.nodeMap[node.nodeId] = node;
node.depth = parent.depth + 1;
}
node.childNodes.forEach(child => {
linkParent(child, node);
});
}
export function nextElement(node) {
while (node) {
if (node.nodeType === 1) {
return node;
}
node = node.nextSibling;
}
}
export function previousElement(node) {
while (node) {
if (node.nodeType === 1) {
return node;
}
node = node.previousSibling;
}
}

View File

@ -0,0 +1,16 @@
import JSONProxy from './proxy'
export function observe(target) {
target.observe = true
}
export function proxyUpdate(ele) {
let timeout = null
ele.data = new JSONProxy(ele.data).observe(false, () => {
clearTimeout(timeout)
timeout = setTimeout(() => {
ele.update()
}, 16.6)
})
}

891
packages/omi-native/src/omi.d.ts vendored Normal file
View File

@ -0,0 +1,891 @@
export = Omi;
export as namespace Omi;
declare namespace Omi {
type Key = string | number;
type Ref<T> = (instance: T) => void;
type ComponentChild = VNode<any> | object | string | number | boolean | null;
type ComponentChildren = ComponentChild[] | ComponentChild;
interface Attributes {
key?: string | number | any;
}
interface ClassAttributes<T> extends Attributes {
ref?: Ref<T>;
}
interface OmiDOMAttributes {
children?: ComponentChildren;
dangerouslySetInnerHTML?: {
__html: string;
};
}
/**
* Use this to manually set the attributes of a custom element
*
* declare global {
* namespace JSX {
* interface IntrinsicElements {
* 'hello-element': CustomElementBaseAttributes & {
* 'prop-from-parent': string;
* }
* }
* }
* }
*/
interface CustomElementBaseAttributes extends ClassAttributes<any>, OmiDOMAttributes {}
/**
* Define the contract for a virtual node in omi.
*
* A virtual node has a name, a map of attributes, an array
* of child {VNode}s and a key. The key is used by omi for
* internal purposes.
*/
interface VNode<P = any> {
nodeName: string;
attributes: P;
children: Array<VNode<any> | string>;
key?: Key | null;
}
type RenderableProps<P, RefType = any> = Readonly<
P & Attributes & { children?: ComponentChildren; ref?: Ref<RefType> }
>;
interface WeElement<P, D> {
install?(): void;
installed?(): void;
uninstall?(): void;
beforeUpdate?(): void;
afterUpdate?(): void;
beforeRender?(): void;
}
abstract class WeElement<P = {}, D = {}> {
constructor();
// Allow static members to reference class type parameters
// https://github.com/Microsoft/TypeScript/issues/24018
static props: object;
static data: object;
props: RenderableProps<P>;
data: D;
host: HTMLElement;
css(): void;
update(): void;
fire(name: string, data?: object): void;
// Abstract methods don't infer argument types
// https://github.com/Microsoft/TypeScript/issues/14887
abstract render(props: RenderableProps<P>, data: D): void;
}
function h<P>(
node: string,
params: Attributes & P | null,
...children: ComponentChildren[]
): VNode<any>;
function h(
node: string,
params: JSX.HTMLAttributes & JSX.SVGAttributes & Record<string, any> | null,
...children: ComponentChildren[]
): VNode<any>;
function render(vnode: ComponentChild, parent: string | Element | Document | ShadowRoot | DocumentFragment, store?: object): void;
function define(name: string, ctor: any): void;
function tag(name: string, pure?: boolean): (ctor: any) => void;
var options: {
vnode?: (vnode: VNode<any>) => void;
event?: (event: Event) => Event;
};
}
type Defaultize<Props, Defaults> =
// Distribute over unions
Props extends any
? // Make any properties included in Default optional
& Partial<Pick<Props, Extract<keyof Props, keyof Defaults>>>
// Include the remaining properties from Props
& Pick<Props, Exclude<keyof Props, keyof Defaults>>
: never;
declare global {
namespace JSX {
interface Element extends Omi.VNode<any> {
}
interface ElementClass extends Omi.WeElement<any, any> {
}
interface ElementAttributesProperty {
props: any;
}
interface ElementChildrenAttribute {
children: any;
}
type LibraryManagedAttributes<Component, Props> =
Component extends { defaultProps: infer Defaults }
? Defaultize<Props, Defaults>
: Props;
interface SVGAttributes extends HTMLAttributes {
accentHeight?: number | string;
accumulate?: "none" | "sum";
additive?: "replace" | "sum";
alignmentBaseline?: "auto" | "baseline" | "before-edge" | "text-before-edge" | "middle" | "central" | "after-edge" | "text-after-edge" | "ideographic" | "alphabetic" | "hanging" | "mathematical" | "inherit";
allowReorder?: "no" | "yes";
alphabetic?: number | string;
amplitude?: number | string;
arabicForm?: "initial" | "medial" | "terminal" | "isolated";
ascent?: number | string;
attributeName?: string;
attributeType?: string;
autoReverse?: number | string;
azimuth?: number | string;
baseFrequency?: number | string;
baselineShift?: number | string;
baseProfile?: number | string;
bbox?: number | string;
begin?: number | string;
bias?: number | string;
by?: number | string;
calcMode?: number | string;
capHeight?: number | string;
clip?: number | string;
clipPath?: string;
clipPathUnits?: number | string;
clipRule?: number | string;
colorInterpolation?: number | string;
colorInterpolationFilters?: "auto" | "sRGB" | "linearRGB" | "inherit";
colorProfile?: number | string;
colorRendering?: number | string;
contentScriptType?: number | string;
contentStyleType?: number | string;
cursor?: number | string;
cx?: number | string;
cy?: number | string;
d?: string;
decelerate?: number | string;
descent?: number | string;
diffuseConstant?: number | string;
direction?: number | string;
display?: number | string;
divisor?: number | string;
dominantBaseline?: number | string;
dur?: number | string;
dx?: number | string;
dy?: number | string;
edgeMode?: number | string;
elevation?: number | string;
enableBackground?: number | string;
end?: number | string;
exponent?: number | string;
externalResourcesRequired?: number | string;
fill?: string;
fillOpacity?: number | string;
fillRule?: "nonzero" | "evenodd" | "inherit";
filter?: string;
filterRes?: number | string;
filterUnits?: number | string;
floodColor?: number | string;
floodOpacity?: number | string;
focusable?: number | string;
fontFamily?: string;
fontSize?: number | string;
fontSizeAdjust?: number | string;
fontStretch?: number | string;
fontStyle?: number | string;
fontVariant?: number | string;
fontWeight?: number | string;
format?: number | string;
from?: number | string;
fx?: number | string;
fy?: number | string;
g1?: number | string;
g2?: number | string;
glyphName?: number | string;
glyphOrientationHorizontal?: number | string;
glyphOrientationVertical?: number | string;
glyphRef?: number | string;
gradientTransform?: string;
gradientUnits?: string;
hanging?: number | string;
horizAdvX?: number | string;
horizOriginX?: number | string;
ideographic?: number | string;
imageRendering?: number | string;
in2?: number | string;
in?: string;
intercept?: number | string;
k1?: number | string;
k2?: number | string;
k3?: number | string;
k4?: number | string;
k?: number | string;
kernelMatrix?: number | string;
kernelUnitLength?: number | string;
kerning?: number | string;
keyPoints?: number | string;
keySplines?: number | string;
keyTimes?: number | string;
lengthAdjust?: number | string;
letterSpacing?: number | string;
lightingColor?: number | string;
limitingConeAngle?: number | string;
local?: number | string;
markerEnd?: string;
markerHeight?: number | string;
markerMid?: string;
markerStart?: string;
markerUnits?: number | string;
markerWidth?: number | string;
mask?: string;
maskContentUnits?: number | string;
maskUnits?: number | string;
mathematical?: number | string;
mode?: number | string;
numOctaves?: number | string;
offset?: number | string;
opacity?: number | string;
operator?: number | string;
order?: number | string;
orient?: number | string;
orientation?: number | string;
origin?: number | string;
overflow?: number | string;
overlinePosition?: number | string;
overlineThickness?: number | string;
paintOrder?: number | string;
panose1?: number | string;
pathLength?: number | string;
patternContentUnits?: string;
patternTransform?: number | string;
patternUnits?: string;
pointerEvents?: number | string;
points?: string;
pointsAtX?: number | string;
pointsAtY?: number | string;
pointsAtZ?: number | string;
preserveAlpha?: number | string;
preserveAspectRatio?: string;
primitiveUnits?: number | string;
r?: number | string;
radius?: number | string;
refX?: number | string;
refY?: number | string;
renderingIntent?: number | string;
repeatCount?: number | string;
repeatDur?: number | string;
requiredExtensions?: number | string;
requiredFeatures?: number | string;
restart?: number | string;
result?: string;
rotate?: number | string;
rx?: number | string;
ry?: number | string;
scale?: number | string;
seed?: number | string;
shapeRendering?: number | string;
slope?: number | string;
spacing?: number | string;
specularConstant?: number | string;
specularExponent?: number | string;
speed?: number | string;
spreadMethod?: string;
startOffset?: number | string;
stdDeviation?: number | string;
stemh?: number | string;
stemv?: number | string;
stitchTiles?: number | string;
stopColor?: string;
stopOpacity?: number | string;
strikethroughPosition?: number | string;
strikethroughThickness?: number | string;
string?: number | string;
stroke?: string;
strokeDasharray?: string | number;
strokeDashoffset?: string | number;
strokeLinecap?: "butt" | "round" | "square" | "inherit";
strokeLinejoin?: "miter" | "round" | "bevel" | "inherit";
strokeMiterlimit?: string;
strokeOpacity?: number | string;
strokeWidth?: number | string;
surfaceScale?: number | string;
systemLanguage?: number | string;
tableValues?: number | string;
targetX?: number | string;
targetY?: number | string;
textAnchor?: string;
textDecoration?: number | string;
textLength?: number | string;
textRendering?: number | string;
to?: number | string;
transform?: string;
u1?: number | string;
u2?: number | string;
underlinePosition?: number | string;
underlineThickness?: number | string;
unicode?: number | string;
unicodeBidi?: number | string;
unicodeRange?: number | string;
unitsPerEm?: number | string;
vAlphabetic?: number | string;
values?: string;
vectorEffect?: number | string;
version?: string;
vertAdvY?: number | string;
vertOriginX?: number | string;
vertOriginY?: number | string;
vHanging?: number | string;
vIdeographic?: number | string;
viewBox?: string;
viewTarget?: number | string;
visibility?: number | string;
vMathematical?: number | string;
widths?: number | string;
wordSpacing?: number | string;
writingMode?: number | string;
x1?: number | string;
x2?: number | string;
x?: number | string;
xChannelSelector?: string;
xHeight?: number | string;
xlinkActuate?: string;
xlinkArcrole?: string;
xlinkHref?: string;
xlinkRole?: string;
xlinkShow?: string;
xlinkTitle?: string;
xlinkType?: string;
xmlBase?: string;
xmlLang?: string;
xmlns?: string;
xmlnsXlink?: string;
xmlSpace?: string;
y1?: number | string;
y2?: number | string;
y?: number | string;
yChannelSelector?: string;
z?: number | string;
zoomAndPan?: string;
}
interface PathAttributes {
d: string;
}
interface EventHandler<E extends Event> {
(event: E): void;
}
type ClipboardEventHandler = EventHandler<ClipboardEvent>;
type CompositionEventHandler = EventHandler<CompositionEvent>;
type DragEventHandler = EventHandler<DragEvent>;
type FocusEventHandler = EventHandler<FocusEvent>;
type KeyboardEventHandler = EventHandler<KeyboardEvent>;
type MouseEventHandler = EventHandler<MouseEvent>;
type TouchEventHandler = EventHandler<TouchEvent>;
type UIEventHandler = EventHandler<UIEvent>;
type WheelEventHandler = EventHandler<WheelEvent>;
type AnimationEventHandler = EventHandler<AnimationEvent>;
type TransitionEventHandler = EventHandler<TransitionEvent>;
type GenericEventHandler = EventHandler<Event>;
type PointerEventHandler = EventHandler<PointerEvent>;
interface DOMAttributes extends Omi.OmiDOMAttributes {
// Image Events
onLoad?: GenericEventHandler;
onError?: GenericEventHandler;
onLoadCapture?: GenericEventHandler;
// Clipboard Events
onCopy?: ClipboardEventHandler;
onCopyCapture?: ClipboardEventHandler;
onCut?: ClipboardEventHandler;
onCutCapture?: ClipboardEventHandler;
onPaste?: ClipboardEventHandler;
onPasteCapture?: ClipboardEventHandler;
// Composition Events
onCompositionEnd?: CompositionEventHandler;
onCompositionEndCapture?: CompositionEventHandler;
onCompositionStart?: CompositionEventHandler;
onCompositionStartCapture?: CompositionEventHandler;
onCompositionUpdate?: CompositionEventHandler;
onCompositionUpdateCapture?: CompositionEventHandler;
// Focus Events
onFocus?: FocusEventHandler;
onFocusCapture?: FocusEventHandler;
onBlur?: FocusEventHandler;
onBlurCapture?: FocusEventHandler;
// Form Events
onChange?: GenericEventHandler;
onChangeCapture?: GenericEventHandler;
onInput?: GenericEventHandler;
onInputCapture?: GenericEventHandler;
onSearch?: GenericEventHandler;
onSearchCapture?: GenericEventHandler;
onSubmit?: GenericEventHandler;
onSubmitCapture?: GenericEventHandler;
// Keyboard Events
onKeyDown?: KeyboardEventHandler;
onKeyDownCapture?: KeyboardEventHandler;
onKeyPress?: KeyboardEventHandler;
onKeyPressCapture?: KeyboardEventHandler;
onKeyUp?: KeyboardEventHandler;
onKeyUpCapture?: KeyboardEventHandler;
// Media Events
onAbort?: GenericEventHandler;
onAbortCapture?: GenericEventHandler;
onCanPlay?: GenericEventHandler;
onCanPlayCapture?: GenericEventHandler;
onCanPlayThrough?: GenericEventHandler;
onCanPlayThroughCapture?: GenericEventHandler;
onDurationChange?: GenericEventHandler;
onDurationChangeCapture?: GenericEventHandler;
onEmptied?: GenericEventHandler;
onEmptiedCapture?: GenericEventHandler;
onEncrypted?: GenericEventHandler;
onEncryptedCapture?: GenericEventHandler;
onEnded?: GenericEventHandler;
onEndedCapture?: GenericEventHandler;
onLoadedData?: GenericEventHandler;
onLoadedDataCapture?: GenericEventHandler;
onLoadedMetadata?: GenericEventHandler;
onLoadedMetadataCapture?: GenericEventHandler;
onLoadStart?: GenericEventHandler;
onLoadStartCapture?: GenericEventHandler;
onPause?: GenericEventHandler;
onPauseCapture?: GenericEventHandler;
onPlay?: GenericEventHandler;
onPlayCapture?: GenericEventHandler;
onPlaying?: GenericEventHandler;
onPlayingCapture?: GenericEventHandler;
onProgress?: GenericEventHandler;
onProgressCapture?: GenericEventHandler;
onRateChange?: GenericEventHandler;
onRateChangeCapture?: GenericEventHandler;
onSeeked?: GenericEventHandler;
onSeekedCapture?: GenericEventHandler;
onSeeking?: GenericEventHandler;
onSeekingCapture?: GenericEventHandler;
onStalled?: GenericEventHandler;
onStalledCapture?: GenericEventHandler;
onSuspend?: GenericEventHandler;
onSuspendCapture?: GenericEventHandler;
onTimeUpdate?: GenericEventHandler;
onTimeUpdateCapture?: GenericEventHandler;
onVolumeChange?: GenericEventHandler;
onVolumeChangeCapture?: GenericEventHandler;
onWaiting?: GenericEventHandler;
onWaitingCapture?: GenericEventHandler;
// MouseEvents
onClick?: MouseEventHandler;
onClickCapture?: MouseEventHandler;
onContextMenu?: MouseEventHandler;
onContextMenuCapture?: MouseEventHandler;
onDblClick?: MouseEventHandler;
onDblClickCapture?: MouseEventHandler;
onDrag?: DragEventHandler;
onDragCapture?: DragEventHandler;
onDragEnd?: DragEventHandler;
onDragEndCapture?: DragEventHandler;
onDragEnter?: DragEventHandler;
onDragEnterCapture?: DragEventHandler;
onDragExit?: DragEventHandler;
onDragExitCapture?: DragEventHandler;
onDragLeave?: DragEventHandler;
onDragLeaveCapture?: DragEventHandler;
onDragOver?: DragEventHandler;
onDragOverCapture?: DragEventHandler;
onDragStart?: DragEventHandler;
onDragStartCapture?: DragEventHandler;
onDrop?: DragEventHandler;
onDropCapture?: DragEventHandler;
onMouseDown?: MouseEventHandler;
onMouseDownCapture?: MouseEventHandler;
onMouseEnter?: MouseEventHandler;
onMouseEnterCapture?: MouseEventHandler;
onMouseLeave?: MouseEventHandler;
onMouseLeaveCapture?: MouseEventHandler;
onMouseMove?: MouseEventHandler;
onMouseMoveCapture?: MouseEventHandler;
onMouseOut?: MouseEventHandler;
onMouseOutCapture?: MouseEventHandler;
onMouseOver?: MouseEventHandler;
onMouseOverCapture?: MouseEventHandler;
onMouseUp?: MouseEventHandler;
onMouseUpCapture?: MouseEventHandler;
// Selection Events
onSelect?: GenericEventHandler;
onSelectCapture?: GenericEventHandler;
// Touch Events
onTouchCancel?: TouchEventHandler;
onTouchCancelCapture?: TouchEventHandler;
onTouchEnd?: TouchEventHandler;
onTouchEndCapture?: TouchEventHandler;
onTouchMove?: TouchEventHandler;
onTouchMoveCapture?: TouchEventHandler;
onTouchStart?: TouchEventHandler;
onTouchStartCapture?: TouchEventHandler;
// Pointer Events
onPointerOver?: PointerEventHandler;
onPointerOverCapture?: PointerEventHandler;
onPointerEnter?: PointerEventHandler;
onPointerEnterCapture?: PointerEventHandler;
onPointerDown?: PointerEventHandler;
onPointerDownCapture?: PointerEventHandler;
onPointerMove?: PointerEventHandler;
onPointerMoveCapture?: PointerEventHandler;
onPointerUp?: PointerEventHandler;
onPointerUpCapture?: PointerEventHandler;
onPointerCancel?: PointerEventHandler;
onPointerCancelCapture?: PointerEventHandler;
onPointerOut?: PointerEventHandler;
onPointerOutCapture?: PointerEventHandler;
onPointerLeave?: PointerEventHandler;
onPointerLeaveCapture?: PointerEventHandler;
onGotPointerCapture?: PointerEventHandler;
onGotPointerCaptureCapture?: PointerEventHandler;
onLostPointerCapture?: PointerEventHandler;
onLostPointerCaptureCapture?: PointerEventHandler;
// UI Events
onScroll?: UIEventHandler;
onScrollCapture?: UIEventHandler;
// Wheel Events
onWheel?: WheelEventHandler;
onWheelCapture?: WheelEventHandler;
// Animation Events
onAnimationStart?: AnimationEventHandler;
onAnimationStartCapture?: AnimationEventHandler;
onAnimationEnd?: AnimationEventHandler;
onAnimationEndCapture?: AnimationEventHandler;
onAnimationIteration?: AnimationEventHandler;
onAnimationIterationCapture?: AnimationEventHandler;
// Transition Events
onTransitionEnd?: TransitionEventHandler;
onTransitionEndCapture?: TransitionEventHandler;
}
interface HTMLAttributes extends Omi.ClassAttributes<any>, DOMAttributes {
// Standard HTML Attributes
accept?: string;
acceptCharset?: string;
accessKey?: string;
action?: string;
allowFullScreen?: boolean;
allowTransparency?: boolean;
alt?: string;
async?: boolean;
autocomplete?: string;
autofocus?: boolean;
autoPlay?: boolean;
capture?: boolean;
cellPadding?: number | string;
cellSpacing?: number | string;
charSet?: string;
challenge?: string;
checked?: boolean;
class?: string;
className?: string;
cols?: number;
colSpan?: number;
content?: string;
contentEditable?: boolean;
contextMenu?: string;
controls?: boolean;
controlsList?: string;
coords?: string;
crossOrigin?: string;
data?: string;
dateTime?: string;
default?: boolean;
defer?: boolean;
dir?: string;
disabled?: boolean;
download?: any;
draggable?: boolean;
encType?: string;
form?: string;
formAction?: string;
formEncType?: string;
formMethod?: string;
formNoValidate?: boolean;
formTarget?: string;
frameBorder?: number | string;
headers?: string;
height?: number | string;
hidden?: boolean;
high?: number;
href?: string;
hrefLang?: string;
for?: string;
httpEquiv?: string;
icon?: string;
id?: string;
inputMode?: string;
integrity?: string;
is?: string;
keyParams?: string;
keyType?: string;
kind?: string;
label?: string;
lang?: string;
list?: string;
loop?: boolean;
low?: number;
manifest?: string;
marginHeight?: number;
marginWidth?: number;
max?: number | string;
maxLength?: number;
media?: string;
mediaGroup?: string;
method?: string;
min?: number | string;
minLength?: number;
multiple?: boolean;
muted?: boolean;
name?: string;
noValidate?: boolean;
open?: boolean;
optimum?: number;
pattern?: string;
placeholder?: string;
playsInline?: boolean;
poster?: string;
preload?: string;
radioGroup?: string;
readOnly?: boolean;
rel?: string;
required?: boolean;
role?: string;
rows?: number;
rowSpan?: number;
sandbox?: string;
scope?: string;
scoped?: boolean;
scrolling?: string;
seamless?: boolean;
selected?: boolean;
shape?: string;
size?: number;
sizes?: string;
slot?: string;
span?: number;
spellcheck?: boolean;
src?: string;
srcset?: string;
srcDoc?: string;
srcLang?: string;
srcSet?: string;
start?: number;
step?: number | string;
style?: any;
summary?: string;
tabIndex?: number;
target?: string;
title?: string;
type?: string;
useMap?: string;
value?: string | string[] | number;
width?: number | string;
wmode?: string;
wrap?: string;
// RDFa Attributes
about?: string;
datatype?: string;
inlist?: any;
prefix?: string;
property?: string;
resource?: string;
typeof?: string;
vocab?: string;
}
interface IntrinsicElements {
// HTML
a: HTMLAttributes;
abbr: HTMLAttributes;
address: HTMLAttributes;
area: HTMLAttributes;
article: HTMLAttributes;
aside: HTMLAttributes;
audio: HTMLAttributes;
b: HTMLAttributes;
base: HTMLAttributes;
bdi: HTMLAttributes;
bdo: HTMLAttributes;
big: HTMLAttributes;
blockquote: HTMLAttributes;
body: HTMLAttributes;
br: HTMLAttributes;
button: HTMLAttributes;
canvas: HTMLAttributes;
caption: HTMLAttributes;
cite: HTMLAttributes;
code: HTMLAttributes;
col: HTMLAttributes;
colgroup: HTMLAttributes;
data: HTMLAttributes;
datalist: HTMLAttributes;
dd: HTMLAttributes;
del: HTMLAttributes;
details: HTMLAttributes;
dfn: HTMLAttributes;
dialog: HTMLAttributes;
div: HTMLAttributes;
dl: HTMLAttributes;
dt: HTMLAttributes;
em: HTMLAttributes;
embed: HTMLAttributes;
fieldset: HTMLAttributes;
figcaption: HTMLAttributes;
figure: HTMLAttributes;
footer: HTMLAttributes;
form: HTMLAttributes;
h1: HTMLAttributes;
h2: HTMLAttributes;
h3: HTMLAttributes;
h4: HTMLAttributes;
h5: HTMLAttributes;
h6: HTMLAttributes;
head: HTMLAttributes;
header: HTMLAttributes;
hr: HTMLAttributes;
html: HTMLAttributes;
i: HTMLAttributes;
iframe: HTMLAttributes;
img: HTMLAttributes;
input: HTMLAttributes;
ins: HTMLAttributes;
kbd: HTMLAttributes;
keygen: HTMLAttributes;
label: HTMLAttributes;
legend: HTMLAttributes;
li: HTMLAttributes;
link: HTMLAttributes;
main: HTMLAttributes;
map: HTMLAttributes;
mark: HTMLAttributes;
menu: HTMLAttributes;
menuitem: HTMLAttributes;
meta: HTMLAttributes;
meter: HTMLAttributes;
nav: HTMLAttributes;
noscript: HTMLAttributes;
object: HTMLAttributes;
ol: HTMLAttributes;
optgroup: HTMLAttributes;
option: HTMLAttributes;
output: HTMLAttributes;
p: HTMLAttributes;
param: HTMLAttributes;
picture: HTMLAttributes;
pre: HTMLAttributes;
progress: HTMLAttributes;
q: HTMLAttributes;
rp: HTMLAttributes;
rt: HTMLAttributes;
ruby: HTMLAttributes;
s: HTMLAttributes;
samp: HTMLAttributes;
script: HTMLAttributes;
section: HTMLAttributes;
select: HTMLAttributes;
slot: HTMLAttributes;
small: HTMLAttributes;
source: HTMLAttributes;
span: HTMLAttributes;
strong: HTMLAttributes;
style: HTMLAttributes;
sub: HTMLAttributes;
summary: HTMLAttributes;
sup: HTMLAttributes;
table: HTMLAttributes;
tbody: HTMLAttributes;
td: HTMLAttributes;
textarea: HTMLAttributes;
tfoot: HTMLAttributes;
th: HTMLAttributes;
thead: HTMLAttributes;
time: HTMLAttributes;
title: HTMLAttributes;
tr: HTMLAttributes;
track: HTMLAttributes;
u: HTMLAttributes;
ul: HTMLAttributes;
"var": HTMLAttributes;
video: HTMLAttributes;
wbr: HTMLAttributes;
//SVG
svg: SVGAttributes;
animate: SVGAttributes;
circle: SVGAttributes;
clipPath: SVGAttributes;
defs: SVGAttributes;
ellipse: SVGAttributes;
feBlend: SVGAttributes;
feColorMatrix: SVGAttributes;
feComponentTransfer: SVGAttributes;
feComposite: SVGAttributes;
feConvolveMatrix: SVGAttributes;
feDiffuseLighting: SVGAttributes;
feDisplacementMap: SVGAttributes;
feFlood: SVGAttributes;
feGaussianBlur: SVGAttributes;
feImage: SVGAttributes;
feMerge: SVGAttributes;
feMergeNode: SVGAttributes;
feMorphology: SVGAttributes;
feOffset: SVGAttributes;
feSpecularLighting: SVGAttributes;
feTile: SVGAttributes;
feTurbulence: SVGAttributes;
filter: SVGAttributes;
foreignObject: SVGAttributes;
g: SVGAttributes;
image: SVGAttributes;
line: SVGAttributes;
linearGradient: SVGAttributes;
marker: SVGAttributes;
mask: SVGAttributes;
path: SVGAttributes;
pattern: SVGAttributes;
polygon: SVGAttributes;
polyline: SVGAttributes;
radialGradient: SVGAttributes;
rect: SVGAttributes;
stop: SVGAttributes;
symbol: SVGAttributes;
text: SVGAttributes;
tspan: SVGAttributes;
use: SVGAttributes;
[tagName: string]: any;
}
}
}

View File

@ -0,0 +1,40 @@
import { h, h as createElement } from './h'
import options from './options'
import WeElement from './we-element'
import { render } from './render'
import { define } from './define'
import { tag } from './tag'
import { observe } from './observe'
import { cloneElement } from './clone-element'
import { getHost } from './get-host'
const omi = {
tag,
WeElement,
render,
h,
createElement,
options,
define,
observe,
cloneElement,
getHost
}
options.root.Omi = omi
options.root.Omi.version = '4.0.15'
export default omi
export {
tag,
WeElement,
render,
h,
createElement,
options,
define,
observe,
cloneElement,
getHost
}

View File

@ -0,0 +1,27 @@
function getGlobal() {
if (
typeof global !== 'object' ||
!global ||
global.Math !== Math ||
global.Array !== Array
) {
return (
self ||
window ||
global ||
(function() {
return this
})()
)
}
return global
}
/** Global options
* @public
* @namespace options {Object}
*/
export default {
store: null,
root: getGlobal()
}

View File

@ -0,0 +1,390 @@
/*!
* https://github.com/Palindrom/JSONPatcherProxy
* (c) 2017 Starcounter
* MIT license
*/
/** Class representing a JS Object observer */
const JSONPatcherProxy = (function() {
/**
* Deep clones your object and returns a new object.
*/
function deepClone(obj) {
switch (typeof obj) {
case 'object':
return JSON.parse(JSON.stringify(obj)) //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5
case 'undefined':
return null //this is how JSON.stringify behaves for array items
default:
return obj //no need to clone primitives
}
}
JSONPatcherProxy.deepClone = deepClone
function escapePathComponent(str) {
if (str.indexOf('/') == -1 && str.indexOf('~') == -1) return str
return str.replace(/~/g, '~0').replace(/\//g, '~1')
}
JSONPatcherProxy.escapePathComponent = escapePathComponent
/**
* Walk up the parenthood tree to get the path
* @param {JSONPatcherProxy} instance
* @param {Object} obj the object you need to find its path
*/
function findObjectPath(instance, obj) {
const pathComponents = []
let parentAndPath = instance.parenthoodMap.get(obj)
while (parentAndPath && parentAndPath.path) {
// because we're walking up-tree, we need to use the array as a stack
pathComponents.unshift(parentAndPath.path)
parentAndPath = instance.parenthoodMap.get(parentAndPath.parent)
}
if (pathComponents.length) {
const path = pathComponents.join('/')
return '/' + path
}
return ''
}
/**
* A callback to be used as th proxy set trap callback.
* It updates parenthood map if needed, proxifies nested newly-added objects, calls default callbacks with the changes occurred.
* @param {JSONPatcherProxy} instance JSONPatcherProxy instance
* @param {Object} target the affected object
* @param {String} key the effect property's name
* @param {Any} newValue the value being set
*/
function setTrap(instance, target, key, newValue) {
const parentPath = findObjectPath(instance, target)
const destinationPropKey = parentPath + '/' + escapePathComponent(key)
if (instance.proxifiedObjectsMap.has(newValue)) {
const newValueOriginalObject = instance.proxifiedObjectsMap.get(newValue)
instance.parenthoodMap.set(newValueOriginalObject.originalObject, {
parent: target,
path: key
})
}
/*
mark already proxified values as inherited.
rationale: proxy.arr.shift()
will emit
{op: replace, path: '/arr/1', value: arr_2}
{op: remove, path: '/arr/2'}
by default, the second operation would revoke the proxy, and this renders arr revoked.
That's why we need to remember the proxies that are inherited.
*/
const revokableInstance = instance.proxifiedObjectsMap.get(newValue)
/*
Why do we need to check instance.isProxifyingTreeNow?
We need to make sure we mark revokables as inherited ONLY when we're observing,
because throughout the first proxification, a sub-object is proxified and then assigned to
its parent object. This assignment of a pre-proxified object can fool us into thinking
that it's a proxified object moved around, while in fact it's the first assignment ever.
Checking isProxifyingTreeNow ensures this is not happening in the first proxification,
but in fact is is a proxified object moved around the tree
*/
if (revokableInstance && !instance.isProxifyingTreeNow) {
revokableInstance.inherited = true
}
// if the new value is an object, make sure to watch it
if (
newValue &&
typeof newValue == 'object' &&
!instance.proxifiedObjectsMap.has(newValue)
) {
instance.parenthoodMap.set(newValue, {
parent: target,
path: key
})
newValue = instance._proxifyObjectTreeRecursively(target, newValue, key)
}
// let's start with this operation, and may or may not update it later
const operation = {
op: 'remove',
path: destinationPropKey
}
if (typeof newValue == 'undefined') {
// applying De Morgan's laws would be a tad faster, but less readable
if (!Array.isArray(target) && !target.hasOwnProperty(key)) {
// `undefined` is being set to an already undefined value, keep silent
return Reflect.set(target, key, newValue)
}
// when array element is set to `undefined`, should generate replace to `null`
if (Array.isArray(target)) {
// undefined array elements are JSON.stringified to `null`
;(operation.op = 'replace'), (operation.value = null)
}
const oldValue = instance.proxifiedObjectsMap.get(target[key])
// was the deleted a proxified object?
if (oldValue) {
instance.parenthoodMap.delete(target[key])
instance.disableTrapsForProxy(oldValue)
instance.proxifiedObjectsMap.delete(oldValue)
}
} else {
if (Array.isArray(target) && !Number.isInteger(+key.toString())) {
/* array props (as opposed to indices) don't emit any patches, to avoid needless `length` patches */
if (key != 'length') {
console.warn(
'JSONPatcherProxy noticed a non-integer prop was set for an array. This will not emit a patch'
)
}
return Reflect.set(target, key, newValue)
}
operation.op = 'add'
if (target.hasOwnProperty(key)) {
if (typeof target[key] !== 'undefined' || Array.isArray(target)) {
operation.op = 'replace' // setting `undefined` array elements is a `replace` op
}
}
operation.value = newValue
}
const reflectionResult = Reflect.set(target, key, newValue)
instance.defaultCallback(operation)
return reflectionResult
}
/**
* A callback to be used as th proxy delete trap callback.
* It updates parenthood map if needed, calls default callbacks with the changes occurred.
* @param {JSONPatcherProxy} instance JSONPatcherProxy instance
* @param {Object} target the effected object
* @param {String} key the effected property's name
*/
function deleteTrap(instance, target, key) {
if (typeof target[key] !== 'undefined') {
const parentPath = findObjectPath(instance, target)
const destinationPropKey = parentPath + '/' + escapePathComponent(key)
const revokableProxyInstance = instance.proxifiedObjectsMap.get(
target[key]
)
if (revokableProxyInstance) {
if (revokableProxyInstance.inherited) {
/*
this is an inherited proxy (an already proxified object that was moved around),
we shouldn't revoke it, because even though it was removed from path1, it is still used in path2.
And we know that because we mark moved proxies with `inherited` flag when we move them
it is a good idea to remove this flag if we come across it here, in deleteProperty trap.
We DO want to revoke the proxy if it was removed again.
*/
revokableProxyInstance.inherited = false
} else {
instance.parenthoodMap.delete(revokableProxyInstance.originalObject)
instance.disableTrapsForProxy(revokableProxyInstance)
instance.proxifiedObjectsMap.delete(target[key])
}
}
const reflectionResult = Reflect.deleteProperty(target, key)
instance.defaultCallback({
op: 'remove',
path: destinationPropKey
})
return reflectionResult
}
}
/* pre-define resume and pause functions to enhance constructors performance */
function resume() {
this.defaultCallback = operation => {
this.isRecording && this.patches.push(operation)
this.userCallback && this.userCallback(operation)
}
this.isObserving = true
}
function pause() {
this.defaultCallback = () => {}
this.isObserving = false
}
/**
* Creates an instance of JSONPatcherProxy around your object of interest `root`.
* @param {Object|Array} root - the object you want to wrap
* @param {Boolean} [showDetachedWarning = true] - whether to log a warning when a detached sub-object is modified @see {@link https://github.com/Palindrom/JSONPatcherProxy#detached-objects}
* @returns {JSONPatcherProxy}
* @constructor
*/
function JSONPatcherProxy(root, showDetachedWarning) {
this.isProxifyingTreeNow = false
this.isObserving = false
this.proxifiedObjectsMap = new Map()
this.parenthoodMap = new Map()
// default to true
if (typeof showDetachedWarning !== 'boolean') {
showDetachedWarning = true
}
this.showDetachedWarning = showDetachedWarning
this.originalObject = root
this.cachedProxy = null
this.isRecording = false
this.userCallback
/**
* @memberof JSONPatcherProxy
* Restores callback back to the original one provided to `observe`.
*/
this.resume = resume.bind(this)
/**
* @memberof JSONPatcherProxy
* Replaces your callback with a noop function.
*/
this.pause = pause.bind(this)
}
JSONPatcherProxy.prototype.generateProxyAtPath = function(parent, obj, path) {
if (!obj) {
return obj
}
const traps = {
set: (target, key, value, receiver) =>
setTrap(this, target, key, value, receiver),
deleteProperty: (target, key) => deleteTrap(this, target, key)
}
const revocableInstance = Proxy.revocable(obj, traps)
// cache traps object to disable them later.
revocableInstance.trapsInstance = traps
revocableInstance.originalObject = obj
/* keeping track of object's parent and path */
this.parenthoodMap.set(obj, { parent, path })
/* keeping track of all the proxies to be able to revoke them later */
this.proxifiedObjectsMap.set(revocableInstance.proxy, revocableInstance)
return revocableInstance.proxy
}
// grab tree's leaves one by one, encapsulate them into a proxy and return
JSONPatcherProxy.prototype._proxifyObjectTreeRecursively = function(
parent,
root,
path
) {
for (let key in root) {
if (root.hasOwnProperty(key)) {
if (root[key] instanceof Object) {
root[key] = this._proxifyObjectTreeRecursively(
root,
root[key],
escapePathComponent(key)
)
}
}
}
return this.generateProxyAtPath(parent, root, path)
}
// this function is for aesthetic purposes
JSONPatcherProxy.prototype.proxifyObjectTree = function(root) {
/*
while proxyifying object tree,
the proxyifying operation itself is being
recorded, which in an unwanted behavior,
that's why we disable recording through this
initial process;
*/
this.pause()
this.isProxifyingTreeNow = true
const proxifiedObject = this._proxifyObjectTreeRecursively(
undefined,
root,
''
)
/* OK you can record now */
this.isProxifyingTreeNow = false
this.resume()
return proxifiedObject
}
/**
* Turns a proxified object into a forward-proxy object; doesn't emit any patches anymore, like a normal object
* @param {Proxy} proxy - The target proxy object
*/
JSONPatcherProxy.prototype.disableTrapsForProxy = function(
revokableProxyInstance
) {
if (this.showDetachedWarning) {
const message =
"You're accessing an object that is detached from the observedObject tree, see https://github.com/Palindrom/JSONPatcherProxy#detached-objects"
revokableProxyInstance.trapsInstance.set = (
targetObject,
propKey,
newValue
) => {
console.warn(message)
return Reflect.set(targetObject, propKey, newValue)
}
revokableProxyInstance.trapsInstance.set = (
targetObject,
propKey,
newValue
) => {
console.warn(message)
return Reflect.set(targetObject, propKey, newValue)
}
revokableProxyInstance.trapsInstance.deleteProperty = (
targetObject,
propKey
) => {
return Reflect.deleteProperty(targetObject, propKey)
}
} else {
delete revokableProxyInstance.trapsInstance.set
delete revokableProxyInstance.trapsInstance.get
delete revokableProxyInstance.trapsInstance.deleteProperty
}
}
/**
* Proxifies the object that was passed in the constructor and returns a proxified mirror of it. Even though both parameters are options. You need to pass at least one of them.
* @param {Boolean} [record] - whether to record object changes to a later-retrievable patches array.
* @param {Function} [callback] - this will be synchronously called with every object change with a single `patch` as the only parameter.
*/
JSONPatcherProxy.prototype.observe = function(record, callback) {
if (!record && !callback) {
throw new Error('You need to either record changes or pass a callback')
}
this.isRecording = record
this.userCallback = callback
/*
I moved it here to remove it from `unobserve`,
this will also make the constructor faster, why initiate
the array before they decide to actually observe with recording?
They might need to use only a callback.
*/
if (record) this.patches = []
this.cachedProxy = this.proxifyObjectTree(this.originalObject)
return this.cachedProxy
}
/**
* If the observed is set to record, it will synchronously return all the patches and empties patches array.
*/
JSONPatcherProxy.prototype.generate = function() {
if (!this.isRecording) {
throw new Error('You should set record to true to get patches later')
}
return this.patches.splice(0, this.patches.length)
}
/**
* Revokes all proxies rendering the observed object useless and good for garbage collection @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/revocable}
*/
JSONPatcherProxy.prototype.revoke = function() {
this.proxifiedObjectsMap.forEach(el => {
el.revoke()
})
}
/**
* Disables all proxies' traps, turning the observed object into a forward-proxy object, like a normal object that you can modify silently.
*/
JSONPatcherProxy.prototype.disableTraps = function() {
this.proxifiedObjectsMap.forEach(this.disableTrapsForProxy, this)
}
return JSONPatcherProxy
})()
export default JSONPatcherProxy

View File

@ -0,0 +1,142 @@
import { diff } from './vdom/diff'
import JSONProxy from './proxy'
export function render(vnode, parent, store) {
parent = typeof parent === 'string' ? document.querySelector(parent) : parent
if (store) {
store.instances = []
extendStoreUpate(store)
let timeout = null
let patchs = {}
store.data = new JSONProxy(store.data).observe(false, function(patch) {
clearTimeout(timeout)
if (patch.op === 'remove') {
// fix arr splice
const kv = getArrayPatch(patch.path, store)
patchs[kv.k] = kv.v
timeout = setTimeout(() => {
update(patchs, store)
patchs = {}
}, 16.6)
} else {
const key = fixPath(patch.path)
patchs[key] = patch.value
timeout = setTimeout(() => {
update(patchs, store)
patchs = {}
}, 16.6)
}
})
parent.store = store
}
diff(null, vnode, {}, false, parent, false)
}
function update(patch, store) {
store.update(patch)
}
function extendStoreUpate(store) {
store.update = function(patch) {
const updateAll = matchGlobalData(this.globalData, patch)
if (Object.keys(patch).length > 0) {
this.instances.forEach(instance => {
if (
updateAll ||
this.updateAll ||
(instance.constructor.updatePath &&
needUpdate(patch, instance.constructor.updatePath))
) {
instance.update()
}
})
this.onChange && this.onChange(patch)
}
}
}
export function matchGlobalData(globalData, diffResult) {
if (!globalData) return false
for (let keyA in diffResult) {
if (globalData.indexOf(keyA) > -1) {
return true
}
for (let i = 0, len = globalData.length; i < len; i++) {
if (includePath(keyA, globalData[i])) {
return true
}
}
}
return false
}
export function needUpdate(diffResult, updatePath) {
for (let keyA in diffResult) {
if (updatePath[keyA]) {
return true
}
for (let keyB in updatePath) {
if (includePath(keyA, keyB)) {
return true
}
}
}
return false
}
function includePath(pathA, pathB) {
if (pathA.indexOf(pathB) === 0) {
const next = pathA.substr(pathB.length, 1)
if (next === '[' || next === '.') {
return true
}
}
return false
}
export function fixPath(path) {
let mpPath = ''
const arr = path.replace('/', '').split('/')
arr.forEach((item, index) => {
if (index) {
if (isNaN(Number(item))) {
mpPath += '.' + item
} else {
mpPath += '[' + item + ']'
}
} else {
mpPath += item
}
})
return mpPath
}
function getArrayPatch(path, store) {
const arr = path.replace('/', '').split('/')
let current = store.data[arr[0]]
for (let i = 1, len = arr.length; i < len - 1; i++) {
current = current[arr[i]]
}
return { k: fixArrPath(path), v: current }
}
function fixArrPath(path) {
let mpPath = ''
const arr = path.replace('/', '').split('/')
const len = arr.length
arr.forEach((item, index) => {
if (index < len - 1) {
if (index) {
if (isNaN(Number(item))) {
mpPath += '.' + item
} else {
mpPath += '[' + item + ']'
}
} else {
mpPath += item
}
}
})
return mpPath
}

View File

@ -0,0 +1,8 @@
import { define } from './define'
import WeElement from './we-element'
export function tag(name, pure) {
return function(target) {
target.pure = pure
define(name, target)
}
}

View File

@ -0,0 +1,88 @@
/**
* @license
* Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
/**
* This shim allows elements written in, or compiled to, ES5 to work on native
* implementations of Custom Elements v1. It sets new.target to the value of
* this.constructor so that the native HTMLElement constructor can access the
* current under-construction element's definition.
*/
;(function() {
if (
// No Reflect, no classes, no need for shim because native custom elements
// require ES2015 classes or Reflect.
window.Reflect === undefined ||
window.customElements === undefined ||
// The webcomponentsjs custom elements polyfill doesn't require
// ES2015-compatible construction (`super()` or `Reflect.construct`).
window.customElements.hasOwnProperty('polyfillWrapFlushCallback')
) {
return
}
const BuiltInHTMLElement = HTMLElement
window.HTMLElement = function HTMLElement() {
return Reflect.construct(BuiltInHTMLElement, [], this.constructor)
}
HTMLElement.prototype = BuiltInHTMLElement.prototype
HTMLElement.prototype.constructor = HTMLElement
Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement)
})()
export function cssToDom(css) {
const node = document.createElement('style')
node.textContent = css
return node
}
export function npn(str) {
return str.replace(/-(\w)/g, ($, $1) => {
return $1.toUpperCase()
})
}
export function extend(obj, props) {
for (let i in props) obj[i] = props[i]
return obj
}
/** Invoke or update a ref, depending on whether it is a function or object ref.
* @param {object|function} [ref=null]
* @param {any} [value]
*/
export function applyRef(ref, value) {
if (ref != null) {
if (typeof ref == 'function') ref(value)
else ref.current = value
}
}
/**
* Call a function asynchronously, as soon as possible. Makes
* use of HTML Promise to schedule the callback if available,
* otherwise falling back to `setTimeout` (mainly for IE<11).
* @type {(callback: function) => void}
*/
export const defer =
typeof Promise == 'function'
? Promise.resolve().then.bind(Promise.resolve())
: setTimeout
export function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]'
}
export function nProps(props) {
if (!props || isArray(props)) return {}
const result = {}
Object.keys(props).forEach(key => {
result[key] = props[key].value
})
return result
}

View File

@ -0,0 +1,364 @@
import { ATTR_KEY } from '../constants'
import { isSameNodeType, isNamedNode } from './index'
import { createNode, setAccessor } from '../dom/index'
import { npn, isArray } from '../util'
import { removeNode } from '../dom/index'
/** Queue of components that have been mounted and are awaiting componentDidMount */
export const mounts = []
/** Diff recursion count, used to track the end of the diff cycle. */
export let diffLevel = 0
/** Global flag indicating if the diff is currently within an SVG */
let isSvgMode = false
/** Global flag indicating if the diff is performing hydration */
let hydrating = false
/** Apply differences in a given vnode (and it's deep children) to a real DOM Node.
* @param {Element} [dom=null] A DOM node to mutate into the shape of the `vnode`
* @param {VNode} vnode A VNode (with descendants forming a tree) representing the desired DOM structure
* @returns {Element} dom The created/mutated element
* @private
*/
export function diff(dom, vnode, context, mountAll, parent, componentRoot) {
// diffLevel having been 0 here indicates initial entry into the diff (not a subdiff)
let ret
if (!diffLevel++) {
// when first starting the diff, check if we're diffing an SVG or within an SVG
isSvgMode = parent != null && parent.ownerSVGElement !== undefined
// hydration is indicated by the existing element to be diffed not having a prop cache
hydrating = dom != null && !(ATTR_KEY in dom)
}
if (isArray(vnode)) {
ret = []
let parentNode = null
if (isArray(dom)) {
parentNode = dom[0].parentNode
dom.forEach(function(item, index) {
ret.push(idiff(item, vnode[index], context, mountAll, componentRoot))
})
} else {
vnode.forEach(function(item) {
ret.push(idiff(dom, item, context, mountAll, componentRoot))
})
}
if (parent) {
ret.forEach(function(vnode) {
parent.appendChild(vnode)
})
} else if (isArray(dom)) {
dom.forEach(function(node) {
parentNode.appendChild(node)
})
}
} else {
ret = idiff(dom, vnode, context, mountAll, componentRoot)
// append the element if its a new parent
if (parent && ret.parentNode !== parent) parent.appendChild(ret)
}
// diffLevel being reduced to 0 means we're exiting the diff
if (!--diffLevel) {
hydrating = false
// invoke queued componentDidMount lifecycle methods
}
return ret
}
/** Internals of `diff()`, separated to allow bypassing diffLevel / mount flushing. */
function idiff(dom, vnode, context, mountAll, componentRoot) {
if (dom && dom.props) {
dom.props.children = vnode.children
}
let out = dom,
prevSvgMode = isSvgMode
// empty values (null, undefined, booleans) render as empty Text nodes
if (vnode == null || typeof vnode === 'boolean') vnode = ''
// Fast case: Strings & Numbers create/update Text nodes.
if (typeof vnode === 'string' || typeof vnode === 'number') {
// update if it's already a Text node:
if (
dom &&
dom.splitText !== undefined &&
dom.parentNode &&
(!dom._component || componentRoot)
) {
/* istanbul ignore if */ /* Browser quirk that can't be covered: https://github.com/developit/preact/commit/fd4f21f5c45dfd75151bd27b4c217d8003aa5eb9 */
if (dom.nodeValue != vnode) {
dom.nodeValue = vnode
}
} else {
// it wasn't a Text node: replace it with one and recycle the old Element
out = document.createTextNode(vnode)
if (dom) {
if (dom.parentNode) dom.parentNode.replaceChild(out, dom)
recollectNodeTree(dom, true)
}
}
out[ATTR_KEY] = true
return out
}
// If the VNode represents a Component, perform a component diff:
let vnodeName = vnode.nodeName
// Tracks entering and exiting SVG namespace when descending through the tree.
isSvgMode =
vnodeName === 'svg'
? true
: vnodeName === 'foreignObject'
? false
: isSvgMode
// If there's no existing element or it's the wrong type, create a new one:
vnodeName = String(vnodeName)
if (!dom || !isNamedNode(dom, vnodeName)) {
out = createNode(vnodeName, isSvgMode)
if (dom) {
// move children into the replacement node
while (dom.firstChild) out.appendChild(dom.firstChild)
// if the previous Element was mounted into the DOM, replace it inline
if (dom.parentNode) dom.parentNode.replaceChild(out, dom)
// recycle the old element (skips non-Element node types)
recollectNodeTree(dom, true)
}
}
let fc = out.firstChild,
props = out[ATTR_KEY],
vchildren = vnode.children
if (props == null) {
props = out[ATTR_KEY] = {}
for (let a = out.attributes, i = a.length; i--; )
props[a[i].name] = a[i].value
}
// Optimization: fast-path for elements containing a single TextNode:
if (
!hydrating &&
vchildren &&
vchildren.length === 1 &&
typeof vchildren[0] === 'string' &&
fc != null &&
fc.splitText !== undefined &&
fc.nextSibling == null
) {
if (fc.nodeValue != vchildren[0]) {
fc.nodeValue = vchildren[0]
}
}
// otherwise, if there are existing or new children, diff them:
else if ((vchildren && vchildren.length) || fc != null) {
innerDiffNode(
out,
vchildren,
context,
mountAll,
hydrating || props.dangerouslySetInnerHTML != null
)
}
// Apply attributes/props from VNode to the DOM Element:
diffAttributes(out, vnode.attributes, props)
if (out.props) {
out.props.children = vnode.children
}
// restore previous SVG mode: (in case we're exiting an SVG namespace)
isSvgMode = prevSvgMode
return out
}
/** Apply child and attribute changes between a VNode and a DOM Node to the DOM.
* @param {Element} dom Element whose children should be compared & mutated
* @param {Array} vchildren Array of VNodes to compare to `dom.childNodes`
* @param {Object} context Implicitly descendant context object (from most recent `getChildContext()`)
* @param {Boolean} mountAll
* @param {Boolean} isHydrating If `true`, consumes externally created elements similar to hydration
*/
function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {
let originalChildren = dom.childNodes,
children = [],
keyed = {},
keyedLen = 0,
min = 0,
len = originalChildren.length,
childrenLen = 0,
vlen = vchildren ? vchildren.length : 0,
j,
c,
f,
vchild,
child
// Build up a map of keyed children and an Array of unkeyed children:
if (len !== 0) {
for (let i = 0; i < len; i++) {
let child = originalChildren[i],
props = child[ATTR_KEY],
key =
vlen && props
? child._component
? child._component.__key
: props.key
: null
if (key != null) {
keyedLen++
keyed[key] = child
} else if (
props ||
(child.splitText !== undefined
? isHydrating
? child.nodeValue.trim()
: true
: isHydrating)
) {
children[childrenLen++] = child
}
}
}
if (vlen !== 0) {
for (let i = 0; i < vlen; i++) {
vchild = vchildren[i]
child = null
// attempt to find a node based on key matching
let key = vchild.key
if (key != null) {
if (keyedLen && keyed[key] !== undefined) {
child = keyed[key]
keyed[key] = undefined
keyedLen--
}
}
// attempt to pluck a node of the same type from the existing children
else if (!child && min < childrenLen) {
for (j = min; j < childrenLen; j++) {
if (
children[j] !== undefined &&
isSameNodeType((c = children[j]), vchild, isHydrating)
) {
child = c
children[j] = undefined
if (j === childrenLen - 1) childrenLen--
if (j === min) min++
break
}
}
}
// morph the matched/found/created DOM child to match vchild (deep)
child = idiff(child, vchild, context, mountAll)
f = originalChildren[i]
if (child && child !== dom && child !== f) {
if (f == null) {
dom.appendChild(child)
} else if (child === f.nextSibling) {
removeNode(f)
} else {
dom.insertBefore(child, f)
}
}
}
}
// remove unused keyed children:
if (keyedLen) {
for (let i in keyed)
if (keyed[i] !== undefined) recollectNodeTree(keyed[i], false)
}
// remove orphaned unkeyed children:
while (min <= childrenLen) {
if ((child = children[childrenLen--]) !== undefined)
recollectNodeTree(child, false)
}
}
/** Recursively recycle (or just unmount) a node and its descendants.
* @param {Node} node DOM node to start unmount/removal from
* @param {Boolean} [unmountOnly=false] If `true`, only triggers unmount lifecycle, skips removal
*/
export function recollectNodeTree(node, unmountOnly) {
// If the node's VNode had a ref function, invoke it with null here.
// (this is part of the React spec, and smart for unsetting references)
if (node[ATTR_KEY] != null && node[ATTR_KEY].ref) node[ATTR_KEY].ref(null)
if (unmountOnly === false || node[ATTR_KEY] == null) {
removeNode(node)
}
removeChildren(node)
}
/** Recollect/unmount all children.
* - we use .lastChild here because it causes less reflow than .firstChild
* - it's also cheaper than accessing the .childNodes Live NodeList
*/
export function removeChildren(node) {
node = node.lastChild
while (node) {
let next = node.previousSibling
recollectNodeTree(node, true)
node = next
}
}
/** Apply differences in attributes from a VNode to the given DOM Element.
* @param {Element} dom Element with attributes to diff `attrs` against
* @param {Object} attrs The desired end-state key-value attribute pairs
* @param {Object} old Current/previous attributes (from previous VNode or element's prop cache)
*/
function diffAttributes(dom, attrs, old) {
let name
let update = false
let isWeElement = dom.update
// remove attributes no longer present on the vnode by setting them to undefined
for (name in old) {
if (!(attrs && attrs[name] != null) && old[name] != null) {
setAccessor(dom, name, old[name], (old[name] = undefined), isSvgMode)
if (isWeElement) {
delete dom.props[name]
update = true
}
}
}
// add new & update changed attributes
for (name in attrs) {
//diable when using store system?
//!dom.store &&
if (isWeElement && typeof attrs[name] === 'object') {
dom.props[npn(name)] = attrs[name]
update = true
} else if (
name !== 'children' &&
name !== 'innerHTML' &&
(!(name in old) ||
attrs[name] !==
(name === 'value' || name === 'checked' ? dom[name] : old[name]))
) {
setAccessor(dom, name, old[name], (old[name] = attrs[name]), isSvgMode)
if (isWeElement) {
dom.props[npn(name)] = attrs[name]
update = true
}
}
}
dom.parentNode && update && isWeElement && dom.update()
}

View File

@ -0,0 +1,56 @@
import { extend } from '../util'
/**
* Check if two nodes are equivalent.
*
* @param {Node} node DOM Node to compare
* @param {VNode} vnode Virtual DOM node to compare
* @param {boolean} [hydrating=false] If true, ignores component constructors when comparing.
* @private
*/
export function isSameNodeType(node, vnode, hydrating) {
if (typeof vnode === 'string' || typeof vnode === 'number') {
return node.splitText !== undefined
}
if (typeof vnode.nodeName === 'string') {
return !node._componentConstructor && isNamedNode(node, vnode.nodeName)
}
return hydrating || node._componentConstructor === vnode.nodeName
}
/**
* Check if an Element has a given nodeName, case-insensitively.
*
* @param {Element} node A DOM Element to inspect the name of.
* @param {String} nodeName Unnormalized name to compare against.
*/
export function isNamedNode(node, nodeName) {
return (
node.normalizedNodeName === nodeName ||
node.nodeName.toLowerCase() === nodeName.toLowerCase()
)
}
/**
* Reconstruct Component-style `props` from a VNode.
* Ensures default/fallback values from `defaultProps`:
* Own-properties of `defaultProps` not present in `vnode.attributes` are added.
*
* @param {VNode} vnode
* @returns {Object} props
*/
export function getNodeProps(vnode) {
let props = extend({}, vnode.attributes)
props.children = vnode.children
let defaultProps = vnode.nodeName.defaultProps
if (defaultProps !== undefined) {
for (let i in defaultProps) {
if (props[i] === undefined) {
props[i] = defaultProps[i]
}
}
}
return props
}

View File

@ -0,0 +1,2 @@
/** Virtual DOM Node */
export function VNode() {}

View File

@ -0,0 +1,99 @@
import { cssToDom, nProps, isArray } from './util'
import { diff } from './vdom/diff'
import options from './options'
import { proxyUpdate } from './observe'
import HTMLElement from './native/html-element'
export default class WeElement extends HTMLElement {
static is = 'WeElement'
constructor() {
super()
this.props = nProps(this.constructor.props)
this.data = this.constructor.data || {}
}
connectedCallback() {
if (!this.constructor.pure) {
let p = this.parentNode
while (p && !this.store) {
this.store = p.store
p = p.parentNode || p.host
}
if (this.store) {
this.store.instances.push(this)
}
}
this.install()
const shadowRoot = this.attachShadow({ mode: 'open' })
this.css && shadowRoot.appendChild(cssToDom(this.css()))
this.beforeRender()
options.afterInstall && options.afterInstall(this)
if (this.constructor.observe) {
proxyUpdate(this)
}
this.host = diff(
null,
this.render(
this.props,
!this.constructor.pure && this.store ? this.store.data : this.data
),
{},
false,
null,
false
)
if (isArray(this.host)) {
this.host.forEach(function(item) {
shadowRoot.appendChild(item)
})
} else {
shadowRoot.appendChild(this.host)
}
this.installed()
this._isInstalled = true
}
disconnectedCallback() {
this.uninstall()
if (this.store) {
for (let i = 0, len = this.store.instances.length; i < len; i++) {
if (this.store.instances[i] === this) {
this.store.instances.splice(i, 1)
break
}
}
}
}
update() {
this.beforeUpdate()
this.beforeRender()
diff(
this.host,
this.render(
this.props,
!this.constructor.pure && this.store ? this.store.data : this.data
)
)
this.afterUpdate()
}
fire(name, data) {
this.dispatchEvent(new CustomEvent(name, { detail: data }))
}
install() {}
installed() {}
uninstall() {}
beforeUpdate() {}
afterUpdate() {}
beforeRender() {}
}