ajo 0.0.10 → 0.0.11

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 (2) hide show
  1. package/index.js +198 -0
  2. package/package.json +2 -1
package/index.js ADDED
@@ -0,0 +1,198 @@
1
+ export const
2
+ Fragment = ({ children }) => children,
3
+
4
+ h = (nodeName, props, ...children) => {
5
+ children = children.length == 0 ? null : children.length == 1 ? children[0] : children
6
+ return { children, ...props, nodeName }
7
+ },
8
+
9
+ component = setup => ({ is, key, host, ref, ...props }) => h(is ?? setup.is ?? 'div', {
10
+ key, ...setup.host, ...host, skip: true, ref: host => (refresh(host, props, setup), isFn(ref) && ref(host))
11
+ }),
12
+
13
+ render = (h, host) => {
14
+
15
+ let child = host.firstChild, node, byKey = keyed.get(host)
16
+
17
+ for (h of normalize(h, host)) {
18
+
19
+ if (typeof h == 'string') {
20
+
21
+ for (node = child; node; node = node.nextSibling) if (node.nodeType == 3) break
22
+ node ? node.data !== h && (node.data = h) : node = document.createTextNode(h)
23
+
24
+ } else if (h instanceof Node) {
25
+
26
+ node = h
27
+
28
+ } else {
29
+
30
+ const { key, nodeName, skip, block, children, ref, ...props } = h
31
+
32
+ if (key != null && (node = byKey?.get(key)));
33
+ else for (node = child; node; node = node.nextSibling) if (node.localName == nodeName) break
34
+
35
+ node ||= document.createElement(nodeName)
36
+
37
+ key != null && (byKey ||= keyed.set(host, new Map)).set(key, node)
38
+
39
+ update(props, node)
40
+
41
+ !(skip || block != null && every(deps.get(node), deps.set(node, block))) && render(children, node)
42
+
43
+ isFn(ref) && ref(node)
44
+ }
45
+
46
+ node === child ? child = child.nextSibling : before(host, child, node)
47
+ }
48
+
49
+ while (child) {
50
+ const next = child.nextSibling
51
+ host.removeChild(child).nodeType == 1 && dispose(child)
52
+ child = next
53
+ }
54
+ },
55
+
56
+ refresh = (host, props, setup) => {
57
+ try {
58
+ if (setup && !isFn(setup)) throwTypeError('Setup', setup, fn)
59
+ props = props ? memo.set(host, { ...setup?.props, ...props }) : memo.get(host) ?? {}
60
+ render((renders.get(host) ?? renders.set(host, setup(props, host)))(props, host), host)
61
+ } catch (error) {
62
+ propagate(host, error)
63
+ }
64
+ },
65
+
66
+ provide = (host, key, value) => (provisions.get(host) ?? provisions.set(host, new Map)).set(key, value),
67
+
68
+ consume = (host, key, fallback) => {
69
+ let map
70
+ while (host) {
71
+ if ((map = provisions.get(host)) && map.has(key)) return map.get(key)
72
+ host = host.parentNode
73
+ }
74
+ return fallback
75
+ },
76
+
77
+ intercept = (host, interceptor) => {
78
+ if (!isFn(interceptor)) throwTypeError('Interceptor', interceptor, fn)
79
+ interceptors.set(host, interceptor)
80
+ },
81
+
82
+ propagate = (host, error) => {
83
+ for (let interceptor; host; host = host.parentNode)
84
+ if (interceptor = interceptors.get(host)) return render(host, interceptor(error))
85
+ throw error
86
+ },
87
+
88
+ cleanup = (host, cleaner) => {
89
+ if (!isFn(cleaner)) throwTypeError('Cleaner', cleaner, fn);
90
+ (cleaners.get(host) ?? cleaners.set(host, new Set)).add(cleaner)
91
+ },
92
+
93
+ clx = o => keys(o).filter(k => o[k]).join(' ') || null,
94
+ stx = o => entries(o).map(t => t.join(':')).join(';') || null,
95
+ keb = o => keys(o).reduce((r, k) => ((r[k.replace(search, replace).toLowerCase()] = o[k]), r), {})
96
+
97
+ const
98
+ wm = () => {
99
+ const instance = new WeakMap, { set } = instance
100
+ instance.set = (key, value) => (set.call(instance, key, value), value)
101
+ return instance
102
+ },
103
+
104
+ throwTypeError = (name, value, expected) => {
105
+ throw new TypeError(`Expected ${name} to be of type ${expected}, got ${typeof value} instead`)
106
+ },
107
+
108
+ every = (a, b) => a === b || isArray(a) && isArray(b) && a.length == b.length && a.every((v, i) => v === b[i]),
109
+ apply = (o, { name, value }) => ((o[name] = value), o),
110
+ reduce = list => from(list).reduce(apply, {}),
111
+ isFn = v => typeof v == fn,
112
+
113
+ { keys, entries } = Object, { isArray, from } = Array,
114
+
115
+ fn = 'function', search = /([a-z0-9])([A-Z])/g, replace = '$1-$2',
116
+
117
+ keyed = wm(), deps = wm(), memo = wm(), renders = wm(), provisions = wm(), interceptors = wm(), cleaners = wm(), cache = wm(),
118
+
119
+ normalize = function* (h, host) {
120
+
121
+ let type, buffer = ''
122
+
123
+ for (h of isFn(h?.[Symbol.iterator]) ? h : [h]) {
124
+
125
+ if (h == null || (type = typeof h) == 'boolean') continue
126
+
127
+ if (type == 'string' || type == 'number') {
128
+ buffer += h
129
+ continue
130
+ }
131
+
132
+ if ('nodeName' in Object(h)) {
133
+
134
+ if (isFn(h.nodeName)) {
135
+ yield* normalize(h.nodeName(h, host), host)
136
+ continue
137
+ }
138
+
139
+ if (buffer) {
140
+ yield buffer
141
+ buffer = ''
142
+ }
143
+
144
+ yield h
145
+ continue
146
+ }
147
+
148
+ isFn(h[Symbol.iterator]) ? yield* normalize(h, host) : buffer += h
149
+ }
150
+
151
+ if (buffer) yield buffer
152
+ },
153
+
154
+ update = (props, host) => {
155
+
156
+ const prev = cache.get(host) ?? (host.hasAttributes() ? reduce(host.attributes) : {})
157
+
158
+ for (const name in { ...prev, ...props }) {
159
+
160
+ let value = props[name]
161
+
162
+ if (value === prev[name]) continue
163
+
164
+ if (name.startsWith('set:')) {
165
+ host[name.slice(4)] = value
166
+ continue
167
+ }
168
+
169
+ if (value === true) value = ''
170
+ else if (value == null || value === false) {
171
+ host.removeAttribute(name)
172
+ continue
173
+ }
174
+
175
+ host.setAttribute(name, value)
176
+ }
177
+
178
+ cache.set(host, props)
179
+ },
180
+
181
+ before = (host, child, node) => {
182
+ if (node.contains?.(document.activeElement)) {
183
+
184
+ const ref = node.nextSibling
185
+
186
+ while (child && child !== node) {
187
+ const next = child.nextSibling
188
+ host.insertBefore(child, ref)
189
+ child = next
190
+ }
191
+
192
+ } else host.insertBefore(node, child)
193
+ },
194
+
195
+ dispose = host => {
196
+ for (const child of host.children) dispose(child)
197
+ for (const cleaner of cleaners.get(host) ?? []) cleaner(host)
198
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ajo",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "description": "ajo is a JavaScript view library for building user interfaces",
5
5
  "type": "module",
6
6
  "module": "index.js",
@@ -13,6 +13,7 @@
13
13
  }
14
14
  },
15
15
  "files": [
16
+ "index.js",
16
17
  "index.min.js"
17
18
  ],
18
19
  "scripts": {