solid-panes 4.4.0 → 4.4.1

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 (75) hide show
  1. package/README.md +4 -2
  2. package/dist/RDFXMLPane.css +70 -0
  3. package/dist/RDFXMLPane.d.ts +13 -0
  4. package/dist/RDFXMLPane.d.ts.map +1 -0
  5. package/dist/RDFXMLPane.js +46 -5
  6. package/dist/dataContentPane.css +271 -0
  7. package/dist/dataContentPane.d.ts +14 -0
  8. package/dist/dataContentPane.d.ts.map +1 -0
  9. package/dist/dataContentPane.js +68 -101
  10. package/dist/defaultPane.css +97 -0
  11. package/dist/defaultPane.d.ts +14 -0
  12. package/dist/defaultPane.d.ts.map +1 -0
  13. package/dist/defaultPane.js +9 -2
  14. package/dist/form/formPane.css +120 -0
  15. package/dist/form/pane.d.ts +4 -0
  16. package/dist/form/pane.d.ts.map +1 -0
  17. package/dist/form/pane.js +120 -54
  18. package/dist/humanReadablePane.css +129 -0
  19. package/dist/humanReadablePane.d.ts +13 -0
  20. package/dist/humanReadablePane.d.ts.map +1 -0
  21. package/dist/humanReadablePane.js +29 -18
  22. package/dist/icons/signUp.svg +9 -0
  23. package/dist/imagePane.css +4 -0
  24. package/dist/imagePane.d.ts +12 -0
  25. package/dist/imagePane.d.ts.map +1 -0
  26. package/dist/imagePane.js +19 -21
  27. package/dist/internal/internalPane.css +14 -0
  28. package/dist/internal/internalPane.d.ts +1 -0
  29. package/dist/internal/internalPane.d.ts.map +1 -1
  30. package/dist/internal/internalPane.js +5 -6
  31. package/dist/mainPage/header.js +2 -2
  32. package/dist/mainPage/index.d.ts +2 -1
  33. package/dist/mainPage/index.d.ts.map +1 -1
  34. package/dist/mainPage/index.js +23 -0
  35. package/dist/mainPage/menu.d.ts.map +1 -1
  36. package/dist/mainPage/menu.js +29 -2
  37. package/dist/n3Pane.css +49 -0
  38. package/dist/n3Pane.d.ts +13 -0
  39. package/dist/n3Pane.d.ts.map +1 -0
  40. package/dist/n3Pane.js +36 -5
  41. package/dist/outline/manager.js +20 -1
  42. package/dist/pad/padPane.css +6 -2
  43. package/dist/pad/padPane.js +1 -1
  44. package/dist/registerPanes.js +8 -8
  45. package/dist/schedule/schedulePane.css +294 -0
  46. package/dist/schedule/schedulePane.d.ts +23 -0
  47. package/dist/schedule/schedulePane.d.ts.map +1 -0
  48. package/dist/schedule/schedulePane.js +161 -61
  49. package/dist/social/editProfileDetails.d.ts +3 -3
  50. package/dist/social/editProfileDetails.d.ts.map +1 -1
  51. package/dist/social/editProfileDetails.js +222 -127
  52. package/dist/social/icons.d.ts +2 -0
  53. package/dist/social/icons.d.ts.map +1 -1
  54. package/dist/social/icons.js +39 -4
  55. package/dist/social/socialPane.css +838 -178
  56. package/dist/social/socialPane.d.ts.map +1 -1
  57. package/dist/social/socialPane.js +136 -43
  58. package/dist/social/socialSections.d.ts +11 -0
  59. package/dist/social/socialSections.d.ts.map +1 -1
  60. package/dist/social/socialSections.js +138 -62
  61. package/dist/social/spinner.d.ts +3 -0
  62. package/dist/social/spinner.d.ts.map +1 -0
  63. package/dist/social/spinner.js +13 -0
  64. package/dist/social/triage.d.ts +17 -0
  65. package/dist/social/triage.d.ts.map +1 -0
  66. package/dist/social/triage.js +79 -0
  67. package/dist/solid-panes.js +25772 -9576
  68. package/dist/solid-panes.js.map +1 -1
  69. package/dist/solid-panes.min.js +2583 -927
  70. package/dist/solid-panes.min.js.map +1 -1
  71. package/dist/{style → styles}/tabbedtab.css +0 -157
  72. package/dist/styles/utilities.css +5 -0
  73. package/dist/versionInfo.js +14 -14
  74. package/package.json +26 -25
  75. package/dist/icons/signup.png +0 -0
