@symbo.ls/element 3.14.0
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.
- package/index.js +1 -0
- package/package.json +21 -0
- package/src/cache.js +124 -0
- package/src/create.js +1705 -0
- package/src/delegate.js +163 -0
- package/src/dispose.js +76 -0
- package/src/extends.js +105 -0
- package/src/index.js +8 -0
- package/src/methods.js +257 -0
- package/src/registry.js +79 -0
- package/src/update.js +124 -0
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/index.js'
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@symbo.ls/element",
|
|
3
|
+
"version": "3.14.0",
|
|
4
|
+
"description": "Core element creation, update, and disposal engine for smbls v4",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.js",
|
|
7
|
+
"module": "./index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.js",
|
|
10
|
+
"./src/*": "./src/*"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@symbo.ls/signal": "^3.14.0",
|
|
14
|
+
"@symbo.ls/state": "^3.14.0",
|
|
15
|
+
"@symbo.ls/utils": "^3.14.0",
|
|
16
|
+
"css-in-props": "^3.14.0",
|
|
17
|
+
"attrs-in-props": "^3.14.0"
|
|
18
|
+
},
|
|
19
|
+
"files": ["src", "index.js"],
|
|
20
|
+
"license": "CC-BY-NC-4.0"
|
|
21
|
+
}
|
package/src/cache.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Node caching - cloneNode from cached prototypes instead of createElement
|
|
4
|
+
// This is already a v3 optimization that works well -- preserved in v4
|
|
5
|
+
|
|
6
|
+
const SVG_NS = 'http://www.w3.org/2000/svg'
|
|
7
|
+
|
|
8
|
+
const SVG_TAGS = new Set([
|
|
9
|
+
'svg', 'path', 'circle', 'ellipse', 'line', 'polyline', 'polygon',
|
|
10
|
+
'rect', 'g', 'defs', 'use', 'symbol', 'clipPath', 'mask',
|
|
11
|
+
'pattern', 'image', 'text', 'tspan', 'textPath',
|
|
12
|
+
'marker', 'linearGradient', 'radialGradient', 'stop',
|
|
13
|
+
'filter', 'feBlend', 'feColorMatrix', 'feComponentTransfer',
|
|
14
|
+
'feComposite', 'feConvolveMatrix', 'feDiffuseLighting',
|
|
15
|
+
'feDisplacementMap', 'feFlood', 'feGaussianBlur', 'feImage',
|
|
16
|
+
'feMerge', 'feMergeNode', 'feMorphology', 'feOffset',
|
|
17
|
+
'feSpecularLighting', 'feTile', 'feTurbulence',
|
|
18
|
+
'animate', 'animateMotion', 'animateTransform', 'set',
|
|
19
|
+
'foreignObject', 'desc', 'title', 'metadata'
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
const VALID_HTML_TAGS = new Set([
|
|
23
|
+
'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio',
|
|
24
|
+
'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button',
|
|
25
|
+
'canvas', 'caption', 'cite', 'code', 'col', 'colgroup',
|
|
26
|
+
'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt',
|
|
27
|
+
'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form',
|
|
28
|
+
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr',
|
|
29
|
+
'i', 'iframe', 'img', 'input', 'ins', 'kbd',
|
|
30
|
+
'label', 'legend', 'li', 'link',
|
|
31
|
+
'main', 'map', 'mark', 'menu', 'meta', 'meter',
|
|
32
|
+
'nav', 'noscript',
|
|
33
|
+
'object', 'ol', 'optgroup', 'option', 'output',
|
|
34
|
+
'p', 'param', 'picture', 'pre', 'progress',
|
|
35
|
+
'q', 'rp', 'rt', 'ruby',
|
|
36
|
+
's', 'samp', 'script', 'search', 'section', 'select', 'slot', 'small',
|
|
37
|
+
'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup',
|
|
38
|
+
'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead',
|
|
39
|
+
'time', 'title', 'tr', 'track',
|
|
40
|
+
'u', 'ul', 'var', 'video', 'wbr',
|
|
41
|
+
// special
|
|
42
|
+
'string', 'fragment', 'shadow'
|
|
43
|
+
])
|
|
44
|
+
|
|
45
|
+
export function isValidTag(tag) {
|
|
46
|
+
return VALID_HTML_TAGS.has(tag) || SVG_TAGS.has(tag)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function isSvgTag(tag) {
|
|
50
|
+
return SVG_TAGS.has(tag)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function detectTag(element) {
|
|
54
|
+
let { tag, key } = element
|
|
55
|
+
|
|
56
|
+
if (typeof tag === 'function') tag = tag(element)
|
|
57
|
+
if (tag === true) tag = key
|
|
58
|
+
|
|
59
|
+
if (typeof tag === 'string' && isValidTag(tag)) return tag
|
|
60
|
+
if (!key || typeof key !== 'string') return 'div'
|
|
61
|
+
|
|
62
|
+
// Tags that should never be auto-detected from key names
|
|
63
|
+
const STRUCTURAL_TAGS = new Set([
|
|
64
|
+
'html', 'head', 'body', 'meta', 'link', 'script', 'style',
|
|
65
|
+
'title', 'base', 'noscript', 'template'
|
|
66
|
+
])
|
|
67
|
+
|
|
68
|
+
// Try key as tag
|
|
69
|
+
let keyAsTag = key.toLowerCase()
|
|
70
|
+
if (keyAsTag.includes('.')) keyAsTag = keyAsTag.split('.')[0]
|
|
71
|
+
if (keyAsTag.includes('_')) keyAsTag = keyAsTag.split('_')[0]
|
|
72
|
+
if (isValidTag(keyAsTag) && !STRUCTURAL_TAGS.has(keyAsTag)) return keyAsTag
|
|
73
|
+
|
|
74
|
+
return 'div'
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const nodeCaches = {}
|
|
78
|
+
|
|
79
|
+
export function createHTMLNode(tag, element) {
|
|
80
|
+
const doc = element?.context?.document || globalThis.document
|
|
81
|
+
if (!doc) return null
|
|
82
|
+
|
|
83
|
+
if (tag === 'string') return doc.createTextNode(element?.text || '')
|
|
84
|
+
if (tag === 'fragment') return doc.createDocumentFragment()
|
|
85
|
+
|
|
86
|
+
if (isSvgTag(tag)) {
|
|
87
|
+
const parent = element?.parent
|
|
88
|
+
const inSvgContext = tag === 'svg' || parent?.node?.namespaceURI === SVG_NS
|
|
89
|
+
if (inSvgContext) {
|
|
90
|
+
return doc.createElementNS(SVG_NS, tag)
|
|
91
|
+
}
|
|
92
|
+
// SVG child tags outside <svg> context — fall back to div
|
|
93
|
+
if (tag !== 'svg') return doc.createElement('div')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return doc.createElement(tag)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function cacheNode(element) {
|
|
100
|
+
const tag = element.tag = detectTag(element)
|
|
101
|
+
|
|
102
|
+
const isSvgContext = isSvgTag(tag) &&
|
|
103
|
+
(tag === 'svg' || element.parent?.node?.namespaceURI === SVG_NS)
|
|
104
|
+
const cacheKey = isSvgContext ? 'svg:' + tag : tag
|
|
105
|
+
|
|
106
|
+
const targetDoc = element?.context?.document || globalThis.document
|
|
107
|
+
|
|
108
|
+
let cached = nodeCaches[cacheKey]
|
|
109
|
+
if (!cached) {
|
|
110
|
+
cached = nodeCaches[cacheKey] = createHTMLNode(tag, element)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!cached) return null
|
|
114
|
+
|
|
115
|
+
// If target document differs from cached node's document (e.g. iframe),
|
|
116
|
+
// create a fresh node instead of cloning to ensure correct ownerDocument
|
|
117
|
+
const cloned = (targetDoc && cached.ownerDocument !== targetDoc)
|
|
118
|
+
? createHTMLNode(tag, element)
|
|
119
|
+
: cached.cloneNode(true)
|
|
120
|
+
if (tag === 'string') cloned.nodeValue = element.text || ''
|
|
121
|
+
return cloned
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export { SVG_TAGS, SVG_NS }
|