@panneau/core 4.1.1 → 5.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +83 -0
  2. package/dist/definition/abilities.d.ts +21 -0
  3. package/dist/definition/abilities.d.ts.map +1 -0
  4. package/dist/definition/abilities.js +47 -0
  5. package/dist/definition/abilities.js.map +1 -0
  6. package/dist/definition/form.d.ts +31 -0
  7. package/dist/definition/form.d.ts.map +1 -0
  8. package/dist/definition/form.js +54 -0
  9. package/dist/definition/form.js.map +1 -0
  10. package/dist/definition/list.d.ts +44 -0
  11. package/dist/definition/list.d.ts.map +1 -0
  12. package/dist/definition/list.js +70 -0
  13. package/dist/definition/list.js.map +1 -0
  14. package/dist/definition/resource.d.ts +21 -0
  15. package/dist/definition/resource.d.ts.map +1 -0
  16. package/dist/definition/resource.js +24 -0
  17. package/dist/definition/resource.js.map +1 -0
  18. package/dist/form/form.d.ts +148 -0
  19. package/dist/form/form.d.ts.map +1 -0
  20. package/dist/form/form.js +239 -0
  21. package/dist/form/form.js.map +1 -0
  22. package/dist/form/messages.d.ts +7 -0
  23. package/dist/form/messages.d.ts.map +1 -0
  24. package/dist/form/messages.js +25 -0
  25. package/dist/form/messages.js.map +1 -0
  26. package/dist/form/problem.d.ts +16 -0
  27. package/dist/form/problem.d.ts.map +1 -0
  28. package/dist/form/problem.js +34 -0
  29. package/dist/form/problem.js.map +1 -0
  30. package/dist/form/selectors.d.ts +16 -0
  31. package/dist/form/selectors.d.ts.map +1 -0
  32. package/dist/form/selectors.js +27 -0
  33. package/dist/form/selectors.js.map +1 -0
  34. package/dist/form/store.d.ts +19 -0
  35. package/dist/form/store.d.ts.map +1 -0
  36. package/dist/form/store.js +29 -0
  37. package/dist/form/store.js.map +1 -0
  38. package/dist/index.d.ts +17 -692
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +17 -536
  41. package/dist/list/list.d.ts +68 -0
  42. package/dist/list/list.d.ts.map +1 -0
  43. package/dist/list/list.js +191 -0
  44. package/dist/list/list.js.map +1 -0
  45. package/dist/list/router.d.ts +26 -0
  46. package/dist/list/router.d.ts.map +1 -0
  47. package/dist/list/router.js +54 -0
  48. package/dist/list/router.js.map +1 -0
  49. package/dist/plugins.d.ts +73 -0
  50. package/dist/plugins.d.ts.map +1 -0
  51. package/dist/plugins.js +54 -0
  52. package/dist/plugins.js.map +1 -0
  53. package/dist/react/provider.d.ts +38 -0
  54. package/dist/react/provider.d.ts.map +1 -0
  55. package/dist/react/provider.js +63 -0
  56. package/dist/react/provider.js.map +1 -0
  57. package/dist/react/useForm.d.ts +26 -0
  58. package/dist/react/useForm.d.ts.map +1 -0
  59. package/dist/react/useForm.js +115 -0
  60. package/dist/react/useForm.js.map +1 -0
  61. package/dist/react/useList.d.ts +11 -0
  62. package/dist/react/useList.d.ts.map +1 -0
  63. package/dist/react/useList.js +47 -0
  64. package/dist/react/useList.js.map +1 -0
  65. package/dist/values.d.ts +12 -0
  66. package/dist/values.d.ts.map +1 -0
  67. package/dist/values.js +44 -0
  68. package/dist/values.js.map +1 -0
  69. package/package.json +19 -81
  70. package/dist/contexts.d.ts +0 -667
  71. package/dist/contexts.js +0 -1772
  72. package/dist/hooks.d.ts +0 -512
  73. package/dist/hooks.js +0 -2146
  74. package/dist/utils.d.ts +0 -457
  75. package/dist/utils.js +0 -557
