sol-components 2.1.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.
Files changed (150) hide show
  1. package/README.md +7 -0
  2. package/core/activate.js +27 -0
  3. package/core/adopt.js +71 -0
  4. package/core/auth-core.js +73 -0
  5. package/core/auth-fetch.js +154 -0
  6. package/core/component-mount.js +110 -0
  7. package/core/defaults.js +48 -0
  8. package/core/define.js +15 -0
  9. package/core/display-target.js +166 -0
  10. package/core/edit-placements.js +28 -0
  11. package/core/editor-self.js +127 -0
  12. package/core/editor.js +162 -0
  13. package/core/events.js +27 -0
  14. package/core/extension-points.js +189 -0
  15. package/core/form-utils.js +210 -0
  16. package/core/from-query.js +138 -0
  17. package/core/from-rdf.js +52 -0
  18. package/core/here.js +33 -0
  19. package/core/include-core.js +73 -0
  20. package/core/inrupt-global.js +18 -0
  21. package/core/menu-consumer.js +41 -0
  22. package/core/menu-rdf.js +154 -0
  23. package/core/pod-ops.js +392 -0
  24. package/core/pod-registry.js +82 -0
  25. package/core/popup-proxy.js +255 -0
  26. package/core/rdf-core.js +280 -0
  27. package/core/rdf-render.js +136 -0
  28. package/core/rdf-utils.js +411 -0
  29. package/core/rdf.js +154 -0
  30. package/core/services.js +106 -0
  31. package/core/shape-to-form.js +741 -0
  32. package/core/sparql-safety.js +20 -0
  33. package/core/utils.js +196 -0
  34. package/dist/importmap-cdn.json +49 -0
  35. package/dist/importmap-local.json +49 -0
  36. package/dist/sol-loader.manifest.json +140 -0
  37. package/dist/vendor/@comunica-query-sparql.js +137851 -0
  38. package/dist/vendor/@inrupt-solid-client-authn-browser.js +7503 -0
  39. package/dist/vendor/dompurify.js +1476 -0
  40. package/dist/vendor/ical.js.js +9739 -0
  41. package/dist/vendor/marked.js +85 -0
  42. package/dist/vendor/n3.js +14670 -0
  43. package/dist/vendor/rdf-validate-shacl.js +6970 -0
  44. package/dist/vendor/rdflib.js +35172 -0
  45. package/dist/vendor/solid-logic.js +6819 -0
  46. package/dist/vendor/solid-ui.js +21945 -0
  47. package/node/sol-form.js +133 -0
  48. package/node/sol-include.js +55 -0
  49. package/node/sol-login.js +632 -0
  50. package/node/sol-menu.js +639 -0
  51. package/node/sol-query.js +116 -0
  52. package/package.json +133 -0
  53. package/web/menu-from-rdf.js +23 -0
  54. package/web/scripts/prefs.js +25 -0
  55. package/web/sol-accordion.js +114 -0
  56. package/web/sol-basic.js +50 -0
  57. package/web/sol-breadcrumb.js +131 -0
  58. package/web/sol-button.js +244 -0
  59. package/web/sol-calendar.js +465 -0
  60. package/web/sol-default.js +118 -0
  61. package/web/sol-dropdown-button.js +222 -0
  62. package/web/sol-feed.js +1336 -0
  63. package/web/sol-form.js +949 -0
  64. package/web/sol-full.js +43 -0
  65. package/web/sol-gallery.js +303 -0
  66. package/web/sol-include.js +246 -0
  67. package/web/sol-live-edit.js +415 -0
  68. package/web/sol-login.js +856 -0
  69. package/web/sol-menu.js +593 -0
  70. package/web/sol-modal.js +377 -0
  71. package/web/sol-pod-extras.js +17 -0
  72. package/web/sol-pod-ops.js +680 -0
  73. package/web/sol-pod.js +1039 -0
  74. package/web/sol-query.js +546 -0
  75. package/web/sol-rolodex.js +95 -0
  76. package/web/sol-search.js +402 -0
  77. package/web/sol-settings.js +199 -0
  78. package/web/sol-solidos.js +93 -0
  79. package/web/sol-tabs.js +445 -0
  80. package/web/sol-time.js +194 -0
  81. package/web/sol-tree-edit.js +492 -0
  82. package/web/sol-wac.js +456 -0
  83. package/web/sol-weather.js +337 -0
  84. package/web/sol-window.js +142 -0
  85. package/web/styles/buttons-css.js +108 -0
  86. package/web/styles/help.css +242 -0
  87. package/web/styles/root.css +112 -0
  88. package/web/styles/sol-accordion-css.js +97 -0
  89. package/web/styles/sol-calendar-css.js +154 -0
  90. package/web/styles/sol-feed-css.js +475 -0
  91. package/web/styles/sol-form-css.js +471 -0
  92. package/web/styles/sol-gallery-css.js +181 -0
  93. package/web/styles/sol-include-css.js +95 -0
  94. package/web/styles/sol-live-edit-css.js +84 -0
  95. package/web/styles/sol-live-edit.css +101 -0
  96. package/web/styles/sol-login-css.js +116 -0
  97. package/web/styles/sol-menu-css.js +145 -0
  98. package/web/styles/sol-modal-css.js +134 -0
  99. package/web/styles/sol-pod-css.js +187 -0
  100. package/web/styles/sol-pod-modal-css.js +203 -0
  101. package/web/styles/sol-query-css.js +140 -0
  102. package/web/styles/sol-query-help.css +267 -0
  103. package/web/styles/sol-query-one-pager.css +67 -0
  104. package/web/styles/sol-search-css.js +157 -0
  105. package/web/styles/sol-solidos-css.js +7 -0
  106. package/web/styles/sol-tabs-css.js +114 -0
  107. package/web/styles/sol-time-css.js +30 -0
  108. package/web/styles/sol-wac-css.js +73 -0
  109. package/web/styles/sol-weather-css.js +59 -0
  110. package/web/styles/solid-logo.svg +9 -0
  111. package/web/styles/view-accordion-css.js +66 -0
  112. package/web/styles/view-anchorlist-css.js +22 -0
  113. package/web/styles/view-autocomplete-css.js +59 -0
  114. package/web/styles/view-rolodex-css.js +102 -0
  115. package/web/styles/view-select-css.js +21 -0
  116. package/web/utils/calendar-fetch.js +388 -0
  117. package/web/utils/code-mirror-editor.js +82 -0
  118. package/web/utils/commons-fetch.js +108 -0
  119. package/web/utils/feed-edit.js +159 -0
  120. package/web/utils/feed-edit.smoke.mjs +74 -0
  121. package/web/utils/feed-fetch.js +573 -0
  122. package/web/utils/live-edit-help/csv.js +64 -0
  123. package/web/utils/live-edit-help/graphviz.js +41 -0
  124. package/web/utils/live-edit-help/jsonld.js +55 -0
  125. package/web/utils/live-edit-help/markdown.js +52 -0
  126. package/web/utils/live-edit-help/mermaid.js +48 -0
  127. package/web/utils/live-edit-help/turtle.js +85 -0
  128. package/web/utils/rdf-config.js +125 -0
  129. package/web/utils/renderers/csv.js +124 -0
  130. package/web/utils/renderers/d3-force.js +82 -0
  131. package/web/utils/renderers/graphviz.js +13 -0
  132. package/web/utils/renderers/html.js +10 -0
  133. package/web/utils/renderers/jsonld.js +63 -0
  134. package/web/utils/renderers/markdown.js +19 -0
  135. package/web/utils/renderers/mermaid.js +54 -0
  136. package/web/utils/renderers/turtle.js +51 -0
  137. package/web/utils/sol-query-triple-patterns.js +151 -0
  138. package/web/utils/sol-query-ui.js +250 -0
  139. package/web/utils/sol-query-views.js +32 -0
  140. package/web/views/_helpers.js +34 -0
  141. package/web/views/accordion.js +133 -0
  142. package/web/views/anchorlist.js +59 -0
  143. package/web/views/auto-complete.js +183 -0
  144. package/web/views/dl.js +38 -0
  145. package/web/views/list.js +19 -0
  146. package/web/views/menu.js +56 -0
  147. package/web/views/rolodex.js +126 -0
  148. package/web/views/select.js +79 -0
  149. package/web/views/table.js +73 -0
  150. package/web/views/tabs.js +57 -0
