@spcsn/taro-runtime 0.1.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/LICENSE +1 -153
  2. package/README.md +16 -39
  3. package/dist/bom/{URL.js → URL2.js} +3 -4
  4. package/dist/bom/URL2.js.map +1 -0
  5. package/dist/bom/document.d.ts +0 -1
  6. package/dist/bom/document.js +1 -55
  7. package/dist/bom/document.js.map +1 -1
  8. package/dist/bom/get-computed-style.js +8 -0
  9. package/dist/bom/get-computed-style.js.map +1 -0
  10. package/dist/bom/history.js +1 -2
  11. package/dist/bom/history.js.map +1 -1
  12. package/dist/bom/location.js +2 -3
  13. package/dist/bom/location.js.map +1 -1
  14. package/dist/bom/navigator.js +1 -2
  15. package/dist/bom/navigator.js.map +1 -1
  16. package/dist/bom/raf.d.ts +2 -2
  17. package/dist/bom/raf.js +2 -2
  18. package/dist/bom/raf.js.map +1 -1
  19. package/dist/bom/url-search-params.d.ts +14 -0
  20. package/dist/bom/{URLSearchParams.js → url-search-params.js} +12 -15
  21. package/dist/bom/url-search-params.js.map +1 -0
  22. package/dist/bom/{URL.d.ts → url.d.ts} +1 -0
  23. package/dist/bom/url.js +196 -0
  24. package/dist/bom/url.js.map +1 -0
  25. package/dist/bom/window.d.ts +3 -3
  26. package/dist/bom/window.js +2 -2
  27. package/dist/bom/window.js.map +1 -1
  28. package/dist/current.d.ts +3 -0
  29. package/dist/current.js +10 -1
  30. package/dist/current.js.map +1 -1
  31. package/dist/dom/anchor-element.js +1 -1
  32. package/dist/dom/class-list.js +2 -1
  33. package/dist/dom/class-list.js.map +1 -1
  34. package/dist/dom/document.js.map +1 -1
  35. package/dist/dom/element.js +7 -7
  36. package/dist/dom/element.js.map +1 -1
  37. package/dist/dom/event.d.ts +1 -1
  38. package/dist/dom/event.js +3 -13
  39. package/dist/dom/event.js.map +1 -1
  40. package/dist/dom/form.js +1 -1
  41. package/dist/dom/form.js.map +1 -1
  42. package/dist/dom/node.d.ts +4 -3
  43. package/dist/dom/node.js +14 -7
  44. package/dist/dom/node.js.map +1 -1
  45. package/dist/dom/root.js +2 -2
  46. package/dist/dom/root.js.map +1 -1
  47. package/dist/dom/{style_properties.js → style-properties.js} +2 -2
  48. package/dist/dom/{style_properties.js.map → style-properties.js.map} +1 -1
  49. package/dist/dom/style.js +1 -1
  50. package/dist/dom/style.js.map +1 -1
  51. package/dist/dom/text.d.ts +1 -1
  52. package/dist/dom/text.js.map +1 -1
  53. package/dist/dom/tree.js.map +1 -1
  54. package/dist/dsl/common.js +26 -47
  55. package/dist/dsl/common.js.map +1 -1
  56. package/dist/env.js +2 -2
  57. package/dist/env.js.map +1 -1
  58. package/dist/hydrate.js +1 -1
  59. package/dist/hydrate.js.map +1 -1
  60. package/dist/index.cjs.d.ts +4 -4
  61. package/dist/index.cjs.js +331 -708
  62. package/dist/index.cjs.js.map +1 -1
  63. package/dist/index.d.ts +4 -4
  64. package/dist/index.js +6 -6
  65. package/dist/next-tick.js +1 -6
  66. package/dist/next-tick.js.map +1 -1
  67. package/dist/perf.js +1 -1
  68. package/dist/perf.js.map +1 -1
  69. package/dist/polyfill/index.js +1 -6
  70. package/dist/polyfill/index.js.map +1 -1
  71. package/dist/runtime.esm.d.ts +4 -4
  72. package/dist/runtime.esm.js +330 -708
  73. package/dist/runtime.esm.js.map +1 -1
  74. package/dist/utils/index.js.map +1 -1
  75. package/package.json +16 -10
  76. package/dist/bom/URL.js.map +0 -1
  77. package/dist/bom/URLSearchParams.d.ts +0 -1
  78. package/dist/bom/URLSearchParams.js.map +0 -1
  79. package/dist/bom/getComputedStyle.js +0 -9
  80. package/dist/bom/getComputedStyle.js.map +0 -1
  81. package/dist/polyfill/intersection-observer.js +0 -494
  82. package/dist/polyfill/intersection-observer.js.map +0 -1
  83. /package/dist/bom/{getComputedStyle.d.ts → get-computed-style.d.ts} +0 -0
  84. /package/dist/dom/{node_types.d.ts → node-types.d.ts} +0 -0
  85. /package/dist/dom/{style_properties.d.ts → style-properties.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["getComponentsAlias","_getComponentsAlias"],"sources":["../../src/utils/index.ts"],"sourcesContent":["import {\n getComponentsAlias as _getComponentsAlias,\n internalComponents,\n isFunction,\n Shortcuts,\n} from '@spcsn/taro-shared';\n\nimport { CLASS, COMMENT, ID, ROOT_STR, STYLE, UID } from '../constants';\nimport { NodeType } from '../dom/node_types';\n\nimport type { TaroElement } from '../dom/element';\nimport type { TaroNode } from '../dom/node';\nimport type { TaroText } from '../dom/text';\nimport type { TFunc } from '../interface';\n\nexport const incrementId = () => {\n const chatCodes: number[] = [];\n // A-Z\n for (let i = 65; i <= 90; i++) {\n chatCodes.push(i);\n }\n // a-z\n for (let i = 97; i <= 122; i++) {\n chatCodes.push(i);\n }\n const chatCodesLen = chatCodes.length - 1;\n const list = [0, 0];\n return () => {\n const target = list.map((item) => chatCodes[item]);\n const res = String.fromCharCode(...target);\n\n let tailIdx = list.length - 1;\n\n list[tailIdx]++;\n\n while (list[tailIdx] > chatCodesLen) {\n list[tailIdx] = 0;\n tailIdx = tailIdx - 1;\n if (tailIdx < 0) {\n list.push(0);\n break;\n }\n list[tailIdx]++;\n }\n\n return res;\n };\n};\n\nexport function isElement(node: TaroNode): node is TaroElement {\n return node.nodeType === NodeType.ELEMENT_NODE;\n}\n\nexport function isText(node: TaroNode): node is TaroText {\n return node.nodeType === NodeType.TEXT_NODE;\n}\n\nexport function isComment(node: TaroNode): boolean {\n return node.nodeName === COMMENT;\n}\n\nexport function isHasExtractProp(el: TaroElement): boolean {\n const res = Object.keys(el.props).find((prop) => {\n return !(/^(class|style|id)$/.test(prop) || prop.startsWith('data-'));\n });\n return Boolean(res);\n}\n\n/**\n * 往上寻找组件树直到 root,寻找是否有祖先组件绑定了同类型的事件\n * @param node 当前组件\n * @param type 事件类型\n */\nexport function isParentBound(node: TaroElement | null, type: string): boolean {\n while ((node = node?.parentElement || null)) {\n if (!node || node.nodeName === ROOT_STR || node.nodeName === 'root-portal') {\n return false;\n } else if (node.__handlers[type]?.length) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function shortcutAttr(key: string): string {\n switch (key) {\n case STYLE:\n return Shortcuts.Style;\n case ID:\n return UID;\n case CLASS:\n return Shortcuts.Class;\n default:\n return key;\n }\n}\n\nexport const customWrapperCache = new Map<string, Record<string, any>>();\n\ninterface Ctor {\n new (...args: any[]): any;\n}\n\nexport function extend(ctor: Ctor, methodName: string, options: TFunc | Record<string, any>) {\n if (isFunction(options)) {\n options = {\n value: options,\n };\n }\n Object.defineProperty(ctor.prototype, methodName, {\n configurable: true,\n enumerable: true,\n ...options,\n });\n}\n\nlet componentsAlias;\nexport function getComponentsAlias() {\n if (!componentsAlias) {\n componentsAlias = _getComponentsAlias(internalComponents);\n }\n return componentsAlias;\n}\n\nexport function convertNumber2PX(value: number) {\n return value + 'px';\n}\n\nexport * from './lodash';\nexport * from './router';\n"],"mappings":";;;;;;AAeA,MAAa,oBAAoB;CAC/B,MAAM,YAAsB,CAAC;CAE7B,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,KACxB,UAAU,KAAK,CAAC;CAGlB,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KACzB,UAAU,KAAK,CAAC;CAElB,MAAM,eAAe,UAAU,SAAS;CACxC,MAAM,OAAO,CAAC,GAAG,CAAC;CAClB,aAAa;EACX,MAAM,SAAS,KAAK,KAAK,SAAS,UAAU,KAAK;EACjD,MAAM,MAAM,OAAO,aAAa,GAAG,MAAM;EAEzC,IAAI,UAAU,KAAK,SAAS;EAE5B,KAAK;EAEL,OAAO,KAAK,WAAW,cAAc;GACnC,KAAK,WAAW;GAChB,UAAU,UAAU;GACpB,IAAI,UAAU,GAAG;IACf,KAAK,KAAK,CAAC;IACX;GACF;GACA,KAAK;EACP;EAEA,OAAO;CACT;AACF;AAEA,SAAgB,UAAU,MAAqC;CAC7D,OAAO,KAAK,aAAA;AACd;AAEA,SAAgB,OAAO,MAAkC;CACvD,OAAO,KAAK,aAAA;AACd;AAEA,SAAgB,UAAU,MAAyB;CACjD,OAAO,KAAK,aAAa;AAC3B;AAEA,SAAgB,iBAAiB,IAA0B;CACzD,MAAM,MAAM,OAAO,KAAK,GAAG,KAAK,EAAE,MAAM,SAAS;EAC/C,OAAO,EAAE,qBAAqB,KAAK,IAAI,KAAK,KAAK,WAAW,OAAO;CACrE,CAAC;CACD,OAAO,QAAQ,GAAG;AACpB;;;;;;AAOA,SAAgB,cAAc,MAA0B,MAAuB;CAC7E,OAAQ,QAAA,SAAA,QAAA,SAAA,KAAA,IAAA,KAAA,IAAO,KAAM,kBAAiB,MAAO;;EAC3C,IAAI,CAAC,QAAQ,KAAK,aAAA,UAAyB,KAAK,aAAa,eAC3D,OAAO;OACF,KAAA,wBAAI,KAAK,WAAW,WAAA,QAAA,0BAAA,KAAA,IAAA,KAAA,IAAA,sBAAO,QAChC,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAgB,aAAa,KAAqB;CAChD,QAAQ,KAAR;EACE,KAAK,OACH,OAAO,UAAU;EACnB,KAAA,MACE,OAAA;EACF,KAAK,OACH,OAAO,UAAU;EACnB,SACE,OAAO;CACX;AACF;AAEA,MAAa,qCAAqB,IAAI,IAAiC;AAMvE,SAAgB,OAAO,MAAY,YAAoB,SAAsC;CAC3F,IAAI,WAAW,OAAO,GACpB,UAAU,EACR,OAAO,QACT;CAEF,OAAO,eAAe,KAAK,WAAW,YAAA,eAAA;EACpC,cAAc;EACd,YAAY;IACT,OACL,CAAC;AACH;AAEA,IAAI;AACJ,SAAgBA,uBAAqB;CACnC,IAAI,CAAC,iBACH,kBAAkBC,mBAAoB,kBAAkB;CAE1D,OAAO;AACT;AAEA,SAAgB,iBAAiB,OAAe;CAC9C,OAAO,QAAQ;AACjB"}