package/dist/index.js CHANGED
@@ -1,536 +1,17 @@
1
- import isObject from 'lodash-es/isObject';
2
- import { flattenComponents, getComponentFromName } from '@panneau/core/utils';
3
- import isArray from 'lodash-es/isArray';
4
- import uniqBy from 'lodash-es/uniqBy';
5
- import EventEmitter from 'wolfy87-eventemitter';
6
- import { Tracking as Tracking$1 } from '@folklore/tracking';
7
-
8
- class ComponentsManager {
9
- // Nested components maps are flattened with their key as namespace
10
- constructor(components = {}) {
11
- this.components = flattenComponents(components);
12
- }
13
- addComponent(name, component, namespace = null) {
14
- return this.addComponents({
15
- [name]: component
16
- }, namespace);
17
- }
18
- addComponents(components, namespace = null) {
19
- const newComponents = namespace !== null ? Object.keys(components).reduce((componentsMaps, name) => ({
20
- ...componentsMaps,
21
- [`${namespace}.${name}`]: components[name]
22
- }), {}) : components;
23
- this.components = {
24
- ...this.components,
25
- ...newComponents
26
- };
27
- return this;
28
- }
29
- merge(manager, namespace = null) {
30
- return this.addComponents(manager.getComponents(), namespace);
31
- }
32
- addNamespace(namespace) {
33
- if (namespace === null) {
34
- return this;
35
- }
36
- this.components = Object.keys(this.components).reduce((componentsMap, name) => ({
37
- ...componentsMap,
38
- [`${namespace}.${name}`]: this.components[name]
39
- }), {});
40
- return this;
41
- }
42
- getComponent(name, namespace = null) {
43
- if (isObject(name)) {
44
- return name;
45
- }
46
- const components = this.getComponents(namespace);
47
- return getComponentFromName(name, components);
48
- }
49
- getComponents(namespace = null) {
50
- return namespace !== null ? Object.keys(this.components || {}).reduce((componentsMap, name) => {
51
- const pattern = new RegExp(`^${namespace}\\.(.*)$`);
52
- const matches = pattern.exec(name);
53
- return matches !== null ? {
54
- ...(componentsMap || {}),
55
- [matches[1]]: this.components[name]
56
- } : componentsMap;
57
- }, null) : this.components;
58
- }
59
- hasComponent(name, namespace = null) {
60
- return this.components !== null && typeof this.components[namespace !== null ? `${namespace}.${name}` : name] !== 'undefined';
61
- }
62
- }
63
-
64
- class DefinitionsManager {
65
- constructor(definitions = []) {
66
- this.definitions = definitions || [];
67
- }
68
- addDefinition(definition) {
69
- this.addDefinitions(isArray(definition) ? definition : [definition]);
70
- return this;
71
- }
72
- addDefinitions(definitions) {
73
- this.definitions = uniqBy([...definitions, ...this.definitions], it => it.id);
74
- return this;
75
- }
76
- merge(manager) {
77
- return this.addDefinitions(manager.getDefinitions());
78
- }
79
- getDefinition(id) {
80
- if (id === null) {
81
- return null;
82
- }
83
- return this.definitions.find(it => it.id === id) || null;
84
- }
85
- getDefinitions() {
86
- return this.definitions;
87
- }
88
- hasDefinition(id) {
89
- return this.getDefinition(id) !== null;
90
- }
91
- getComponent(id) {
92
- const {
93
- component = null
94
- } = this.getDefinition(id) || {};
95
- return component;
96
- }
97
- getComponents() {
98
- return this.definitions.reduce((allComponents, {
99
- id,
100
- component = null
101
- }) => component !== null ? {
102
- ...allComponents,
103
- [id]: component
104
- } : allComponents, {});
105
- }
106
- }
107
-
108
- class EventsManager extends EventEmitter {
109
- constructor(element) {
110
- super();
111
- this.element = element;
112
- this.events = {};
113
- this.listeners = {};
114
- }
115
- subscribe(event, callback) {
116
- this.on(event, callback);
117
- this.events = {
118
- ...this.events,
119
- [event]: [...(this.events[event] || []), callback]
120
- };
121
- if (this.events[event].length === 1) {
122
- this.addEventListener(event);
123
- }
124
- }
125
- unsubscribe(event, callback) {
126
- this.off(event, callback);
127
- this.events = Object.keys(this.events).reduce((newEvents, eventName) => {
128
- if (eventName !== event) {
129
- return {
130
- ...newEvents,
131
- [eventName]: this.events[eventName]
132
- };
133
- }
134
- const newListeners = this.events[eventName].filter(listener => listener !== callback);
135
- return newListeners.length > 0 ? {
136
- ...newEvents,
137
- [eventName]: newListeners
138
- } : newEvents;
139
- }, {});
140
- if (typeof this.events[event] === 'undefined') {
141
- this.removeEventListener(event);
142
- }
143
- }
144
- addEventListener(event) {
145
- if (typeof this.listeners[event] === 'undefined') {
146
- this.listeners[event] = (...args) => this.emit(event, ...args);
147
- }
148
- this.element.addEventListener(event, this.listeners[event]);
149
- }
150
- removeEventListener(event) {
151
- this.element.removeEventListener(event, this.listeners[event]);
152
- }
153
- }
154
-
155
- class FieldsManager extends DefinitionsManager {}
156
-
157
- class FontsParser {
158
- constructor({
159
- fieldsManager,
160
- screensManager
161
- }) {
162
- this.fieldsManager = fieldsManager;
163
- this.screensManager = screensManager;
164
- }
165
-
166
- // Extract fonts
167
- parse(story) {
168
- if (story === null) {
169
- return story;
170
- }
171
-
172
- // Extract fonts from screen
173
- const {
174
- theme = null,
175
- components = []
176
- } = story || {};
177
- const fonts = uniqBy(components.reduce((currentFonts, screen) => {
178
- const {
179
- type
180
- } = screen;
181
- const {
182
- fields = []
183
- } = this.screensManager.getDefinition(type) || {};
184
- const fieldsPattern = this.getFieldsPattern(fields);
185
- const newFonts = FontsParser.extractFontsWithPaths(screen, fieldsPattern);
186
- return newFonts.length > 0 ? [...currentFonts, ...newFonts] : currentFonts;
187
- }, []), 'name');
188
-
189
- // Extract fonts from theme
190
- if (theme !== null) {
191
- const {
192
- fonts: themeFonts = [],
193
- ...newTheme
194
- } = this.parse(theme);
195
- return fonts.length > 0 || themeFonts.length > 0 ? {
196
- ...story,
197
- theme: newTheme,
198
- fonts: uniqBy([...themeFonts, ...fonts], 'name')
199
- } : story;
200
- }
201
- return fonts.length > 0 ? {
202
- ...story,
203
- fonts
204
- } : story;
205
- }
206
- getFieldsPattern(fields, namePrefix = null) {
207
- return fields.reduce((patterns, field) => {
208
- const {
209
- name = null,
210
- type = null
211
- } = field;
212
- const path = [namePrefix, name].filter(it => it !== null).join('\\.');
213
- const fieldDefinition = {
214
- ...(type !== null ? this.fieldsManager.getDefinition(type) : null),
215
- ...field
216
- };
217
-
218
- // also check settings fields
219
- const {
220
- fields: subFields = [],
221
- itemsField = null,
222
- settings = []
223
- } = fieldDefinition;
224
- return [...patterns, ...(FontsParser.fieldIsFontFamily(fieldDefinition) ? [new RegExp(`^${path}$`)] : []), ...this.getFieldsPattern(subFields, path), ...this.getFieldsPattern(settings, path), ...(itemsField !== null ? this.getFieldsPattern([itemsField], `${path}\\.[0-9]+`) : [])];
225
- }, []);
226
- }
227
- static fieldIsFontFamily({
228
- id = null
229
- }) {
230
- return id === 'font-family';
231
- }
232
- static valueIsFont({
233
- type = null
234
- }) {
235
- return type === 'custom' || type === 'google';
236
- }
237
- static extractFontsWithPaths(data, patterns, keyPrefix = null) {
238
- const dataIsArray = isArray(data);
239
- const keys = dataIsArray ? [...data.keys()] : Object.keys(data);
240
- return keys.reduce((currentFonts, key) => {
241
- const path = [keyPrefix, key].filter(it => it !== null).join('.');
242
- const patternMatch = patterns.reduce((found, pattern) => found || pattern.test(path), false);
243
- const value = data[key];
244
- let font = null;
245
- let subFonts = null;
246
- if (patternMatch && isObject(value) && FontsParser.valueIsFont(value)) {
247
- font = value;
248
- } else if (isObject(value) || isArray(value)) {
249
- subFonts = FontsParser.extractFontsWithPaths(value, patterns, path);
250
- }
251
- return subFonts !== null || font !== null ? [...currentFonts, ...(subFonts || []), ...(font !== null ? [font] : [])] : currentFonts;
252
- }, []);
253
- }
254
- }
255
-
256
- class FormsManager extends DefinitionsManager {}
257
-
258
- class MediasParser {
259
- constructor({
260
- fieldsManager,
261
- screensManager = null
262
- }) {
263
- this.fieldsManager = fieldsManager;
264
- this.screensManager = screensManager;
265
- }
266
-
267
- // Convert medias object to path
268
- toPath(story) {
269
- if (story === null) {
270
- return story;
271
- }
272
- const {
273
- theme = null,
274
- components = []
275
- } = story || {};
276
- const {
277
- components: newComponents,
278
- medias
279
- } = components.reduce(({
280
- components: previousComponents,
281
- medias: currentMedias
282
- }, screen) => {
283
- const {
284
- type
285
- } = screen;
286
- const {
287
- fields = []
288
- } = this.screensManager?.getDefinition(type) || {};
289
- const fieldsPattern = this.getMediaFieldsPattern(fields);
290
- const {
291
- data: newScreen,
292
- medias: newMedias
293
- } = MediasParser.replaceMediasWithPaths(screen, fieldsPattern);
294
- return {
295
- components: [...previousComponents, newScreen],
296
- medias: {
297
- ...currentMedias,
298
- ...newMedias
299
- }
300
- };
301
- }, {
302
- components: [],
303
- medias: null
304
- });
305
- if (theme !== null) {
306
- const {
307
- medias: themeMedias,
308
- ...newTheme
309
- } = this.toPath(theme);
310
- return medias !== null || themeMedias !== null ? {
311
- ...story,
312
- theme: newTheme,
313
- components: newComponents,
314
- medias: {
315
- ...themeMedias,
316
- ...medias
317
- }
318
- } : story;
319
- }
320
- return medias !== null ? {
321
- ...story,
322
- components: newComponents,
323
- medias
324
- } : story;
325
- }
326
-
327
- // Convert path to medias object
328
- fromPath(story, defaultMedias = null) {
329
- if (story === null) {
330
- return story;
331
- }
332
- const {
333
- theme = null,
334
- components = [],
335
- medias = defaultMedias
336
- } = story || {};
337
- if (medias === null && theme === null) {
338
- return story;
339
- }
340
-
341
- // Replace path with medias objects
342
- const newComponents = medias !== null ? components.map(screen => {
343
- const {
344
- type
345
- } = screen;
346
- const {
347
- fields = []
348
- } = this.screensManager?.getDefinition(type) || {};
349
- const fieldsPattern = this.getMediaFieldsPattern(fields);
350
- return MediasParser.replacePathsWithMedias(screen, medias, fieldsPattern);
351
- }) : components;
352
-
353
- // Replace path with medias object in theme
354
- if (theme !== null) {
355
- const newTheme = this.fromPath(theme, medias);
356
- return newTheme !== theme || newComponents !== components ? {
357
- ...story,
358
- theme: newTheme,
359
- components: newComponents
360
- } : story;
361
- }
362
- return newComponents !== components ? {
363
- ...story,
364
- components: newComponents
365
- } : story;
366
- }
367
- getMediaFieldsPattern(fields, namePrefix = null) {
368
- return fields.reduce((patterns, field) => {
369
- const {
370
- name = null,
371
- type = null
372
- } = field;
373
- const path = [namePrefix, name].filter(it => it !== null).join('\\.');
374
- const fieldDefinition = {
375
- ...(type !== null ? this.fieldsManager.getDefinition(type) : null),
376
- ...field
377
- };
378
-
379
- // also check settings fields
380
- const {
381
- fields: subFields = [],
382
- itemsField = null,
383
- settings = []
384
- } = fieldDefinition;
385
- return [...patterns, ...(MediasParser.fieldIsMedia(fieldDefinition) ? [new RegExp(`^${path}$`)] : []), ...(MediasParser.fieldIsFontFamily(fieldDefinition) ? [new RegExp(`^${path}\\.media$`)] : []), ...this.getMediaFieldsPattern(subFields, path), ...this.getMediaFieldsPattern(settings, path), ...(itemsField !== null ? this.getMediaFieldsPattern([itemsField], `${path}\\.[0-9]+`) : [])];
386
- }, []);
387
- }
388
- static fieldIsMedia({
389
- media = false
390
- }) {
391
- return media;
392
- }
393
- static fieldIsFontFamily({
394
- id = null
395
- }) {
396
- return id === 'font-family';
397
- }
398
- static replacePathsWithMedias(data, medias, patterns, keyPrefix = null) {
399
- const dataIsArray = isArray(data);
400
- const keys = dataIsArray ? [...data.keys()] : Object.keys(data);
401
- return keys.reduce((newData, key) => {
402
- const path = [keyPrefix, key].filter(it => it !== null).join('.');
403
- const patternMatch = patterns.reduce((found, pattern) => found || pattern.test(path), false);
404
- const value = data[key];
405
- let newValue;
406
- if (patternMatch) {
407
- newValue = isObject(value) ? value : medias[value] || null;
408
- } else {
409
- newValue = isObject(value) || isArray(value) ? MediasParser.replacePathsWithMedias(value, medias, patterns, path) : value;
410
- }
411
- return dataIsArray ? [...newData, newValue] : {
412
- ...newData,
413
- [key]: newValue
414
- };
415
- }, dataIsArray ? [] : {});
416
- }
417
- static getMediaPath({
418
- id = null
419
- }) {
420
- return id !== null ? `media://${id}` : null;
421
- }
422
- static replaceMediasWithPaths(data, patterns, medias = null, keyPrefix = null) {
423
- const dataIsArray = isArray(data);
424
- const keys = dataIsArray ? [...data.keys()] : Object.keys(data);
425
- return keys.reduce(({
426
- data: currentData,
427
- medias: currentMedias
428
- }, key) => {
429
- const path = [keyPrefix, key].filter(it => it !== null).join('.');
430
- const patternMatch = patterns.reduce((found, pattern) => found || pattern.test(path), false);
431
- const value = data[key];
432
- let newValue;
433
- let media = null;
434
- let subMedias = null;
435
- if (patternMatch && isObject(value)) {
436
- const mediaPath = MediasParser.getMediaPath(value);
437
- newValue = mediaPath !== null ? mediaPath : value;
438
- media = mediaPath !== null ? value : null;
439
- } else if (isObject(value) || isArray(value)) {
440
- const subReturn = MediasParser.replaceMediasWithPaths(value, patterns, medias, path);
441
- newValue = subReturn.data;
442
- subMedias = subReturn.medias;
443
- } else {
444
- newValue = value;
445
- }
446
- return {
447
- data: dataIsArray ? [...(currentData || []), newValue] : {
448
- ...currentData,
449
- [key]: newValue
450
- },
451
- medias: media !== null ? {
452
- ...currentMedias,
453
- ...subMedias,
454
- [newValue]: media
455
- } : {
456
- ...currentMedias,
457
- ...subMedias
458
- }
459
- };
460
- }, {
461
- data: dataIsArray ? [] : {},
462
- medias
463
- });
464
- }
465
- }
466
-
467
- /* eslint-disable no-console */
468
- class Tracking extends Tracking$1 {
469
- setVariables(variables) {
470
- this.variables = variables;
471
- if (variables !== null) {
472
- this.push(variables);
473
- }
474
- }
475
- getVariables() {
476
- return this.variables;
477
- }
478
- trackScreenView(screen, screenIndex) {
479
- const {
480
- id: screenId = null,
481
- type: screenType = null
482
- } = screen || {};
483
- const data = {
484
- event: 'screenView',
485
- screenId,
486
- screenType,
487
- screenIndex
488
- };
489
- this.push(data);
490
- }
491
-
492
- // The options can also be a value, to stay compatible with the base trackEvent signature
493
- trackEvent(category, action, label, options = {}) {
494
- const {
495
- value = null,
496
- ...opts
497
- } = isObject(options) ? options : {
498
- value: options
499
- };
500
- const data = {
501
- ...opts,
502
- event: 'eventInteraction',
503
- eventCategory: category,
504
- eventAction: action,
505
- eventLabel: label,
506
- eventValue: value
507
- };
508
- this.push(data);
509
- }
510
- trackMedia(type, media, action, {
511
- value = null,
512
- ...opts
513
- } = {}) {
514
- const {
515
- id: mediaId = null,
516
- name = null,
517
- duration = null,
518
- currentTime = null
519
- } = media || {};
520
- const label = name;
521
- const data = {
522
- ...opts,
523
- event: 'eventInteraction',
524
- eventCategory: type,
525
- eventAction: action,
526
- eventLabel: label,
527
- eventValue: value,
528
- mediaId,
529
- mediaCurrentTime: currentTime !== null ? Math.round(currentTime) : null,
530
- mediaProgress: currentTime !== null && duration !== null && duration > 0 ? Math.round(currentTime / duration * 100) : null
531
- };
532
- this.push(data);
533
- }
534
- }
535
-
536
- export { ComponentsManager, DefinitionsManager, EventsManager, FieldsManager, FontsParser, FormsManager, MediasParser, Tracking };
1
+ import { can, canRunAction, getActionPlacements, isActionAllowedOn, partitionByAction } from "./definition/abilities.js";
2
+ import { getLayoutFieldNames, resolveFields, resolveForm } from "./definition/form.js";
3
+ import { DEFAULT_PER_PAGE, groupActions, resolveList } from "./definition/list.js";
4
+ import { findResource, resolveResource } from "./definition/resource.js";
5
+ import { isEqual, setValue } from "./values.js";
6
+ import { formatRuleFailure } from "./form/messages.js";
7
+ import { getItemValues, getProblem, isItem } from "./form/problem.js";
8
+ import { selectErrorCount, selectErrors, selectValue, selectVisible } from "./form/selectors.js";
9
+ import { createLocalStore } from "./form/store.js";
10
+ import { createForm, getDefaultValues } from "./form/form.js";
11
+ import { createList } from "./list/list.js";
12
+ import { createHistoryRouter, createMemoryRouter } from "./list/router.js";
13
+ import { createPluginRegistry, definePlugin, loadMessages } from "./plugins.js";
14
+ import { PanneauProvider, usePanneau, usePlugins, useResource } from "./react/provider.js";
15
+ import { useForm, useFormField } from "./react/useForm.js";
16
+ import { useList } from "./react/useList.js";
17
+ export { DEFAULT_PER_PAGE, PanneauProvider, can, canRunAction, createForm, createHistoryRouter, createList, createLocalStore, createMemoryRouter, createPluginRegistry, definePlugin, findResource, formatRuleFailure, getActionPlacements, getDefaultValues, getItemValues, getLayoutFieldNames, getProblem, groupActions, isActionAllowedOn, isEqual, isItem, loadMessages, partitionByAction, resolveFields, resolveForm, resolveList, resolveResource, selectErrorCount, selectErrors, selectValue, selectVisible, setValue, useForm, useFormField, useList, usePanneau, usePlugins, useResource };
@@ -0,0 +1,68 @@
1
+ import { type FilterValue, type ListQuery, type Selection } from '@panneau/protocol';
2
+ import type { ResolvedList } from '../definition/list';
3
+ import type { Router } from './router';
4
+ /**
5
+ * Selected items: some ids, or every item matching the list query (filters and search) except
6
+ * some ids. "All matching" covers the items of every page.
7
+ */
8
+ export type ListSelection = {
9
+ mode: 'ids';
10
+ ids: readonly string[];
11
+ } | {
12
+ mode: 'all';
13
+ except: readonly string[];
14
+ };
15
+ export interface ListState {
16
+ /** The query to fetch: the list's defaults, overridden by the current state. */
17
+ query: ListQuery;
18
+ selection: ListSelection;
19
+ }
20
+ export interface ListDefaults {
21
+ perPage?: number;
22
+ /** Default sort, as `sort` query values (`['-published_at']`). */
23
+ sort?: string[];
24
+ }
25
+ export interface ListOptions {
26
+ /** A resolved list, for the defaults (`perPage`, `defaultSort`). */
27
+ list?: ResolvedList;
28
+ /** Defaults, over those of `list`. Default values are not written to the URL. */
29
+ defaults?: ListDefaults;
30
+ /** The starting query, when there is no router. */
31
+ query?: ListQuery;
32
+ /** Keeps the query in the URL. The router's query string wins over `query`. */
33
+ router?: Router | null;
34
+ }
35
+ /** A headless list: query and selection. React components use `useList()`. */
36
+ export interface List {
37
+ getState(): ListState;
38
+ subscribe(listener: () => void): () => void;
39
+ setPage(page: number): void;
40
+ /** Sets the page size, and goes back to the first page. */
41
+ setPerPage(perPage: number): void;
42
+ /** Sets the sort (`['-published_at', 'title']`), and goes back to the first page. */
43
+ setSort(sort: readonly string[]): void;
44
+ /** Sorts by a field: ascending, then descending, then back to the default sort. */
45
+ toggleSort(field: string): void;
46
+ /** Sets or removes (`undefined`) a filter, goes back to the first page, and clears the selection. */
47
+ setFilter(id: string, value: FilterValue | undefined): void;
48
+ /** Sets the search, goes back to the first page, and clears the selection. */
49
+ setSearch(q: string): void;
50
+ /** Removes the page, filters, search and sort: back to the defaults. */
51
+ resetQuery(): void;
52
+ /** Adds ids to the selection (removes them from the exceptions in "all matching" mode). */
53
+ select(ids: readonly string[]): void;
54
+ /** Removes ids from the selection (adds them to the exceptions in "all matching" mode). */
55
+ deselect(ids: readonly string[]): void;
56
+ toggle(id: string): void;
57
+ /** Selects every item matching the query, on every page. */
58
+ selectAllMatching(): void;
59
+ clearSelection(): void;
60
+ isSelected(id: string): boolean;
61
+ /** How many items are selected, given the total of the list. */
62
+ getSelectedCount(total: number): number;
63
+ /** The selection to send with an action, or `null` when nothing is selected. */
64
+ getSelection(): Selection | null;
65
+ }
66
+ /** Creates a headless list. */
67
+ export declare function createList(options?: ListOptions): List;
68
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/list/list.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,SAAS,EAGjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAEzF,MAAM,WAAW,SAAS;IACtB,gFAAgF;IAChF,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,aAAa,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IACxB,oEAAoE;IACpE,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,mDAAmD;IACnD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,8EAA8E;AAC9E,MAAM,WAAW,IAAI;IACjB,QAAQ,IAAI,SAAS,CAAC;IACtB,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,2DAA2D;IAC3D,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,qFAAqF;IACrF,OAAO,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACvC,mFAAmF;IACnF,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qGAAqG;IACrG,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5D,8EAA8E;IAC9E,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,wEAAwE;IACxE,UAAU,IAAI,IAAI,CAAC;IACnB,2FAA2F;IAC3F,MAAM,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACrC,2FAA2F;IAC3F,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,4DAA4D;IAC5D,iBAAiB,IAAI,IAAI,CAAC;IAC1B,cAAc,IAAI,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,gEAAgE;IAChE,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACxC,gFAAgF;IAChF,YAAY,IAAI,SAAS,GAAG,IAAI,CAAC;CACpC;AAkCD,+BAA+B;AAC/B,wBAAgB,UAAU,CAAC,OAAO,GAAE,WAAgB,GAAG,IAAI,CAgL1D"}