enigmatic 0.31.0 → 0.33.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enigmatic",
3
- "version": "0.31.0",
3
+ "version": "0.33.0",
4
4
  "unpkg": "./public/client.js",
5
5
  "scripts": {
6
6
  "start": "bun --hot ./bun-server.js",
package/public/client.js CHANGED
@@ -1,137 +1,80 @@
1
- window.api_url = "https://localhost:3000"
2
- window.$ = document.querySelector.bind(document)
3
- window.$$ = document.querySelectorAll.bind(document)
4
- window.$c = (selector) => $0.closest(selector);
1
+ const D = document, W = window, Enc = encodeURIComponent;
5
2
 
6
- // Initialize custom elements
7
- window.initCustomElements = function() {
8
- Object.keys(window.custom || {}).forEach(tagName => {
9
- $$(tagName).forEach(async el => {
10
- const f = window.custom[tagName];
11
- if (typeof f === 'function') {
12
- el.innerHTML = await f();
13
- } else if (f && typeof f.render === 'function') {
14
- el.innerHTML = f.render();
15
- }
16
- });
17
- });
18
- }
3
+ // 1. Unified Render Logic (Handles both State & Custom Elements)
4
+ const ren = async (el, v) => {
5
+ const f = W.custom?.[el.tagName.toLowerCase()];
6
+ if (f) {
7
+ const dataAttr = el.getAttribute('data');
8
+ const val = v !== undefined ? v : (dataAttr ? W.state[dataAttr] : undefined);
9
+ try { el.innerHTML = await (f.render || f)(val) } catch(e) { console.error(e) }
10
+ }
11
+ };
19
12
 
20
- // Make window.custom a Proxy that auto-initializes when properties are added
21
- if (!window.custom) window.custom = {};
22
- const customProxy = new Proxy(window.custom, {
23
- set(target, prop, value) {
24
- target[prop] = value;
25
- if (typeof value === 'function' || (value && typeof value.render === 'function')) {
26
- setTimeout(() => {
27
- $$(prop).forEach(async el => {
28
- try {
29
- if (typeof value === 'function') {
30
- el.innerHTML = await value();
31
- } else if (value && typeof value.render === 'function') {
32
- el.innerHTML = value.render();
33
- }
34
- } catch (e) {
35
- console.error('Custom element error:', e);
36
- }
37
- });
38
- }, 0);
39
- }
13
+ // 2. Proxies setup
14
+ const cProx = new Proxy({}, {
15
+ set(t, p, v) {
16
+ t[p] = v;
17
+ setTimeout(() => W.$$(p).forEach(el => ren(el)), 0);
40
18
  return true;
41
19
  }
42
20
  });
43
- Object.defineProperty(window, 'custom', {
44
- get: () => customProxy,
45
- set: (val) => {
46
- Object.keys(val || {}).forEach(key => customProxy[key] = val[key]);
47
- window.initCustomElements();
48
- },
49
- configurable: true
50
- });
21
+ Object.defineProperty(W, 'custom', { get: () => cProx, set: v => Object.assign(cProx, v) });
51
22
 
52
- window.state = new Proxy({}, {
53
- set(obj, prop, value) {
54
- obj[prop] = value
55
- $$(`[data="${prop}"]`).forEach(el => {
56
- console.log('setting', el.tagName);
57
- const f = window.custom?.[el.tagName.toLowerCase()];
58
- if (!f) return;
59
- if(typeof f === 'function') {
60
- el.innerHTML = f(value);
61
- } else if (f && typeof f.render === 'function') {
62
- el.innerHTML = f.render(value);
63
- }
64
- });
65
- return true
23
+ const sProx = new Proxy({}, {
24
+ set(o, p, v) {
25
+ o[p] = v;
26
+ W.$$(`[data="${p}"]`).forEach(el => ren(el, v));
27
+ return true;
66
28
  }
67
- })
68
- window.get = async function(key) {
69
- const res = await fetch(`${window.api_url}/${encodeURIComponent(key)}`)
70
- return await res.json()
71
- }
72
- window.set = async function(key, value) {
73
- const res = await fetch(`${window.api_url}/${encodeURIComponent(key)}`, {
74
- method: 'POST', body: typeof value === 'string' ? value : JSON.stringify(value)
75
- })
76
- return await res.json()
77
- }
78
- window.delete = async function(key) {
79
- const res = await fetch(`${window.api_url}/${encodeURIComponent(key)}`, {
80
- method: 'DELETE'
81
- })
82
- return await res.json()
83
- }
84
- window.put = async function(key, body) {
85
- const res = await fetch(`${window.api_url}/${encodeURIComponent(key)}`, {
86
- method: 'PUT', body: body instanceof Blob ? body : typeof body === 'string' ? body : JSON.stringify(body)
87
- })
88
- return await res.json()
89
- }
90
- window.purge = async function(key) {
91
- const res = await fetch(`${window.api_url}/${encodeURIComponent(key)}`, {
92
- method: 'PURGE'
93
- })
94
- return await res.json()
95
- }
96
- window.list = async function() {
97
- const res = await fetch(`${window.api_url}`, {
98
- method: 'PROPFIND'
99
- })
100
- return await res.json()
101
- }
102
- window.download = async function(key) {
103
- try {
104
- console.log('Downloading with method DOWNLOAD:', key);
105
- const res = await fetch(`${window.api_url}/${encodeURIComponent(key)}`, { method: 'PATCH' });
106
- console.log('Response:', key, res.status, res.statusText);
107
- if (!res.ok) throw new Error('Download failed');
108
- const blob = await res.blob();
109
- const url = URL.createObjectURL(blob);
110
- const a = document.createElement('a');
111
- a.href = url;
112
- a.download = key;
29
+ });
30
+
31
+ // 3. API & DOM Helpers
32
+ const req = (m, k, b) => fetch(`${W.api_url}/${k ? Enc(k) : ''}`, {
33
+ method: m, body: b instanceof Blob || typeof b === 'string' ? b : JSON.stringify(b)
34
+ });
35
+
36
+ Object.assign(W, {
37
+ $: s => D.querySelector(s),
38
+ $$: s => D.querySelectorAll(s),
39
+ $c: s => $0.closest(s),
40
+ state: sProx,
41
+ get: k => req('GET', k).then(r => r.json()),
42
+ set: (k, v) => req('POST', k, v).then(r => r.json()),
43
+ put: (k, v) => req('PUT', k, v).then(r => r.json()),
44
+ delete: k => req('DELETE', k).then(r => r.json()),
45
+ purge: k => req('PURGE', k).then(r => r.json()),
46
+ list: () => req('PROPFIND').then(r => r.json()),
47
+ login: () => W.location.href = `${W.api_url}/login`,
48
+ logout: () => W.location.href = `${W.api_url}/logout`,
49
+ download: async (k) => {
50
+ const r = await req('PATCH', k);
51
+ if (!r.ok) throw new Error('Download failed');
52
+ const a = D.createElement('a');
53
+ a.href = URL.createObjectURL(await r.blob());
54
+ a.download = k;
113
55
  a.click();
114
- URL.revokeObjectURL(url);
115
- } catch (err) {
116
- console.error('Download error:', err);
117
- throw err;
118
- }
119
- }
120
- window.login = function() {
121
- window.location.href = `${window.api_url}/login`
122
- }
123
- window.logout = function() {
124
- window.location.href = `${window.api_url}/logout`
125
- }
56
+ URL.revokeObjectURL(a.href);
57
+ },
58
+ initCustomElements: () => Object.keys(W.custom || {}).forEach(t => W.$$(t).forEach(el => ren(el)))
59
+ });
126
60
 
127
- // Auto-initialize on load and watch for new elements
128
- if (document.readyState === 'loading') {
129
- document.addEventListener('DOMContentLoaded', () => {
130
- window.initCustomElements();
131
- // Watch for new custom elements added to DOM
132
- new MutationObserver(() => window.initCustomElements()).observe(document.body, { childList: true, subtree: true });
133
- });
134
- } else {
135
- window.initCustomElements();
136
- new MutationObserver(() => window.initCustomElements()).observe(document.body, { childList: true, subtree: true });
137
- }
61
+ // 4. Initialization & Observers
62
+ const boot = () => {
63
+ W.initCustomElements();
64
+ new MutationObserver((mutations) => {
65
+ mutations.forEach(m => {
66
+ m.addedNodes.forEach(node => {
67
+ if (node.nodeType === 1) { // Element node
68
+ const tag = node.tagName?.toLowerCase();
69
+ if (tag && W.custom?.[tag]) ren(node);
70
+ // Also check children
71
+ node.querySelectorAll && Array.from(node.querySelectorAll('*')).forEach(child => {
72
+ const childTag = child.tagName?.toLowerCase();
73
+ if (childTag && W.custom?.[childTag]) ren(child);
74
+ });
75
+ }
76
+ });
77
+ });
78
+ }).observe(D.body, { childList: true, subtree: true });
79
+ };
80
+ D.readyState === 'loading' ? D.addEventListener('DOMContentLoaded', boot) : boot();
@@ -1,3 +1,9 @@
1
- <script src='https://unpkg.com/enigmatic@0.30.0/public/client.js'></script>
1
+ <script src='client.js'></script>
2
2
 
3
- <hello-world></hello-world>
3
+ <script>
4
+ window.api_url = 'http://localhost:3000';
5
+ custom.hw = (data) => `Hello ${data}`;
6
+ state.message = "World";
7
+ </script>
8
+
9
+ <hw data="message"></hw>