@semapps/activitypub-components 1.1.3 → 1.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/dist/index.cjs.js CHANGED
@@ -4,19 +4,24 @@ var $583VT$reactadmin = require("react-admin");
4
4
  var $583VT$rainputrichtext = require("ra-input-rich-text");
5
5
  var $583VT$tiptapextensionplaceholder = require("@tiptap/extension-placeholder");
6
6
  var $583VT$muimaterial = require("@mui/material");
7
- var $583VT$muistylesmakeStyles = require("@mui/styles/makeStyles");
7
+ var $583VT$tssreactmui = require("tss-react/mui");
8
8
  var $583VT$muiiconsmaterialSend = require("@mui/icons-material/Send");
9
9
  var $583VT$semappssemanticdataprovider = require("@semapps/semantic-data-provider");
10
10
  var $583VT$semappsauthprovider = require("@semapps/auth-provider");
11
- var $583VT$reactquery = require("react-query");
12
- var $583VT$rdfvalidateshacl = require("rdf-validate-shacl");
11
+ var $583VT$tanstackreactquery = require("@tanstack/react-query");
12
+ var $583VT$jsonld = require("jsonld");
13
13
  var $583VT$rdfext = require("rdf-ext");
14
- var $583VT$rdfjsparserjsonld = require("@rdfjs/parser-jsonld");
15
- var $583VT$readablewebtonodestream = require("readable-web-to-node-stream");
16
14
  var $583VT$rdfjsparsern3 = require("@rdfjs/parser-n3");
15
+ var $583VT$readablestream = require("readable-stream");
16
+ var $583VT$shaclengine = require("shacl-engine");
17
+ var $583VT$activitypodsshapedefinitions = require("@activitypods/shape-definitions");
18
+ var $583VT$readablewebtonodestream = require("readable-web-to-node-stream");
17
19
  var $583VT$tiptapcore = require("@tiptap/core");
18
20
  var $583VT$tiptapextensionmention = require("@tiptap/extension-mention");
19
21
  var $583VT$semappsfieldcomponents = require("@semapps/field-components");
22
+ var $583VT$ldoconnected = require("@ldo/connected");
23
+ var $583VT$ldoconnectedsolid = require("@ldo/connected-solid");
24
+ var $583VT$activitypodsldoshapes = require("@activitypods/ldo-shapes");
20
25
  var $583VT$tiptapreact = require("@tiptap/react");
21
26
  var $583VT$tippyjs = require("tippy.js");
22
27
 
@@ -29,19 +34,20 @@ function $parcel$interopDefault(a) {
29
34
  return a && a.__esModule ? a.default : a;
30
35
  }
31
36
 
32
- $parcel$export(module.exports, "CommentsField", () => $2e5504cc4159ca8d$export$2e2bcd8739ae039);
33
- $parcel$export(module.exports, "CollectionList", () => $505d598a33288aad$export$2e2bcd8739ae039);
34
- $parcel$export(module.exports, "ReferenceCollectionField", () => $b0c94a9bdea99da5$export$2e2bcd8739ae039);
37
+ $parcel$export(module.exports, "CommentsField", () => $484cf98a20a766f7$export$2e2bcd8739ae039);
38
+ $parcel$export(module.exports, "CollectionList", () => $78e7af8b8abfe6a7$export$2e2bcd8739ae039);
39
+ $parcel$export(module.exports, "ReferenceCollectionField", () => $63048bed1787ac97$export$2e2bcd8739ae039);
35
40
  $parcel$export(module.exports, "useCollection", () => $5ca5f7e9fc1c3544$export$2e2bcd8739ae039);
41
+ $parcel$export(module.exports, "useTypedCollection", () => $c778e69ff9ab90c6$export$2e2bcd8739ae039);
36
42
  $parcel$export(module.exports, "useInbox", () => $486f741c94cd8f74$export$2e2bcd8739ae039);
37
43
  $parcel$export(module.exports, "useNodeinfo", () => $59fc2d2cba62bd8e$export$2e2bcd8739ae039);
38
44
  $parcel$export(module.exports, "useOutbox", () => $456aea3814dded7d$export$2e2bcd8739ae039);
39
- $parcel$export(module.exports, "useWebfinger", () => $5b61553556e35016$export$2e2bcd8739ae039);
40
- $parcel$export(module.exports, "useMentions", () => $968ea07fb81eda0b$export$2e2bcd8739ae039);
41
- $parcel$export(module.exports, "ACTIVITY_TYPES", () => $ebea823cebb2f44b$export$1ec8e53e7d982d22);
42
- $parcel$export(module.exports, "ACTOR_TYPES", () => $ebea823cebb2f44b$export$9649665d7ccb0dc2);
43
- $parcel$export(module.exports, "OBJECT_TYPES", () => $ebea823cebb2f44b$export$c49cfb2681596b20);
44
- $parcel$export(module.exports, "PUBLIC_URI", () => $ebea823cebb2f44b$export$4d8d554031975581);
45
+ $parcel$export(module.exports, "useWebfinger", () => $10f3abf411a5e9d4$export$2e2bcd8739ae039);
46
+ $parcel$export(module.exports, "useMentions", () => $351e26ed1a2af792$export$2e2bcd8739ae039);
47
+ $parcel$export(module.exports, "ACTIVITY_TYPES", () => $ca4f6bb216ebdfdd$export$1ec8e53e7d982d22);
48
+ $parcel$export(module.exports, "ACTOR_TYPES", () => $ca4f6bb216ebdfdd$export$9649665d7ccb0dc2);
49
+ $parcel$export(module.exports, "OBJECT_TYPES", () => $ca4f6bb216ebdfdd$export$c49cfb2681596b20);
50
+ $parcel$export(module.exports, "PUBLIC_URI", () => $ca4f6bb216ebdfdd$export$4d8d554031975581);
45
51
  // Components
46
52
 
47
53
 
