@panneau/lists 4.1.1 → 5.0.0-alpha.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 (138) hide show
  1. package/README.md +116 -0
  2. package/dist/List.d.ts +26 -0
  3. package/dist/List.d.ts.map +1 -0
  4. package/dist/List.js +38 -0
  5. package/dist/List.js.map +1 -0
  6. package/dist/ListView.css +101 -0
  7. package/dist/ListView.d.ts +76 -0
  8. package/dist/ListView.d.ts.map +1 -0
  9. package/dist/ListView.js +325 -0
  10. package/dist/ListView.js.map +1 -0
  11. package/dist/ListView.module.js +28 -0
  12. package/dist/ListView.module.js.map +1 -0
  13. package/dist/actions/ActionButton.d.ts +18 -0
  14. package/dist/actions/ActionButton.d.ts.map +1 -0
  15. package/dist/actions/ActionButton.js +34 -0
  16. package/dist/actions/ActionButton.js.map +1 -0
  17. package/dist/actions/Actions.css +58 -0
  18. package/dist/actions/Actions.module.js +20 -0
  19. package/dist/actions/Actions.module.js.map +1 -0
  20. package/dist/actions/ConfirmDialog.d.ts +15 -0
  21. package/dist/actions/ConfirmDialog.d.ts.map +1 -0
  22. package/dist/actions/ConfirmDialog.js +157 -0
  23. package/dist/actions/ConfirmDialog.js.map +1 -0
  24. package/dist/actions/RowActions.d.ts +20 -0
  25. package/dist/actions/RowActions.d.ts.map +1 -0
  26. package/dist/actions/RowActions.js +99 -0
  27. package/dist/actions/RowActions.js.map +1 -0
  28. package/dist/actions/actions.d.ts +23 -0
  29. package/dist/actions/actions.d.ts.map +1 -0
  30. package/dist/actions/actions.js +56 -0
  31. package/dist/actions/actions.js.map +1 -0
  32. package/dist/actions/icons.d.ts +10 -0
  33. package/dist/actions/icons.d.ts.map +1 -0
  34. package/dist/actions/icons.js +27 -0
  35. package/dist/actions/icons.js.map +1 -0
  36. package/dist/cx.d.ts +3 -0
  37. package/dist/cx.d.ts.map +1 -0
  38. package/dist/cx.js +9 -0
  39. package/dist/cx.js.map +1 -0
  40. package/dist/displays/Displays.css +71 -0
  41. package/dist/displays/Displays.module.js +30 -0
  42. package/dist/displays/Displays.module.js.map +1 -0
  43. package/dist/displays/displays.d.ts +36 -0
  44. package/dist/displays/displays.d.ts.map +1 -0
  45. package/dist/displays/displays.js +570 -0
  46. package/dist/displays/displays.js.map +1 -0
  47. package/dist/filters/Filters.css +71 -0
  48. package/dist/filters/Filters.d.ts +38 -0
  49. package/dist/filters/Filters.d.ts.map +1 -0
  50. package/dist/filters/Filters.js +240 -0
  51. package/dist/filters/Filters.js.map +1 -0
  52. package/dist/filters/Filters.module.js +24 -0
  53. package/dist/filters/Filters.module.js.map +1 -0
  54. package/dist/filters/controls.d.ts +23 -0
  55. package/dist/filters/controls.d.ts.map +1 -0
  56. package/dist/filters/controls.js +431 -0
  57. package/dist/filters/controls.js.map +1 -0
  58. package/dist/filters/format.d.ts +16 -0
  59. package/dist/filters/format.d.ts.map +1 -0
  60. package/dist/filters/format.js +46 -0
  61. package/dist/filters/format.js.map +1 -0
  62. package/dist/index.d.ts +19 -10
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +18 -66
  65. package/dist/layouts/CardsLayout.css +72 -0
  66. package/dist/layouts/CardsLayout.d.ts +4 -0
  67. package/dist/layouts/CardsLayout.d.ts.map +1 -0
  68. package/dist/layouts/CardsLayout.js +111 -0
  69. package/dist/layouts/CardsLayout.js.map +1 -0
  70. package/dist/layouts/CardsLayout.module.js +24 -0
  71. package/dist/layouts/CardsLayout.module.js.map +1 -0
  72. package/dist/layouts/ItemTitle.d.ts +10 -0
  73. package/dist/layouts/ItemTitle.d.ts.map +1 -0
  74. package/dist/layouts/ItemTitle.js +30 -0
  75. package/dist/layouts/ItemTitle.js.map +1 -0
  76. package/dist/layouts/TableLayout.css +177 -0
  77. package/dist/layouts/TableLayout.d.ts +9 -0
  78. package/dist/layouts/TableLayout.d.ts.map +1 -0
  79. package/dist/layouts/TableLayout.js +208 -0
  80. package/dist/layouts/TableLayout.js.map +1 -0
  81. package/dist/layouts/TableLayout.module.js +32 -0
  82. package/dist/layouts/TableLayout.module.js.map +1 -0
  83. package/dist/layouts/builtIn.d.ts +6 -0
  84. package/dist/layouts/builtIn.d.ts.map +1 -0
  85. package/dist/layouts/builtIn.js +12 -0
  86. package/dist/layouts/builtIn.js.map +1 -0
  87. package/dist/layouts/link.css +16 -0
  88. package/dist/layouts/link.module.js +8 -0
  89. package/dist/layouts/link.module.js.map +1 -0
  90. package/dist/messages.d.ts +2 -0
  91. package/dist/messages.d.ts.map +1 -0
  92. package/dist/messages.js +1 -0
  93. package/dist/plugin.d.ts +13 -0
  94. package/dist/plugin.d.ts.map +1 -0
  95. package/dist/plugin.js +19 -0
  96. package/dist/plugin.js.map +1 -0
  97. package/dist/query.d.ts +21 -0
  98. package/dist/query.d.ts.map +1 -0
  99. package/dist/query.js +70 -0
  100. package/dist/query.js.map +1 -0
  101. package/dist/selection.d.ts +9 -0
  102. package/dist/selection.d.ts.map +1 -0
  103. package/dist/selection.js +19 -0
  104. package/dist/selection.js.map +1 -0
  105. package/dist/toolbar/LayoutSwitch.d.ts +8 -0
  106. package/dist/toolbar/LayoutSwitch.d.ts.map +1 -0
  107. package/dist/toolbar/LayoutSwitch.js +108 -0
  108. package/dist/toolbar/LayoutSwitch.js.map +1 -0
  109. package/dist/toolbar/Pagination.d.ts +13 -0
  110. package/dist/toolbar/Pagination.d.ts.map +1 -0
  111. package/dist/toolbar/Pagination.js +62 -0
  112. package/dist/toolbar/Pagination.js.map +1 -0
  113. package/dist/toolbar/SearchField.d.ts +9 -0
  114. package/dist/toolbar/SearchField.d.ts.map +1 -0
  115. package/dist/toolbar/SearchField.js +64 -0
  116. package/dist/toolbar/SearchField.js.map +1 -0
  117. package/dist/toolbar/SortSelect.d.ts +9 -0
  118. package/dist/toolbar/SortSelect.d.ts.map +1 -0
  119. package/dist/toolbar/SortSelect.js +90 -0
  120. package/dist/toolbar/SortSelect.js.map +1 -0
  121. package/dist/toolbar/Toolbar.css +72 -0
  122. package/dist/toolbar/Toolbar.module.js +22 -0
  123. package/dist/toolbar/Toolbar.module.js.map +1 -0
  124. package/dist/types.d.ts +106 -0
  125. package/dist/types.d.ts.map +1 -0
  126. package/dist/useDraft.d.ts +11 -0
  127. package/dist/useDraft.d.ts.map +1 -0
  128. package/dist/useDraft.js +77 -0
  129. package/dist/useDraft.js.map +1 -0
  130. package/dist/useListState.d.ts +4 -0
  131. package/dist/useListState.d.ts.map +1 -0
  132. package/dist/useListState.js +10 -0
  133. package/dist/useListState.js.map +1 -0
  134. package/dist/values.d.ts +21 -0
  135. package/dist/values.d.ts.map +1 -0
  136. package/dist/values.js +52 -0
  137. package/dist/values.js.map +1 -0
  138. package/package.json +27 -57
