sol-components 2.1.0 → 2.2.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/README.md CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  ## This is a Work In Progress!
4
4
 
5
- See the <a href="https://solidos.github.io/sol-components/">help pages</a> for details.
5
+ See the <a href="https://jeff-zucker.github.io/sol-components/">help pages</a> for details.
6
6
 
7
7
  (c) 2023-2026, Jeff Zucker, may be freely distributed under an MIT or Apache license.
@@ -0,0 +1,88 @@
1
+ // handler.js — the `handler` capability (part of component-interop).
2
+ //
3
+ // Lets ANY element (a library's own button/menu, a plain link) activate a
4
+ // component or a script, with NO display logic in component-interop: ci catches
5
+ // the activation, optionally instantiates a named component, forwards the
6
+ // element's data, and fires ONE event — the consuming app decides what happens
7
+ // and where any result goes.
8
+ //
9
+ // <a data-handler="my-viewer" href="report.ttl" data-mode="compact">Open</a> <!-- component -->
10
+ // <button data-handler="exportCsv" data-format="utf8">Export</button> <!-- script -->
11
+ //
12
+ // document.addEventListener('interop:activate', (e) => {
13
+ // const { handler, element, data, source } = e.detail;
14
+ // if (element) source.closest('.pane').querySelector('.output').replaceChildren(element);
15
+ // else if (handler === 'exportCsv') exportTheTable(data);
16
+ // });
17
+ //
18
+ // Zero imports. Activation is delegated at the document level, so dynamically
19
+ // added elements and shadow-DOM buttons (composed events) work with no setup.
20
+
21
+ // A custom-element tag (must contain a hyphen) or an already-registered element
22
+ // → instantiate a component; otherwise it's a bare-name action (script).
23
+ function isComponentTag(name) {
24
+ return !!name && (name.indexOf('-') !== -1 || !!customElements.get(name));
25
+ }
26
+
27
+ // Collect the element's payload: href (if any) + data-* attributes with the
28
+ // `data-` prefix stripped, excluding `data-handler` itself.
29
+ function collectData(el) {
30
+ const data = {};
31
+ const href = el.getAttribute && el.getAttribute('href');
32
+ if (href != null) data.href = href;
33
+ const attrs = el.attributes || [];
34
+ for (let i = 0; i < attrs.length; i++) {
35
+ const a = attrs[i];
36
+ if (a.name === 'data-handler') continue;
37
+ if (a.name.indexOf('data-') === 0) data[a.name.slice(5)] = a.value;
38
+ }
39
+ return data;
40
+ }
41
+
42
+ // Forward the payload onto the instantiated component as attributes
43
+ // (href → href, data-mode → mode, …). The component reads its own attributes.
44
+ function forwardAttrs(target, data) {
45
+ for (const key in data) {
46
+ if (Object.prototype.hasOwnProperty.call(data, key)) target.setAttribute(key, data[key]);
47
+ }
48
+ }
49
+
50
+ function activate(el) {
51
+ const name = el.getAttribute('data-handler');
52
+ if (!name) return;
53
+ const data = collectData(el);
54
+
55
+ let element = null;
56
+ if (isComponentTag(name)) {
57
+ element = document.createElement(name);
58
+ forwardAttrs(element, data);
59
+ }
60
+
61
+ el.dispatchEvent(new CustomEvent('interop:activate', {
62
+ bubbles: true, composed: true,
63
+ detail: { handler: name, element: element, data: data, source: el },
64
+ }));
65
+ }
66
+
67
+ function onClick(e) {
68
+ const el = e.target && e.target.closest && e.target.closest('[data-handler]');
69
+ if (!el) return;
70
+ e.preventDefault(); // don't navigate / submit — the app routes it
71
+ activate(el);
72
+ }
73
+
74
+ function onKeydown(e) {
75
+ if (e.key !== 'Enter' && e.key !== ' ' && e.key !== 'Spacebar') return;
76
+ const el = e.target && e.target.closest && e.target.closest('[data-handler]');
77
+ if (!el) return;
78
+ e.preventDefault();
79
+ activate(el);
80
+ }
81
+
82
+ if (typeof document !== 'undefined' && !document.__ciHandlerWired) {
83
+ document.__ciHandlerWired = true;
84
+ document.addEventListener('click', onClick);
85
+ document.addEventListener('keydown', onKeydown);
86
+ }
87
+
88
+ export { activate, isComponentTag, collectData };
@@ -120,6 +120,7 @@
120
120
 
121
121
  "attributes": {
122
122
  "data-from-query": "sol-components/core/from-query.js",
123
+ "data-handler": "sol-components/core/handler.js",
123
124
  "data-edit-shape data-from-rdf": "rdf-bundle"
124
125
  },
125
126
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sol-components",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Web components and Node.js tools for querying, including, and editing RDF/Linked Data on Solid Pods",
5
5
  "type": "module",
6
6
  "exports": {