1
+ {"version":3,"file":"index.js","names":["getComponentsAlias","_getComponentsAlias"],"sources":["../../src/utils/index.ts"],"sourcesContent":["import {\n getComponentsAlias as _getComponentsAlias,\n internalComponents,\n isFunction,\n Shortcuts,\n} from '@spcsn/taro-shared';\n\nimport { CLASS, COMMENT, ID, ROOT_STR, STYLE, UID } from '../constants';\nimport { NodeType } from '../dom/node-types';\n\nimport type { TaroElement } from '../dom/element';\nimport type { TaroNode } from '../dom/node';\nimport type { TaroText } from '../dom/text';\nimport type { TFunc } from '../interface';\n\nexport const incrementId = () => {\n const chatCodes: number[] = [];\n // A-Z\n for (let i = 65; i <= 90; i++) {\n chatCodes.push(i);\n }\n // a-z\n for (let i = 97; i <= 122; i++) {\n chatCodes.push(i);\n }\n const chatCodesLen = chatCodes.length - 1;\n const list = [0, 0];\n return () => {\n const target = list.map((item) => chatCodes[item]);\n const res = String.fromCharCode(...target);\n\n let tailIdx = list.length - 1;\n\n list[tailIdx]++;\n\n while (list[tailIdx] > chatCodesLen) {\n list[tailIdx] = 0;\n tailIdx = tailIdx - 1;\n if (tailIdx < 0) {\n list.push(0);\n break;\n }\n list[tailIdx]++;\n }\n\n return res;\n };\n};\n\nexport function isElement(node: TaroNode): node is TaroElement {\n return node.nodeType === NodeType.ELEMENT_NODE;\n}\n\nexport function isText(node: TaroNode): node is TaroText {\n return node.nodeType === NodeType.TEXT_NODE;\n}\n\nexport function isComment(node: TaroNode): boolean {\n return node.nodeName === COMMENT;\n}\n\nexport function isHasExtractProp(el: TaroElement): boolean {\n const res = Object.keys(el.props).find((prop) => {\n return !(/^(class|style|id)$/.test(prop) || prop.startsWith('data-'));\n });\n return Boolean(res);\n}\n\n/**\n * 往上寻找组件树直到 root,寻找是否有祖先组件绑定了同类型的事件\n * @param node 当前组件\n * @param type 事件类型\n */\nexport function isParentBound(node: TaroElement | null, type: string): boolean {\n while ((node = node?.parentElement || null)) {\n if (!node || node.nodeName === ROOT_STR || node.nodeName === 'root-portal') {\n return false;\n } else if (node.__handlers[type]?.length) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function shortcutAttr(key: string): string {\n switch (key) {\n case STYLE:\n return Shortcuts.Style;\n case ID:\n return UID;\n case CLASS:\n return Shortcuts.Class;\n default:\n return key;\n }\n}\n\nexport const customWrapperCache = new Map<string, Record<string, any>>();\n\ninterface Ctor {\n new (...args: any[]): any;\n}\n\nexport function extend(ctor: Ctor, methodName: string, options: TFunc | Record<string, any>) {\n if (isFunction(options)) {\n options = {\n value: options,\n };\n }\n Object.defineProperty(ctor.prototype, methodName, {\n configurable: true,\n enumerable: true,\n ...options,\n });\n}\n\nlet componentsAlias;\nexport function getComponentsAlias() {\n if (!componentsAlias) {\n componentsAlias = _getComponentsAlias(internalComponents);\n }\n return componentsAlias;\n}\n\nexport function convertNumber2PX(value: number) {\n return value + 'px';\n}\n\nexport * from './lodash';\nexport * from './router';\n"],"mappings":";;;;;;AAeA,MAAa,oBAAoB;CAC/B,MAAM,YAAsB,CAAC;CAE7B,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,KACxB,UAAU,KAAK,CAAC;CAGlB,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KACzB,UAAU,KAAK,CAAC;CAElB,MAAM,eAAe,UAAU,SAAS;CACxC,MAAM,OAAO,CAAC,GAAG,CAAC;CAClB,aAAa;EACX,MAAM,SAAS,KAAK,KAAK,SAAS,UAAU,KAAK;EACjD,MAAM,MAAM,OAAO,aAAa,GAAG,MAAM;EAEzC,IAAI,UAAU,KAAK,SAAS;EAE5B,KAAK;EAEL,OAAO,KAAK,WAAW,cAAc;GACnC,KAAK,WAAW;GAChB,UAAU,UAAU;GACpB,IAAI,UAAU,GAAG;IACf,KAAK,KAAK,CAAC;IACX;GACF;GACA,KAAK;EACP;EAEA,OAAO;CACT;AACF;AAEA,SAAgB,UAAU,MAAqC;CAC7D,OAAO,KAAK,aAAA;AACd;AAEA,SAAgB,OAAO,MAAkC;CACvD,OAAO,KAAK,aAAA;AACd;AAEA,SAAgB,UAAU,MAAyB;CACjD,OAAO,KAAK,aAAa;AAC3B;AAEA,SAAgB,iBAAiB,IAA0B;CACzD,MAAM,MAAM,OAAO,KAAK,GAAG,KAAK,EAAE,MAAM,SAAS;EAC/C,OAAO,EAAE,qBAAqB,KAAK,IAAI,KAAK,KAAK,WAAW,OAAO;CACrE,CAAC;CACD,OAAO,QAAQ,GAAG;AACpB;;;;;;AAOA,SAAgB,cAAc,MAA0B,MAAuB;CAC7E,OAAQ,QAAA,SAAA,QAAA,SAAA,KAAA,IAAA,KAAA,IAAO,KAAM,kBAAiB,MAAO;;EAC3C,IAAI,CAAC,QAAQ,KAAK,aAAA,UAAyB,KAAK,aAAa,eAC3D,OAAO;OACF,KAAA,wBAAI,KAAK,WAAW,WAAA,QAAA,0BAAA,KAAA,IAAA,KAAA,IAAA,sBAAO,QAChC,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAgB,aAAa,KAAqB;CAChD,QAAQ,KAAR;EACE,KAAK,OACH,OAAO,UAAU;EACnB,KAAA,MACE,OAAA;EACF,KAAK,OACH,OAAO,UAAU;EACnB,SACE,OAAO;CACX;AACF;AAEA,MAAa,qCAAqB,IAAI,IAAiC;AAMvE,SAAgB,OAAO,MAAY,YAAoB,SAAsC;CAC3F,IAAI,WAAW,OAAO,GACpB,UAAU,EACR,OAAO,QACT;CAEF,OAAO,eAAe,KAAK,WAAW,YAAA,eAAA;EACpC,cAAc;EACd,YAAY;IACT,OACL,CAAC;AACH;AAEA,IAAI;AACJ,SAAgBA,uBAAqB;CACnC,IAAI,CAAC,iBACH,kBAAkBC,mBAAoB,kBAAkB;CAE1D,OAAO;AACT;AAEA,SAAgB,iBAAiB,OAAe;CAC9C,OAAO,QAAQ;AACjB"}
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@spcsn/taro-runtime",
3
- "version": "0.1.2",
4
- "description": "taro runtime for mini apps.",
5
- "author": "O2Team",
3
+ "version": "1.0.1",
4
+ "description": "SPCSN Taro runtime for mini apps.",
5
+ "author": "Samuel Ouyang",
6
6
  "license": "MIT",