@@ -56,7 +62,7 @@ $parcel$export(module.exports, "PUBLIC_URI", () => $ebea823cebb2f44b$export$4d8d
56
62
 
57
63
 
58
64
 
59
- const $ebea823cebb2f44b$export$1ec8e53e7d982d22 = {
65
+ const $ca4f6bb216ebdfdd$export$1ec8e53e7d982d22 = {
60
66
  ACCEPT: 'Accept',
61
67
  ADD: 'Add',
62
68
  ANNOUNCE: 'Announce',
@@ -86,14 +92,14 @@ const $ebea823cebb2f44b$export$1ec8e53e7d982d22 = {
86
92
  UPDATE: 'Update',
87
93
  VIEW: 'View'
88
94
  };
89
- const $ebea823cebb2f44b$export$9649665d7ccb0dc2 = {
95
+ const $ca4f6bb216ebdfdd$export$9649665d7ccb0dc2 = {
90
96
  APPLICATION: 'Application',
91
97
  GROUP: 'Group',
92
98
  ORGANIZATION: 'Organization',
93
99
  PERSON: 'Person',
94
100
  SERVICE: 'Service'
95
101
  };
96
- const $ebea823cebb2f44b$export$c49cfb2681596b20 = {
102
+ const $ca4f6bb216ebdfdd$export$c49cfb2681596b20 = {
97
103
  ARTICLE: 'Article',
98
104
  AUDIO: 'Audio',
99
105
  DOCUMENT: 'Document',
@@ -107,7 +113,11 @@ const $ebea823cebb2f44b$export$c49cfb2681596b20 = {
107
113
  TOMBSTONE: 'Tombstone',
108
114
  VIDEO: 'Video'
109
115
  };
110
- const $ebea823cebb2f44b$export$4d8d554031975581 = 'https://www.w3.org/ns/activitystreams#Public';
116
+ const $ca4f6bb216ebdfdd$export$4d8d554031975581 = 'https://www.w3.org/ns/activitystreams#Public';
117
+
118
+
119
+
120
+
111
121
 
112
122
 
113
123
 
@@ -138,6 +148,45 @@ const $03510abb28fd3d8a$export$34aed805e991a647 = (iterable, predicate)=>{
138
148
  return true;
139
149
  });
140
150
  };
151
+ const $03510abb28fd3d8a$export$2684df65fa35e98e = async (jsonLdObject)=>{
152
+ // Convert JSON-LD object to N-Quads string
153
+ const nquads = await (0, ($parcel$interopDefault($583VT$jsonld))).toRDF(jsonLdObject, {
154
+ format: 'application/n-quads'
155
+ });
156
+ // Parse N-Quads string to RDF/JS quads
157
+ const parser = new (0, ($parcel$interopDefault($583VT$rdfjsparsern3)))();
158
+ const quadStream = parser.import((0, $583VT$readablestream.Readable).from([
159
+ nquads
160
+ ]));
161
+ const dataset = await (0, ($parcel$interopDefault($583VT$rdfext))).dataset().import(quadStream);
162
+ return dataset;
163
+ };
164
+ const $03510abb28fd3d8a$export$7089f01fea2fc5c2 = async (jsonLdObject)=>{
165
+ // Convert JSON-LD object to N-Quads string
166
+ const nquads = await (0, ($parcel$interopDefault($583VT$jsonld))).toRDF(jsonLdObject, {
167
+ format: 'application/n-quads'
168
+ });
169
+ // Parse N-Quads string to RDF/JS quads
170
+ const parser = new (0, ($parcel$interopDefault($583VT$rdfjsparsern3)))();
171
+ const quadStream = parser.import((0, $583VT$readablestream.Readable).from([
172
+ nquads
173
+ ]));
174
+ // Convert the quad stream to an array of quads
175
+ const quads = [];
176
+ quadStream.on('data', (quad)=>{
177
+ quads.push(quad);
178
+ });
179
+ return new Promise((resolve, reject)=>{
180
+ quadStream.on('end', ()=>{
181
+ resolve(quads);
182
+ });
183
+ quadStream.on('error', (error)=>{
184
+ reject(error);
185
+ });
186
+ });
187
+ };
188
+
189
+
141
190
 
142
191
 
143
192
 
@@ -145,10 +194,8 @@ const $03510abb28fd3d8a$export$34aed805e991a647 = (iterable, predicate)=>{
145
194
 
146
195
 
147
196
 
148
- // Cache of SHACL validators
149
- const $24b34de916fb30a8$var$validatorCache = {};
150
197
  // Helper function to convert a string to a Node.js Readable stream
151
- const $24b34de916fb30a8$var$stringToStream = (str)=>{
198
+ const $a370eba7b7eca32b$export$7b2e5d6b7377fcaf = (str)=>{
152
199
  // Create a TextEncoder to convert string to Uint8Array
153
200
  const encoder = new TextEncoder();
154
201
  const uint8Array = encoder.encode(str);
@@ -162,82 +209,135 @@ const $24b34de916fb30a8$var$stringToStream = (str)=>{
162
209
  // Convert the web ReadableStream to a Node.js Readable stream
163
210
  return new (0, $583VT$readablewebtonodestream.ReadableWebToNodeStream)(readableStream);
164
211
  };
165
- // Helper function to parse JSON-LD and convert to RDF-ext quads
166
- const $24b34de916fb30a8$export$2684df65fa35e98e = async (jsonLdObj, context)=>{
212
+ const $a370eba7b7eca32b$export$7304a15200aa09e5 = async (turtleData)=>{
213
+ // Convert Turtle data to a stream
214
+ const textStream = $a370eba7b7eca32b$export$7b2e5d6b7377fcaf(turtleData);
215
+ // Use ParserN3 which outputs rdf-ext compatible quads directly
216
+ const parser = new (0, ($parcel$interopDefault($583VT$rdfjsparsern3)))({
217
+ factory: (0, ($parcel$interopDefault($583VT$rdfext)))
218
+ });
219
+ const quadStream = parser.import(textStream);
220
+ const dataset = await (0, ($parcel$interopDefault($583VT$rdfext))).dataset().import(quadStream);
221
+ return dataset;
222
+ };
223
+
224
+
225
+ const $24b34de916fb30a8$var$activitystreams = (0, $583VT$activitypodsshapedefinitions.jsonld).activitystreams;
226
+ // Cache of SHACL validators
227
+ const $24b34de916fb30a8$var$validatorCache = {};
228
+ /**
229
+ * Returns a SHACL validator for ActivityStreams shapes.
230
+ *
231
+ * This function creates a SHACL validator for ActivityStreams shapes using the
232
+ * `@activitypods/shape-definitions` package. It caches the validator to avoid
233
+ * creating it multiple times.
234
+ *
235
+ * @returns A Promise that resolves to a SHACL Validator instance.
236
+ */ const $24b34de916fb30a8$export$8b707c2a07270e94 = async ()=>{
237
+ // Check if the validator is already cached
238
+ if ($24b34de916fb30a8$var$validatorCache.activityStreams) return $24b34de916fb30a8$var$validatorCache.activityStreams;
167
239
  try {
168
- // Add context to the JSON-LD object if needed
169
- const jsonLdWithContext = {
170
- ...jsonLdObj,
171
- '@context': context
172
- };
173
- // Convert JSON-LD object to string
174
- const jsonString = JSON.stringify(jsonLdWithContext);
175
- // Convert string to stream using the helper function
176
- const textStream = $24b34de916fb30a8$var$stringToStream(jsonString);
177
- // Use the JsonLdParser that outputs rdf-ext compatible quads directly
178
- const parser = new (0, ($parcel$interopDefault($583VT$rdfjsparserjsonld)))({
179
- factory: (0, ($parcel$interopDefault($583VT$rdfext)))
240
+ const shapeDataset = await (0, $a370eba7b7eca32b$export$7304a15200aa09e5)($24b34de916fb30a8$var$activitystreams);
241
+ // Create and cache the SHACL validator using the dataset
242
+ $24b34de916fb30a8$var$validatorCache.activityStreams = new (0, $583VT$shaclengine.Validator)(shapeDataset, {
243
+ factory: (0, ($parcel$interopDefault($583VT$rdfext))),
244
+ debug: true
180
245
  });
181
- const quadStream = parser.import(textStream);
182
- // Collect quads into a dataset
183
- const dataset = (0, ($parcel$interopDefault($583VT$rdfext))).dataset();
184
- for await (const quad of quadStream)dataset.add(quad);
185
- return dataset;
246
+ return $24b34de916fb30a8$var$validatorCache.activityStreams;
186
247
  } catch (error) {
187
- console.error('Error parsing JSON-LD:', error);
188
- throw error;
248
+ throw new Error(`Failed to create ActivityStreams validator: ${error instanceof Error ? error.message : 'Unknown error'}`);
189
249
  }
250
+ const shapeDataset = await (0, $a370eba7b7eca32b$export$7304a15200aa09e5)($24b34de916fb30a8$var$activitystreams);
251
+ // Create and cache the SHACL validator using the dataset
252
+ $24b34de916fb30a8$var$validatorCache.activityStreams = new (0, $583VT$shaclengine.Validator)(shapeDataset, {
253
+ factory: (0, ($parcel$interopDefault($583VT$rdfext))),
254
+ debug: true
255
+ });
256
+ return $24b34de916fb30a8$var$validatorCache.activitystreams;
190
257
  };
191
258
  // Helper function to load a SHACL shape and return a validator
192
259
  const $24b34de916fb30a8$export$6de257db5bb9fd74 = async (shapeUri)=>{
193
260
  // Check if the validator is already cached
194
261
  if ($24b34de916fb30a8$var$validatorCache[shapeUri]) return $24b34de916fb30a8$var$validatorCache[shapeUri];
195
- const response = await fetch(shapeUri, {
196
- headers: {
197
- Accept: 'text/turtle'
198
- }
199
- });
200
- if (!response.ok) throw new Error(`Failed to load shape: ${response.status} ${response.statusText}`);
201
- // Get the Turtle data as text
202
- const turtleData = await response.text();
203
- // Convert text to stream using the helper function
204
- const textStream = $24b34de916fb30a8$var$stringToStream(turtleData);
205
- // Use ParserN3 which outputs rdf-ext compatible quads directly
206
- const parser = new (0, ($parcel$interopDefault($583VT$rdfjsparsern3)))({
207
- factory: (0, ($parcel$interopDefault($583VT$rdfext)))
208
- });
209
- const quadStream = parser.import(textStream);
210
- // Collect quads into a dataset
211
- const shapeDataset = (0, ($parcel$interopDefault($583VT$rdfext))).dataset();
212
- for await (const quad of quadStream)shapeDataset.add(quad);
213
- // Create and cache the SHACL validator using the dataset
214
- $24b34de916fb30a8$var$validatorCache[shapeUri] = new (0, ($parcel$interopDefault($583VT$rdfvalidateshacl)))(shapeDataset, {
215
- factory: (0, ($parcel$interopDefault($583VT$rdfext)))
216
- });
217
- return $24b34de916fb30a8$var$validatorCache[shapeUri];
262
+ try {
263
+ const response = await fetch(shapeUri, {
264
+ headers: {
265
+ Accept: 'text/turtle'
266
+ }
267
+ });
268
+ if (!response.ok) throw new Error(`Failed to load shape: ${response.status} ${response.statusText}`);
269
+ // Get the Turtle data as text
270
+ const turtleData = await response.text();
271
+ const shapeDataset = await (0, $a370eba7b7eca32b$export$7304a15200aa09e5)(turtleData);
272
+ // Create and cache the SHACL validator using the dataset
273
+ $24b34de916fb30a8$var$validatorCache[shapeUri] = new (0, $583VT$shaclengine.Validator)(shapeDataset, {
274
+ factory: (0, ($parcel$interopDefault($583VT$rdfext)))
275
+ });
276
+ return $24b34de916fb30a8$var$validatorCache[shapeUri];
277
+ } catch (error) {
278
+ throw new Error(`Failed to create SHACL validator for ${shapeUri}: ${error instanceof Error ? error.message : 'Unknown error'}`);
279
+ }
218
280
  };
219
- const $24b34de916fb30a8$export$1558e55ae3912bbb = async (items, shaclValidator, context)=>{
281
+ /**
282
+ * Validates an array of items against a SHACL shape and returns the validation results.
283
+ *
284
+ * @param items The items to validate
285
+ * @param shaclValidator The SHACL validator to use
286
+ * @param context The context to use for the items
287
+ *
288
+ * @returns An array of objects containing the item and its validation result
289
+ */ const $24b34de916fb30a8$export$1558e55ae3912bbb = async (items, shaclValidator, context)=>{
220
290
  if (!shaclValidator) throw new Error('validateItems: shaclValidator is required');
221
- if (!context) throw new Error('validateItems: context is required');
222
291
  return Promise.all(items.map(async (item)=>{
223
292
  try {
293
+ if (!item['@context']) item['@context'] = context;
224
294
  // Create a dataset from the item's JSON-LD
225
- const itemDataset = await $24b34de916fb30a8$export$2684df65fa35e98e(item, context);
295
+ const itemDataset = await (0, $03510abb28fd3d8a$export$2684df65fa35e98e)(item);
226
296
  // Validate against the SHACL shape
227
- const report = shaclValidator?.validate(itemDataset);
297
+ const report = shaclValidator.validate({
298
+ dataset: itemDataset
299
+ });
228
300
  return {
229
301
  item: item,
230
- isValid: report?.conforms
302
+ isValid: report.conforms
231
303
  };
232
304
  } catch (error) {
233
- console.error(`Error validating item ${item.id}:`, error);
234
305
  return {
235
306
  item: item,
236
- isValid: false
307
+ isValid: false,
308
+ error: error
237
309
  };
238
310
  }
239
311
  }));
240
312
  };
313
+ /**
314
+ * Validates a subject against a set of SHACL shapes and returns the typed item if valid.
315
+ *
316
+ * @param subjectUri The subject to validate
317
+ * @param dataset The dataset containing the subject
318
+ * @param shapeTypes The shape types to validate against
319
+ * @param validator The SHACL validator to use
320
+ *
321
+ * @returns A typed item if valid, or null if not valid
322
+ */ const $24b34de916fb30a8$export$c4cb1062f0ffb837 = async (subjectUri, dataset, shapeTypes, validator)=>{
323
+ const validationReport = await validator.validate(// Terms means the entry point from which should be validated, in our case the current item.
324
+ {
325
+ dataset: dataset,
326
+ terms: [
327
+ (0, ($parcel$interopDefault($583VT$rdfext))).namedNode(subjectUri)
328
+ ]
329
+ }, // Here, terms means the shapes to validate against.
330
+ {
331
+ terms: shapeTypes.map((shapeType)=>(0, ($parcel$interopDefault($583VT$rdfext))).namedNode(shapeType.shape))
332
+ });
333
+ if (!validationReport.conforms) return null;
334
+ const { results: results } = validationReport;
335
+ // Find the shape that matched the item in the report results.
336
+ const shapeType = shapeTypes.find((st)=>results.find((res)=>res.focusNode === subjectUri && res.shape === st.shape));
337
+ if (!shapeType) return null;
338
+ const typedItem = dataset.usingType(shapeType).fromSubject(subjectUri);
339
+ return typedItem;
340
+ };
241
341
 
242
342
 
243
343
  // Used to avoid re-renders
@@ -255,14 +355,17 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
255
355
  items
256
356
  ]);
257
357
  // Dereference all items, if necessary (even if shouldDereference is false, the hook needs to be called).
258
- const itemQueries = (0, $583VT$reactquery.useQueries)(!shouldDereference ? $5ca5f7e9fc1c3544$var$emptyArray : items.filter((item)=>typeof item === 'string').map((itemUri)=>({
259
- queryKey: [
260
- 'resource',
261
- itemUri
262
- ],
263
- queryFn: async ()=>(await dataProvider.fetch(itemUri)).json,
264
- staleTime: Infinity // Activities are immutable, so no need to refetch..
265
- })));
358
+ const itemQueries = (0, $583VT$tanstackreactquery.useQueries)({
359
+ queries: !shouldDereference ? $5ca5f7e9fc1c3544$var$emptyArray : items.filter((item)=>typeof item === 'string').map((itemUri)=>({
360
+ queryKey: [
361
+ 'resource',
362
+ itemUri
363
+ ],
364
+ queryFn: async ()=>(await dataProvider.fetch(itemUri)).json,
365
+ // TODO: Collections don't have to contain activities only, do they?
366
+ staleTime: Infinity // Activities are immutable, so no need to refetch..
367
+ }))
368
+ });
266
369
  if (!shouldDereference) return {
267
370
  loadedItems: items,
268
371
  isLoading: false,
@@ -281,7 +384,7 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
281
384
  };
282
385
  };
283
386
  /**
284
- * Subscribe a collection. Supports pagination.
387
+ * Subscribe toa collection. Supports pagination.
285
388
  * @param predicateOrUrl The collection URI or the predicate to get the collection URI from the identity (webId).
286
389
  * @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: false }`
287
390
  */ const $5ca5f7e9fc1c3544$var$useCollection = (predicateOrUrl, options = {})=>{
@@ -290,7 +393,7 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
290
393
  const [totalItems, setTotalItems] = (0, $583VT$react.useState)(0);
291
394
  const [isPaginated, setIsPaginated] = (0, $583VT$react.useState)(false); // true if the collection is paginated
292
395
  const [yieldsTotalItems, setYieldsTotalItems] = (0, $583VT$react.useState)(false); // true if the collection server yields totalItems
293
- const queryClient = (0, $583VT$reactquery.useQueryClient)();
396
+ const queryClient = (0, $583VT$tanstackreactquery.useQueryClient)();
294
397
  const [hasLiveUpdates, setHasLiveUpdates] = (0, $583VT$react.useState)({
295
398
  status: 'connecting'
296
399
  });
@@ -299,7 +402,7 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
299
402
  // Get collectionUrl from webId predicate or URL.
300
403
  const collectionUrl = (0, $583VT$react.useMemo)(()=>{
301
404
  if (predicateOrUrl) {
302
- if (predicateOrUrl.startsWith('http')) return predicateOrUrl;
405
+ if (predicateOrUrl.startsWith('http') || predicateOrUrl.startsWith('did:ng:')) return predicateOrUrl;
303
406
  if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
304
407
  }
305
408
  return undefined;
@@ -317,10 +420,16 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
317
420
  let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
318
421
  // If first page, handle this here.
319
422
  if ((json.type === 'OrderedCollection' || json.type === 'Collection') && json.first) {
320
- if (json.first?.items) {
321
- if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
423
+ const firstItems = json.first?.items || json.first?.orderedItems;
424
+ if (firstItems) {
425
+ if (firstItems.length === 0 && json.first?.next) // Special case where the first property is an object without items
322
426
  ({ json: json } = await dataProvider.fetch(json.first?.next));
323
- else json = json.first;
427
+ else // Add the @context to the json, so that it can be used to expand the items
428
+ // That is necessary for the validation of the items
429
+ json = {
430
+ '@context': json['@context'],
431
+ ...json.first
432
+ };
324
433
  } else // Fetch the first page
325
434
  ({ json: json } = await dataProvider.fetch(json.first));
326
435
  }
@@ -342,6 +451,8 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
342
451
  // Validate the json with the SHACL shape
343
452
  if (shaclShapeUri !== '' && json[itemsKey] && json[itemsKey].length > 0) try {
344
453
  if (!json['@context']) throw new Error(`No context returned by the server.\nA context is required to expand the collection's items and validate them.`);
454
+ // TODO: Research: Is this used with the multi-purpose viewer already?
455
+ // How can multiple shapes be validated? Can we get this typed here?
345
456
  const shaclValidator = await (0, $24b34de916fb30a8$export$6de257db5bb9fd74)(shaclShapeUri);
346
457
  const validatedResults = await (0, $24b34de916fb30a8$export$1558e55ae3912bbb)((0, $03510abb28fd3d8a$export$e57ff0f701c44363)(json[itemsKey]), shaclValidator, json['@context']);
347
458
  // Keep only the valid item in the collection
@@ -360,16 +471,19 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
360
471
  shaclShapeUri
361
472
  ]);
362
473
  // Use infiniteQuery to handle pagination, fetching, etc.
363
- const { data: pageData, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $583VT$reactquery.useInfiniteQuery)([
364
- 'collection',
365
- {
366
- collectionUrl: collectionUrl,
367
- shaclShapeUri: shaclShapeUri
368
- }
369
- ], fetchCollection, {
474
+ const { data: pageData, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $583VT$tanstackreactquery.useInfiniteQuery)({
475
+ queryKey: [
476
+ 'collection',
477
+ {
478
+ collectionUrl: collectionUrl,
479
+ shaclShapeUri: shaclShapeUri
480
+ }
481
+ ],
370
482
  enabled: !!(collectionUrl && identity?.id),
483
+ initialPageParam: collectionUrl,
371
484
  getNextPageParam: (lastPage)=>lastPage.next,
372
- getPreviousPageParam: (firstPage)=>firstPage.prev
485
+ getPreviousPageParam: (firstPage)=>firstPage.prev,
486
+ queryFn: fetchCollection
373
487
  });
374
488
  // Put all items together in a list (and dereference, if required).
375
489
  const { loadedItems: items, isLoading: isLoadingItems, isFetching: isFetchingItems, errors: itemErrors } = $5ca5f7e9fc1c3544$var$useItemsFromPages(pageData?.pages ?? $5ca5f7e9fc1c3544$var$emptyArray, dereferenceItems);
@@ -399,13 +513,14 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
399
513
  oldData.pages = pages;
400
514
  return oldData;
401
515
  });
402
- if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
403
- 'collection',
404
- {
405
- collectionUrl: collectionUrl
406
- }
407
- ], {
408
- active: true,
516
+ if (shouldRefetch) setTimeout(async ()=>queryClient.refetchQueries({
517
+ queryKey: [
518
+ 'collection',
519
+ {
520
+ collectionUrl: collectionUrl
521
+ }
522
+ ],
523
+ type: 'active',
409
524
  exact: true
410
525
  }), typeof shouldRefetch === 'number' ? shouldRefetch : 2000);
411
526
  }, [
@@ -437,13 +552,14 @@ const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
437
552
  oldData.pages = pages;
438
553
  return oldData;
439
554
  });
440
- if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
441
- 'collection',
442
- {
443
- collectionUrl: collectionUrl
444
- }
445
- ], {
446
- active: true,
555
+ if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries({
556
+ queryKey: [
557
+ 'collection',
558
+ {
559
+ collectionUrl: collectionUrl
560
+ }
561
+ ],
562
+ type: 'active',
447
563
  exact: true
448
564
  }), typeof shouldRefetch === 'number' ? shouldRefetch : 2000);
449
565
  }, [
@@ -649,7 +765,7 @@ var $456aea3814dded7d$export$2e2bcd8739ae039 = $456aea3814dded7d$var$useOutbox;
649
765
  // Fix a bug in the current version of the mention extension
650
766
  // (The { id, label } object is located inside the id property)
651
767
  // See https://github.com/ueberdosis/tiptap/pull/1322
652
- const $9b1343b281972d72$var$CustomMention = (0, ($parcel$interopDefault($583VT$tiptapextensionmention))).extend({
768
+ const $b8eb0286f5686802$var$CustomMention = (0, ($parcel$interopDefault($583VT$tiptapextensionmention))).extend({
653
769
  renderHTML ({ node: node, HTMLAttributes: HTMLAttributes }) {
654
770
  return [
655
771
  'span',
@@ -690,10 +806,10 @@ const $9b1343b281972d72$var$CustomMention = (0, ($parcel$interopDefault($583VT$t
690
806
  };
691
807
  }
692
808
  });
693
- var $9b1343b281972d72$export$2e2bcd8739ae039 = $9b1343b281972d72$var$CustomMention;
809
+ var $b8eb0286f5686802$export$2e2bcd8739ae039 = $b8eb0286f5686802$var$CustomMention;
694
810
 
695
811
 
696
- const $703eba3e46be7ee5$var$useStyles = (0, ($parcel$interopDefault($583VT$muistylesmakeStyles)))((theme)=>({
812
+ const $a2b68b573919c8a3$var$useStyles = (0, $583VT$tssreactmui.makeStyles)()((theme)=>({
697
813
  form: {
698
814
  marginTop: -12 // Negative margin to keep the form close to the label
699
815
  },
@@ -739,12 +855,12 @@ const $703eba3e46be7ee5$var$useStyles = (0, ($parcel$interopDefault($583VT$muist
739
855
  marginBottom: 15
740
856
  }
741
857
  }));
742
- const $703eba3e46be7ee5$var$EmptyToolbar = ()=>null;
743
- const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder: placeholder, helperText: helperText, mentions: mentions, userResource: userResource, addItem: addItem, removeItem: removeItem })=>{
858
+ const $a2b68b573919c8a3$var$EmptyToolbar = ()=>null;
859
+ const $a2b68b573919c8a3$var$PostCommentForm = ({ context: context, placeholder: placeholder, helperText: helperText, mentions: mentions, userResource: userResource, addItem: addItem, removeItem: removeItem })=>{
744
860
  const record = (0, $583VT$reactadmin.useRecordContext)();
745
861
  const { data: identity, isLoading: isLoading } = (0, $583VT$reactadmin.useGetIdentity)();
746
862
  const userDataModel = (0, $583VT$semappssemanticdataprovider.useDataModel)(userResource);
747
- const classes = $703eba3e46be7ee5$var$useStyles();
863
+ const { classes: classes } = $a2b68b573919c8a3$var$useStyles();
748
864
  const notify = (0, $583VT$reactadmin.useNotify)();
749
865
  const outbox = (0, $456aea3814dded7d$export$2e2bcd8739ae039)();
750
866
  const [expanded, setExpanded] = (0, $583VT$react.useState)(false);
@@ -754,11 +870,14 @@ const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder:
754
870
  const mentions = Array.from(document.body.getElementsByClassName('mention'));
755
871
  const mentionedUsersUris = [];
756
872
  mentions.forEach((node)=>{
873
+ // @ts-expect-error TS(7015): Element implicitly has an 'any' type because index... Remove this comment to see the full error message
757
874
  const userUri = node.attributes['data-mention-id'].value;
875
+ // @ts-expect-error TS(7015): Element implicitly has an 'any' type because index... Remove this comment to see the full error message
758
876
  const userLabel = node.attributes['data-mention-label'].value;
759
877
  const link = document.createElement('a');
760
878
  link.setAttribute('href', `${new URL(window.location.href).origin}/${userResource}/${encodeURIComponent(userUri)}/show`);
761
879
  link.textContent = `@${userLabel}`;
880
+ // @ts-expect-error TS(2531): Object is possibly 'null'.
762
881
  node.parentNode.replaceChild(link, node);
763
882
  mentionedUsersUris.push(userUri);
764
883
  });
@@ -768,10 +887,10 @@ const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder:
768
887
  else {
769
888
  const tempId = Date.now();
770
889
  const note = {
771
- type: (0, $ebea823cebb2f44b$export$c49cfb2681596b20).NOTE,
890
+ type: (0, $ca4f6bb216ebdfdd$export$c49cfb2681596b20).NOTE,
772
891
  attributedTo: outbox.owner,
773
892
  content: document.body.innerHTML,
774
- inReplyTo: record[context],
893
+ inReplyTo: record?.[context],
775
894
  published: new Date().toISOString()
776
895
  };
777
896
  try {
@@ -785,7 +904,7 @@ const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder:
785
904
  ...note,
786
905
  to: [
787
906
  ...mentionedUsersUris,
788
- (0, $ebea823cebb2f44b$export$4d8d554031975581)
907
+ (0, $ca4f6bb216ebdfdd$export$4d8d554031975581)
789
908
  ]
790
909
  });
791
910
  notify("Commentaire post\xe9 avec succ\xe8s", {
@@ -824,13 +943,15 @@ const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder:
824
943
  onClick: openAuthIfDisconnected,
825
944
  children: [
826
945
  /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $583VT$muimaterial.Avatar), {
827
- src: identity?.webIdData?.[userDataModel?.fieldsMapping?.image] || identity?.profileData?.[userDataModel?.fieldsMapping?.image],
946
+ src: // @ts-expect-error TS(2339): Property 'image' does not exist on type '{ title: ... Remove this comment to see the full error message
947
+ identity?.webIdData?.[userDataModel?.fieldsMapping?.image] || // @ts-expect-error TS(2339): Property 'image' does not exist on type '{ title: ... Remove this comment to see the full error message
948
+ identity?.profileData?.[userDataModel?.fieldsMapping?.image],
828
949
  className: classes.avatar
829
950
  }),
830
951
  /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $583VT$rainputrichtext.RichTextInput), {
831
952
  source: "comment",
832
953
  label: " ",
833
- toolbar: /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)($703eba3e46be7ee5$var$EmptyToolbar, {}),
954
+ toolbar: /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)($a2b68b573919c8a3$var$EmptyToolbar, {}),
834
955
  fullWidth: true,
835
956
  classes: {
836
957
  editorContent: classes.editorContent
@@ -841,11 +962,12 @@ const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder:
841
962
  setExpanded(true);
842
963
  },
843
964
  extensions: [
965
+ // @ts-expect-error TS(2461): Type 'Extensions | undefined' is not an array type... Remove this comment to see the full error message
844
966
  ...(0, $583VT$rainputrichtext.DefaultEditorOptions).extensions,
845
967
  placeholder ? (0, ($parcel$interopDefault($583VT$tiptapextensionplaceholder))).configure({
846
968
  placeholder: placeholder
847
969
  }) : null,
848
- mentions ? (0, $9b1343b281972d72$export$2e2bcd8739ae039).configure({
970
+ mentions ? (0, $b8eb0286f5686802$export$2e2bcd8739ae039).configure({
849
971
  HTMLAttributes: {
850
972
  class: 'mention'
851
973
  },
@@ -877,7 +999,7 @@ const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder:
877
999
  ]
878
1000
  });
879
1001
  };
880
- var $703eba3e46be7ee5$export$2e2bcd8739ae039 = $703eba3e46be7ee5$var$PostCommentForm;
1002
+ var $a2b68b573919c8a3$export$2e2bcd8739ae039 = $a2b68b573919c8a3$var$PostCommentForm;
881
1003
 
882
1004
 
883
1005
 
@@ -887,7 +1009,7 @@ var $703eba3e46be7ee5$export$2e2bcd8739ae039 = $703eba3e46be7ee5$var$PostComment
887
1009
 
888
1010
 
889
1011
 
890
- const $d68cd57b2d06b6d5$var$useStyles = (0, ($parcel$interopDefault($583VT$muistylesmakeStyles)))(()=>({
1012
+ const $0120d12473c65b5c$var$useStyles = (0, $583VT$tssreactmui.makeStyles)()(()=>({
891
1013
  container: {
892
1014
  paddingLeft: 80,
893
1015
  marginTop: 8,
@@ -931,13 +1053,13 @@ const $d68cd57b2d06b6d5$var$useStyles = (0, ($parcel$interopDefault($583VT$muist
931
1053
  marginTop: 5
932
1054
  }
933
1055
  }));
934
- const $d68cd57b2d06b6d5$var$CommentsList = ({ comments: comments, userResource: userResource, loading: loading })=>{
935
- const classes = $d68cd57b2d06b6d5$var$useStyles();
1056
+ const $0120d12473c65b5c$var$CommentsList = ({ comments: comments, userResource: userResource, loading: loading })=>{
1057
+ const { classes: classes } = $0120d12473c65b5c$var$useStyles();
936
1058
  const userDataModel = (0, $583VT$semappssemanticdataprovider.useDataModel)(userResource);
937
1059
  return /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsxs)((0, $583VT$muimaterial.Box), {
938
1060
  position: "relative",
939
1061
  children: [
940
- comments && comments.sort((a, b)=>new Date(b.published) - new Date(a.published)).map((comment)=>/*#__PURE__*/ (0, $583VT$reactjsxruntime.jsxs)((0, $583VT$muimaterial.Box), {
1062
+ comments && comments.sort((a, b)=>new Date(b.published).getTime() - new Date(a.published).getTime()).map((comment)=>/*#__PURE__*/ (0, $583VT$reactjsxruntime.jsxs)((0, $583VT$muimaterial.Box), {
941
1063
  className: classes.container,
942
1064
  children: [
943
1065
  /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $583VT$muimaterial.Box), {
@@ -965,7 +1087,7 @@ const $d68cd57b2d06b6d5$var$CommentsList = ({ comments: comments, userResource:
965
1087
  linkType: "show",
966
1088
  children: /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $583VT$reactadmin.TextField), {
967
1089
  variant: "body2",
968
- source: userDataModel?.fieldsMapping?.title,
1090
+ source: userDataModel?.fieldsMapping?.title || '',
969
1091
  className: classes.label
970
1092
  })
971
1093
  }),
@@ -1002,17 +1124,19 @@ const $d68cd57b2d06b6d5$var$CommentsList = ({ comments: comments, userResource:
1002
1124
  ]
1003
1125
  });
1004
1126
  };
1005
- var $d68cd57b2d06b6d5$export$2e2bcd8739ae039 = $d68cd57b2d06b6d5$var$CommentsList;
1127
+ var $0120d12473c65b5c$export$2e2bcd8739ae039 = $0120d12473c65b5c$var$CommentsList;
1006
1128
 
1007
1129
 
1008
1130
 
1009
- const $2e5504cc4159ca8d$var$CommentsField = ({ source: source, context: context, helperText: helperText, placeholder: placeholder, userResource: userResource, mentions: mentions })=>{
1131
+ const $484cf98a20a766f7$var$CommentsField = ({ source: source = 'id', context: context = 'id', helperText: helperText, placeholder: placeholder = "Commencez \xe0 taper votre commentaire...", userResource: userResource, mentions: mentions })=>{
1010
1132
  const record = (0, $583VT$reactadmin.useRecordContext)();
1011
- const { items: comments, loading: loading, addItem: addItem, removeItem: removeItem } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)(record.replies);
1133
+ const { items: comments, isLoading: isLoading, addItem: addItem, removeItem: removeItem } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)(record?.replies, {
1134
+ liveUpdates: true
1135
+ });
1012
1136
  if (!userResource) throw new Error('No userResource defined for CommentsField');
1013
1137
  return /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsxs)((0, $583VT$reactjsxruntime.Fragment), {
1014
1138
  children: [
1015
- /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $703eba3e46be7ee5$export$2e2bcd8739ae039), {
1139
+ /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $a2b68b573919c8a3$export$2e2bcd8739ae039), {
1016
1140
  context: context,
1017
1141
  helperText: helperText,
1018
1142
  userResource: userResource,
@@ -1021,28 +1145,22 @@ const $2e5504cc4159ca8d$var$CommentsField = ({ source: source, context: context,
1021
1145
  addItem: addItem,
1022
1146
  removeItem: removeItem
1023
1147
  }),
1024
- /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $d68cd57b2d06b6d5$export$2e2bcd8739ae039), {
1148
+ /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $0120d12473c65b5c$export$2e2bcd8739ae039), {
1025
1149
  comments: comments,
1026
- loading: loading,
1150
+ loading: isLoading,
1027
1151
  userResource: userResource
1028
1152
  })
1029
1153
  ]
1030
1154
  });
1031
1155
  };
1032
- $2e5504cc4159ca8d$var$CommentsField.defaultProps = {
1033
- label: 'Commentaires',
1034
- placeholder: "Commencez \xe0 taper votre commentaire...",
1035
- source: 'id',
1036
- context: 'id'
1037
- };
1038
- var $2e5504cc4159ca8d$export$2e2bcd8739ae039 = $2e5504cc4159ca8d$var$CommentsField;
1156
+ var $484cf98a20a766f7$export$2e2bcd8739ae039 = $484cf98a20a766f7$var$CommentsField;
1039
1157
 
1040
1158
 
1041
1159
 
1042
1160
 
1043
1161
 
1044
1162
 
1045
- const $505d598a33288aad$var$CollectionList = ({ collectionUrl: collectionUrl, resource: resource, children: children })=>{
1163
+ const $78e7af8b8abfe6a7$var$CollectionList = ({ collectionUrl: collectionUrl, resource: resource, children: children })=>{
1046
1164
  if ((0, ($parcel$interopDefault($583VT$react))).Children.count(children) !== 1) throw new Error('<CollectionList> only accepts a single child');
1047
1165
  const { items: actorsUris } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)(collectionUrl);
1048
1166
  const { data: data, isLoading: isLoading, isFetching: isFetching } = (0, $583VT$reactadmin.useGetMany)(resource, {
@@ -1062,31 +1180,302 @@ const $505d598a33288aad$var$CollectionList = ({ collectionUrl: collectionUrl, re
1062
1180
  children: children
1063
1181
  });
1064
1182
  };
1065
- var $505d598a33288aad$export$2e2bcd8739ae039 = $505d598a33288aad$var$CollectionList;
1183
+ var $78e7af8b8abfe6a7$export$2e2bcd8739ae039 = $78e7af8b8abfe6a7$var$CollectionList;
1066
1184
 
1067
1185
 
1068
1186
 
1069
1187
 
1070
1188
 
1071
1189
 
1072
- const $b0c94a9bdea99da5$var$ReferenceCollectionField = ({ source: source, reference: reference, children: children, ...rest })=>{
1190
+ const $63048bed1787ac97$var$ReferenceCollectionField = ({ source: source, reference: reference, children: children, ...rest })=>{
1073
1191
  const record = (0, $583VT$reactadmin.useRecordContext)();
1074
1192
  if ((0, ($parcel$interopDefault($583VT$react))).Children.count(children) !== 1) throw new Error('<ReferenceCollectionField> only accepts a single child');
1075
1193
  if (!record || !record[source]) return null;
1076
- return /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $505d598a33288aad$export$2e2bcd8739ae039), {
1194
+ return /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)((0, $78e7af8b8abfe6a7$export$2e2bcd8739ae039), {
1077
1195
  resource: reference,
1078
1196
  collectionUrl: record[source],
1079
1197
  ...rest,
1080
1198
  children: children
1081
1199
  });
1082
1200
  };
1083
- var $b0c94a9bdea99da5$export$2e2bcd8739ae039 = $b0c94a9bdea99da5$var$ReferenceCollectionField;
1201
+ var $63048bed1787ac97$export$2e2bcd8739ae039 = $63048bed1787ac97$var$ReferenceCollectionField;
1202
+
1203
+
1084
1204
 
1085
1205
 
1086
1206
 
1087
1207
 
1088
1208
 
1089
1209
 
1210
+
1211
+
1212
+
1213
+
1214
+
1215
+ /**
1216
+ * Subscribe to a collection. Supports pagination.
1217
+ * @param collectionUri The collection URI or the predicate to get the collection URI from the identity (webId).
1218
+ * @param {UseCollectionOptions & UseTypedCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: false, pageSize: 10 }` and requires at least one ldo @see {ShapeType}.
1219
+ */ const $c778e69ff9ab90c6$var$useTypedCollection = (collectionUri, options)=>{
1220
+ const { pageSize: pageSize = 10, liveUpdates: subscribeToUpdates = false, shapeTypes: shapeTypes } = options;
1221
+ if (!shapeTypes.length) throw new Error('At least one ShapeType is required to filter the collection by.');
1222
+ // 1. Fetch the collection
1223
+ const collectionQuery = $c778e69ff9ab90c6$var$useInfiniteCollectionQuery(collectionUri);
1224
+ const { totalItems: totalItems, isPaginated: isPaginated } = $c778e69ff9ab90c6$var$useTotalItemsFromPages(collectionQuery.data);
1225
+ // 2. Filter items from the collection pages that match the given shape types.
1226
+ const filteredItems = $c778e69ff9ab90c6$var$useFilteredItemsFromPages(collectionQuery.data, shapeTypes);
1227
+ // 3. Set up notifications for live updates, if enabled.
1228
+ const liveUpdatesStatus = $c778e69ff9ab90c6$var$useSubscribeToUpdates({
1229
+ uri: collectionUri,
1230
+ enabled: subscribeToUpdates,
1231
+ onAddItem: (_item)=>{
1232
+ // Since we don't know where the item was added, we refetch the whole collection ¯\_(ツ)_/¯.
1233
+ collectionQuery.refetch();
1234
+ },
1235
+ onRemoveItem: (uri)=>{
1236
+ $c778e69ff9ab90c6$var$removeItemFromQueryData(uri, collectionQuery);
1237
+ }
1238
+ });
1239
+ // 4. Pagination logic.
1240
+ const [requestedNextItems, setRequestedNextItems] = (0, $583VT$react.useState)(pageSize);
1241
+ const [requestedPrevItems, setRequestedPrevItems] = (0, $583VT$react.useState)(0);
1242
+ // Automatically fetch next page, if more items are requested.
1243
+ (0, $583VT$react.useEffect)(()=>{
1244
+ if (requestedNextItems > filteredItems.length && collectionQuery.hasNextPage && !collectionQuery.isLoading) collectionQuery.fetchNextPage();
1245
+ }, [
1246
+ requestedNextItems,
1247
+ filteredItems.length,
1248
+ collectionQuery.hasNextPage,
1249
+ collectionQuery.isLoading
1250
+ ]);
1251
+ // Automatically fetch previous page, if more items are requested.
1252
+ (0, $583VT$react.useEffect)(()=>{
1253
+ if (requestedPrevItems > filteredItems.length && collectionQuery.hasPreviousPage && !collectionQuery.isLoading) collectionQuery.fetchPreviousPage();
1254
+ }, [
1255
+ requestedPrevItems,
1256
+ filteredItems.length,
1257
+ collectionQuery.hasPreviousPage,
1258
+ collectionQuery.isLoading
1259
+ ]);
1260
+ /** Fetch next n (filtered) items. */ const fetchNext = (0, $583VT$react.useCallback)((noItems = pageSize)=>{
1261
+ setRequestedNextItems(filteredItems.length + noItems);
1262
+ }, [
1263
+ filteredItems.length,
1264
+ pageSize
1265
+ ]);
1266
+ /** Fetch previous n (filtered) items. */ const fetchPrevious = (0, $583VT$react.useCallback)((noItems = pageSize)=>{
1267
+ setRequestedPrevItems(filteredItems.length + noItems);
1268
+ }, [
1269
+ filteredItems.length,
1270
+ pageSize
1271
+ ]);
1272
+ return {
1273
+ // TODO: Do we want to expose all properties from the collection query?
1274
+ ...collectionQuery,
1275
+ items: filteredItems,
1276
+ liveUpdatesStatus: liveUpdatesStatus,
1277
+ fetchNext: fetchNext,
1278
+ fetchPrevious: fetchPrevious,
1279
+ totalItems: totalItems,
1280
+ isPaginated: isPaginated
1281
+ };
1282
+ };
1283
+ var $c778e69ff9ab90c6$export$2e2bcd8739ae039 = $c778e69ff9ab90c6$var$useTypedCollection;
1284
+ const $c778e69ff9ab90c6$var$useSubscribeToUpdates = ({ uri: uri, enabled: enabled = true, onAddItem: onAddItem, onRemoveItem: onRemoveItem })=>{
1285
+ const { fetch: fetchFn } = (0, $583VT$reactadmin.useDataProvider)();
1286
+ const [status, setStatus] = (0, $583VT$react.useState)({
1287
+ status: enabled ? 'connecting' : 'disabled'
1288
+ });
1289
+ (0, $583VT$react.useEffect)(()=>{
1290
+ const webSocketRef = (0, $583VT$react.useRef)(null);
1291
+ // Nothing to do, return empty clean up function.
1292
+ if (!enabled || !uri) return ()=>{};
1293
+ // Create ws that listens to collectionUri changes
1294
+ (0, $583VT$semappssemanticdataprovider.getOrCreateWsChannel)(fetchFn, uri).then((ws)=>{
1295
+ webSocketRef.current = ws; // Keep a ref to the webSocket so that it can be used elsewhere
1296
+ webSocketRef.current.addEventListener('message', (event)=>{
1297
+ // TODO: correct ldo type
1298
+ const data = JSON.parse(event.data);
1299
+ if (data.type === 'Add') onAddItem(data.object);
1300
+ else if (data.type === 'Remove') onRemoveItem(data.object);
1301
+ });
1302
+ webSocketRef.current.addEventListener('error', (event)=>{
1303
+ setStatus({
1304
+ error: event,
1305
+ status: 'error'
1306
+ });
1307
+ // TODO: Retry after a while (use react query?).
1308
+ });
1309
+ webSocketRef.current.addEventListener('close', (_event)=>{
1310
+ if (!status.error) setStatus({
1311
+ status: 'closed'
1312
+ });
1313
+ });
1314
+ }).catch((error)=>{
1315
+ setStatus({
1316
+ status: 'error',
1317
+ error: error
1318
+ });
1319
+ });
1320
+ // Clean up, i.e. close channel.
1321
+ return ()=>{
1322
+ webSocketRef.current?.close();
1323
+ };
1324
+ }, [
1325
+ uri,
1326
+ enabled,
1327
+ onAddItem,
1328
+ onRemoveItem
1329
+ ]);
1330
+ return status;
1331
+ };
1332
+ const $c778e69ff9ab90c6$var$useInfiniteCollectionQuery = (collectionUri)=>{
1333
+ const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
1334
+ const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
1335
+ const { fetch: fetchFn } = dataProvider;
1336
+ const infiniteQueryData = (0, $583VT$tanstackreactquery.useInfiniteQuery)({
1337
+ queryKey: [
1338
+ 'collection',
1339
+ {
1340
+ uri: collectionUri
1341
+ }
1342
+ ],
1343
+ queryFn: $c778e69ff9ab90c6$var$getFetchCollectionPage(fetchFn),
1344
+ initialPageParam: collectionUri,
1345
+ enabled: !!(collectionUri && identity?.id),
1346
+ getNextPageParam: (current)=>current.data?.next,
1347
+ getPreviousPageParam: (current)=>current.data?.prev
1348
+ });
1349
+ return infiniteQueryData;
1350
+ };
1351
+ const $c778e69ff9ab90c6$var$getFetchCollectionPage = (fetchFn)=>async ({ pageParam: pageUri })=>{
1352
+ // Note, page is not necessarily of type OrderedCollectionPage but it is a partial in any case.
1353
+ const jsonPage = await (await fetchFn(pageUri)).json();
1354
+ if (!jsonPage || typeof jsonPage !== 'object') throw new Error(`Could not fetch page ${pageUri}. Response is invalid.`);
1355
+ const itemsKey = 'orderedItems' in jsonPage ? 'orderedItems' : 'items';
1356
+ if ((0, $03510abb28fd3d8a$export$e57ff0f701c44363)(jsonPage[itemsKey]).length === 0) // No items in page.
1357
+ return {
1358
+ itemIds: [],
1359
+ dataset: null,
1360
+ data: null
1361
+ };
1362
+ // Keep track of item ids in this order (in the rdf dataset the order is lost).
1363
+ const itemIds = (0, $03510abb28fd3d8a$export$e57ff0f701c44363)(jsonPage[itemsKey]).map((itemOrId)=>itemOrId?.['@id'] || itemOrId?.id || itemOrId).filter((item)=>item); // Ensure item is not undefined.
1364
+ // Parse the page into a dataset.
1365
+ // TODO: Move to data provider.
1366
+ const dataset = (0, $583VT$ldoconnected.createConnectedLdoDataset)([
1367
+ (0, $583VT$ldoconnectedsolid.solidConnectedPlugin)
1368
+ ]);
1369
+ dataset.setContext('solid', {
1370
+ fetch: fetchFn
1371
+ });
1372
+ dataset.addAll(await (0, $03510abb28fd3d8a$export$7089f01fea2fc5c2)(jsonPage));
1373
+ const resource = dataset.getResource(pageUri);
1374
+ if (resource.type === 'InvalidIdentifierResource') return {
1375
+ itemIds: itemIds,
1376
+ dataset: null,
1377
+ pageUri: pageUri,
1378
+ data: null
1379
+ };
1380
+ const ldoBuilder = dataset.usingType((0, $583VT$activitypodsldoshapes.OrderedCollectionPageShapeType));
1381
+ // Run a link query to ensure that all items are dereferenced (the results are kept in the dataset).
1382
+ await ldoBuilder.startLinkQuery(resource, pageUri, {
1383
+ items: true,
1384
+ orderedItems: true
1385
+ }).run({
1386
+ reload: false
1387
+ });
1388
+ return {
1389
+ dataset: dataset,
1390
+ itemIds: itemIds,
1391
+ pageUri: pageUri,
1392
+ data: ldoBuilder.fromSubject(pageUri)
1393
+ };
1394
+ };
1395
+ const $c778e69ff9ab90c6$var$useTotalItemsFromPages = (queryData)=>{
1396
+ if (!queryData?.pages.length) return {
1397
+ isPaginated: undefined,
1398
+ totalItems: undefined
1399
+ };
1400
+ const { pages: pages } = queryData;
1401
+ // Check if collection is paginated. We assume that the collection is paginated if there are pages with first, last, prev or next.
1402
+ const isPaginated = pages.length === 0 ? undefined : !!pages.find((page)=>page.data && ('first' in page.data || 'next' in page.data || 'last' in page.data || 'prev' in page.data));
1403
+ // Approach 1: Get total items info by checking if the page has a totalItems property.
1404
+ const totalItemsByCollectionInfo = pages.find((page)=>'totalItems' in page)?.data?.totalItems;
1405
+ if (totalItemsByCollectionInfo) return {
1406
+ totalItems: totalItemsByCollectionInfo,
1407
+ isPaginated: isPaginated
1408
+ };
1409
+ // Approach 2: If collection is not paginated, we count the number of items in the collection.
1410
+ if (!isPaginated) return {
1411
+ totalItems: pages[0].itemIds.length,
1412
+ isPaginated: isPaginated
1413
+ };
1414
+ // Approach 3: If we have the whole collection loaded, we can count the items.
1415
+ const firstPage = pages.find((page)=>page.data?.first)?.data?.first;
1416
+ const lastPage = pages.find((page)=>page.data?.last)?.data?.last;
1417
+ // We assume that all pages are loaded if the first and last page is available.
1418
+ // In that case, count all pages' items.
1419
+ if (firstPage && lastPage) return {
1420
+ isPaginated: isPaginated,
1421
+ totalItems: pages// Get length of page
1422
+ .map((page)=>page.data?.orderedItems?.size || page.data?.items?.size || 0)// Sum all page length counts.
1423
+ .reduce((prev, current)=>prev + current)
1424
+ };
1425
+ // If no approach succeeded, we return undefined.
1426
+ return {
1427
+ totalItems: undefined,
1428
+ isPaginated: isPaginated
1429
+ };
1430
+ };
1431
+ const $c778e69ff9ab90c6$var$useFilteredItemsFromPages = (queryData, shapeTypes)=>{
1432
+ const [filteredItems, setFilteredItems] = (0, $583VT$react.useState)([]);
1433
+ const filterItems = (0, $583VT$react.useCallback)(async ()=>{
1434
+ // We need to load the shacl resources and match them to the shape types.
1435
+ const validator = await (0, $24b34de916fb30a8$export$8b707c2a07270e94)();
1436
+ const pages = queryData?.pages;
1437
+ if (!pages || pages.length === 0) {
1438
+ setFilteredItems([]);
1439
+ return;
1440
+ }
1441
+ const validatedItems = await Promise.all(// For every page, ...
1442
+ queryData.pages.map(async (page)=>{
1443
+ const items = await Promise.all(// For every item in the page, ...
1444
+ page.itemIds.map(async (itemId)=>// Validate item against the shape types and return the ldo object of the correct type, if it is valid.
1445
+ page.dataset && (0, $24b34de916fb30a8$export$c4cb1062f0ffb837)(itemId, page.dataset, shapeTypes, validator))).then((results)=>results.filter((item)=>!!item)); // Filter out null items.
1446
+ return items;
1447
+ })).then((results)=>results.flat());
1448
+ // TODO: Order items by ids.
1449
+ setFilteredItems(validatedItems);
1450
+ // TODO: Cache filtered items by page, so that we don't have to re-filter them every time?
1451
+ }, [
1452
+ queryData?.pages,
1453
+ shapeTypes
1454
+ ]);
1455
+ (0, $583VT$react.useEffect)(()=>{
1456
+ filterItems();
1457
+ }, [
1458
+ filterItems
1459
+ ]);
1460
+ return filteredItems;
1461
+ };
1462
+ /** A somewhat hacky way to remove an item from the useInfiniteCollectionQuery. */ const $c778e69ff9ab90c6$var$removeItemFromQueryData = (itemUri, collectionQuery)=>{
1463
+ // Manipulate data about total items. Sorry, a bit hacky...
1464
+ collectionQuery.data?.pages.forEach((page)=>{
1465
+ if (!page.dataset) return;
1466
+ page.dataset.deleteMatches((0, ($parcel$interopDefault($583VT$rdfext))).namedNode(itemUri));
1467
+ // There might be a totalItems property in the page, so we need to update it.
1468
+ if (page.data.totalItems && Number.isInteger(page.data.totalItems)) // eslint-disable-next-line no-param-reassign
1469
+ page.data.totalItems -= 1;
1470
+ });
1471
+ }; // Open Question:
1472
+ // - Use one dataset? It has the benefit of only having to define a single solid connected dataset and makes ng switching easier -> no need to create a connected dataset.
1473
+ // - On the other hand (the only downside I can think of rn): Either you have to remove expired items from the dataset or you don't care about old data that is not used by react admin anymore. At a refetch all old data would have to be removed though.
1474
+
1475
+
1476
+
1477
+
1478
+
1090
1479
  /**
1091
1480
  * Hook to fetch the inbox of the logged user.
1092
1481
  * Returns the same data as the useCollection hooks, plus:
@@ -1145,7 +1534,7 @@ var $59fc2d2cba62bd8e$export$2e2bcd8739ae039 = $59fc2d2cba62bd8e$var$useNodeinfo
1145
1534
 
1146
1535
 
1147
1536
 
1148
- const $5b61553556e35016$var$useWebfinger = ()=>{
1537
+ const $10f3abf411a5e9d4$var$useWebfinger = ()=>{
1149
1538
  // Post an activity to the logged user's outbox and return its URI
1150
1539
  const fetch = (0, $583VT$react.useCallback)(async (id)=>{
1151
1540
  // eslint-disable-next-line
@@ -1166,7 +1555,7 @@ const $5b61553556e35016$var$useWebfinger = ()=>{
1166
1555
  fetch: fetch
1167
1556
  };
1168
1557
  };
1169
- var $5b61553556e35016$export$2e2bcd8739ae039 = $5b61553556e35016$var$useWebfinger;
1558
+ var $10f3abf411a5e9d4$export$2e2bcd8739ae039 = $10f3abf411a5e9d4$var$useWebfinger;
1170
1559
 
1171
1560
 
1172
1561
 
@@ -1177,7 +1566,7 @@ var $5b61553556e35016$export$2e2bcd8739ae039 = $5b61553556e35016$var$useWebfinge
1177
1566
 
1178
1567
 
1179
1568
 
1180
- const $27d3788851661769$var$useStyles = (0, ($parcel$interopDefault($583VT$muistylesmakeStyles)))((theme)=>({
1569
+ const $d217d582899c7580$var$useStyles = (0, $583VT$tssreactmui.makeStyles)()((theme)=>({
1181
1570
  items: {
1182
1571
  background: '#fff',
1183
1572
  borderRadius: '0.5rem',
@@ -1202,24 +1591,29 @@ const $27d3788851661769$var$useStyles = (0, ($parcel$interopDefault($583VT$muist
1202
1591
  }
1203
1592
  }
1204
1593
  }));
1205
- var $27d3788851661769$export$2e2bcd8739ae039 = /*#__PURE__*/ (0, $583VT$react.forwardRef)((props, ref)=>{
1594
+ var $d217d582899c7580$export$2e2bcd8739ae039 = /*#__PURE__*/ (0, $583VT$react.forwardRef)((props, ref)=>{
1206
1595
  const [selectedIndex, setSelectedIndex] = (0, $583VT$react.useState)(0);
1207
- const classes = $27d3788851661769$var$useStyles();
1596
+ const { classes: classes } = $d217d582899c7580$var$useStyles();
1208
1597
  const selectItem = (index)=>{
1598
+ // @ts-expect-error TS(2339): Property 'items' does not exist on type '{}'.
1209
1599
  const item = props.items[index];
1210
- if (item) props.command({
1600
+ if (item) // @ts-expect-error TS(2339): Property 'command' does not exist on type '{}'.
1601
+ props.command({
1211
1602
  id: item
1212
1603
  });
1213
1604
  };
1214
1605
  const upHandler = ()=>{
1606
+ // @ts-expect-error TS(2339): Property 'items' does not exist on type '{}'.
1215
1607
  setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length);
1216
1608
  };
1217
1609
  const downHandler = ()=>{
1610
+ // @ts-expect-error TS(2339): Property 'items' does not exist on type '{}'.
1218
1611
  setSelectedIndex((selectedIndex + 1) % props.items.length);
1219
1612
  };
1220
1613
  const enterHandler = ()=>{
1221
1614
  selectItem(selectedIndex);
1222
1615
  };
1616
+ // @ts-expect-error TS(2339): Property 'items' does not exist on type '{}'.
1223
1617
  (0, $583VT$react.useEffect)(()=>setSelectedIndex(0), [
1224
1618
  props.items
1225
1619
  ]);
@@ -1242,7 +1636,8 @@ var $27d3788851661769$export$2e2bcd8739ae039 = /*#__PURE__*/ (0, $583VT$react.fo
1242
1636
  }));
1243
1637
  return /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)("div", {
1244
1638
  className: classes.items,
1245
- children: props.items.length ? props.items.map((item, index)=>/*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)("button", {
1639
+ children: props.items.length ? // @ts-expect-error TS(2339): Property 'items' does not exist on type '{}'.
1640
+ props.items.map((item, index)=>/*#__PURE__*/ (0, $583VT$reactjsxruntime.jsx)("button", {
1246
1641
  className: classes.item + (index === selectedIndex ? ' selected' : ''),
1247
1642
  onClick: ()=>selectItem(index),
1248
1643
  children: item.label
@@ -1254,12 +1649,12 @@ var $27d3788851661769$export$2e2bcd8739ae039 = /*#__PURE__*/ (0, $583VT$react.fo
1254
1649
  });
1255
1650
 
1256
1651
 
1257
- const $7b7f4b18327176f8$var$renderMentions = ()=>{
1652
+ const $05d587317cba4616$var$renderMentions = ()=>{
1258
1653
  let component;
1259
1654
  let popup;
1260
1655
  return {
1261
1656
  onStart: (props)=>{
1262
- component = new (0, $583VT$tiptapreact.ReactRenderer)((0, $27d3788851661769$export$2e2bcd8739ae039), {
1657
+ component = new (0, $583VT$tiptapreact.ReactRenderer)((0, $d217d582899c7580$export$2e2bcd8739ae039), {
1263
1658
  props: props,
1264
1659
  editor: props.editor
1265
1660
  });
@@ -1292,10 +1687,10 @@ const $7b7f4b18327176f8$var$renderMentions = ()=>{
1292
1687
  }
1293
1688
  };
1294
1689
  };
1295
- var $7b7f4b18327176f8$export$2e2bcd8739ae039 = $7b7f4b18327176f8$var$renderMentions;
1690
+ var $05d587317cba4616$export$2e2bcd8739ae039 = $05d587317cba4616$var$renderMentions;
1296
1691
 
1297
1692
 
1298
- const $968ea07fb81eda0b$var$useMentions = (userResource)=>{
1693
+ const $351e26ed1a2af792$var$useMentions = (userResource)=>{
1299
1694
  const userDataModel = (0, $583VT$semappssemanticdataprovider.useDataModel)(userResource);
1300
1695
  const { data: data } = (0, $583VT$reactadmin.useGetList)(userResource, {
1301
1696
  filter: {
@@ -1310,7 +1705,7 @@ const $968ea07fb81eda0b$var$useMentions = (userResource)=>{
1310
1705
  const availableMentions = (0, $583VT$react.useMemo)(()=>{
1311
1706
  if (data) return data.map((item)=>({
1312
1707
  id: item.id,
1313
- label: item[userDataModel?.fieldsMapping?.title]
1708
+ label: item[userDataModel?.fieldsMapping?.title || '']
1314
1709
  }));
1315
1710
  }, [
1316
1711
  data
@@ -1324,10 +1719,10 @@ const $968ea07fb81eda0b$var$useMentions = (userResource)=>{
1324
1719
  ]);
1325
1720
  return {
1326
1721
  items: items,
1327
- render: (0, $7b7f4b18327176f8$export$2e2bcd8739ae039)
1722
+ render: (0, $05d587317cba4616$export$2e2bcd8739ae039)
1328
1723
  };
1329
1724
  };
1330
- var $968ea07fb81eda0b$export$2e2bcd8739ae039 = $968ea07fb81eda0b$var$useMentions;
1725
+ var $351e26ed1a2af792$export$2e2bcd8739ae039 = $351e26ed1a2af792$var$useMentions;
1331
1726
 
1332
1727
 
1333
1728