@@ -0,0 +1,244 @@
1
+ /**
2
+ * <sol-button> — declarative launcher.
3
+ *
4
+ * Renders an HTML button (the slot contents become its label) that, on
5
+ * click, mounts a `<handler source="…" …>` element inside the element
6
+ * identified by `target`. Uses the same `[data-menu-item="<name>"]`
7
+ * wrapper convention sol-menu's ui:Component items use, so a sol-button
8
+ * launcher coexists with menu-driven items in the same display area.
9
+ * Every (target, name) pair is a persistent tab: clicking the button
10
+ * a second time re-shows the existing mount with all its state intact
11
+ * (login sessions, scroll, open panels, in-flight fetches) instead of
12
+ * tearing it down and rebuilding.
13
+ *
14
+ * Reserved attributes (consumed by sol-button itself):
15
+ * handler — tag name of the component to mount (optional; when absent,
16
+ * inferred from `source`: same-origin → sol-include, external
17
+ * → iframe)
18
+ * region — where the content surfaces. A CSS selector (a pane the page
19
+ * declares) OR a keyword that conjures an ephemeral surface with
20
+ * no author-placed element: modal | floating | tab | window.
21
+ * Resolved by cascade — this attribute, else a parent container,
22
+ * else an enclosing <sol-menu>, else <sol-default>.
23
+ * inline — boolean: toggle the content INLINE into a host, non-keep-alive
24
+ * (see below). The host is resolved through the SAME region cascade
25
+ * (a parent [region] or <sol-default region="#host">), so the host
26
+ * can be declared once on <sol-default> rather than on every button.
27
+ * for — (inline only) explicit host selector, overriding the cascade;
28
+ * defaults to the button's own parent when nothing resolves.
29
+ *
30
+ * `handler` names what the button does — a component OR an action, treated the
31
+ * same way. A custom-element tag (has a "-", e.g. sol-include) is mounted; a
32
+ * bare name that isn't a registered element (e.g. "installPod") is an action:
33
+ * it dispatches `sol-command` (detail.command = the handler) for the host app's
34
+ * registry to resolve, with `params` (JSON or a bare string) as detail.params.
35
+ * name — wrapper identifier (data-menu-item); defaults to the
36
+ * element's id if set, otherwise to a slug of source
37
+ * source — forwarded to the handler (e.g. sol-include's `source`)
38
+ * replace — boolean: rebuild a pane wrapper's contents on every click
39
+ * instead of reusing them.
40
+ *
41
+ * Every OTHER attribute on sol-button is forwarded as-is to the handler
42
+ * element, so authoring is just like inlining the handler:
43
+ *
44
+ * <sol-button handler="sol-include" source="pages/settings.html"
45
+ * target="#dk-content" name="Settings" trusted>
46
+ * ⚙
47
+ * </sol-button>
48
+ *
49
+ * on click → <sol-include source="pages/settings.html" trusted>
50
+ * gets mounted inside #dk-content > [data-menu-item="Settings"]
51
+ *
52
+ * <sol-default region="#main"></sol-default>
53
+ * <sol-button handler="sol-include" inline source="help.html">?</sol-button>
54
+ *
55
+ * click → toggles <sol-include source="help.html"> inside #main (the host
56
+ * from the region cascade; a .sol-inline-panel wrapper); click again
57
+ * removes it. The button gets `open` + aria-expanded while shown.
58
+ *
59
+ * Events:
60
+ * sol-button-activate — detail: { name, handler, wrapper, open? }
61
+ * (`open` is present in inline mode: true on show, false on hide)
62
+ *
63
+ * The trigger button is exposed as `::part(trigger)` for external
64
+ * styling, matching sol-modal's pattern.
65
+ */
66
+
67
+ import { define } from '../core/define.js';
68
+ import { ensureHandler, dispatchCommand, isCommandName } from '../core/rdf-render.js';
69
+ import { displayItem, isExternal, resolveRegion } from '../core/display-target.js';
70
+
71
+ const RESERVED = new Set(['handler', 'region', 'name', 'replace', 'inline', 'for', 'params', 'class', 'style']);
72
+
73
+ class SolButton extends HTMLElement {
74
+ constructor() {
75
+ super();
76
+ this.attachShadow({ mode: 'open' });
77
+ }
78
+
79
+ connectedCallback() {
80
+ if (this._rendered) return;
81
+ this._rendered = true;
82
+ this.shadowRoot.innerHTML = `
83
+ <button class="sol-btn sol-button-trigger" part="trigger" type="button">
84
+ <slot></slot>
85
+ </button>`;
86
+ const btn = this.shadowRoot.querySelector('.sol-button-trigger');
87
+ const a11y = this.getAttribute('aria-label') || this.getAttribute('title');
88
+ if (a11y) btn.setAttribute('aria-label', a11y);
89
+ const tip = this.getAttribute('title');
90
+ if (tip) btn.setAttribute('title', tip);
91
+ btn.addEventListener('click', () => this._activate());
92
+
93
+ // Sync our trigger's active state to the page's current tab so the
94
+ // gear (or any sol-button) lights up while its tab is the visible
95
+ // one, even when activation came from elsewhere.
96
+ this._onTabActivate = (e) => {
97
+ btn.classList.toggle('active', e.detail?.name === this._resolveName());
98
+ };
99
+ document.addEventListener('sol-tab-activate', this._onTabActivate);
100
+ }
101
+
102
+ disconnectedCallback() {
103
+ if (this._onTabActivate) {
104
+ document.removeEventListener('sol-tab-activate', this._onTabActivate);
105
+ this._onTabActivate = null;
106
+ }
107
+ }
108
+
109
+ _resolveName() {
110
+ return this.getAttribute('name')
111
+ || this.id
112
+ || (this.getAttribute('source') || this.getAttribute('handler') || '').split(/[\/#?]/).filter(Boolean).pop()
113
+ || this.getAttribute('handler');
114
+ }
115
+
116
+ /** Compute the content element to mount: explicit `handler` wins; else infer
117
+ * from the href origin (same-origin → trusted sol-include, external → iframe).
118
+ * Returns { tag, attrs, href, replace }. */
119
+ _handlerSpec() {
120
+ const href = this.getAttribute('source') || null;
121
+ const explicit = this.getAttribute('handler');
122
+ const attrs = [];
123
+ for (const a of this.attributes) {
124
+ if (RESERVED.has(a.name)) continue;
125
+ if (a.name.startsWith('aria-')) continue;
126
+ attrs.push([a.name, a.value]);
127
+ }
128
+ let tag, replace = this.hasAttribute('replace');
129
+ if (explicit) {
130
+ tag = explicit;
131
+ } else if (href && isExternal(href)) {
132
+ tag = 'iframe';
133
+ attrs.push(['src', href]);
134
+ replace = true;
135
+ } else {
136
+ tag = 'sol-include';
137
+ if (href && !attrs.some(([k]) => k === 'trusted')) attrs.push(['trusted', 'true']);
138
+ }
139
+ return { tag, attrs, href, replace };
140
+ }
141
+
142
+ _activate() {
143
+ // `handler` names what the button does — a component (a custom-element tag,
144
+ // mounted) OR an action (a bare name that isn't a registered element →
145
+ // dispatch `sol-command` for the app's registry, same allow-list as sol-menu
146
+ // command items). isCommandName() draws the line (custom elements need a -).
147
+ const handler = this.getAttribute('handler');
148
+ if (handler && isCommandName(handler)) {
149
+ const raw = this.getAttribute('params');
150
+ let params;
151
+ if (raw != null) { try { params = JSON.parse(raw); } catch { params = raw; } }
152
+ dispatchCommand(this, handler, params);
153
+ return;
154
+ }
155
+ if (this.hasAttribute('inline')) { this.toggleInline(); return; }
156
+
157
+ const { tag, attrs, href, replace } = this._handlerSpec();
158
+ const ensure = (t) => ensureHandler(t, this, import.meta.url, 'sol-button');
159
+ ensure(tag);
160
+
161
+ const name = this._resolveName();
162
+ const wrapper = displayItem({
163
+ launcher: this, id: null, name, tag, attrs, href, replace, ensure,
164
+ });
165
+ if (wrapper == null) {
166
+ console.warn('<sol-button>: no region resolved — set region= on the button, a container, <sol-menu>, or <sol-default>.');
167
+ }
168
+ this.dispatchEvent(new CustomEvent('sol-button-activate', {
169
+ bubbles: true, composed: true,
170
+ detail: { name, handler: tag, wrapper },
171
+ }));
172
+ }
173
+
174
+ // ── Inline region (region="inline") ─────────────────────────────────────────
175
+ // Toggle the handler INLINE into a page-declared host (`for="<selector>"`,
176
+ // else the button's own parent). Non-keep-alive: the content is built fresh on
177
+ // open and removed on close, so the panel never accumulates state. Open state
178
+ // is reflected as `open` on the host element and aria-expanded on the trigger,
179
+ // so the page can style the trigger (and react via CSS :has()).
180
+
181
+ _inlineHost() {
182
+ // Explicit `for` wins; otherwise resolve through the region cascade
183
+ // (a parent [region] or <sol-default region="…">); else the button's parent.
184
+ const sel = this.getAttribute('for');
185
+ if (sel) { try { return document.querySelector(sel); } catch { return null; } }
186
+ const r = resolveRegion(this, this._resolveName());
187
+ return r.kind === 'element' ? r.element : this.parentElement;
188
+ }
189
+
190
+ get inlineOpen() { return !!(this._inlinePanel && this._inlinePanel.isConnected); }
191
+
192
+ toggleInline() { this.inlineOpen ? this.closeInline() : this.openInline(); }
193
+
194
+ openInline() {
195
+ if (this.inlineOpen) return;
196
+ const host = this._inlineHost();
197
+ if (!host) {
198
+ console.warn('<sol-button region="inline">: no host — set for="<selector>" or place the button inside a container.');
199
+ return;
200
+ }
201
+ const { tag, attrs } = this._handlerSpec();
202
+ ensureHandler(tag, this, import.meta.url, 'sol-button');
203
+ const panel = document.createElement('div');
204
+ panel.className = 'sol-inline-panel';
205
+ panel.dataset.solInline = this._resolveName();
206
+ const content = document.createElement(tag);
207
+ for (const [k, v] of attrs) content.setAttribute(k, v);
208
+ panel.appendChild(content);
209
+ host.appendChild(panel);
210
+ this._inlinePanel = panel;
211
+ this._reflectOpen(true);
212
+ this.dispatchEvent(new CustomEvent('sol-button-activate', {
213
+ bubbles: true, composed: true,
214
+ detail: { name: this._resolveName(), handler: tag, wrapper: panel, open: true },
215
+ }));
216
+ }
217
+
218
+ closeInline() {
219
+ if (!this.inlineOpen) { this._reflectOpen(false); return; }
220
+ this._inlinePanel.remove();
221
+ this._inlinePanel = null;
222
+ this._reflectOpen(false);
223
+ this.dispatchEvent(new CustomEvent('sol-button-activate', {
224
+ bubbles: true, composed: true,
225
+ detail: { name: this._resolveName(), open: false },
226
+ }));
227
+ }
228
+
229
+ /** Public: dismiss the inline panel (e.g. the page closing it on navigation). */
230
+ close() { this.closeInline(); }
231
+
232
+ _reflectOpen(open) {
233
+ this.toggleAttribute('open', open);
234
+ const btn = this.shadowRoot.querySelector('.sol-button-trigger');
235
+ if (btn) {
236
+ btn.setAttribute('aria-expanded', open ? 'true' : 'false');
237
+ btn.classList.toggle('active', open);
238
+ }
239
+ }
240
+ }
241
+
242
+ define('sol-button', SolButton);
243
+ export { SolButton };
244
+ export default SolButton;