package/dist/form/pane.js CHANGED
@@ -7,6 +7,7 @@ exports.formPane = void 0;
7
7
  var UI = _interopRequireWildcard(require("solid-ui"));
8
8
  var _solidLogic = require("solid-logic");
9
9
  var $rdf = _interopRequireWildcard(require("rdflib"));
10
+ require("./formPane.css");
10
11
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
12
  /*
12
13
  ** Pane for running existing forms for any object
@@ -14,12 +15,63 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
14
15
  */
15
16
 
16
17
  const ns = UI.ns;
18
+ function isNamedNode(term) {
19
+ return term?.termType === 'NamedNode';
20
+ }
21
+
22
+ /* The following helper was generated by AI GPT-5.4 Model */
23
+ /* Prompt: Add a compatibility shim in the form pane for mixed `ui:Group` plus field typing. */
24
+ function normalizeAmbiguousFieldTypes(store, form) {
25
+ const formDoc = form.doc ? form.doc() : undefined;
26
+ const types = store.each(form, ns.rdf('type'), undefined, formDoc).filter(isNamedNode);
27
+ const hasGroupType = types.some(type => type.sameTerm(ns.ui('Group')));
28
+ const hasOtherFieldType = types.some(type => !type.sameTerm(ns.ui('Group')) && !type.sameTerm(ns.ui('Form')));
29
+ const hasProperty = !!store.any(form, ns.ui('property'), undefined, formDoc);
30
+ const partsList = store.any(form, ns.ui('parts'), undefined, formDoc);
31
+ const hasParts = !!partsList?.elements?.length || store.each(form, ns.ui('part'), undefined, formDoc).length > 0;
32
+
33
+ // Some legacy forms mark a leaf field as both ui:Group and a concrete input type.
34
+ // solid-ui may then choose the Group renderer and produce an empty nested box.
35
+ if (hasGroupType && hasOtherFieldType && hasProperty && !hasParts) {
36
+ store.removeMany(form, ns.rdf('type'), ns.ui('Group'), formDoc);
37
+ }
38
+ const listParts = partsList?.elements ?? [];
39
+ for (const part of listParts) {
40
+ if (isNamedNode(part)) {
41
+ normalizeAmbiguousFieldTypes(store, part);
42
+ }
43
+ }
44
+ const unorderedParts = store.each(form, ns.ui('part'), undefined, formDoc);
45
+ for (const part of unorderedParts) {
46
+ if (isNamedNode(part)) {
47
+ normalizeAmbiguousFieldTypes(store, part);
48
+ }
49
+ }
50
+ }
51
+ function tagMobileTextareaRows(renderedForm) {
52
+ const textareas = Array.from(renderedForm.querySelectorAll('textarea'));
53
+ for (const textarea of textareas) {
54
+ let row = textarea.parentElement;
55
+ while (row) {
56
+ const firstChild = row.firstElementChild;
57
+ const hasLabelColumn = !!firstChild && (firstChild.classList.contains('formFieldName') || firstChild.querySelector('a') !== null);
58
+ if (hasLabelColumn && row.children.length >= 2) {
59
+ row.classList.add('formPane__mobileTextareaRow');
60
+ firstChild.classList.add('formPane__mobileTextareaLabel');
61
+ const valueColumn = row.children[1];
62
+ valueColumn.classList.add('formPane__mobileTextareaValue');
63
+ break;
64
+ }
65
+ row = row.parentElement;
66
+ }
67
+ }
68
+ }
17
69
  const formPane = exports.formPane = {
18
70
  icon: UI.icons.iconBase + 'noun_122196.svg',
19
71
  name: 'form',
20
72
  audience: [ns.solid('PowerUser')],
21
73
  // Does the subject deserve this pane?
22
- label: function (subject) {
74
+ label: function (subject, _context) {
23
75
  const n = UI.widgets.formsFor(subject).length;
24
76
  UI.log.debug('Form pane: forms for ' + subject + ': ' + n);
25
77
  if (!n) return null;
@@ -28,14 +80,21 @@ const formPane = exports.formPane = {
28
80
  render: function (subject, context) {
29
81
  const kb = context.session.store;
30
82
  const dom = context.dom;
31
- const mention = function complain(message, style) {
83
+ const box = dom.createElement('div');
84
+ box.setAttribute('class', 'formPane');
85
+ function applyEnvironmentAttributes(element) {
86
+ const environment = context.environment ?? {};
87
+ element.dataset.layout = environment.layout ?? 'desktop';
88
+ }
89
+ applyEnvironmentAttributes(box);
90
+ const mention = function (message, modifier = 'info') {
32
91
  const pre = dom.createElement('p');
33
- pre.setAttribute('style', style || 'color: grey; background-color: white');
92
+ pre.className = `formPane__message formPane__message--${modifier}`;
34
93
  box.appendChild(pre).textContent = message;
35
94
  return pre;
36
95
  };
37
- const complain = function complain(message, style) {
38
- mention(message, 'style', style || 'color: grey; background-color: #fdd;');
96
+ const complain = function (message) {
97
+ return mention(message, 'error');
39
98
  };
40
99
  const complainIfBad = function (ok, body) {
41
100
  if (ok) {
@@ -51,8 +110,6 @@ const formPane = exports.formPane = {
51
110
  // const t = kb.findTypeURIs(subject)
52
111
 
53
112
  const me = _solidLogic.authn.currentUser();
54
- const box = dom.createElement('div');
55
- box.setAttribute('class', 'formPane');
56
113
  if (!me) {
57
114
  mention('You are not logged in. If you log in and have ' + 'workspaces then you would be able to select workspace in which ' + 'to put this new information');
58
115
  } else {
@@ -66,30 +123,33 @@ const formPane = exports.formPane = {
66
123
 
67
124
  // Render forms using a given store
68
125
 
69
- const renderFormsFor = function (store, subject) {
70
- kb.fetcher.nowOrWhenFetched(store.uri, subject, function (ok, body) {
71
- if (!ok) return complain('Cannot load store ' + store.uri + ': ' + body);
126
+ const renderFormsFor = function (storeNode, targetSubject) {
127
+ kb.fetcher.nowOrWhenFetched(storeNode.uri, targetSubject, function (ok, body) {
128
+ if (!ok) return complain('Cannot load store ' + storeNode.uri + ': ' + body);
72
129
 
73
130
  // Render the forms
74
131
 
75
- const forms = UI.widgets.formsFor(subject);
132
+ const forms = UI.widgets.formsFor(targetSubject);
76
133
 
77
134
  // complain('Form for editing this form:');
78
- for (let i = 0; i < forms.length; i++) {
79
- const form = forms[i];
135
+ for (const form of forms) {
136
+ normalizeAmbiguousFieldTypes(kb, form);
80
137
  const heading = dom.createElement('h4');
138
+ heading.classList.add('formPane__heading');
81
139
  box.appendChild(heading);
140
+ /* The edit Form is not working in the local environment. it does not find
141
+ the ui FormForm ontology. Need to research further and check in production. */
82
142
  if (form.uri) {
83
143
  const formStore = $rdf.Util.uri.document(form.uri);
84
144
  if (formStore.uri !== form.uri) {
85
- // The form is a hash-type URI
86
- const e = box.appendChild(UI.widgets.editFormButton(dom, box, form, formStore, complainIfBad));
87
- e.setAttribute('style', 'margin-left: auto; display: block;');
145
+ const editButton = box.appendChild(UI.widgets.editFormButton(dom, box, form, formStore, complainIfBad));
146
+ editButton.classList.add('formPane__editButton');
88
147
  }
89
148
  }
90
149
  const anchor = dom.createElement('a');
150
+ anchor.classList.add('formPane__headingLink');
91
151
  anchor.setAttribute('href', form.uri);
92
- heading.appendChild(anchor);
152
+ heading.insertBefore(anchor, heading.firstChild);
93
153
  anchor.textContent = UI.utils.label(form, true);
94
154
 
95
155
  /* Keep tis as a reminder to let a New one have its URI given by user
@@ -103,7 +163,8 @@ const formPane = exports.formPane = {
103
163
  ele.value = store.uri
104
164
  */
105
165
 
106
- UI.widgets.appendForm(dom, box, {}, subject, form, store, complainIfBad);
166
+ UI.widgets.appendForm(dom, box, {}, targetSubject, form, storeNode, complainIfBad);
167
+ tagMobileTextareaRows(box);
107
168
  }
108
169
  }); // end: when store loded
109
170
  }; // renderFormsFor
@@ -112,64 +173,69 @@ const formPane = exports.formPane = {
112
173
 
113
174
  // Which places are editable and have stuff about the subject?
114
175
 
115
- let store = null;
176
+ let targetStore = null;
116
177
 
117
178
  // 1. The document URI of the subject itself
118
179
  const docuri = $rdf.Util.uri.docpart(subject.uri);
119
- if (subject.uri !== docuri && kb.updater.editable(docuri, kb)) {
120
- store = subject.doc();
180
+ if (kb.updater.editable(docuri, kb)) {
181
+ targetStore = subject.doc();
121
182
  } // an editable data file with hash
122
183
 
123
- store = store || kb.any(kb.sym(docuri), ns.link('annotationStore'));
184
+ const annotationStore = kb.any(kb.sym(docuri), ns.link('annotationStore'));
185
+ if (!targetStore && isNamedNode(annotationStore)) {
186
+ targetStore = annotationStore;
187
+ }
124
188
 
125
189
  // 2. where stuff is already stored
126
- if (!store) {
127
- const docs = {};
128
- const docList = [];
129
- store.statementsMatching(subject).forEach(function (st) {
130
- docs[st.why.uri] = 1;
190
+ if (!targetStore) {
191
+ const docs = new Map();
192
+ kb.statementsMatching(subject).forEach(function (st) {
193
+ if (st.why.value) {
194
+ docs.set(st.why.value, 1);
195
+ }
131
196
  });
132
- store.statementsMatching(undefined, undefined, subject).forEach(function (st) {
133
- docs[st.why.uri] = 2;
197
+ kb.statementsMatching(undefined, undefined, subject).forEach(function (st) {
198
+ if (st.why.value) {
199
+ docs.set(st.why.value, 2);
200
+ }
201
+ });
202
+ const docList = Array.from(docs.entries()).sort(function ([uriA, scoreA], [uriB, scoreB]) {
203
+ return scoreA - scoreB || uriA.localeCompare(uriB);
134
204
  });
135
- for (const d in docs) docList.push(docs[d], d);
136
- docList.sort();
137
- for (let i = 0; i < docList.length; i++) {
138
- const uri = docList[i][1];
139
- if (uri && store.updater.editable(uri)) {
140
- store = store.sym(uri);
205
+ for (const [uri] of docList) {
206
+ if (uri && kb.updater.editable(uri, kb)) {
207
+ targetStore = kb.sym(uri);
141
208
  break;
142
209
  }
143
210
  }
144
211
  }
145
212
 
146
213
  // 3. In a workspace store
147
- // @@ TODO: Can probably remove _followeach (not done this time because the commit is a very safe refactor)
148
- const _followeach = function (kb, subject, path) {
149
- if (path.length === 0) return [subject];
150
- const oo = kb.each(subject, path[0]);
151
- let res = [];
152
- for (let i = 0; i < oo.length; i++) {
153
- res = res.concat(_followeach(kb, oo[i], path.slice(1)));
154
- }
155
- return res;
156
- };
157
214
  const date = '2014'; // @@@@@@@@@@@@ pass as parameter
158
215
 
159
- if (store) {
216
+ if (targetStore) {
160
217
  // mention("@@ Ok, we have a store <" + store.uri + ">.");
161
- renderFormsFor(store, subject);
218
+ renderFormsFor(targetStore, subject);
162
219
  } else {
163
220
  complain('No suitable store is known, to edit <' + subject.uri + '>.');
164
- const foobarbaz = UI.login.selectWorkspace(dom, function (ws) {
165
- mention('Workspace selected OK: ' + ws);
166
- const activities = store.each(undefined, ns.space('workspace'), ws);
221
+ const workspaceDetails = {
222
+ noun: 'form',
223
+ appPathSegment: 'form'
224
+ };
225
+ const foobarbaz = UI.login.selectWorkspace(dom, workspaceDetails, function (workspaceUri) {
226
+ const workspace = workspaceUri ? kb.sym(workspaceUri) : null;
227
+ if (!workspace) {
228
+ complain('Workspace selection was cancelled.');
229
+ return;
230
+ }
231
+ mention('Workspace selected OK: ' + workspace.uri);
232
+ const activities = kb.each(undefined, ns.space('workspace'), workspace).filter(isNamedNode);
167
233
  for (let j = 0; j < activities.length; j++) {
168
234
  const act = activities[j];
169
- const subjectDoc2 = store.any(ws, ns.space('store'));
170
- const start = store.any(ws, ns.cal('dtstart')).value();
171
- const end = store.any(ws, ns.cal('dtend')).value();
172
- if (subjectDoc2 && start && end && start <= date && end > date) {
235
+ const subjectDoc2 = kb.any(act, ns.space('store'));
236
+ const start = kb.any(act, ns.cal('dtstart'))?.value;
237
+ const end = kb.any(act, ns.cal('dtend'))?.value;
238
+ if (isNamedNode(subjectDoc2) && start && end && start <= date && end > date) {
173
239
  renderFormsFor(subjectDoc2, subject);
174
240
  break;
175
241
  } else {
@@ -0,0 +1,129 @@
1
+ .human-readable-pane {
2
+ display: block;
3
+ min-width: 0;
4
+ width: 100%;
5
+ max-width: 100%;
6
+ box-sizing: border-box;
7
+ }
8
+
9
+ .human-readable-pane__container {
10
+ display: block;
11
+ min-width: 0;
12
+ width: 100%;
13
+ max-width: 100%;
14
+ box-sizing: border-box;
15
+ overflow-x: hidden;
16
+ }
17
+
18
+ .human-readable-pane__frame {
19
+ display: block;
20
+ border: 1px solid;
21
+ padding: 1rem;
22
+ height: var(--human-readable-pane-height, 30rem);
23
+ min-width: 0;
24
+ max-width: 100%;
25
+ width: 100%;
26
+ box-sizing: border-box;
27
+ resize: both;
28
+ overflow: auto;
29
+ }
30
+
31
+ .human-readable-pane__frame--iframe {
32
+ padding: 0;
33
+ overflow: hidden;
34
+ width: 100%;
35
+ max-width: 100%;
36
+ min-height: 18rem;
37
+ background: var(--color-background, white);
38
+ }
39
+
40
+ .human-readable-pane__frame--markdown {
41
+ overflow-wrap: anywhere;
42
+ word-break: break-word;
43
+ }
44
+
45
+ .human-readable-pane__frame--plain-text {
46
+ font-family: monospace;
47
+ white-space: pre-wrap;
48
+ overflow-wrap: anywhere;
49
+ word-break: break-word;
50
+ }
51
+
52
+ .human-readable-pane__frame--markdown > * {
53
+ max-width: 100%;
54
+ box-sizing: border-box;
55
+ }
56
+
57
+ .human-readable-pane__frame--markdown img,
58
+ .human-readable-pane__frame--markdown video,
59
+ .human-readable-pane__frame--markdown canvas,
60
+ .human-readable-pane__frame--markdown iframe {
61
+ max-width: 100%;
62
+ height: auto;
63
+ }
64
+
65
+ .human-readable-pane__frame--markdown pre,
66
+ .human-readable-pane__frame--markdown code {
67
+ max-width: 100%;
68
+ overflow-wrap: anywhere;
69
+ word-break: break-word;
70
+ }
71
+
72
+ .human-readable-pane__frame--markdown pre {
73
+ white-space: pre-wrap;
74
+ }
75
+
76
+ .human-readable-pane__frame--markdown table {
77
+ display: block;
78
+ width: 100%;
79
+ max-width: 100%;
80
+ overflow-x: auto;
81
+ box-sizing: border-box;
82
+ }
83
+
84
+ .human-readable-pane__frame--markdown th,
85
+ .human-readable-pane__frame--markdown td {
86
+ white-space: normal;
87
+ overflow-wrap: anywhere;
88
+ word-break: break-word;
89
+ }
90
+
91
+ .human-readable-pane[data-layout='mobile'] .human-readable-pane__frame {
92
+ padding: 0.75rem;
93
+ resize: none;
94
+ min-width: 0;
95
+ }
96
+
97
+ .human-readable-pane[data-layout='mobile'] .human-readable-pane__frame--markdown,
98
+ .human-readable-pane[data-layout='mobile'] .human-readable-pane__frame--plain-text {
99
+ overflow-wrap: anywhere;
100
+ word-break: break-word;
101
+ }
102
+
103
+ .human-readable-pane[data-layout='mobile'] .human-readable-pane__frame--iframe {
104
+ width: 100%;
105
+ max-width: 100%;
106
+ min-height: 16rem;
107
+ height: min(var(--human-readable-pane-height, 30rem), 75vh);
108
+ }
109
+
110
+ @media (max-width: 576px) {
111
+ .human-readable-pane__frame {
112
+ padding: 0.75rem;
113
+ resize: none;
114
+ min-width: 0;
115
+ }
116
+
117
+ .human-readable-pane__frame--markdown,
118
+ .human-readable-pane__frame--plain-text {
119
+ overflow-wrap: anywhere;
120
+ word-break: break-word;
121
+ }
122
+
123
+ .human-readable-pane__frame--iframe {
124
+ width: 100%;
125
+ max-width: 100%;
126
+ min-height: 16rem;
127
+ height: min(var(--human-readable-pane-height, 30rem), 75vh);
128
+ }
129
+ }
@@ -0,0 +1,13 @@
1
+ import type { DataBrowserContext } from 'pane-registry';
2
+ import type { NamedNode } from 'rdflib';
3
+ import './humanReadablePane.css';
4
+ type HumanReadableIcon = string | Promise<string>;
5
+ type HumanReadablePaneDefinition = {
6
+ icon: (subject: NamedNode, context: DataBrowserContext) => HumanReadableIcon;
7
+ name: string;
8
+ label: (subject: NamedNode, context: DataBrowserContext) => 'view' | 'View' | null;
9
+ render: (subject: NamedNode, context: DataBrowserContext) => HTMLDivElement;
10
+ };
11
+ declare const humanReadablePane: HumanReadablePaneDefinition;
12
+ export default humanReadablePane;
13
+ //# sourceMappingURL=humanReadablePane.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"humanReadablePane.d.ts","sourceRoot":"","sources":["../src/humanReadablePane.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAqB,MAAM,eAAe,CAAA;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,yBAAyB,CAAA;AAKhC,KAAK,iBAAiB,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AAEjD,KAAK,2BAA2B,GAAG;IACjC,IAAI,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,KAAK,iBAAiB,CAAA;IAC5E,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,KAAK,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAClF,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,KAAK,cAAc,CAAA;CAC5E,CAAA;AAsBD,QAAA,MAAM,iBAAiB,EAAE,2BAuQxB,CAAA;AAED,eAAe,iBAAiB,CAAA"}
@@ -8,6 +8,7 @@ var _solidUi = require("solid-ui");
8
8
  var _rdflib = require("rdflib");
9
9
  var _marked = require("marked");
10
10
  var _dompurify = _interopRequireDefault(require("dompurify"));
11
+ require("./humanReadablePane.css");
11
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
13
  /* Human-readable Pane
13
14
  **
@@ -16,6 +17,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
16
17
  */
17
18
 
18
19
  // Helper function to check if a URI has a markdown file extension
20
+
19
21
  const isMarkdownFile = uri => {
20
22
  if (!uri) return false;
21
23
  const path = uri.split('?')[0].split('#')[0]; // Remove query string and fragment
@@ -24,6 +26,12 @@ const isMarkdownFile = uri => {
24
26
 
25
27
  // Cache for dokieli detection results (keyed by subject URI)
26
28
  const dokieliCache = new Map();
29
+ function applyFrameClasses(frame, modifier, lines) {
30
+ frame.className = '';
31
+ frame.classList.add('human-readable-pane__frame');
32
+ frame.classList.add(`human-readable-pane__frame--${modifier}`);
33
+ frame.style.setProperty('--human-readable-pane-height', `${lines}em`);
34
+ }
27
35
  const humanReadablePane = {
28
36
  icon: function (subject, context) {
29
37
  // Markdown files detected by extension
@@ -131,6 +139,10 @@ const humanReadablePane = {
131
139
  const myDocument = context.dom;
132
140
  const div = myDocument.createElement('div');
133
141
  const kb = context.session.store;
142
+ function applyEnvironmentAttributes(element) {
143
+ const environment = context.environment ?? {};
144
+ element.dataset.layout = environment.layout ?? 'desktop';
145
+ }
134
146
  const cts = kb.fetcher.getHeader(subject.doc(), 'content-type');
135
147
  const ct = cts ? cts[0].split(';', 1)[0].trim() : null; // remove content-type parameters
136
148
 
@@ -144,19 +156,20 @@ const humanReadablePane = {
144
156
  }
145
157
 
146
158
  // @@ When we can, use CSP to turn off scripts within the iframe
147
- div.setAttribute('class', 'docView');
148
- div.setAttribute('style', 'display: block; width: 100%; max-width: 100%; box-sizing: border-box;');
159
+ div.classList.add('human-readable-pane');
160
+ applyEnvironmentAttributes(div);
149
161
 
150
162
  // render markdown to html in a DIV element
151
163
  const renderMarkdownContent = function (frame) {
152
164
  kb.fetcher.webOperation('GET', subject.uri).then(response => {
153
- const markdownText = response.responseText;
165
+ const markdownText = response.responseText ?? '';
154
166
  const lines = Math.min(30, markdownText.split(/\n/).length + 5);
155
- const res = _marked.marked.parse(markdownText);
167
+ const res = _marked.marked.parse(markdownText, {
168
+ async: false
169
+ });
156
170
  const clean = _dompurify.default.sanitize(res);
157
171
  frame.innerHTML = clean;
158
- frame.setAttribute('class', 'doc');
159
- frame.setAttribute('style', `display: block; border: 1px solid; padding: 1em; height: ${lines}em; max-width: 100%; width: 100%; box-sizing: border-box; resize: both; overflow: auto;`);
172
+ applyFrameClasses(frame, 'markdown', lines);
160
173
  }).catch(error => {
161
174
  console.error('Error fetching markdown content:', error);
162
175
  frame.innerHTML = '<p>Error loading content</p>';
@@ -166,11 +179,10 @@ const humanReadablePane = {
166
179
  // render plain text in a PRE element
167
180
  const renderPlainTextContent = function (frame) {
168
181
  kb.fetcher.webOperation('GET', subject.uri).then(response => {
169
- const plainText = response.responseText;
182
+ const plainText = response.responseText ?? '';
170
183
  const lines = Math.min(30, plainText.split(/\n/).length + 5);
171
184
  frame.textContent = plainText;
172
- frame.setAttribute('class', 'doc');
173
- frame.setAttribute('style', `display: block; border: 1px solid; padding: 1em; height: ${lines}em; max-width: 100%; width: 100%; box-sizing: border-box; resize: both; overflow: auto; font-family: monospace; white-space: pre-wrap; word-wrap: break-word;`);
185
+ applyFrameClasses(frame, 'plain-text', lines);
174
186
  }).catch(error => {
175
187
  console.error('Error fetching plain text content:', error);
176
188
  frame.textContent = 'Error loading content';
@@ -178,28 +190,27 @@ const humanReadablePane = {
178
190
  };
179
191
  const setIframeAttributes = (frame, lines) => {
180
192
  frame.setAttribute('src', subject.uri);
181
- frame.setAttribute('class', 'doc');
182
- frame.setAttribute('style', `display: block; border: 1px solid; padding: 1em; height: ${lines}em; max-width: 100%; width: 100%; box-sizing: border-box; resize: both; overflow: auto;`);
193
+ applyFrameClasses(frame, 'iframe', lines);
183
194
  };
184
195
  if (isMarkdown) {
185
196
  // For markdown, use a DIV element and render the content
186
- const frame = myDocument.createElement('DIV');
197
+ const frame = myDocument.createElement('div');
187
198
  renderMarkdownContent(frame);
188
199
  const frameContainer = myDocument.createElement('div');
189
- frameContainer.setAttribute('style', 'display: block; width: 100%; max-width: 100%; box-sizing: border-box;');
200
+ frameContainer.classList.add('human-readable-pane__container');
190
201
  frameContainer.appendChild(frame);
191
202
  div.appendChild(frameContainer);
192
203
  } else if (isPlainText) {
193
204
  // For plain text, use a PRE element and render the content
194
- const frame = myDocument.createElement('PRE');
205
+ const frame = myDocument.createElement('pre');
195
206
  renderPlainTextContent(frame);
196
207
  const frameContainer = myDocument.createElement('div');
197
- frameContainer.setAttribute('style', 'display: block; width: 100%; max-width: 100%; box-sizing: border-box;');
208
+ frameContainer.classList.add('human-readable-pane__container');
198
209
  frameContainer.appendChild(frame);
199
210
  div.appendChild(frameContainer);
200
211
  } else {
201
212
  // For other content types, use IFRAME
202
- const frame = myDocument.createElement('IFRAME');
213
+ const frame = myDocument.createElement('iframe');
203
214
 
204
215
  // Apply sandbox for HTML/XHTML
205
216
  if (ct === 'text/html' || ct === 'application/xhtml+xml') {
@@ -208,7 +219,7 @@ const humanReadablePane = {
208
219
 
209
220
  // Fetch content to calculate lines dynamically
210
221
  kb.fetcher.webOperation('GET', subject.uri).then(response => {
211
- const blobText = response.responseText;
222
+ const blobText = response.responseText ?? '';
212
223
  const newLines = blobText.includes('<script src="https://dokie.li/scripts/dokieli.js">') ? -10 : 5;
213
224
  const lines = Math.min(30, blobText.split(/\n/).length + newLines);
214
225
 
@@ -222,7 +233,7 @@ const humanReadablePane = {
222
233
  setIframeAttributes(frame, 30);
223
234
  });
224
235
  const frameContainer = myDocument.createElement('div');
225
- frameContainer.setAttribute('style', 'display: block; width: 100%; max-width: 100%; box-sizing: border-box;');
236
+ frameContainer.classList.add('human-readable-pane__container');
226
237
  frameContainer.appendChild(frame);
227
238
  div.appendChild(frameContainer);
228
239
  }
@@ -0,0 +1,9 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg"
2
+ viewBox="0 0 24 24"
3
+ fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
4
+ class="lucide lucide-square-arrow-right-enter-icon lucide-square-arrow-right-enter">
5
+
6
+ <path d="m10 16 4-4-4-4"/>
7
+ <path d="M3 12h11"/>
8
+ <path d="M3 8V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3"/>
9
+ </svg>
@@ -0,0 +1,4 @@
1
+ .image-pane__image {
2
+ max-width: 100%;
3
+ max-height: 100%;
4
+ }
@@ -0,0 +1,12 @@
1
+ import type { DataBrowserContext } from 'pane-registry';
2
+ import type { NamedNode } from 'rdflib';
3
+ import './imagePane.css';
4
+ type ImagePane = {
5
+ icon: string;
6
+ name: string;
7
+ label: (subject: NamedNode, context: DataBrowserContext) => string | null;
8
+ render: (subject: NamedNode, context: DataBrowserContext) => HTMLDivElement;
9
+ };
10
+ export declare const imagePane: ImagePane;
11
+ export {};
12
+ //# sourceMappingURL=imagePane.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imagePane.d.ts","sourceRoot":"","sources":["../src/imagePane.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,iBAAiB,CAAA;AAWxB,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,KAAK,MAAM,GAAG,IAAI,CAAA;IACzE,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,KAAK,cAAc,CAAA;CAC5E,CAAA;AAuBD,eAAO,MAAM,SAAS,EAAE,SA+CvB,CAAA"}
package/dist/imagePane.js CHANGED
@@ -5,12 +5,27 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.imagePane = void 0;
7
7
  var UI = _interopRequireWildcard(require("solid-ui"));
8
+ require("./imagePane.css");
8
9
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
9
10
  /* Image Pane
10
11
  **
11
12
  ** This outline pane contains the document contents for an Image document
12
13
  */
13
14
 
15
+ function contentTypeMatch(store, subject, contentTypes) {
16
+ const contentTypesForSubject = store.fetcher.getHeader(subject, 'content-type');
17
+ if (!contentTypesForSubject) {
18
+ return false;
19
+ }
20
+ for (const contentType of contentTypesForSubject) {
21
+ for (const candidate of contentTypes) {
22
+ if (contentType.includes(candidate)) {
23
+ return true;
24
+ }
25
+ }
26
+ }
27
+ return false;
28
+ }
14
29
  const imagePane = exports.imagePane = {
15
30
  icon: UI.icons.originalIconBase + 'tango/22-image-x-generic.png',
16
31
  name: 'image',
@@ -23,19 +38,6 @@ const imagePane = exports.imagePane = {
23
38
 
24
39
  // See also the source pane, which has lower precedence.
25
40
 
26
- const contentTypeMatch = function (store, x, contentTypes) {
27
- const cts = store.fetcher.getHeader(x, 'content-type');
28
- if (cts) {
29
- for (let j = 0; j < cts.length; j++) {
30
- for (let k = 0; k < contentTypes.length; k++) {
31
- if (cts[j].indexOf(contentTypes[k]) >= 0) {
32
- return true;
33
- }
34
- }
35
- }
36
- }
37
- return false;
38
- };
39
41
  const suppressed = ['application/pdf'];
40
42
  if (contentTypeMatch(store, subject, suppressed)) {
41
43
  return null;
@@ -46,8 +48,8 @@ const imagePane = exports.imagePane = {
46
48
  const myDocument = context.dom;
47
49
  const store = context.session.store;
48
50
  const div = myDocument.createElement('div');
49
- div.setAttribute('class', 'imageView');
50
- const img = myDocument.createElement('IMG');
51
+ div.setAttribute('class', 'image-pane');
52
+ const img = myDocument.createElement('img');
51
53
 
52
54
  // get image with authenticated fetch
53
55
  store.fetcher._fetch(subject.uri).then(function (response) {
@@ -56,12 +58,8 @@ const imagePane = exports.imagePane = {
56
58
  const objectURL = URL.createObjectURL(myBlob);
57
59
  img.setAttribute('src', objectURL); // w640 h480 //
58
60
  });
59
- img.setAttribute('style', 'max-width: 100%; max-height: 100%;');
60
- // div.style['max-width'] = '640'
61
- // div.style['max-height'] = '480'
62
- const tr = myDocument.createElement('TR'); // why need tr?
63
- tr.appendChild(img);
64
- div.appendChild(tr);
61
+ img.classList.add('image-pane__image');
62
+ div.appendChild(img);
65
63
  return div;
66
64
  }
67
65
  };
@@ -0,0 +1,14 @@
1
+ .internalPaneContent {
2
+ background-color: #ddddff;
3
+ padding: var(--spacing-xs, 0.5em);
4
+ border-radius: 1rem;
5
+ }
6
+
7
+ .internalPaneControls {
8
+ width: 100%;
9
+ margin: var(--spacing-sm, 1em);
10
+ }
11
+
12
+ .internalPaneDeleteButton {
13
+ height: var(--icon-base, 2em);
14
+ }