@@ -0,0 +1,431 @@
1
+ import { messages } from "../messages.js";
2
+ import { useDraft } from "../useDraft.js";
3
+ import Filters_module_default from "./Filters.module.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { Fieldset, Select, Switch, TextInput, usePanneauIntl } from "@panneau/ui";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { useFieldsContext } from "@panneau/fields";
8
+ import { useEffect } from "react";
9
+ import { DateField } from "@panneau/fields/date";
10
+ import { RelationField, useRelationReferences } from "@panneau/fields/relation";
11
+ import { isFilterRange } from "@panneau/protocol/runtime";
12
+ //#region src/filters/controls.tsx
13
+ function asStrings(value) {
14
+ if (isFilterRange(value)) return [];
15
+ if (Array.isArray(value)) return value.map(String);
16
+ return value === void 0 || value === null || value === "" ? [] : [String(value)];
17
+ }
18
+ /** A text filter: the list changes once the user stops typing. */
19
+ function TextFilter(t0) {
20
+ const $ = c(10);
21
+ const { label, value, onChange } = t0;
22
+ const current = typeof value === "string" || typeof value === "number" ? String(value) : "";
23
+ let t1;
24
+ if ($[0] !== onChange) {
25
+ t1 = (next) => onChange(next !== "" ? next : void 0);
26
+ $[0] = onChange;
27
+ $[1] = t1;
28
+ } else t1 = $[1];
29
+ const { draft, setDraft, flush } = useDraft(current, t1);
30
+ let t2;
31
+ if ($[2] !== flush) {
32
+ t2 = (event) => {
33
+ if (event.key === "Enter") flush();
34
+ };
35
+ $[2] = flush;
36
+ $[3] = t2;
37
+ } else t2 = $[3];
38
+ let t3;
39
+ if ($[4] !== draft || $[5] !== flush || $[6] !== label || $[7] !== setDraft || $[8] !== t2) {
40
+ t3 = /* @__PURE__ */ jsx(TextInput, {
41
+ label,
42
+ value: draft,
43
+ onChange: setDraft,
44
+ onKeyDown: t2,
45
+ onBlur: flush,
46
+ className: Filters_module_default.control
47
+ });
48
+ $[4] = draft;
49
+ $[5] = flush;
50
+ $[6] = label;
51
+ $[7] = setDraft;
52
+ $[8] = t2;
53
+ $[9] = t3;
54
+ } else t3 = $[9];
55
+ return t3;
56
+ }
57
+ /** A choice among the options, or several with `multiple`. */
58
+ function SelectFilter(t0) {
59
+ const $ = c(27);
60
+ const { filter, label, options, value, onChange } = t0;
61
+ const intl = usePanneauIntl();
62
+ let T0;
63
+ let t1;
64
+ let t2;
65
+ let t3;
66
+ let t4;
67
+ let t5;
68
+ if ($[0] !== filter.multiple || $[1] !== intl || $[2] !== label || $[3] !== onChange || $[4] !== options || $[5] !== value) {
69
+ t5 = Symbol.for("react.early_return_sentinel");
70
+ bb0: {
71
+ const selected = asStrings(value);
72
+ let t6;
73
+ if ($[12] !== options) {
74
+ t6 = (values) => options.filter((option) => values.includes(String(option.value))).map(_temp);
75
+ $[12] = options;
76
+ $[13] = t6;
77
+ } else t6 = $[13];
78
+ const toOptions = t6;
79
+ let t7;
80
+ if ($[14] !== intl) {
81
+ t7 = intl.formatMessage(messages.any);
82
+ $[14] = intl;
83
+ $[15] = t7;
84
+ } else t7 = $[15];
85
+ const placeholder = t7;
86
+ if (filter.multiple === true) {
87
+ let t8;
88
+ if ($[16] !== onChange) {
89
+ t8 = (next) => onChange(next.length > 0 ? next : void 0);
90
+ $[16] = onChange;
91
+ $[17] = t8;
92
+ } else t8 = $[17];
93
+ t5 = /* @__PURE__ */ jsx(Select, {
94
+ multiple: true,
95
+ label,
96
+ options,
97
+ placeholder,
98
+ value: toOptions(selected),
99
+ onChange: t8,
100
+ className: Filters_module_default.control
101
+ });
102
+ break bb0;
103
+ }
104
+ T0 = Select;
105
+ t1 = label;
106
+ t2 = options;
107
+ t3 = placeholder;
108
+ t4 = toOptions(selected)[0] ?? null;
109
+ }
110
+ $[0] = filter.multiple;
111
+ $[1] = intl;
112
+ $[2] = label;
113
+ $[3] = onChange;
114
+ $[4] = options;
115
+ $[5] = value;
116
+ $[6] = T0;
117
+ $[7] = t1;
118
+ $[8] = t2;
119
+ $[9] = t3;
120
+ $[10] = t4;
121
+ $[11] = t5;
122
+ } else {
123
+ T0 = $[6];
124
+ t1 = $[7];
125
+ t2 = $[8];
126
+ t3 = $[9];
127
+ t4 = $[10];
128
+ t5 = $[11];
129
+ }
130
+ if (t5 !== Symbol.for("react.early_return_sentinel")) return t5;
131
+ let t6;
132
+ if ($[18] !== onChange) {
133
+ t6 = (next_0) => onChange(next_0 ?? void 0);
134
+ $[18] = onChange;
135
+ $[19] = t6;
136
+ } else t6 = $[19];
137
+ let t7;
138
+ if ($[20] !== T0 || $[21] !== t1 || $[22] !== t2 || $[23] !== t3 || $[24] !== t4 || $[25] !== t6) {
139
+ t7 = /* @__PURE__ */ jsx(T0, {
140
+ label: t1,
141
+ options: t2,
142
+ placeholder: t3,
143
+ value: t4,
144
+ onChange: t6,
145
+ className: Filters_module_default.control
146
+ });
147
+ $[20] = T0;
148
+ $[21] = t1;
149
+ $[22] = t2;
150
+ $[23] = t3;
151
+ $[24] = t4;
152
+ $[25] = t6;
153
+ $[26] = t7;
154
+ } else t7 = $[26];
155
+ return t7;
156
+ }
157
+ /** On or off: on filters with `true`, off removes the filter. */
158
+ function _temp(option_0) {
159
+ return option_0.value;
160
+ }
161
+ function ToggleFilter(t0) {
162
+ const $ = c(6);
163
+ const { label, value, onChange } = t0;
164
+ const t1 = String(value) === "true";
165
+ let t2;
166
+ if ($[0] !== onChange) {
167
+ t2 = (checked) => onChange(checked ? true : void 0);
168
+ $[0] = onChange;
169
+ $[1] = t2;
170
+ } else t2 = $[1];
171
+ let t3;
172
+ if ($[2] !== label || $[3] !== t1 || $[4] !== t2) {
173
+ t3 = /* @__PURE__ */ jsx(Switch, {
174
+ isSelected: t1,
175
+ onChange: t2,
176
+ className: Filters_module_default.toggle,
177
+ children: label
178
+ });
179
+ $[2] = label;
180
+ $[3] = t1;
181
+ $[4] = t2;
182
+ $[5] = t3;
183
+ } else t3 = $[5];
184
+ return t3;
185
+ }
186
+ /** A day (`2026-10-15`). */
187
+ function DateFilter(t0) {
188
+ const $ = c(6);
189
+ const { label, value, onChange } = t0;
190
+ const t1 = typeof value === "string" && value !== "" ? value : null;
191
+ let t2;
192
+ if ($[0] !== onChange) {
193
+ t2 = (next) => onChange(next ?? void 0);
194
+ $[0] = onChange;
195
+ $[1] = t2;
196
+ } else t2 = $[1];
197
+ let t3;
198
+ if ($[2] !== label || $[3] !== t1 || $[4] !== t2) {
199
+ t3 = /* @__PURE__ */ jsx(DateField, {
200
+ label,
201
+ value: t1,
202
+ onChange: t2,
203
+ className: Filters_module_default.control
204
+ });
205
+ $[2] = label;
206
+ $[3] = t1;
207
+ $[4] = t2;
208
+ $[5] = t3;
209
+ } else t3 = $[5];
210
+ return t3;
211
+ }
212
+ /**
213
+ * A range of days, sent as its bounds (`filter[published_at][from]=2026-01-01&…[to]=…`). Either end
214
+ * can be open: it is left out.
215
+ */
216
+ function DateRangeFilter(t0) {
217
+ const $ = c(26);
218
+ const { label, value, onChange } = t0;
219
+ const intl = usePanneauIntl();
220
+ let t1;
221
+ if ($[0] !== value) {
222
+ t1 = isFilterRange(value) ? value : {};
223
+ $[0] = value;
224
+ $[1] = t1;
225
+ } else t1 = $[1];
226
+ const range = t1;
227
+ const from = range.from !== void 0 ? String(range.from) : "";
228
+ const to = range.to !== void 0 ? String(range.to) : "";
229
+ let t2;
230
+ if ($[2] !== onChange) {
231
+ t2 = (nextFrom, nextTo) => onChange(nextFrom === "" && nextTo === "" ? void 0 : {
232
+ ...nextFrom !== "" ? { from: nextFrom } : {},
233
+ ...nextTo !== "" ? { to: nextTo } : {}
234
+ });
235
+ $[2] = onChange;
236
+ $[3] = t2;
237
+ } else t2 = $[3];
238
+ const set = t2;
239
+ let t3;
240
+ if ($[4] !== intl) {
241
+ t3 = intl.formatMessage(messages.from);
242
+ $[4] = intl;
243
+ $[5] = t3;
244
+ } else t3 = $[5];
245
+ const t4 = from !== "" ? from : null;
246
+ let t5;
247
+ if ($[6] !== set || $[7] !== to) {
248
+ t5 = (next) => set(next ?? "", to);
249
+ $[6] = set;
250
+ $[7] = to;
251
+ $[8] = t5;
252
+ } else t5 = $[8];
253
+ let t6;
254
+ if ($[9] !== t3 || $[10] !== t4 || $[11] !== t5) {
255
+ t6 = /* @__PURE__ */ jsx(DateField, {
256
+ label: t3,
257
+ value: t4,
258
+ onChange: t5
259
+ });
260
+ $[9] = t3;
261
+ $[10] = t4;
262
+ $[11] = t5;
263
+ $[12] = t6;
264
+ } else t6 = $[12];
265
+ let t7;
266
+ if ($[13] !== intl) {
267
+ t7 = intl.formatMessage(messages.to);
268
+ $[13] = intl;
269
+ $[14] = t7;
270
+ } else t7 = $[14];
271
+ const t8 = to !== "" ? to : null;
272
+ let t9;
273
+ if ($[15] !== from || $[16] !== set) {
274
+ t9 = (next_0) => set(from, next_0 ?? "");
275
+ $[15] = from;
276
+ $[16] = set;
277
+ $[17] = t9;
278
+ } else t9 = $[17];
279
+ let t10;
280
+ if ($[18] !== t7 || $[19] !== t8 || $[20] !== t9) {
281
+ t10 = /* @__PURE__ */ jsx(DateField, {
282
+ label: t7,
283
+ value: t8,
284
+ onChange: t9
285
+ });
286
+ $[18] = t7;
287
+ $[19] = t8;
288
+ $[20] = t9;
289
+ $[21] = t10;
290
+ } else t10 = $[21];
291
+ let t11;
292
+ if ($[22] !== label || $[23] !== t10 || $[24] !== t6) {
293
+ t11 = /* @__PURE__ */ jsxs(Fieldset, {
294
+ legend: label,
295
+ className: Filters_module_default.range,
296
+ children: [t6, t10]
297
+ });
298
+ $[22] = label;
299
+ $[23] = t10;
300
+ $[24] = t6;
301
+ $[25] = t11;
302
+ } else t11 = $[25];
303
+ return t11;
304
+ }
305
+ /**
306
+ * An item of another resource (`resource`), or several with `multiple`, picked with the relation
307
+ * source of the fields context. The filter keeps their ids; their labels are remembered for the
308
+ * chips.
309
+ */
310
+ function RelationFilter(t0) {
311
+ const $ = c(27);
312
+ const { filter, label, value, onChange, onLabel, getValueLabel } = t0;
313
+ const resource = filter.resource ?? filter.id;
314
+ const t1 = useFieldsContext().relationSource;
315
+ let t2;
316
+ if ($[0] !== getValueLabel || $[1] !== value) {
317
+ let t3;
318
+ if ($[3] !== getValueLabel) {
319
+ t3 = (id) => ({
320
+ id,
321
+ label: getValueLabel(id) ?? id
322
+ });
323
+ $[3] = getValueLabel;
324
+ $[4] = t3;
325
+ } else t3 = $[4];
326
+ t2 = asStrings(value).map(t3);
327
+ $[0] = getValueLabel;
328
+ $[1] = value;
329
+ $[2] = t2;
330
+ } else t2 = $[2];
331
+ const references = useRelationReferences(t1, resource, t2);
332
+ let t3;
333
+ if ($[5] !== onLabel) {
334
+ t3 = (next) => next.forEach((reference) => onLabel(reference.id, reference.label));
335
+ $[5] = onLabel;
336
+ $[6] = t3;
337
+ } else t3 = $[6];
338
+ const remember = t3;
339
+ let t4;
340
+ let t5;
341
+ if ($[7] !== onLabel || $[8] !== references) {
342
+ t4 = () => {
343
+ references.filter(_temp2).forEach((reference_1) => onLabel(reference_1.id, reference_1.label));
344
+ };
345
+ t5 = [references, onLabel];
346
+ $[7] = onLabel;
347
+ $[8] = references;
348
+ $[9] = t4;
349
+ $[10] = t5;
350
+ } else {
351
+ t4 = $[9];
352
+ t5 = $[10];
353
+ }
354
+ useEffect(t4, t5);
355
+ if (filter.multiple === true) {
356
+ let t6;
357
+ if ($[11] !== onChange || $[12] !== remember) {
358
+ t6 = (next_0) => {
359
+ remember(next_0 ?? []);
360
+ const ids = next_0 !== null && next_0.length > 0 ? next_0.map(_temp3) : void 0;
361
+ onChange(ids);
362
+ };
363
+ $[11] = onChange;
364
+ $[12] = remember;
365
+ $[13] = t6;
366
+ } else t6 = $[13];
367
+ let t7;
368
+ if ($[14] !== label || $[15] !== references || $[16] !== resource || $[17] !== t6) {
369
+ t7 = /* @__PURE__ */ jsx(RelationField, {
370
+ multiple: true,
371
+ label,
372
+ resource,
373
+ value: references,
374
+ onChange: t6,
375
+ className: Filters_module_default.control
376
+ });
377
+ $[14] = label;
378
+ $[15] = references;
379
+ $[16] = resource;
380
+ $[17] = t6;
381
+ $[18] = t7;
382
+ } else t7 = $[18];
383
+ return t7;
384
+ }
385
+ const t6 = references[0] ?? null;
386
+ let t7;
387
+ if ($[19] !== onChange || $[20] !== remember) {
388
+ t7 = (next_1) => {
389
+ remember(next_1 !== null ? [next_1] : []);
390
+ onChange(next_1?.id);
391
+ };
392
+ $[19] = onChange;
393
+ $[20] = remember;
394
+ $[21] = t7;
395
+ } else t7 = $[21];
396
+ let t8;
397
+ if ($[22] !== label || $[23] !== resource || $[24] !== t6 || $[25] !== t7) {
398
+ t8 = /* @__PURE__ */ jsx(RelationField, {
399
+ label,
400
+ resource,
401
+ value: t6,
402
+ onChange: t7,
403
+ className: Filters_module_default.control
404
+ });
405
+ $[22] = label;
406
+ $[23] = resource;
407
+ $[24] = t6;
408
+ $[25] = t7;
409
+ $[26] = t8;
410
+ } else t8 = $[26];
411
+ return t8;
412
+ }
413
+ /** The built-in filter controls, by filter type. Unknown types are text filters. */
414
+ function _temp3(reference_2) {
415
+ return reference_2.id;
416
+ }
417
+ function _temp2(reference_0) {
418
+ return reference_0.label !== reference_0.id;
419
+ }
420
+ var builtInFilters = {
421
+ text: TextFilter,
422
+ select: SelectFilter,
423
+ toggle: ToggleFilter,
424
+ date: DateFilter,
425
+ "date-range": DateRangeFilter,
426
+ relation: RelationFilter
427
+ };
428
+ //#endregion
429
+ export { DateFilter, DateRangeFilter, RelationFilter, SelectFilter, TextFilter, ToggleFilter, builtInFilters };
430
+
431
+ //# sourceMappingURL=controls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controls.js","names":["label","draft","setDraft","flush","options","placeholder","option","reference","next","resource","references","_c","styles"],"sources":["../../src/filters/controls.tsx"],"sourcesContent":["import { useEffect } from 'react';\n\nimport { useFieldsContext } from '@panneau/fields';\nimport { DateField } from '@panneau/fields/date';\nimport { RelationField, useRelationReferences } from '@panneau/fields/relation';\nimport type { FilterValue } from '@panneau/protocol';\nimport { isFilterRange } from '@panneau/protocol/runtime';\nimport { Fieldset, type OptionValue, Select, Switch, TextInput, usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../messages';\nimport type { FilterControlProps, FilterEntry } from '../types';\nimport { useDraft } from '../useDraft';\nimport styles from './Filters.module.css';\n\nfunction asStrings(value: unknown): string[] {\n if (isFilterRange(value)) {\n return [];\n }\n if (Array.isArray(value)) {\n return value.map(String);\n }\n return value === undefined || value === null || value === '' ? [] : [String(value)];\n}\n\n/** A text filter: the list changes once the user stops typing. */\nexport function TextFilter({ label, value, onChange }: FilterControlProps) {\n const current = typeof value === 'string' || typeof value === 'number' ? String(value) : '';\n const { draft, setDraft, flush } = useDraft(current, (next) =>\n onChange(next !== '' ? next : undefined),\n );\n return (\n <TextInput\n label={label}\n value={draft}\n onChange={setDraft}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n flush();\n }\n }}\n onBlur={flush}\n className={styles.control}\n />\n );\n}\n\n/** A choice among the options, or several with `multiple`. */\nexport function SelectFilter({ filter, label, options, value, onChange }: FilterControlProps) {\n const intl = usePanneauIntl();\n const selected = asStrings(value);\n // Values from the URL are strings: match them to the options' values.\n const toOptions = (values: readonly string[]): OptionValue[] =>\n options\n .filter((option) => values.includes(String(option.value)))\n .map((option) => option.value);\n const placeholder = intl.formatMessage(messages.any);\n if (filter.multiple === true) {\n return (\n <Select\n multiple\n label={label}\n options={options}\n placeholder={placeholder}\n value={toOptions(selected)}\n onChange={(next) => onChange(next.length > 0 ? next : undefined)}\n className={styles.control}\n />\n );\n }\n return (\n <Select\n label={label}\n options={options}\n placeholder={placeholder}\n value={toOptions(selected)[0] ?? null}\n onChange={(next) => onChange(next ?? undefined)}\n className={styles.control}\n />\n );\n}\n\n/** On or off: on filters with `true`, off removes the filter. */\nexport function ToggleFilter({ label, value, onChange }: FilterControlProps) {\n return (\n <Switch\n isSelected={String(value) === 'true'}\n onChange={(checked) => onChange(checked ? true : undefined)}\n className={styles.toggle}\n >\n {label}\n </Switch>\n );\n}\n\n/** A day (`2026-10-15`). */\nexport function DateFilter({ label, value, onChange }: FilterControlProps) {\n return (\n <DateField\n label={label}\n value={typeof value === 'string' && value !== '' ? value : null}\n onChange={(next) => onChange(next ?? undefined)}\n className={styles.control}\n />\n );\n}\n\n/**\n * A range of days, sent as its bounds (`filter[published_at][from]=2026-01-01&…[to]=…`). Either end\n * can be open: it is left out.\n */\nexport function DateRangeFilter({ label, value, onChange }: FilterControlProps) {\n const intl = usePanneauIntl();\n const range = isFilterRange(value) ? value : {};\n const from = range.from !== undefined ? String(range.from) : '';\n const to = range.to !== undefined ? String(range.to) : '';\n const set = (nextFrom: string, nextTo: string) =>\n onChange(\n nextFrom === '' && nextTo === ''\n ? undefined\n : {\n ...(nextFrom !== '' ? { from: nextFrom } : {}),\n ...(nextTo !== '' ? { to: nextTo } : {}),\n },\n );\n return (\n <Fieldset legend={label} className={styles.range}>\n <DateField\n label={intl.formatMessage(messages.from)}\n value={from !== '' ? from : null}\n onChange={(next) => set(next ?? '', to)}\n />\n <DateField\n label={intl.formatMessage(messages.to)}\n value={to !== '' ? to : null}\n onChange={(next) => set(from, next ?? '')}\n />\n </Fieldset>\n );\n}\n\n/**\n * An item of another resource (`resource`), or several with `multiple`, picked with the relation\n * source of the fields context. The filter keeps their ids; their labels are remembered for the\n * chips.\n */\nexport function RelationFilter({\n filter,\n label,\n value,\n onChange,\n onLabel,\n getValueLabel,\n}: FilterControlProps) {\n const resource = filter.resource ?? filter.id;\n // Ids from the URL have no label: the relation source resolves them, for the picker and chips.\n const references = useRelationReferences(\n useFieldsContext().relationSource,\n resource,\n asStrings(value).map((id) => ({ id, label: getValueLabel(id) ?? id })),\n );\n const remember = (next: readonly { id: string; label: string }[]) =>\n next.forEach((reference) => onLabel(reference.id, reference.label));\n useEffect(() => {\n references\n .filter((reference) => reference.label !== reference.id)\n .forEach((reference) => onLabel(reference.id, reference.label));\n }, [references, onLabel]);\n if (filter.multiple === true) {\n return (\n <RelationField\n multiple\n label={label}\n resource={resource}\n value={references}\n onChange={(next) => {\n remember(next ?? []);\n const ids: FilterValue | undefined =\n next !== null && next.length > 0\n ? next.map((reference) => reference.id)\n : undefined;\n onChange(ids);\n }}\n className={styles.control}\n />\n );\n }\n return (\n <RelationField\n label={label}\n resource={resource}\n value={references[0] ?? null}\n onChange={(next) => {\n remember(next !== null ? [next] : []);\n onChange(next?.id);\n }}\n className={styles.control}\n />\n );\n}\n\n/** The built-in filter controls, by filter type. Unknown types are text filters. */\nexport const builtInFilters: Readonly<Record<string, FilterEntry>> = {\n text: TextFilter,\n select: SelectFilter,\n toggle: ToggleFilter,\n date: DateFilter,\n 'date-range': DateRangeFilter,\n relation: RelationFilter,\n};\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { IntlShape } from 'react-intl';
2
+ import type { Field, Filter, Option } from '@panneau/protocol';
3
+ import type { ListColumn } from '../types';
4
+ /** The label of a filter: its `label`, the label of its field, or its id. */
5
+ export declare function getFilterLabel(filter: Filter, columns: readonly ListColumn[], fields: readonly Field[]): string;
6
+ /** The field a filter filters, when a column or the list's fields have one with its id. */
7
+ export declare function findFilterField(filter: Filter, columns: readonly ListColumn[], fields: readonly Field[]): Field | null;
8
+ /** The options of a filter: its own, or those of the field it filters. */
9
+ export declare function getFilterOptions(filter: Filter, columns: readonly ListColumn[], fields: readonly Field[]): readonly Option[];
10
+ /** The value of an active filter, as the text of its chip. */
11
+ export declare function formatFilterValue(filter: Filter, value: unknown, { intl, options, getValueLabel, }: {
12
+ intl: IntlShape;
13
+ options: readonly Option[];
14
+ getValueLabel: (value: string) => string | null;
15
+ }): string;
16
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/filters/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAG3C,6EAA6E;AAC7E,wBAAgB,cAAc,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,MAAM,EAAE,SAAS,KAAK,EAAE,GACzB,MAAM,CAMR;AAED,2FAA2F;AAC3F,wBAAgB,eAAe,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,MAAM,EAAE,SAAS,KAAK,EAAE,GACzB,KAAK,GAAG,IAAI,CAMd;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,MAAM,EAAE,SAAS,KAAK,EAAE,GACzB,SAAS,MAAM,EAAE,CAEnB;AAcD,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,EACI,IAAI,EACJ,OAAO,EACP,aAAa,GAChB,EAAE;IACC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACnD,GACF,MAAM,CAuBR"}
@@ -0,0 +1,46 @@
1
+ import { messages } from "../messages.js";
2
+ import { getFieldOptions, getOptionLabel } from "../values.js";
3
+ import { isFilterRange } from "@panneau/protocol/runtime";
4
+ //#region src/filters/format.ts
5
+ /** The label of a filter: its `label`, the label of its field, or its id. */
6
+ function getFilterLabel(filter, columns, fields) {
7
+ if (filter.label !== void 0) return filter.label;
8
+ return findFilterField(filter, columns, fields)?.label ?? filter.id;
9
+ }
10
+ /** The field a filter filters, when a column or the list's fields have one with its id. */
11
+ function findFilterField(filter, columns, fields) {
12
+ return fields.find((field) => field.name === filter.id) ?? columns.find((column) => column.field?.name === filter.id)?.field ?? null;
13
+ }
14
+ /** The options of a filter: its own, or those of the field it filters. */
15
+ function getFilterOptions(filter, columns, fields) {
16
+ return filter.options ?? getFieldOptions(findFilterField(filter, columns, fields));
17
+ }
18
+ var DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
19
+ function formatDay(value, intl) {
20
+ const match = DATE_ONLY.exec(value);
21
+ if (match === null) return value;
22
+ return intl.formatDate(new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])), { dateStyle: "medium" });
23
+ }
24
+ /** The value of an active filter, as the text of its chip. */
25
+ function formatFilterValue(filter, value, { intl, options, getValueLabel }) {
26
+ const values = Array.isArray(value) ? value : [value];
27
+ switch (filter.type) {
28
+ case "toggle": return intl.formatMessage(String(value) === "true" ? messages.yes : messages.no);
29
+ case "date": return formatDay(String(value), intl);
30
+ case "date-range": {
31
+ const range = isFilterRange(value) ? value : {};
32
+ const from = range.from !== void 0 ? String(range.from) : "";
33
+ const to = range.to !== void 0 ? String(range.to) : "";
34
+ return intl.formatMessage(messages.dateRange, {
35
+ from: from !== "" ? formatDay(from, intl) : "…",
36
+ to: to !== "" ? formatDay(to, intl) : "…"
37
+ });
38
+ }
39
+ case "relation": return values.map((entry) => getValueLabel(String(entry)) ?? String(entry)).join(", ");
40
+ default: return values.map((entry) => getOptionLabel(options, entry) ?? String(entry)).join(", ");
41
+ }
42
+ }
43
+ //#endregion
44
+ export { findFilterField, formatFilterValue, getFilterLabel, getFilterOptions };
45
+
46
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","names":[],"sources":["../../src/filters/format.ts"],"sourcesContent":["import type { IntlShape } from 'react-intl';\n\nimport type { Field, Filter, Option } from '@panneau/protocol';\nimport { isFilterRange } from '@panneau/protocol/runtime';\n\nimport { messages } from '../messages';\nimport type { ListColumn } from '../types';\nimport { getFieldOptions, getOptionLabel } from '../values';\n\n/** The label of a filter: its `label`, the label of its field, or its id. */\nexport function getFilterLabel(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): string {\n if (filter.label !== undefined) {\n return filter.label;\n }\n const field = findFilterField(filter, columns, fields);\n return field?.label ?? filter.id;\n}\n\n/** The field a filter filters, when a column or the list's fields have one with its id. */\nexport function findFilterField(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): Field | null {\n return (\n fields.find((field) => field.name === filter.id) ??\n columns.find((column) => column.field?.name === filter.id)?.field ??\n null\n );\n}\n\n/** The options of a filter: its own, or those of the field it filters. */\nexport function getFilterOptions(\n filter: Filter,\n columns: readonly ListColumn[],\n fields: readonly Field[],\n): readonly Option[] {\n return filter.options ?? getFieldOptions(findFilterField(filter, columns, fields));\n}\n\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nfunction formatDay(value: string, intl: IntlShape): string {\n const match = DATE_ONLY.exec(value);\n if (match === null) {\n return value;\n }\n return intl.formatDate(new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])), {\n dateStyle: 'medium',\n });\n}\n\n/** The value of an active filter, as the text of its chip. */\nexport function formatFilterValue(\n filter: Filter,\n value: unknown,\n {\n intl,\n options,\n getValueLabel,\n }: {\n intl: IntlShape;\n options: readonly Option[];\n getValueLabel: (value: string) => string | null;\n },\n): string {\n const values: unknown[] = Array.isArray(value) ? value : [value];\n switch (filter.type) {\n case 'toggle':\n return intl.formatMessage(String(value) === 'true' ? messages.yes : messages.no);\n case 'date':\n return formatDay(String(value), intl);\n case 'date-range': {\n const range = isFilterRange(value) ? value : {};\n const from = range.from !== undefined ? String(range.from) : '';\n const to = range.to !== undefined ? String(range.to) : '';\n return intl.formatMessage(messages.dateRange, {\n from: from !== '' ? formatDay(from, intl) : '…',\n to: to !== '' ? formatDay(to, intl) : '…',\n });\n }\n case 'relation':\n return values.map((entry) => getValueLabel(String(entry)) ?? String(entry)).join(', ');\n default:\n return values\n .map((entry) => getOptionLabel(options, entry) ?? String(entry))\n .join(', ');\n }\n}\n"],"mappings":";;;;;AAUA,SAAgB,eACZ,QACA,SACA,QACM;CACN,IAAI,OAAO,UAAU,KAAA,GACjB,OAAO,OAAO;CAGlB,OADc,gBAAgB,QAAQ,SAAS,MACxC,CAAA,EAAO,SAAS,OAAO;AAClC;;AAGA,SAAgB,gBACZ,QACA,SACA,QACY;CACZ,OACI,OAAO,MAAM,UAAU,MAAM,SAAS,OAAO,EAAE,KAC/C,QAAQ,MAAM,WAAW,OAAO,OAAO,SAAS,OAAO,EAAE,CAAC,EAAE,SAC5D;AAER;;AAGA,SAAgB,iBACZ,QACA,SACA,QACiB;CACjB,OAAO,OAAO,WAAW,gBAAgB,gBAAgB,QAAQ,SAAS,MAAM,CAAC;AACrF;AAEA,IAAM,YAAY;AAElB,SAAS,UAAU,OAAe,MAAyB;CACvD,MAAM,QAAQ,UAAU,KAAK,KAAK;CAClC,IAAI,UAAU,MACV,OAAO;CAEX,OAAO,KAAK,WAAW,IAAI,KAAK,OAAO,MAAM,EAAE,GAAG,OAAO,MAAM,EAAE,IAAI,GAAG,OAAO,MAAM,EAAE,CAAC,GAAG,EACvF,WAAW,SACf,CAAC;AACL;;AAGA,SAAgB,kBACZ,QACA,OACA,EACI,MACA,SACA,iBAME;CACN,MAAM,SAAoB,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;CAC/D,QAAQ,OAAO,MAAf;EACI,KAAK,UACD,OAAO,KAAK,cAAc,OAAO,KAAK,MAAM,SAAS,SAAS,MAAM,SAAS,EAAE;EACnF,KAAK,QACD,OAAO,UAAU,OAAO,KAAK,GAAG,IAAI;EACxC,KAAK,cAAc;GACf,MAAM,QAAQ,cAAc,KAAK,IAAI,QAAQ,CAAC;GAC9C,MAAM,OAAO,MAAM,SAAS,KAAA,IAAY,OAAO,MAAM,IAAI,IAAI;GAC7D,MAAM,KAAK,MAAM,OAAO,KAAA,IAAY,OAAO,MAAM,EAAE,IAAI;GACvD,OAAO,KAAK,cAAc,SAAS,WAAW;IAC1C,MAAM,SAAS,KAAK,UAAU,MAAM,IAAI,IAAI;IAC5C,IAAI,OAAO,KAAK,UAAU,IAAI,IAAI,IAAI;GAC1C,CAAC;EACL;EACA,KAAK,YACD,OAAO,OAAO,KAAK,UAAU,cAAc,OAAO,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;EACzF,SACI,OAAO,OACF,KAAK,UAAU,eAAe,SAAS,KAAK,KAAK,OAAO,KAAK,CAAC,CAAC,CAC/D,KAAK,IAAI;CACtB;AACJ"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,19 @@
1
- import * as react from 'react';
2
- import { ReactNode } from 'react';
3
-
4
- interface ListsProviderProps {
5
- components?: Record<string, unknown> | null;
6
- children?: ReactNode;
7
- }
8
- declare function ListsProvider({ components: injectedComponents, children, ...props }: ListsProviderProps): react.JSX.Element;
9
-
10
- export { ListsProvider as default };
1
+ export { type ListActions, getActionHref, groupListActions, isAllowedOn } from './actions/actions';
2
+ export { ConfirmDialog, type ConfirmDialogProps } from './actions/ConfirmDialog';
3
+ export { type ActionIcons, getActionIcon } from './actions/icons';
4
+ export { BooleanDisplay, ColorDisplay, DateDisplay, DateTimeDisplay, EmailDisplay, EmptyValue, MediaDisplay, NumberDisplay, RelationDisplay, RichTextDisplay, SelectDisplay, TextDisplay, TimeDisplay, UrlDisplay, builtInDisplays, } from './displays/displays';
5
+ export { DateFilter, DateRangeFilter, RelationFilter, SelectFilter, TextFilter, ToggleFilter, builtInFilters, } from './filters/controls';
6
+ export { CardsLayout } from './layouts/CardsLayout';
7
+ export { TableLayout } from './layouts/TableLayout';
8
+ export { builtInLayouts } from './layouts/builtIn';
9
+ export { List, type ListProps } from './List';
10
+ export { ListView, type ListViewProps } from './ListView';
11
+ export { listsPlugin } from './plugin';
12
+ export { type LocalQueryOptions, type LocalQueryResult, applyListQuery } from './query';
13
+ export { countSelected, getPageSelection, isItemSelected } from './selection';
14
+ export { Pagination, type PaginationProps } from './toolbar/Pagination';
15
+ export { SearchField, type SearchFieldProps } from './toolbar/SearchField';
16
+ export type { DisplayEntry, DisplayProps, FilterControlProps, FilterEntry, ListActionEvent, ListActionHandler, ListColumn, ListItem, ListLayoutEntry, ListLayoutProps, } from './types';
17
+ export { useListState } from './useListState';
18
+ export { getLocalizedValue, toText } from './values';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EACH,cAAc,EACd,YAAY,EACZ,WAAW,EACX,eAAe,EACf,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,eAAe,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,UAAU,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,cAAc,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,YAAY,EACR,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,QAAQ,EACR,eAAe,EACf,eAAe,GAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,66 +1,18 @@
1
- import { c } from 'react/compiler-runtime';
2
- import { ComponentsProvider, LISTS_NAMESPACE } from '@panneau/core/contexts';
3
- import listTable from '@panneau/list-table';
4
- import listCards from '@panneau/list-cards';
5
- import listCalendar from '@panneau/list-calendar';
6
- import { jsx } from 'react/jsx-runtime';
7
-
8
- var components = /*#__PURE__*/Object.freeze({
9
- __proto__: null,
10
- Calendar: listCalendar,
11
- Cards: listCards,
12
- Table: listTable
13
- });
14
-
15
- function ListsProvider(t0) {
16
- const $ = c(10);
17
- let props;
18
- let t1;
19
- let t2;
20
- if ($[0] !== t0) {
21
- ({
22
- components: t1,
23
- children: t2,
24
- ...props
25
- } = t0);
26
- $[0] = t0;
27
- $[1] = props;
28
- $[2] = t1;
29
- $[3] = t2;
30
- } else {
31
- props = $[1];
32
- t1 = $[2];
33
- t2 = $[3];
34
- }
35
- const injectedComponents = t1 === undefined ? null : t1;
36
- const children = t2 === undefined ? null : t2;
37
- let t3;
38
- if ($[4] !== injectedComponents) {
39
- t3 = {
40
- ...components,
41
- ...injectedComponents
42
- };
43
- $[4] = injectedComponents;
44
- $[5] = t3;
45
- } else {
46
- t3 = $[5];
47
- }
48
- let t4;
49
- if ($[6] !== children || $[7] !== props || $[8] !== t3) {
50
- t4 = /*#__PURE__*/jsx(ComponentsProvider, {
51
- namespace: LISTS_NAMESPACE,
52
- components: t3,
53
- ...props,
54
- children: children
55
- });
56
- $[6] = children;
57
- $[7] = props;
58
- $[8] = t3;
59
- $[9] = t4;
60
- } else {
61
- t4 = $[9];
62
- }
63
- return t4;
64
- }
65
-
66
- export { ListsProvider as default };
1
+ import { getActionHref, groupListActions, isAllowedOn } from "./actions/actions.js";
2
+ import { ConfirmDialog } from "./actions/ConfirmDialog.js";
3
+ import { getActionIcon } from "./actions/icons.js";
4
+ import { getLocalizedValue, toText } from "./values.js";
5
+ import { BooleanDisplay, ColorDisplay, DateDisplay, DateTimeDisplay, EmailDisplay, EmptyValue, MediaDisplay, NumberDisplay, RelationDisplay, RichTextDisplay, SelectDisplay, TextDisplay, TimeDisplay, UrlDisplay, builtInDisplays } from "./displays/displays.js";
6
+ import { DateFilter, DateRangeFilter, RelationFilter, SelectFilter, TextFilter, ToggleFilter, builtInFilters } from "./filters/controls.js";
7
+ import { CardsLayout } from "./layouts/CardsLayout.js";
8
+ import { TableLayout } from "./layouts/TableLayout.js";
9
+ import { builtInLayouts } from "./layouts/builtIn.js";
10
+ import { countSelected, getPageSelection, isItemSelected } from "./selection.js";
11
+ import { Pagination } from "./toolbar/Pagination.js";
12
+ import { SearchField } from "./toolbar/SearchField.js";
13
+ import { useListState } from "./useListState.js";
14
+ import { ListView } from "./ListView.js";
15
+ import { applyListQuery } from "./query.js";
16
+ import { List } from "./List.js";
17
+ import { listsPlugin } from "./plugin.js";
18
+ export { BooleanDisplay, CardsLayout, ColorDisplay, ConfirmDialog, DateDisplay, DateFilter, DateRangeFilter, DateTimeDisplay, EmailDisplay, EmptyValue, List, ListView, MediaDisplay, NumberDisplay, Pagination, RelationDisplay, RelationFilter, RichTextDisplay, SearchField, SelectDisplay, SelectFilter, TableLayout, TextDisplay, TextFilter, TimeDisplay, ToggleFilter, UrlDisplay, applyListQuery, builtInDisplays, builtInFilters, builtInLayouts, countSelected, getActionHref, getActionIcon, getLocalizedValue, getPageSelection, groupListActions, isAllowedOn, isItemSelected, listsPlugin, toText, useListState };