@taybart/corvid 0.1.17 → 0.1.18

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/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # Corvid
2
2
 
3
- fear the crow
3
+ <p align="center"><img src="https://github.com/user-attachments/assets/b3bbf267-d7b0-4116-80a5-b932b409a111" width="100" height="100"></p>
4
4
 
5
- ![crowtein](https://github.com/user-attachments/assets/b3bbf267-d7b0-4116-80a5-b932b409a111)
5
+ <p align="center">fear the crow</p>
6
+
7
+
8
+ <!-- ![crowtein](https://github.com/user-attachments/assets/b3bbf267-d7b0-4116-80a5-b932b409a111) -->
6
9
 
7
10
  ## Usage
8
11
 
@@ -83,7 +86,7 @@ import { network } '@taybart/corvid'
83
86
  const api = network.create({
84
87
  url: 'https://api.example.com',
85
88
  credentials: 'include',
86
- success: 250, // odd success code
89
+ success: 250, // check for non-200 success code
87
90
  // corvid params, string, or custom object that has .toString() and renders url safe params
88
91
  params: new network.params({hello: 'corvid'})
89
92
  })
@@ -115,15 +118,27 @@ style.onDarkMode((isDark) => {
115
118
  // get css variables
116
119
  console.log(`is dark mode: ${isDark} and background is ${style.cssVar('--color-bg')`)
117
120
  })
121
+
122
+ ```
123
+
124
+ Just handle switching automatically
125
+
126
+ ```html
127
+ <script type='module'>
128
+ import { handleThemeSwitch } from '@taybart/corvid/style'
129
+ handleThemeSwitch()
130
+ </script>
118
131
  ```
119
132
 
120
133
  ### QR
121
134
 
122
135
  ```js
136
+ import { dom } from '@taybart/corvid'
123
137
  import { QR } '@taybart/corvid/qr'
124
138
 
139
+ const el = new dom.el('#qr')
125
140
  QR.render({
126
141
  text: 'https://example.com',
127
142
  size: 200,
128
- }, document.getElementById('qr'))
143
+ }, el) // can also be regular element query -> document.getElementById('qr')
129
144
  ```
package/dist/dom.d.ts CHANGED
@@ -25,6 +25,7 @@ type elOpts = {
25
25
  style?: Object;
26
26
  id?: string;
27
27
  parent?: HTMLElement | el;
28
+ attrs?: Object;
28
29
  };
29
30
  export declare class el {
30
31
  el: HTMLElement | null;
package/dist/dom.js CHANGED
@@ -233,7 +233,7 @@ class dom_el {
233
233
  this.el = opts;
234
234
  return;
235
235
  }
236
- const { query, element, type, class: styleClass, style, id, content, parent } = opts;
236
+ const { query, element, type, class: styleClass, style, id, content, parent, attrs } = opts;
237
237
  if (query) {
238
238
  this.log.debug(`using query: ${query}`);
239
239
  this.query = query;
@@ -264,6 +264,10 @@ class dom_el {
264
264
  parent.appendChild(this.el);
265
265
  }
266
266
  }
267
+ if (attrs) for (const [key, val] of Object.entries(attrs)){
268
+ this.log.debug(`setting prop: ${key} to ${val}`);
269
+ this.el.setAttribute(key, val);
270
+ }
267
271
  }
268
272
  }
269
273
  function interpolate(str, params) {
package/dist/index.js CHANGED
@@ -62,9 +62,11 @@ __webpack_require__.r(local_storage_namespaceObject);
62
62
  __webpack_require__.d(local_storage_namespaceObject, {
63
63
  clear: ()=>clear,
64
64
  get: ()=>get,
65
+ getJSON: ()=>getJSON,
65
66
  listen: ()=>listen,
66
67
  set: ()=>set,
67
68
  setObj: ()=>setObj,
69
+ unlisten: ()=>unlisten,
68
70
  update: ()=>local_storage_update
69
71
  });
70
72
  function bytesToHuman(bytes, options = {}) {
@@ -411,7 +413,7 @@ class dom_el {
411
413
  this.el = opts;
412
414
  return;
413
415
  }
414
- const { query, element, type, class: styleClass, style, id, content, parent } = opts;
416
+ const { query, element, type, class: styleClass, style, id, content, parent, attrs } = opts;
415
417
  if (query) {
416
418
  this.log.debug(`using query: ${query}`);
417
419
  this.query = query;
@@ -442,6 +444,10 @@ class dom_el {
442
444
  parent.appendChild(this.el);
443
445
  }
444
446
  }
447
+ if (attrs) for (const [key, val] of Object.entries(attrs)){
448
+ this.log.debug(`setting prop: ${key} to ${val}`);
449
+ this.el.setAttribute(key, val);
450
+ }
445
451
  }
446
452
  }
447
453
  function interpolate(str, params) {
@@ -544,7 +550,10 @@ class request {
544
550
  const expect = override.expect || this.opts.expect;
545
551
  if (res.status !== expect) {
546
552
  const body = await res.text();
547
- throw new Error(`bad response ${res.status} !== ${expect}, body: ${body}`);
553
+ if (401 === res.status && this.opts.onUnauthorized) {
554
+ this.log.warn("unauthorized");
555
+ this.opts.onUnauthorized(body);
556
+ } else throw new Error(`bad response ${res.status} !== ${expect}, body: ${body}`);
548
557
  }
549
558
  this.log.debug(`content type: ${res.headers.get('content-type')}`);
550
559
  if ('application/json' === res.headers.get('content-type')) return await res.json();
@@ -565,6 +574,7 @@ class request {
565
574
  this.log.debug("converting object params to class");
566
575
  this.opts.params = new network_params(this.opts.params);
567
576
  }
577
+ if (!this.opts.fetch) this.opts.fetch = window.fetch;
568
578
  this.log.debug(`with options: ${JSON.stringify(this.opts)}`);
569
579
  }
570
580
  }
@@ -683,6 +693,11 @@ function get(key, _default) {
683
693
  }
684
694
  return ret;
685
695
  }
696
+ function getJSON(key, _default) {
697
+ const val = get(key, _default);
698
+ if (null === val) return null;
699
+ return JSON.parse(val);
700
+ }
686
701
  function local_storage_update(key, update1, broadcast = false) {
687
702
  const prev = get(key);
688
703
  const value = update1(prev);
@@ -708,6 +723,7 @@ function set(key, value, broadcast = false) {
708
723
  });
709
724
  document.dispatchEvent(event);
710
725
  }
726
+ if ('object' == typeof value) value = JSON.stringify(value);
711
727
  localStorage.setItem(key, value);
712
728
  }
713
729
  function setObj(update, prefix, broadcast = false) {
@@ -725,8 +741,9 @@ function setObj(update, prefix, broadcast = false) {
725
741
  set(key, v, broadcast);
726
742
  }
727
743
  }
744
+ const listeners = new Map();
728
745
  function listen(key, cb) {
729
- document.addEventListener('@corvid/ls-update', (ev)=>{
746
+ const listener = (ev)=>{
730
747
  if (ev.detail.key === key || '*' === key) {
731
748
  if (cb instanceof dom_el) {
732
749
  if (ev.detail.key === key) cb.content(ev.detail.value);
@@ -737,7 +754,19 @@ function listen(key, cb) {
737
754
  value: ev.detail.value
738
755
  });
739
756
  }
740
- });
757
+ };
758
+ if (!listeners.has(key)) listeners.set(key, new Map());
759
+ listeners.get(key).set(cb, listener);
760
+ document.addEventListener('@corvid/ls-update', listener);
761
+ }
762
+ function unlisten(key, cb) {
763
+ const keyListeners = listeners.get(key);
764
+ if (!keyListeners) return;
765
+ const listener = keyListeners.get(cb);
766
+ if (!listener) return;
767
+ document.removeEventListener('@corvid/ls-update', listener);
768
+ keyListeners.delete(cb);
769
+ if (0 === keyListeners.size) listeners.delete(key);
741
770
  }
742
771
  function clear(key) {
743
772
  localStorage.removeItem(key);
@@ -1,5 +1,6 @@
1
1
  import { el } from './dom';
2
2
  export declare function get(key: string, _default?: any): any;
3
+ export declare function getJSON(key: string, _default?: any): any;
3
4
  export declare function update(key: string, update: (current: any) => any, broadcast?: boolean): void;
4
5
  export declare function set(key: string, value: any, broadcast?: boolean): void;
5
6
  export declare function setObj(update: object, prefix?: string, broadcast?: boolean): void;
@@ -7,4 +8,8 @@ export declare function listen(key: string, cb: (update: {
7
8
  key: string;
8
9
  value: any;
9
10
  }) => void | el): void;
11
+ export declare function unlisten(key: string, cb: (update: {
12
+ key: string;
13
+ value: any;
14
+ }) => void | el): void;
10
15
  export declare function clear(key: string): void;
package/dist/ls.js CHANGED
@@ -204,7 +204,7 @@ class dom_el {
204
204
  this.el = opts;
205
205
  return;
206
206
  }
207
- const { query, element, type, class: styleClass, style, id, content, parent } = opts;
207
+ const { query, element, type, class: styleClass, style, id, content, parent, attrs } = opts;
208
208
  if (query) {
209
209
  this.log.debug(`using query: ${query}`);
210
210
  this.query = query;
@@ -235,6 +235,10 @@ class dom_el {
235
235
  parent.appendChild(this.el);
236
236
  }
237
237
  }
238
+ if (attrs) for (const [key, val] of Object.entries(attrs)){
239
+ this.log.debug(`setting prop: ${key} to ${val}`);
240
+ this.el.setAttribute(key, val);
241
+ }
238
242
  }
239
243
  }
240
244
  function interpolate(str, params) {
@@ -251,6 +255,11 @@ function get(key, _default) {
251
255
  }
252
256
  return ret;
253
257
  }
258
+ function getJSON(key, _default) {
259
+ const val = get(key, _default);
260
+ if (null === val) return null;
261
+ return JSON.parse(val);
262
+ }
254
263
  function local_storage_update(key, update1, broadcast = false) {
255
264
  const prev = get(key);
256
265
  const value = update1(prev);
@@ -276,6 +285,7 @@ function set(key, value, broadcast = false) {
276
285
  });
277
286
  document.dispatchEvent(event);
278
287
  }
288
+ if ('object' == typeof value) value = JSON.stringify(value);
279
289
  localStorage.setItem(key, value);
280
290
  }
281
291
  function setObj(update, prefix, broadcast = false) {
@@ -293,8 +303,9 @@ function setObj(update, prefix, broadcast = false) {
293
303
  set(key, v, broadcast);
294
304
  }
295
305
  }
306
+ const listeners = new Map();
296
307
  function listen(key, cb) {
297
- document.addEventListener('@corvid/ls-update', (ev)=>{
308
+ const listener = (ev)=>{
298
309
  if (ev.detail.key === key || '*' === key) {
299
310
  if (cb instanceof dom_el) {
300
311
  if (ev.detail.key === key) cb.content(ev.detail.value);
@@ -305,9 +316,21 @@ function listen(key, cb) {
305
316
  value: ev.detail.value
306
317
  });
307
318
  }
308
- });
319
+ };
320
+ if (!listeners.has(key)) listeners.set(key, new Map());
321
+ listeners.get(key).set(cb, listener);
322
+ document.addEventListener('@corvid/ls-update', listener);
323
+ }
324
+ function unlisten(key, cb) {
325
+ const keyListeners = listeners.get(key);
326
+ if (!keyListeners) return;
327
+ const listener = keyListeners.get(cb);
328
+ if (!listener) return;
329
+ document.removeEventListener('@corvid/ls-update', listener);
330
+ keyListeners.delete(cb);
331
+ if (0 === keyListeners.size) listeners.delete(key);
309
332
  }
310
333
  function clear(key) {
311
334
  localStorage.removeItem(key);
312
335
  }
313
- export { clear, get, listen, set, setObj, local_storage_update as update };
336
+ export { clear, get, getJSON, listen, set, setObj, unlisten, local_storage_update as update };
package/dist/network.d.ts CHANGED
@@ -22,6 +22,8 @@ export type requestOpts = {
22
22
  expect?: number;
23
23
  credentials?: RequestCredentials;
24
24
  insecureNoVerify?: boolean;
25
+ onUnauthorized?: (body: any) => void;
26
+ fetch?: (url: string, init: RequestInit) => Promise<any>;
25
27
  };
26
28
  export declare class request {
27
29
  opts: requestOpts;
package/dist/network.js CHANGED
@@ -141,7 +141,10 @@ class request {
141
141
  const expect = override.expect || this.opts.expect;
142
142
  if (res.status !== expect) {
143
143
  const body = await res.text();
144
- throw new Error(`bad response ${res.status} !== ${expect}, body: ${body}`);
144
+ if (401 === res.status && this.opts.onUnauthorized) {
145
+ this.log.warn("unauthorized");
146
+ this.opts.onUnauthorized(body);
147
+ } else throw new Error(`bad response ${res.status} !== ${expect}, body: ${body}`);
145
148
  }
146
149
  this.log.debug(`content type: ${res.headers.get('content-type')}`);
147
150
  if ('application/json' === res.headers.get('content-type')) return await res.json();
@@ -162,6 +165,7 @@ class request {
162
165
  this.log.debug("converting object params to class");
163
166
  this.opts.params = new network_params(this.opts.params);
164
167
  }
168
+ if (!this.opts.fetch) this.opts.fetch = window.fetch;
165
169
  this.log.debug(`with options: ${JSON.stringify(this.opts)}`);
166
170
  }
167
171
  }
package/dist/qr.js CHANGED
@@ -2110,7 +2110,7 @@ class dom_el {
2110
2110
  this.el = opts;
2111
2111
  return;
2112
2112
  }
2113
- const { query, element, type, class: styleClass, style, id, content, parent } = opts;
2113
+ const { query, element, type, class: styleClass, style, id, content, parent, attrs } = opts;
2114
2114
  if (query) {
2115
2115
  this.log.debug(`using query: ${query}`);
2116
2116
  this.query = query;
@@ -2141,6 +2141,10 @@ class dom_el {
2141
2141
  parent.appendChild(this.el);
2142
2142
  }
2143
2143
  }
2144
+ if (attrs) for (const [key, val] of Object.entries(attrs)){
2145
+ this.log.debug(`setting prop: ${key} to ${val}`);
2146
+ this.el.setAttribute(key, val);
2147
+ }
2144
2148
  }
2145
2149
  }
2146
2150
  function interpolate(str, params) {
package/dist/style.js ADDED
@@ -0,0 +1,37 @@
1
+ function toKebab(str) {
2
+ return str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, (s, ofs)=>(ofs ? '-' : '') + s.toLowerCase());
3
+ }
4
+ function cssVar(name) {
5
+ const style = window.getComputedStyle(document.body);
6
+ return style.getPropertyValue(name);
7
+ }
8
+ function render(style) {
9
+ let s = '';
10
+ Object.entries(style).forEach(([k, v])=>s += `${toKebab(k)}:${v};`);
11
+ return s;
12
+ }
13
+ function isDarkMode() {
14
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
15
+ }
16
+ function onDarkMode(cb) {
17
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (ev)=>{
18
+ cb(ev.matches);
19
+ });
20
+ }
21
+ function switchTheme(theme) {
22
+ document.documentElement.setAttribute('data-theme', theme);
23
+ }
24
+ function handleThemeSwitch() {
25
+ switchTheme(isDarkMode() ? 'dark' : 'light');
26
+ onDarkMode((dark)=>{
27
+ switchTheme(dark ? 'dark' : 'light');
28
+ });
29
+ }
30
+ function gradient(start, end, value) {
31
+ value = Math.max(0, Math.min(100, value));
32
+ const red = Math.round(start.red + (end.red - start.red) * value / 100);
33
+ const green = Math.round(start.green + (end.green - start.green) * value / 100);
34
+ const blue = Math.round(start.blue + (end.blue - start.blue) * value / 100);
35
+ return `rgb(${red}, ${green}, ${blue})`;
36
+ }
37
+ export { cssVar, gradient, handleThemeSwitch, isDarkMode, onDarkMode, render, switchTheme };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taybart/corvid",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "exports": {
@@ -12,6 +12,10 @@
12
12
  "types": "./dist/dom.d.ts",
13
13
  "import": "./dist/dom.js"
14
14
  },
15
+ "./style": {
16
+ "types": "./dist/style.d.ts",
17
+ "import": "./dist/style.js"
18
+ },
15
19
  "./local_storage": {
16
20
  "types": "./dist/ls.d.ts",
17
21
  "import": "./dist/ls.js"
@@ -30,6 +34,10 @@
30
34
  "files": [
31
35
  "dist"
32
36
  ],
37
+ "scripts": {
38
+ "build": "rslib build",
39
+ "dev": "rslib build --watch"
40
+ },
33
41
  "devDependencies": {
34
42
  "@happy-dom/global-registrator": "^17.4.7",
35
43
  "@rslib/core": "^0.6.2",
@@ -39,9 +47,5 @@
39
47
  "@types/jsdom": "^21.1.7",
40
48
  "@types/node": "^22.8.1",
41
49
  "typescript": "^5.8.3"
42
- },
43
- "scripts": {
44
- "build": "rslib build",
45
- "dev": "rslib build --watch"
46
50
  }
47
- }
51
+ }