7
7
  "browser": "dist/index.js",
8
- "main:h5": "dist/runtime.esm.js",
9
8
  "main": "dist/runtime.esm.js",
10
9
  "module": "dist/runtime.esm.js",
11
10
  "types": "./dist/index.d.ts",
@@ -17,26 +16,33 @@
17
16
  ],
18
17
  "repository": {
19
18
  "type": "git",
20
- "url": "https://github.com/NervJS/taro/tree/master/packages/taro-runtime"
19
+ "url": "git+https://github.com/specificshen/taro-lite.git"
21
20
  },
21
+ "bugs": {
22
+ "url": "https://github.com/specificshen/taro-lite/issues"
23
+ },
24
+ "homepage": "https://github.com/specificshen/taro-lite#readme",
22
25
  "engines": {
23
26
  "node": ">= 22"
24
27
  },
25
28
  "dependencies": {
26
- "tslib": "^2.6.2",
27
- "@spcsn/taro-shared": "0.1.2"
29
+ "@spcsn/taro-shared": "1.0.1"
28
30
  },
29
31
  "devDependencies": {
30
32
  "@types/node": "^22.19.19",
33
+ "@vitest/coverage-istanbul": "^3.2.4",
34
+ "concurrently": "^8.2.2",
31
35
  "lodash": "^4.17.21",
32
- "typescript": "~6.0.3"
36
+ "rolldown": "^1.0.1",
37
+ "typescript": "~6.0.3",
38
+ "vitest": "^3.2.4"
33
39
  },
34
40
  "scripts": {
35
41
  "prod": "pnpm run build",
36
42
  "prebuild": "pnpm run clean",
37
43
  "build": "pnpm run build:types && pnpm run rolldown --environment NODE_ENV:production",
38
- "build:types": "tsc --emitDeclarationOnly --declaration --noCheck && node ./scripts/copy-entry-types.mjs",
39
- "clean": "rimraf ./dist",
44
+ "build:types": "tsc --emitDeclarationOnly --declaration --noCheck && bun ./scripts/copy-entry-types.ts",
45
+ "clean": "bun ../../scripts/clean.ts dist",
40
46
  "dev": "concurrently \"pnpm run build:types -- --watch\" \"pnpm run rolldown --environment NODE_ENV:development -w\"",
41
47
  "rolldown": "rolldown --config rolldown.config.mjs",
42
48
  "test": "vitest run",
@@ -1 +0,0 @@
1
- {"version":3,"file":"URL.js","names":[],"sources":["../../src/bom/URL.ts"],"sourcesContent":["import { isString, isUndefined } from '@spcsn/taro-shared';\n\nimport env from '../env';\nimport { URLSearchParams } from './URLSearchParams';\n\nclass TaroURL {\n static createObjectURL() {\n throw new Error('Oops, not support URL.createObjectURL() in miniprogram.');\n }\n\n static revokeObjectURL() {\n throw new Error('Oops, not support URL.revokeObjectURL() in miniprogram.');\n }\n\n /* private property */\n #hash = '';\n #hostname = '';\n #pathname = '';\n #port = '';\n #protocol = '';\n #search: URLSearchParams;\n\n constructor(url: string, base?: string) {\n if (!isString(url)) url = String(url);\n\n const parseResult = parseUrlBase(url, base);\n const { hash, hostname, pathname, port, protocol, search } = parseResult;\n\n this.#hash = hash;\n this.#hostname = hostname;\n this.#pathname = pathname || '/';\n this.#port = port;\n this.#protocol = protocol;\n this.#search = new URLSearchParams(search);\n }\n\n /* public property */\n get protocol() {\n return this.#protocol;\n }\n\n set protocol(val: string) {\n isString(val) && (this.#protocol = val.trim());\n }\n\n get host() {\n return this.hostname + (this.port ? ':' + this.port : '');\n }\n\n set host(val: string) {\n if (val && isString(val)) {\n val = val.trim();\n const { hostname, port } = parseUrl(`//${val}`);\n this.hostname = hostname;\n this.port = port;\n }\n }\n\n get hostname() {\n return this.#hostname;\n }\n\n set hostname(val: string) {\n val && isString(val) && (this.#hostname = val.trim());\n }\n\n get port() {\n return this.#port;\n }\n\n set port(val: string) {\n isString(val) && (this.#port = val.trim());\n }\n\n get pathname() {\n return this.#pathname;\n }\n\n set pathname(val: string) {\n if (isString(val)) {\n val = val.trim();\n const HEAD_REG = /^(\\/|\\.\\/|\\.\\.\\/)/;\n let temp = val;\n while (HEAD_REG.test(temp)) {\n temp = temp.replace(HEAD_REG, '');\n }\n if (temp) this.#pathname = '/' + temp;\n else this.#pathname = '/';\n }\n }\n\n get search() {\n const val = this.#search.toString();\n return val.length === 0 || val.startsWith('?') ? val : `?${val}`;\n }\n\n set search(val: string) {\n if (isString(val)) {\n val = val.trim();\n this.#search = new URLSearchParams(val);\n }\n }\n\n get hash() {\n return this.#hash;\n }\n\n set hash(val: string) {\n if (isString(val)) {\n val = val.trim();\n if (val) this.#hash = val.startsWith('#') ? val : `#${val}`;\n else this.#hash = '';\n }\n }\n\n get href() {\n return `${this.protocol}//${this.host}${this.pathname}${this.search}${this.hash}`;\n }\n\n set href(val: string) {\n if (val && isString(val)) {\n val = val.trim();\n const { protocol, hostname, port, hash, search, pathname } = parseUrl(val);\n this.protocol = protocol;\n this.hostname = hostname;\n this.pathname = pathname;\n this.port = port;\n this.hash = hash;\n this.search = search;\n }\n }\n\n get origin() {\n return `${this.protocol}//${this.host}`;\n }\n\n set origin(val: string) {\n if (val && isString(val)) {\n val = val.trim();\n const { protocol, hostname, port } = parseUrl(val);\n this.protocol = protocol;\n this.hostname = hostname;\n this.port = port;\n }\n }\n\n get searchParams() {\n return this.#search;\n }\n\n // public method\n toString() {\n return this.href;\n }\n\n toJSON() {\n return this.toString();\n }\n\n // convenient for deconstructor\n _toRaw() {\n return {\n protocol: this.protocol,\n port: this.port,\n host: this.host,\n hostname: this.hostname,\n pathname: this.pathname,\n hash: this.hash,\n search: this.search,\n origin: this.origin,\n href: this.href,\n };\n }\n}\n\nexport type { TaroURL };\n\n// Note: 小程序端 vite 打包成 commonjs,const URL = xxx 会报错,所以把 URL 改为 TaroURLProvider\nexport const TaroURLProvider: typeof TaroURL = process.env.TARO_PLATFORM === 'web' ? env.window.URL : TaroURL;\n\nexport function parseUrl(url = '') {\n const result = {\n href: '',\n origin: '',\n protocol: '',\n hostname: '',\n host: '',\n port: '',\n pathname: '',\n search: '',\n hash: '',\n };\n if (!url || !isString(url)) return result;\n\n url = url.trim();\n const PATTERN = /^(([^:/?#]+):)?\\/\\/(([^/?#]+):(.+)@)?([^/?#:]*)(:(\\d+))?([^?#]*)(\\?([^#]*))?(#(.*))?/;\n const matches = url.match(PATTERN);\n\n if (!matches) return result;\n\n // TODO: username & password ?\n result.protocol = matches[1] || 'https:';\n result.hostname = matches[6] || 'taro.com';\n result.port = matches[8] || '';\n result.pathname = matches[9] || '/';\n result.search = matches[10] || '';\n result.hash = matches[12] || '';\n result.href = url;\n result.origin = result.protocol + '//' + result.hostname + (result.port ? `:${result.port}` : '');\n result.host = result.hostname + (result.port ? `:${result.port}` : '');\n\n return result;\n}\n\nfunction parseUrlBase(url: string, base?: string) {\n const VALID_URL = /^(https?:)\\/\\//i;\n\n let fullUrl = '';\n let parsedBase: ReturnType<typeof parseUrl> | null = null;\n\n if (!isUndefined(base)) {\n base = String(base).trim();\n if (!VALID_URL.test(base)) throw new TypeError(`Failed to construct 'URL': Invalid base URL`);\n parsedBase = parseUrl(base);\n }\n\n url = String(url).trim();\n\n if (VALID_URL.test(url)) {\n fullUrl = url;\n } else if (parsedBase) {\n if (url) {\n if (url.startsWith('//')) {\n fullUrl = parsedBase.protocol + url;\n } else {\n fullUrl = parsedBase.origin + (url.startsWith('/') ? url : `/${url}`);\n }\n } else {\n fullUrl = parsedBase.href;\n }\n } else {\n throw new TypeError(`Failed to construct 'URL': Invalid URL`);\n }\n\n return parseUrl(fullUrl);\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- export declare const URLSearchParams: any;
@@ -1 +0,0 @@
1
- {"version":3,"file":"URLSearchParams.js","names":[],"sources":["../../src/bom/URLSearchParams.ts"],"sourcesContent":["import { isArray } from '@spcsn/taro-shared';\n\nimport env from '../env';\n\nconst findReg = /[!'()~]|%20|%00/g;\nconst plusReg = /\\+/g;\nconst replaceCharMap = {\n '!': '%21',\n \"'\": '%27',\n '(': '%28',\n ')': '%29',\n '~': '%7E',\n '%20': '+',\n '%00': '\\x00',\n};\n\nfunction replacer(match: string) {\n return replaceCharMap[match];\n}\n\nfunction appendTo(dict: Record<string, string[]>, name: string, value: string) {\n const res = isArray(value) ? value.join(',') : value;\n if (name in dict) dict[name].push(res);\n else dict[name] = [res];\n}\n\nfunction addEach(value: string, key: string) {\n appendTo(this, key, value);\n}\n\nfunction decode(str: string) {\n return decodeURIComponent(str.replace(plusReg, ' '));\n}\n\nfunction encode(str: string) {\n return encodeURIComponent(str).replace(findReg, replacer);\n}\n\nexport const URLSearchParams =\n process.env.TARO_PLATFORM === 'web'\n ? env.window.URLSearchParams\n : class {\n #dict = Object.create(null);\n\n constructor(query) {\n query ??= '';\n\n const dict = this.#dict;\n\n if (typeof query === 'string') {\n if (query.charAt(0) === '?') {\n query = query.slice(1);\n }\n for (let pairs = query.split('&'), i = 0, length = pairs.length; i < length; i++) {\n const value = pairs[i];\n const index = value.indexOf('=');\n\n // 针对不规范的 url 参数做容错处理,如:word=你%好\n try {\n if (index > -1) {\n appendTo(dict, decode(value.slice(0, index)), decode(value.slice(index + 1)));\n } else if (value.length) {\n appendTo(dict, decode(value), '');\n }\n } catch (err) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`[Taro warn] URL 参数 ${value} decode 异常`);\n }\n }\n }\n } else {\n if (isArray(query)) {\n for (let i = 0, length = query.length; i < length; i++) {\n const value = query[i];\n appendTo(dict, value[0], value[1]);\n }\n } else if (query.forEach) {\n query.forEach(addEach, dict);\n } else {\n for (const key in query) {\n appendTo(dict, key, query[key]);\n }\n }\n }\n }\n\n append(name: string, value: string) {\n appendTo(this.#dict, name, value);\n }\n\n delete(name: string) {\n delete this.#dict[name];\n }\n\n get(name: string) {\n const dict = this.#dict;\n return name in dict ? dict[name][0] : null;\n }\n\n getAll(name: string) {\n const dict = this.#dict;\n return name in dict ? dict[name].slice(0) : [];\n }\n\n has(name: string) {\n return name in this.#dict;\n }\n\n keys() {\n return Object.keys(this.#dict);\n }\n\n set(name: string, value: string) {\n this.#dict[name] = ['' + value];\n }\n\n forEach(callback, thisArg) {\n const dict = this.#dict;\n Object.getOwnPropertyNames(dict).forEach(function (name) {\n dict[name].forEach(function (value: string) {\n callback.call(thisArg, value, name, this);\n }, this);\n }, this);\n }\n\n toJSON() {\n return {};\n }\n\n toString() {\n const dict = this.#dict;\n const query: any[] = [];\n for (const key in dict) {\n const name = encode(key);\n for (let i = 0, value = dict[key]; i < value.length; i++) {\n query.push(name + '=' + encode(value[i]));\n }\n }\n return query.join('&');\n }\n };\n"],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- import env from "../env.js";
2
- //#region src/bom/getComputedStyle.ts
3
- const taroGetComputedStyleProvider = process.env.TARO_PLATFORM === "web" ? env.window.getComputedStyle : function(element) {
4
- return element.style;
5
- };
6
- //#endregion
7
- export { taroGetComputedStyleProvider };
8
-
9
- //# sourceMappingURL=getComputedStyle.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getComputedStyle.js","names":[],"sources":["../../src/bom/getComputedStyle.ts"],"sourcesContent":["import env from '../env';\n\nimport type { TaroElement } from '../dom/element';\nimport type { Style } from '../dom/style';\n\nexport type TGetComputedStyle = typeof window.getComputedStyle | ((el: TaroElement) => Style);\n\n// Note: 小程序端 vite 打包成 commonjs,const getComputedStyle = xxx 会报错,所以把 GetComputedStyle 改为 taroGetComputedStyleProvider\nexport const taroGetComputedStyleProvider: TGetComputedStyle =\n process.env.TARO_PLATFORM === 'web'\n ? env.window.getComputedStyle\n : function (element: TaroElement): Style {\n return element.style;\n };\n"],"mappings":";;AAQA,MAAa,+BACX,QAAQ,IAAI,kBAAkB,QAC1B,IAAI,OAAO,mBACX,SAAU,SAA6B;CACrC,OAAO,QAAQ;AACjB"}
@@ -1,494 +0,0 @@
1
- import { throttle } from "../utils/lodash.js";
2
- import { isFunction, isNumber } from "@spcsn/taro-shared";
3
- //#region src/polyfill/intersection-observer.ts
4
- function handleIntersectionObserverPolyfill() {
5
- if ("IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype) {
6
- if (!("isIntersecting" in window.IntersectionObserverEntry.prototype)) Object.defineProperty(window.IntersectionObserverEntry.prototype, "isIntersecting", { get: function() {
7
- return this.intersectionRatio > 0;
8
- } });
9
- } else handleIntersectionObserverObjectPolyfill();
10
- }
11
- function handleIntersectionObserverObjectPolyfill() {
12
- const document = window.document;
13
- /**
14
- * An IntersectionObserver registry. This registry exists to hold a strong
15
- * reference to IntersectionObserver instances currently observing a target
16
- * element. Without this registry, instances without another reference may be
17
- * garbage collected.
18
- */
19
- const registry = [];
20
- /**
21
- * Creates the global IntersectionObserverEntry constructor.
22
- * https://w3c.github.io/IntersectionObserver/#intersection-observer-entry
23
- * @param {Object} entry A dictionary of instance properties.
24
- * @constructor
25
- */
26
- function IntersectionObserverEntry(entry) {
27
- this.time = entry.time;
28
- this.target = entry.target;
29
- this.rootBounds = entry.rootBounds;
30
- this.boundingClientRect = entry.boundingClientRect;
31
- this.intersectionRect = entry.intersectionRect || getEmptyRect();
32
- this.isIntersecting = !!entry.intersectionRect;
33
- const targetRect = this.boundingClientRect;
34
- const targetArea = targetRect.width * targetRect.height;
35
- const intersectionRect = this.intersectionRect;
36
- const intersectionArea = intersectionRect.width * intersectionRect.height;
37
- if (targetArea) this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4));
38
- else this.intersectionRatio = this.isIntersecting ? 1 : 0;
39
- }
40
- /**
41
- * Creates the global IntersectionObserver constructor.
42
- * https://w3c.github.io/IntersectionObserver/#intersection-observer-interface
43
- * @param {Function} callback The function to be invoked after intersection
44
- * changes have queued. The function is not invoked if the queue has
45
- * been emptied by calling the `takeRecords` method.
46
- * @param {Object=} opt_options Optional configuration options.
47
- * @constructor
48
- */
49
- function IntersectionObserver(callback, options = {}) {
50
- if (!isFunction(callback)) throw new Error("callback must be a function");
51
- if (options.root && options.root.nodeType != 1) throw new Error("root must be an Element");
52
- this._checkForIntersections = throttle(this._checkForIntersections.bind(this), this.THROTTLE_TIMEOUT);
53
- this._callback = callback;
54
- this._observationTargets = [];
55
- this._queuedEntries = [];
56
- this._rootMarginValues = this._parseRootMargin(options.rootMargin);
57
- this.thresholds = this._initThresholds(options.threshold);
58
- this.root = options.root || null;
59
- this.rootMargin = this._rootMarginValues.map(function(margin) {
60
- return margin.value + margin.unit;
61
- }).join(" ");
62
- }
63
- /**
64
- * The minimum interval within which the document will be checked for
65
- * intersection changes.
66
- */
67
- IntersectionObserver.prototype.THROTTLE_TIMEOUT = 100;
68
- /**
69
- * The frequency in which the polyfill polls for intersection changes.
70
- * this can be updated on a per instance basis and must be set prior to
71
- * calling `observe` on the first target.
72
- */
73
- IntersectionObserver.prototype.POLL_INTERVAL = null;
74
- /**
75
- * Use a mutation observer on the root element
76
- * to detect intersection changes.
77
- */
78
- IntersectionObserver.prototype.USE_MUTATION_OBSERVER = true;
79
- /**
80
- * Starts observing a target element for intersection changes based on
81
- * the thresholds values.
82
- * @param {Element} target The DOM element to observe.
83
- */
84
- IntersectionObserver.prototype.observe = function(target) {
85
- if (this._observationTargets.some(function(item) {
86
- return item.element == target;
87
- })) return;
88
- if (!(target && target.nodeType == 1)) throw new Error("target must be an Element");
89
- this._registerInstance();
90
- this._observationTargets.push({
91
- element: target,
92
- entry: null
93
- });
94
- this._monitorIntersections();
95
- this._checkForIntersections();
96
- };
97
- /**
98
- * Stops observing a target element for intersection changes.
99
- * @param {Element} target The DOM element to observe.
100
- */
101
- IntersectionObserver.prototype.unobserve = function(target) {
102
- this._observationTargets = this._observationTargets.filter(function(item) {
103
- return item.element != target;
104
- });
105
- if (!this._observationTargets.length) {
106
- this._unmonitorIntersections();
107
- this._unregisterInstance();
108
- }
109
- };
110
- /**
111
- * Stops observing all target elements for intersection changes.
112
- */
113
- IntersectionObserver.prototype.disconnect = function() {
114
- this._observationTargets = [];
115
- this._unmonitorIntersections();
116
- this._unregisterInstance();
117
- };
118
- /**
119
- * Returns any queue entries that have not yet been reported to the
120
- * callback and clears the queue. This can be used in conjunction with the
121
- * callback to obtain the absolute most up-to-date intersection information.
122
- * @return {Array} The currently queued entries.
123
- */
124
- IntersectionObserver.prototype.takeRecords = function() {
125
- const records = this._queuedEntries.slice();
126
- this._queuedEntries = [];
127
- return records;
128
- };
129
- /**
130
- * Accepts the threshold value from the user configuration object and
131
- * returns a sorted array of unique threshold values. If a value is not
132
- * between 0 and 1 and error is thrown.
133
- * @private
134
- * @param {Array|number=} opt_threshold An optional threshold value or
135
- * a list of threshold values, defaulting to [0].
136
- * @return {Array} A sorted list of unique and valid threshold values.
137
- */
138
- IntersectionObserver.prototype._initThresholds = function(opt_threshold) {
139
- let threshold = opt_threshold || [0];
140
- if (!Array.isArray(threshold)) threshold = [threshold];
141
- return threshold.sort().filter(function(t, i, a) {
142
- if (!isNumber(t) || isNaN(t) || t < 0 || t > 1) throw new Error("threshold must be a number between 0 and 1 inclusively");
143
- return t !== a[i - 1];
144
- });
145
- };
146
- /**
147
- * Accepts the rootMargin value from the user configuration object
148
- * and returns an array of the four margin values as an object containing
149
- * the value and unit properties. If any of the values are not properly
150
- * formatted or use a unit other than px or %, and error is thrown.
151
- * @private
152
- * @param {string=} opt_rootMargin An optional rootMargin value,
153
- * defaulting to '0px'.
154
- * @return {Array<Object>} An array of margin objects with the keys
155
- * value and unit.
156
- */
157
- IntersectionObserver.prototype._parseRootMargin = function(opt_rootMargin) {
158
- const margins = (opt_rootMargin || "0px").split(/\s+/).map(function(margin) {
159
- const parts = /^(-?\d*\.?\d+)(px|%)$/.exec(margin);
160
- if (!parts) throw new Error("rootMargin must be specified in pixels or percent");
161
- return {
162
- value: parseFloat(parts[1]),
163
- unit: parts[2]
164
- };
165
- });
166
- margins[1] = margins[1] || margins[0];
167
- margins[2] = margins[2] || margins[0];
168
- margins[3] = margins[3] || margins[1];
169
- return margins;
170
- };
171
- /**
172
- * Starts polling for intersection changes if the polling is not already
173
- * happening, and if the page's visibility state is visible.
174
- * @private
175
- */
176
- IntersectionObserver.prototype._monitorIntersections = function() {
177
- if (!this._monitoringIntersections) {
178
- this._monitoringIntersections = true;
179
- if (this.POLL_INTERVAL) this._monitoringInterval = setInterval(this._checkForIntersections, this.POLL_INTERVAL);
180
- else {
181
- addEvent(window, "resize", this._checkForIntersections, true);
182
- addEvent(document, "scroll", this._checkForIntersections, true);
183
- if (this.USE_MUTATION_OBSERVER && "MutationObserver" in window) {
184
- this._domObserver = new MutationObserver(this._checkForIntersections);
185
- this._domObserver.observe(document, {
186
- attributes: true,
187
- childList: true,
188
- characterData: true,
189
- subtree: true
190
- });
191
- }
192
- }
193
- }
194
- };
195
- /**
196
- * Stops polling for intersection changes.
197
- * @private
198
- */
199
- IntersectionObserver.prototype._unmonitorIntersections = function() {
200
- if (this._monitoringIntersections) {
201
- this._monitoringIntersections = false;
202
- clearInterval(this._monitoringInterval);
203
- this._monitoringInterval = null;
204
- removeEvent(window, "resize", this._checkForIntersections, true);
205
- removeEvent(document, "scroll", this._checkForIntersections, true);
206
- if (this._domObserver) {
207
- this._domObserver.disconnect();
208
- this._domObserver = null;
209
- }
210
- }
211
- };
212
- /**
213
- * Scans each observation target for intersection changes and adds them
214
- * to the internal entries queue. If new entries are found, it
215
- * schedules the callback to be invoked.
216
- * @private
217
- */
218
- IntersectionObserver.prototype._checkForIntersections = function() {
219
- const rootIsInDom = this._rootIsInDom();
220
- const rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect();
221
- this._observationTargets.forEach(function(item) {
222
- const target = item.element;
223
- const targetRect = getBoundingClientRect(target);
224
- const rootContainsTarget = this._rootContainsTarget(target);
225
- const oldEntry = item.entry;
226
- const intersectionRect = rootIsInDom && rootContainsTarget && this._computeTargetAndRootIntersection(target, rootRect);
227
- const newEntry = item.entry = new IntersectionObserverEntry({
228
- time: now(),
229
- target,
230
- boundingClientRect: targetRect,
231
- rootBounds: rootRect,
232
- intersectionRect,
233
- intersectionRatio: -1,
234
- isIntersecting: false
235
- });
236
- if (!oldEntry) this._queuedEntries.push(newEntry);
237
- else if (rootIsInDom && rootContainsTarget) {
238
- if (this._hasCrossedThreshold(oldEntry, newEntry)) this._queuedEntries.push(newEntry);
239
- } else if (oldEntry && oldEntry.isIntersecting) this._queuedEntries.push(newEntry);
240
- }, this);
241
- if (this._queuedEntries.length) this._callback(this.takeRecords(), this);
242
- };
243
- /**
244
- * Accepts a target and root rect computes the intersection between then
245
- * following the algorithm in the spec.
246
- * TODO(philipwalton): at this time clip-path is not considered.
247
- * https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo
248
- * @param {Element} target The target DOM element
249
- * @param {Object} rootRect The bounding rect of the root after being
250
- * expanded by the rootMargin value.
251
- * @return {?Object} The final intersection rect object or undefined if no
252
- * intersection is found.
253
- * @private
254
- */
255
- IntersectionObserver.prototype._computeTargetAndRootIntersection = function(target, rootRect) {
256
- if (window.getComputedStyle(target).display === "none") return;
257
- let intersectionRect = getBoundingClientRect(target);
258
- let parent = getParentNode(target);
259
- let atRoot = false;
260
- while (!atRoot) {
261
- let parentRect = null;
262
- const parentComputedStyle = parent.nodeType == 1 ? window.getComputedStyle(parent) : {};
263
- if (parentComputedStyle.display === "none") return;
264
- if (parent == this.root || parent == document) {
265
- atRoot = true;
266
- parentRect = rootRect;
267
- } else if (parent != document.body && parent != document.documentElement && parentComputedStyle.overflow != "visible") parentRect = getBoundingClientRect(parent);
268
- if (parentRect) {
269
- intersectionRect = computeRectIntersection(parentRect, intersectionRect);
270
- if (!intersectionRect) break;
271
- }
272
- parent = getParentNode(parent);
273
- }
274
- return intersectionRect;
275
- };
276
- /**
277
- * Returns the root rect after being expanded by the rootMargin value.
278
- * @return {Object} The expanded root rect.
279
- * @private
280
- */
281
- IntersectionObserver.prototype._getRootRect = function() {
282
- let rootRect;
283
- if (this.root) rootRect = getBoundingClientRect(this.root);
284
- else {
285
- const html = document.documentElement;
286
- const body = document.body;
287
- rootRect = {
288
- top: 0,
289
- left: 0,
290
- right: html.clientWidth || body.clientWidth,
291
- width: html.clientWidth || body.clientWidth,
292
- bottom: html.clientHeight || body.clientHeight,
293
- height: html.clientHeight || body.clientHeight
294
- };
295
- }
296
- return this._expandRectByRootMargin(rootRect);
297
- };
298
- /**
299
- * Accepts a rect and expands it by the rootMargin value.
300
- * @param {Object} rect The rect object to expand.
301
- * @return {Object} The expanded rect.
302
- * @private
303
- */
304
- IntersectionObserver.prototype._expandRectByRootMargin = function(rect) {
305
- const margins = this._rootMarginValues.map(function(margin, i) {
306
- return margin.unit === "px" ? margin.value : margin.value * (i % 2 ? rect.width : rect.height) / 100;
307
- });
308
- const newRect = {
309
- top: rect.top - margins[0],
310
- right: rect.right + margins[1],
311
- bottom: rect.bottom + margins[2],
312
- left: rect.left - margins[3]
313
- };
314
- newRect.width = newRect.right - newRect.left;
315
- newRect.height = newRect.bottom - newRect.top;
316
- return newRect;
317
- };
318
- /**
319
- * Accepts an old and new entry and returns true if at least one of the
320
- * threshold values has been crossed.
321
- * @param {?IntersectionObserverEntry} oldEntry The previous entry for a
322
- * particular target element or null if no previous entry exists.
323
- * @param {IntersectionObserverEntry} newEntry The current entry for a
324
- * particular target element.
325
- * @return {boolean} Returns true if a any threshold has been crossed.
326
- * @private
327
- */
328
- IntersectionObserver.prototype._hasCrossedThreshold = function(oldEntry, newEntry) {
329
- const oldRatio = oldEntry && oldEntry.isIntersecting ? oldEntry.intersectionRatio || 0 : -1;
330
- const newRatio = newEntry.isIntersecting ? newEntry.intersectionRatio || 0 : -1;
331
- if (oldRatio === newRatio) return;
332
- for (let i = 0; i < this.thresholds.length; i++) {
333
- const threshold = this.thresholds[i];
334
- if (threshold == oldRatio || threshold == newRatio || threshold < oldRatio !== threshold < newRatio) return true;
335
- }
336
- };
337
- /**
338
- * Returns whether or not the root element is an element and is in the DOM.
339
- * @return {boolean} True if the root element is an element and is in the DOM.
340
- * @private
341
- */
342
- IntersectionObserver.prototype._rootIsInDom = function() {
343
- return !this.root || containsDeep(document, this.root);
344
- };
345
- /**
346
- * Returns whether or not the target element is a child of root.
347
- * @param {Element} target The target element to check.
348
- * @return {boolean} True if the target element is a child of root.
349
- * @private
350
- */
351
- IntersectionObserver.prototype._rootContainsTarget = function(target) {
352
- return containsDeep(this.root || document, target);
353
- };
354
- /**
355
- * Adds the instance to the global IntersectionObserver registry if it isn't
356
- * already present.
357
- * @private
358
- */
359
- IntersectionObserver.prototype._registerInstance = function() {
360
- if (registry.indexOf(this) < 0) registry.push(this);
361
- };
362
- /**
363
- * Removes the instance from the global IntersectionObserver registry.
364
- * @private
365
- */
366
- IntersectionObserver.prototype._unregisterInstance = function() {
367
- const index = registry.indexOf(this);
368
- if (index != -1) registry.splice(index, 1);
369
- };
370
- /**
371
- * Returns the result of the performance.now() method or null in browsers
372
- * that don't support the API.
373
- * @return {number} The elapsed time since the page was requested.
374
- */
375
- function now() {
376
- return window.performance && performance.now && performance.now();
377
- }
378
- /**
379
- * Adds an event handler to a DOM node ensuring cross-browser compatibility.
380
- * @param {Node} node The DOM node to add the event handler to.
381
- * @param {string} event The event name.
382
- * @param {Function} fn The event handler to add.
383
- * @param {boolean} opt_useCapture Optionally adds the even to the capture
384
- * phase. Note: this only works in modern browsers.
385
- */
386
- function addEvent(node, event, fn, opt_useCapture) {
387
- if (isFunction(node.addEventListener)) node.addEventListener(event, fn, opt_useCapture || false);
388
- else if (isFunction(node.attachEvent)) node.attachEvent("on" + event, fn);
389
- }
390
- /**
391
- * Removes a previously added event handler from a DOM node.
392
- * @param {Node} node The DOM node to remove the event handler from.
393
- * @param {string} event The event name.
394
- * @param {Function} fn The event handler to remove.
395
- * @param {boolean} opt_useCapture If the event handler was added with this
396
- * flag set to true, it should be set to true here in order to remove it.
397
- */
398
- function removeEvent(node, event, fn, opt_useCapture) {
399
- if (isFunction(node.removeEventListener)) node.removeEventListener(event, fn, opt_useCapture || false);
400
- else if (isFunction(node.detatchEvent)) node.detatchEvent("on" + event, fn);
401
- }
402
- /**
403
- * Returns the intersection between two rect objects.
404
- * @param {Object} rect1 The first rect.
405
- * @param {Object} rect2 The second rect.
406
- * @return {?Object} The intersection rect or undefined if no intersection
407
- * is found.
408
- */
409
- function computeRectIntersection(rect1, rect2) {
410
- const top = Math.max(rect1.top, rect2.top);
411
- const bottom = Math.min(rect1.bottom, rect2.bottom);
412
- const left = Math.max(rect1.left, rect2.left);
413
- const right = Math.min(rect1.right, rect2.right);
414
- const width = right - left;
415
- const height = bottom - top;
416
- return width >= 0 && height >= 0 && {
417
- top,
418
- bottom,
419
- left,
420
- right,
421
- width,
422
- height
423
- };
424
- }
425
- /**
426
- * Shims the native getBoundingClientRect for compatibility with older IE.
427
- * @param {Element} el The element whose bounding rect to get.
428
- * @return {Object} The (possibly shimmed) rect of the element.
429
- */
430
- function getBoundingClientRect(el) {
431
- let rect;
432
- try {
433
- rect = el.getBoundingClientRect();
434
- } catch (err) {}
435
- if (!rect) return getEmptyRect();
436
- if (!(rect.width && rect.height)) rect = {
437
- top: rect.top,
438
- right: rect.right,
439
- bottom: rect.bottom,
440
- left: rect.left,
441
- width: rect.right - rect.left,
442
- height: rect.bottom - rect.top
443
- };
444
- return rect;
445
- }
446
- /**
447
- * Returns an empty rect object. An empty rect is returned when an element
448
- * is not in the DOM.
449
- * @return {Object} The empty rect.
450
- */
451
- function getEmptyRect() {
452
- return {
453
- top: 0,
454
- bottom: 0,
455
- left: 0,
456
- right: 0,
457
- width: 0,
458
- height: 0
459
- };
460
- }
461
- /**
462
- * Checks to see if a parent element contains a child element (including inside
463
- * shadow DOM).
464
- * @param {Node} parent The parent element.
465
- * @param {Node} child The child element.
466
- * @return {boolean} True if the parent node contains the child node.
467
- */
468
- function containsDeep(parent, child) {
469
- let node = child;
470
- while (node) {
471
- if (node == parent) return true;
472
- node = getParentNode(node);
473
- }
474
- return false;
475
- }
476
- /**
477
- * Gets the parent node of an element or its host element if the parent node
478
- * is a shadow root.
479
- * @param {Node} node The node whose parent to get.
480
- * @return {Node|null} The parent node or null if no parent exists.
481
- */
482
- function getParentNode(node) {
483
- const parent = node.parentNode;
484
- if (parent && parent.nodeType == 11 && parent.host) return parent.host;
485
- if (parent && parent.assignedSlot) return parent.assignedSlot.parentNode;
486
- return parent;
487
- }
488
- window.IntersectionObserver = IntersectionObserver;
489
- window.IntersectionObserverEntry = IntersectionObserverEntry;
490
- }
491
- //#endregion
492
- export { handleIntersectionObserverPolyfill };
493
-
494
- //# sourceMappingURL=intersection-observer.js.map