@thebes/cadmea 1.1.0 → 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.
@@ -1,41 +1,81 @@
1
1
  import { className, createComponent, delegateEvents, effect, insert, memo, setAttribute, template } from "solid-js/web";
2
2
  import { createMutation, createQuery, useQueryClient } from "@tanstack/solid-query";
3
- import { For, Show, Suspense, createEffect, createSignal, lazy } from "solid-js";
3
+ import { For, Index, Show, Suspense, createEffect, createSignal, lazy } from "solid-js";
4
+ import { createForm } from "@tanstack/solid-form";
5
+ import { validateDocument } from "@thebes/cadmus/cms";
4
6
  import { Link, useBlocker } from "@tanstack/solid-router";
7
+ import { createSolidTable, flexRender, getCoreRowModel } from "@tanstack/solid-table";
5
8
  //#region src/CollectionEdit.tsx
6
- var _tmpl$$4 = /*#__PURE__*/ template(`<p class="text-sm text-error"role=alert>`), _tmpl$2$3 = /*#__PURE__*/ template(`<span class="loading loading-spinner loading-sm">`), _tmpl$3$1 = /*#__PURE__*/ template(`<button type=button class="btn flex-1">`), _tmpl$4$1 = /*#__PURE__*/ template(`<button type=button class="btn btn-primary flex-1">`), _tmpl$5$1 = /*#__PURE__*/ template(`<button type=button class="btn btn-outline flex-1">`), _tmpl$6$1 = /*#__PURE__*/ template(`<form class="flex flex-col gap-4"><div class="bg-base-100 sticky bottom-0 flex gap-2 border-t py-3">`), _tmpl$7$1 = /*#__PURE__*/ template(`<span class=text-error> *`), _tmpl$8$1 = /*#__PURE__*/ template(`<div class=form-control><label class=label>`), _tmpl$9$1 = /*#__PURE__*/ template(`<button type=submit class="btn btn-primary flex-1">`), _tmpl$0$1 = /*#__PURE__*/ template(`<input class=input type=text>`), _tmpl$1$1 = /*#__PURE__*/ template(`<select class=select>`), _tmpl$10$1 = /*#__PURE__*/ template(`<option>`), _tmpl$11$1 = /*#__PURE__*/ template(`<input class=input type=number>`), _tmpl$12$1 = /*#__PURE__*/ template(`<input class=input type=text readonly>`), _tmpl$13$1 = /*#__PURE__*/ template(`<input class=checkbox type=checkbox>`), _tmpl$14 = /*#__PURE__*/ template(`<p class="text-sm opacity-70 break-all">`), _tmpl$15 = /*#__PURE__*/ template(`<p class="text-sm text-error">`), _tmpl$16 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2"><input class=file-input type=file>`), _tmpl$17 = /*#__PURE__*/ template(`<select class=select><option value>—`), _tmpl$18 = /*#__PURE__*/ template(`<div class="flex flex-col gap-3"><button type=button class="btn btn-outline btn-sm self-start">Add `), _tmpl$19 = /*#__PURE__*/ template(`<div class="card bg-base-200 flex flex-col gap-2 p-3"><button type=button class="btn btn-error btn-outline btn-sm self-start">Remove`);
9
+ var _tmpl$$4 = /*#__PURE__*/ template(`<p class="text-sm text-error"role=alert>`), _tmpl$2$3 = /*#__PURE__*/ template(`<span class="loading loading-spinner loading-sm">`), _tmpl$3$1 = /*#__PURE__*/ template(`<button type=button class="btn flex-1">`), _tmpl$4$1 = /*#__PURE__*/ template(`<button type=button class="btn btn-primary flex-1">`), _tmpl$5$1 = /*#__PURE__*/ template(`<button type=button class="btn btn-outline flex-1">`), _tmpl$6$1 = /*#__PURE__*/ template(`<form class="flex flex-col gap-4"><div class="bg-base-100 sticky bottom-0 flex gap-2 border-t py-3">`), _tmpl$7$1 = /*#__PURE__*/ template(`<fieldset class="border-base-300 rounded-box border p-4"><legend class="px-2 text-sm font-semibold">`), _tmpl$8$1 = /*#__PURE__*/ template(`<div class="grid grid-cols-1 gap-4 md:grid-cols-2">`), _tmpl$9$1 = /*#__PURE__*/ template(`<span class=text-error> *`), _tmpl$0$1 = /*#__PURE__*/ template(`<p class="text-base-content/60 mb-1 text-xs">`), _tmpl$1$1 = /*#__PURE__*/ template(`<p class="text-error mt-1 text-sm"role=alert>`), _tmpl$10$1 = /*#__PURE__*/ template(`<div><label class=label>`), _tmpl$11$1 = /*#__PURE__*/ template(`<input class=input type=text>`), _tmpl$12$1 = /*#__PURE__*/ template(`<select class=select>`), _tmpl$13$1 = /*#__PURE__*/ template(`<option>`), _tmpl$14 = /*#__PURE__*/ template(`<input class=input type=number>`), _tmpl$15 = /*#__PURE__*/ template(`<input class=input type=text readonly>`), _tmpl$16 = /*#__PURE__*/ template(`<input class=checkbox type=checkbox>`), _tmpl$17 = /*#__PURE__*/ template(`<p class="text-sm opacity-70 break-all">`), _tmpl$18 = /*#__PURE__*/ template(`<p class="text-sm text-error">`), _tmpl$19 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2"><input class=file-input type=file>`), _tmpl$20 = /*#__PURE__*/ template(`<div class="mb-1 flex flex-wrap gap-1">`), _tmpl$21 = /*#__PURE__*/ template(`<button type=button aria-label=Clear class="absolute top-2 right-2 cursor-pointer opacity-60">×`), _tmpl$22 = /*#__PURE__*/ template(`<div role=listbox class="bg-base-100 border-base-300 rounded-box absolute z-10 mt-1 flex max-h-56 w-full flex-col overflow-auto border p-1 shadow">`), _tmpl$23 = /*#__PURE__*/ template(`<div class=relative><input type=text role=combobox autocomplete=off class=input>`), _tmpl$24 = /*#__PURE__*/ template(`<span class="badge badge-primary gap-1"><button type=button class=cursor-pointer>×`), _tmpl$25 = /*#__PURE__*/ template(`<button type=button role=option class="rounded px-3 py-2 text-left">`), _tmpl$26 = /*#__PURE__*/ template(`<div role=menu class="bg-base-100 border-base-300 rounded-box absolute z-10 mt-1 flex flex-col border p-1 shadow">`), _tmpl$27 = /*#__PURE__*/ template(`<div class="relative self-start"><button type=button class="btn btn-outline btn-sm"aria-haspopup=menu>Add block`), _tmpl$28 = /*#__PURE__*/ template(`<div class="form-control md:col-span-2"><div class="label font-medium"></div><div class="flex flex-col gap-3">`), _tmpl$29 = /*#__PURE__*/ template(`<span class="text-base-content/60 truncate text-sm">`), _tmpl$30 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2">`), _tmpl$31 = /*#__PURE__*/ template(`<div class="card bg-base-200 flex flex-col gap-2 p-3"><div class="flex items-center gap-2"><button type=button class="btn btn-ghost btn-sm gap-2"><span aria-hidden=true></span><span class=font-semibold></span></button><div class="ml-auto flex gap-1"><button type=button class="btn btn-ghost btn-xs"aria-label="Move up">↑</button><button type=button class="btn btn-ghost btn-xs"aria-label="Move down">↓</button><button type=button class="btn btn-ghost btn-xs"aria-label=Duplicate>⧉</button><button type=button class="btn btn-ghost btn-xs text-error"aria-label=Remove>Remove`), _tmpl$32 = /*#__PURE__*/ template(`<button type=button class="btn btn-outline btn-sm self-start">Add `), _tmpl$33 = /*#__PURE__*/ template(`<i aria-hidden=true>`), _tmpl$34 = /*#__PURE__*/ template(`<button type=button role=menuitem class="flex items-center gap-2 rounded px-3 py-2 text-left">`);
7
10
  const RichTextEditor = lazy(() => import("../RichTextEditor-BPilh7Pw.js").then((mod) => ({ default: mod.RichTextEditor })));
8
11
  function editableFields(config) {
9
12
  return Object.entries(config.fields).filter(([key]) => key !== "id");
10
13
  }
11
- function CollectionEdit(props) {
12
- const initialSnapshot = JSON.stringify(props.initialValues ?? {});
13
- const [values, setValues] = createSignal(props.initialValues ?? {});
14
- createEffect(() => {
15
- props.onDirtyChange?.(JSON.stringify(values()) !== initialSnapshot);
16
- });
17
- function setField(key, value) {
18
- setValues((prev) => ({
19
- ...prev,
20
- [key]: value
21
- }));
14
+ function humanize(key) {
15
+ const spaced = key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
16
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();
17
+ }
18
+ function labelFor(key, field) {
19
+ return field.admin?.label ?? humanize(key);
20
+ }
21
+ function groupFields(entries) {
22
+ const groups = [];
23
+ const byName = /* @__PURE__ */ new Map();
24
+ for (const entry of entries) {
25
+ const name = entry[1].admin?.group;
26
+ let group = byName.get(name);
27
+ if (!group) {
28
+ group = {
29
+ name,
30
+ fields: []
31
+ };
32
+ byName.set(name, group);
33
+ groups.push(group);
34
+ }
35
+ group.fields.push(entry);
22
36
  }
23
- function editablePayload() {
24
- return Object.fromEntries(Object.entries(values()).filter(([key]) => props.config.fields[key]?.type !== "date"));
37
+ return groups;
38
+ }
39
+ function CollectionEdit(props) {
40
+ const operation = props.initialValues?.id != null ? "update" : "create";
41
+ async function validateForm(value) {
42
+ const violations = await validateDocument(props.config, value, { operation });
43
+ const fields = {};
44
+ for (const v of violations) if (v.severity === "error" && !(v.path in fields)) fields[v.path] = v.message;
45
+ return Object.keys(fields).length > 0 ? { fields } : void 0;
25
46
  }
26
- function handleSubmit(event) {
27
- event.preventDefault();
28
- props.onSubmit(editablePayload());
47
+ const form = createForm(() => ({
48
+ defaultValues: props.initialValues ?? {},
49
+ validators: { onSubmitAsync: ({ value }) => validateForm(value) },
50
+ onSubmit: async ({ value }) => {
51
+ await props.onSubmit(editablePayload(value));
52
+ }
53
+ }));
54
+ const isDefaultValue = form.useStore((s) => s.isDefaultValue);
55
+ createEffect(() => props.onDirtyChange?.(!isDefaultValue()));
56
+ const formValues = form.useStore((s) => s.values);
57
+ function editablePayload(value) {
58
+ return Object.fromEntries(Object.entries(value).filter(([key]) => props.config.fields[key]?.type !== "date"));
29
59
  }
30
60
  const ctx = {
31
- onUploadFile: props.onUploadFile,
32
- relationshipOptions: props.relationshipOptions,
33
- fieldWidgets: props.fieldWidgets
61
+ get onUploadFile() {
62
+ return props.onUploadFile;
63
+ },
64
+ get relationshipOptions() {
65
+ return props.relationshipOptions;
66
+ },
67
+ get fieldWidgets() {
68
+ return props.fieldWidgets;
69
+ }
34
70
  };
71
+ const fieldGroups = groupFields(editableFields(props.config));
35
72
  const versioned = () => props.config.versions?.drafts && props.draftActions;
36
73
  return (() => {
37
74
  var _el$ = _tmpl$6$1(), _el$3 = _el$.firstChild;
38
- _el$.addEventListener("submit", handleSubmit);
75
+ _el$.addEventListener("submit", (event) => {
76
+ event.preventDefault();
77
+ form.handleSubmit();
78
+ });
39
79
  insert(_el$, createComponent(Show, {
40
80
  get when() {
41
81
  return props.error;
@@ -47,24 +87,35 @@ function CollectionEdit(props) {
47
87
  }
48
88
  }), _el$3);
49
89
  insert(_el$, createComponent(For, {
50
- get each() {
51
- return editableFields(props.config);
52
- },
53
- children: ([key, field]) => (() => {
54
- var _el$0 = _tmpl$8$1(), _el$1 = _el$0.firstChild;
55
- setAttribute(_el$1, "for", key);
56
- insert(_el$1, key, null);
57
- insert(_el$1, createComponent(Show, {
58
- get when() {
59
- return field.required;
60
- },
61
- get children() {
62
- return _tmpl$7$1();
63
- }
64
- }), null);
65
- insert(_el$0, () => renderInput(key, field, values()[key], setField, ctx), null);
66
- return _el$0;
67
- })()
90
+ each: fieldGroups,
91
+ children: (group) => createComponent(Show, {
92
+ get when() {
93
+ return group.name;
94
+ },
95
+ get fallback() {
96
+ return createComponent(FieldsGrid, {
97
+ form,
98
+ ctx,
99
+ get fields() {
100
+ return group.fields;
101
+ },
102
+ values: formValues
103
+ });
104
+ },
105
+ get children() {
106
+ var _el$0 = _tmpl$7$1(), _el$1 = _el$0.firstChild;
107
+ insert(_el$1, () => group.name);
108
+ insert(_el$0, createComponent(FieldsGrid, {
109
+ form,
110
+ ctx,
111
+ get fields() {
112
+ return group.fields;
113
+ },
114
+ values: formValues
115
+ }), null);
116
+ return _el$0;
117
+ }
118
+ })
68
119
  }), _el$3);
69
120
  insert(_el$3, createComponent(Show, {
70
121
  get when() {
@@ -76,8 +127,9 @@ function CollectionEdit(props) {
76
127
  return props.capabilities?.canUpdate !== false;
77
128
  },
78
129
  get children() {
79
- var _el$11 = _tmpl$9$1();
80
- insert(_el$11, createComponent(Show, {
130
+ var _el$10 = _tmpl$4$1();
131
+ _el$10.$$click = () => void form.handleSubmit();
132
+ insert(_el$10, createComponent(Show, {
81
133
  get when() {
82
134
  return props.saving;
83
135
  },
@@ -88,8 +140,8 @@ function CollectionEdit(props) {
88
140
  return _tmpl$2$3();
89
141
  }
90
142
  }));
91
- effect(() => _el$11.disabled = props.saving);
92
- return _el$11;
143
+ effect(() => _el$10.disabled = props.saving);
144
+ return _el$10;
93
145
  }
94
146
  });
95
147
  },
@@ -97,7 +149,7 @@ function CollectionEdit(props) {
97
149
  return [
98
150
  (() => {
99
151
  var _el$4 = _tmpl$3$1();
100
- _el$4.$$click = () => void props.draftActions?.onSaveDraft(editablePayload());
152
+ _el$4.$$click = () => void props.draftActions?.onSaveDraft(editablePayload(formValues()));
101
153
  insert(_el$4, createComponent(Show, {
102
154
  get when() {
103
155
  return props.draftActions?.saving;
@@ -157,98 +209,201 @@ function CollectionEdit(props) {
157
209
  return _el$;
158
210
  })();
159
211
  }
160
- function renderInput(key, field, value, setField, ctx) {
161
- const Widget = ctx.fieldWidgets?.[key];
212
+ function FieldsGrid(props) {
213
+ return (() => {
214
+ var _el$12 = _tmpl$8$1();
215
+ insert(_el$12, createComponent(For, {
216
+ get each() {
217
+ return props.fields;
218
+ },
219
+ children: ([key, field]) => createComponent(Show, {
220
+ get when() {
221
+ return !field.admin?.condition || field.admin.condition(props.values());
222
+ },
223
+ get children() {
224
+ return renderField(props.form, props.ctx, key, field, labelFor(key, field));
225
+ }
226
+ })
227
+ }));
228
+ return _el$12;
229
+ })();
230
+ }
231
+ function renderField(form, ctx, name, field, label) {
232
+ if (field.type === "array") return renderArray(form, ctx, name, field, label);
233
+ const spanClass = field.admin?.width === "half" ? "md:col-span-1" : "md:col-span-2";
234
+ return createComponent(form.Field, {
235
+ name,
236
+ children: (fieldApi) => (() => {
237
+ var _el$13 = _tmpl$10$1(), _el$14 = _el$13.firstChild;
238
+ className(_el$13, `form-control ${spanClass}`);
239
+ setAttribute(_el$14, "for", name);
240
+ insert(_el$14, label, null);
241
+ insert(_el$14, createComponent(Show, {
242
+ get when() {
243
+ return field.required;
244
+ },
245
+ get children() {
246
+ return _tmpl$9$1();
247
+ }
248
+ }), null);
249
+ insert(_el$13, createComponent(Show, {
250
+ get when() {
251
+ return field.admin?.description;
252
+ },
253
+ get children() {
254
+ var _el$16 = _tmpl$0$1();
255
+ insert(_el$16, () => field.admin?.description);
256
+ return _el$16;
257
+ }
258
+ }), null);
259
+ insert(_el$13, () => renderControl(ctx, name, field, fieldApi), null);
260
+ insert(_el$13, createComponent(Show, {
261
+ get when() {
262
+ return (fieldApi().state.meta.errors?.length ?? 0) > 0;
263
+ },
264
+ get children() {
265
+ var _el$17 = _tmpl$1$1();
266
+ insert(_el$17, () => fieldApi().state.meta.errors.filter(Boolean).join(", "));
267
+ return _el$17;
268
+ }
269
+ }), null);
270
+ return _el$13;
271
+ })()
272
+ });
273
+ }
274
+ function renderControl(ctx, name, field, fieldApi) {
275
+ const Widget = ctx.fieldWidgets?.[name] ?? ctx.fieldWidgets?.[name.slice(name.lastIndexOf(".") + 1)];
162
276
  if (Widget) return createComponent(Widget, {
163
- fieldKey: key,
164
- value,
165
- setValue: (v) => setField(key, v),
277
+ fieldKey: name,
278
+ get value() {
279
+ return fieldApi().state.value;
280
+ },
281
+ setValue: (v) => fieldApi().handleChange(v),
166
282
  get onUploadFile() {
167
283
  return ctx.onUploadFile;
168
284
  }
169
285
  });
286
+ const readOnly = field.admin?.readOnly;
287
+ const change = (v) => fieldApi().handleChange(v);
170
288
  switch (field.type) {
171
289
  case "text": return (() => {
172
- var _el$13 = _tmpl$0$1();
173
- _el$13.$$input = (e) => setField(key, e.currentTarget.value);
174
- setAttribute(_el$13, "id", key);
175
- _el$13.value = value ?? "";
176
- effect(() => _el$13.required = field.required);
177
- return _el$13;
290
+ var _el$18 = _tmpl$11$1();
291
+ _el$18.addEventListener("blur", () => fieldApi().handleBlur());
292
+ _el$18.$$input = (e) => change(e.currentTarget.value);
293
+ setAttribute(_el$18, "id", name);
294
+ _el$18.readOnly = readOnly;
295
+ effect((_p$) => {
296
+ var _v$ = field.admin?.placeholder, _v$2 = field.required;
297
+ _v$ !== _p$.e && setAttribute(_el$18, "placeholder", _p$.e = _v$);
298
+ _v$2 !== _p$.t && (_el$18.required = _p$.t = _v$2);
299
+ return _p$;
300
+ }, {
301
+ e: void 0,
302
+ t: void 0
303
+ });
304
+ effect(() => _el$18.value = fieldApi().state.value ?? "");
305
+ return _el$18;
178
306
  })();
179
307
  case "select": return (() => {
180
- var _el$14 = _tmpl$1$1();
181
- _el$14.addEventListener("change", (e) => setField(key, e.currentTarget.value));
182
- setAttribute(_el$14, "id", key);
183
- _el$14.value = value ?? "";
184
- insert(_el$14, createComponent(For, {
308
+ var _el$19 = _tmpl$12$1();
309
+ _el$19.addEventListener("blur", () => fieldApi().handleBlur());
310
+ _el$19.addEventListener("change", (e) => change(e.currentTarget.value));
311
+ setAttribute(_el$19, "id", name);
312
+ _el$19.disabled = readOnly;
313
+ insert(_el$19, createComponent(For, {
185
314
  get each() {
186
315
  return field.options;
187
316
  },
188
317
  children: (option) => (() => {
189
- var _el$15 = _tmpl$10$1();
190
- _el$15.value = option;
191
- insert(_el$15, option);
192
- return _el$15;
318
+ var _el$20 = _tmpl$13$1();
319
+ _el$20.value = option;
320
+ insert(_el$20, option);
321
+ return _el$20;
193
322
  })()
194
323
  }));
195
- effect(() => _el$14.required = field.required);
196
- return _el$14;
324
+ effect(() => _el$19.required = field.required);
325
+ effect(() => _el$19.value = fieldApi().state.value ?? "");
326
+ return _el$19;
197
327
  })();
198
328
  case "number": return (() => {
199
- var _el$16 = _tmpl$11$1();
200
- _el$16.$$input = (e) => setField(key, e.currentTarget.valueAsNumber);
201
- setAttribute(_el$16, "id", key);
202
- _el$16.value = value ?? "";
203
- effect(() => _el$16.required = field.required);
204
- return _el$16;
329
+ var _el$21 = _tmpl$14();
330
+ _el$21.addEventListener("blur", () => fieldApi().handleBlur());
331
+ _el$21.$$input = (e) => change(e.currentTarget.valueAsNumber);
332
+ setAttribute(_el$21, "id", name);
333
+ _el$21.readOnly = readOnly;
334
+ effect((_p$) => {
335
+ var _v$3 = field.admin?.placeholder, _v$4 = field.required;
336
+ _v$3 !== _p$.e && setAttribute(_el$21, "placeholder", _p$.e = _v$3);
337
+ _v$4 !== _p$.t && (_el$21.required = _p$.t = _v$4);
338
+ return _p$;
339
+ }, {
340
+ e: void 0,
341
+ t: void 0
342
+ });
343
+ effect(() => _el$21.value = fieldApi().state.value ?? "");
344
+ return _el$21;
205
345
  })();
206
346
  case "date": return (() => {
207
- var _el$17 = _tmpl$12$1();
208
- setAttribute(_el$17, "id", key);
209
- effect(() => _el$17.value = formatDateValue(value));
210
- return _el$17;
347
+ var _el$22 = _tmpl$15();
348
+ setAttribute(_el$22, "id", name);
349
+ effect(() => _el$22.value = formatDateValue(fieldApi().state.value));
350
+ return _el$22;
211
351
  })();
212
352
  case "checkbox": return (() => {
213
- var _el$18 = _tmpl$13$1();
214
- _el$18.addEventListener("change", (e) => setField(key, e.currentTarget.checked));
215
- setAttribute(_el$18, "id", key);
216
- _el$18.checked = value ?? false;
217
- return _el$18;
353
+ var _el$23 = _tmpl$16();
354
+ _el$23.addEventListener("change", (e) => change(e.currentTarget.checked));
355
+ setAttribute(_el$23, "id", name);
356
+ _el$23.disabled = readOnly;
357
+ effect(() => _el$23.checked = fieldApi().state.value ?? false);
358
+ return _el$23;
218
359
  })();
219
- case "upload": return renderUploadInput(key, field, value, setField, ctx);
220
- case "relationship": return renderRelationshipInput(key, field, value, setField, ctx);
221
- case "array": return renderArrayInput(key, field, value, setField, ctx);
360
+ case "upload": return createComponent(UploadControl, {
361
+ name,
362
+ field,
363
+ fieldApi,
364
+ ctx
365
+ });
366
+ case "relationship": return createComponent(RelationshipField, {
367
+ name,
368
+ field,
369
+ fieldApi,
370
+ get options() {
371
+ return ctx.relationshipOptions?.[field.relationTo] ?? [];
372
+ }
373
+ });
222
374
  case "richText": return createComponent(Suspense, {
223
375
  get fallback() {
224
376
  return _tmpl$2$3();
225
377
  },
226
378
  get children() {
227
379
  return createComponent(RichTextEditor, {
228
- id: key,
229
- content: value,
230
- onChange: (doc) => setField(key, doc)
380
+ id: name,
381
+ get content() {
382
+ return fieldApi().state.value;
383
+ },
384
+ onChange: (doc) => change(doc)
231
385
  });
232
386
  }
233
387
  });
234
388
  default: return null;
235
389
  }
236
390
  }
237
- function renderUploadInput(key, field, value, setField, ctx) {
391
+ function UploadControl(props) {
238
392
  const [uploading, setUploading] = createSignal(false);
239
393
  const [uploadError, setUploadError] = createSignal();
394
+ const value = () => props.fieldApi().state.value;
240
395
  async function handleFileChange(e) {
241
396
  const file = e.currentTarget.files?.[0];
242
397
  if (!file) return;
243
- if (!ctx.onUploadFile) {
398
+ if (!props.ctx.onUploadFile) {
244
399
  setUploadError("No upload handler configured for this form.");
245
400
  return;
246
401
  }
247
402
  setUploading(true);
248
403
  setUploadError(void 0);
249
404
  try {
250
- const { url } = await ctx.onUploadFile(file);
251
- setField(key, url);
405
+ const { url } = await props.ctx.onUploadFile(file);
406
+ props.fieldApi().handleChange(url);
252
407
  } catch (err) {
253
408
  setUploadError(err instanceof Error ? err.message : "Upload failed");
254
409
  } finally {
@@ -256,18 +411,19 @@ function renderUploadInput(key, field, value, setField, ctx) {
256
411
  }
257
412
  }
258
413
  return (() => {
259
- var _el$20 = _tmpl$16(), _el$22 = _el$20.firstChild;
260
- insert(_el$20, createComponent(Show, {
261
- when: value,
414
+ var _el$25 = _tmpl$19(), _el$27 = _el$25.firstChild;
415
+ insert(_el$25, createComponent(Show, {
416
+ get when() {
417
+ return value();
418
+ },
262
419
  get children() {
263
- var _el$21 = _tmpl$14();
264
- insert(_el$21, value);
265
- return _el$21;
420
+ var _el$26 = _tmpl$17();
421
+ insert(_el$26, value);
422
+ return _el$26;
266
423
  }
267
- }), _el$22);
268
- _el$22.addEventListener("change", handleFileChange);
269
- setAttribute(_el$22, "id", key);
270
- insert(_el$20, createComponent(Show, {
424
+ }), _el$27);
425
+ _el$27.addEventListener("change", handleFileChange);
426
+ insert(_el$25, createComponent(Show, {
271
427
  get when() {
272
428
  return uploading();
273
429
  },
@@ -275,121 +431,376 @@ function renderUploadInput(key, field, value, setField, ctx) {
275
431
  return _tmpl$2$3();
276
432
  }
277
433
  }), null);
278
- insert(_el$20, createComponent(Show, {
434
+ insert(_el$25, createComponent(Show, {
279
435
  get when() {
280
436
  return uploadError();
281
437
  },
282
438
  get children() {
283
- var _el$24 = _tmpl$15();
284
- insert(_el$24, uploadError);
285
- return _el$24;
439
+ var _el$29 = _tmpl$18();
440
+ insert(_el$29, uploadError);
441
+ return _el$29;
286
442
  }
287
443
  }), null);
288
444
  effect((_p$) => {
289
- var _v$ = field.required && !value, _v$2 = uploading();
290
- _v$ !== _p$.e && (_el$22.required = _p$.e = _v$);
291
- _v$2 !== _p$.t && (_el$22.disabled = _p$.t = _v$2);
445
+ var _v$5 = props.name, _v$6 = props.field.required && !value(), _v$7 = uploading() || props.field.admin?.readOnly;
446
+ _v$5 !== _p$.e && setAttribute(_el$27, "id", _p$.e = _v$5);
447
+ _v$6 !== _p$.t && (_el$27.required = _p$.t = _v$6);
448
+ _v$7 !== _p$.a && (_el$27.disabled = _p$.a = _v$7);
292
449
  return _p$;
293
450
  }, {
294
451
  e: void 0,
295
- t: void 0
452
+ t: void 0,
453
+ a: void 0
296
454
  });
297
- return _el$20;
455
+ return _el$25;
298
456
  })();
299
457
  }
300
- function renderRelationshipInput(key, field, value, setField, ctx) {
301
- if (field.hasMany) return null;
302
- const options = ctx.relationshipOptions?.[field.relationTo] ?? [];
458
+ function RelationshipField(props) {
459
+ const [query, setQuery] = createSignal("");
460
+ const [open, setOpen] = createSignal(false);
461
+ const [active, setActive] = createSignal(0);
462
+ const listId = `${props.name}-listbox`;
463
+ const isMulti = () => props.field.hasMany === true;
464
+ const value = () => props.fieldApi().state.value;
465
+ const selectedIds = () => {
466
+ const v = value();
467
+ if (isMulti()) return Array.isArray(v) ? v : [];
468
+ return v != null ? [v] : [];
469
+ };
470
+ const selectedOptions = () => props.options.filter((o) => selectedIds().includes(o.id));
471
+ const filtered = () => {
472
+ const q = query().toLowerCase();
473
+ return props.options.filter((o) => o.label.toLowerCase().includes(q) && (!isMulti() || !selectedIds().includes(o.id)));
474
+ };
475
+ const singleLabel = () => selectedOptions()[0]?.label ?? "";
476
+ function choose(option) {
477
+ if (isMulti()) {
478
+ props.fieldApi().handleChange([...selectedIds(), option.id]);
479
+ setQuery("");
480
+ } else {
481
+ props.fieldApi().handleChange(option.id);
482
+ setQuery("");
483
+ setOpen(false);
484
+ }
485
+ setActive(0);
486
+ }
487
+ function removeId(id) {
488
+ if (isMulti()) props.fieldApi().handleChange(selectedIds().filter((x) => x !== id));
489
+ else props.fieldApi().handleChange(null);
490
+ }
491
+ function onKeyDown(e) {
492
+ if (e.key === "ArrowDown") {
493
+ e.preventDefault();
494
+ setOpen(true);
495
+ setActive((a) => Math.min(a + 1, filtered().length - 1));
496
+ } else if (e.key === "ArrowUp") {
497
+ e.preventDefault();
498
+ setActive((a) => Math.max(a - 1, 0));
499
+ } else if (e.key === "Enter") {
500
+ e.preventDefault();
501
+ const option = filtered()[active()];
502
+ if (option) choose(option);
503
+ } else if (e.key === "Escape") setOpen(false);
504
+ else if (e.key === "Backspace" && isMulti() && query() === "") {
505
+ const ids = selectedIds();
506
+ if (ids.length > 0) removeId(ids[ids.length - 1]);
507
+ }
508
+ }
303
509
  return (() => {
304
- var _el$25 = _tmpl$17();
305
- _el$25.firstChild;
306
- _el$25.addEventListener("change", (e) => setField(key, e.currentTarget.value === "" ? null : Number(e.currentTarget.value)));
307
- setAttribute(_el$25, "id", key);
308
- insert(_el$25, createComponent(For, {
309
- each: options,
310
- children: (option) => (() => {
311
- var _el$27 = _tmpl$10$1();
312
- insert(_el$27, () => option.label);
313
- effect(() => _el$27.value = option.id);
314
- return _el$27;
315
- })()
510
+ var _el$30 = _tmpl$23(), _el$32 = _el$30.firstChild;
511
+ insert(_el$30, createComponent(Show, {
512
+ get when() {
513
+ return memo(() => !!isMulti())() && selectedOptions().length > 0;
514
+ },
515
+ get children() {
516
+ var _el$31 = _tmpl$20();
517
+ insert(_el$31, createComponent(For, {
518
+ get each() {
519
+ return selectedOptions();
520
+ },
521
+ children: (option) => (() => {
522
+ var _el$35 = _tmpl$24(), _el$36 = _el$35.firstChild;
523
+ insert(_el$35, () => option.label, _el$36);
524
+ _el$36.$$click = () => removeId(option.id);
525
+ effect(() => setAttribute(_el$36, "aria-label", `Remove ${option.label}`));
526
+ return _el$35;
527
+ })()
528
+ }));
529
+ return _el$31;
530
+ }
531
+ }), _el$32);
532
+ _el$32.$$keydown = onKeyDown;
533
+ _el$32.addEventListener("blur", () => setTimeout(() => setOpen(false), 120));
534
+ _el$32.addEventListener("focus", () => setOpen(true));
535
+ _el$32.$$input = (e) => {
536
+ setQuery(e.currentTarget.value);
537
+ setOpen(true);
538
+ setActive(0);
539
+ };
540
+ setAttribute(_el$32, "aria-controls", listId);
541
+ insert(_el$30, createComponent(Show, {
542
+ get when() {
543
+ return memo(() => !!(!isMulti() && value() != null))() && !props.field.required;
544
+ },
545
+ get children() {
546
+ var _el$33 = _tmpl$21();
547
+ _el$33.$$click = () => removeId(value());
548
+ _el$33.$$mousedown = (e) => e.preventDefault();
549
+ return _el$33;
550
+ }
316
551
  }), null);
317
- effect(() => _el$25.required = field.required);
318
- effect(() => _el$25.value = value != null ? String(value) : "");
319
- return _el$25;
552
+ insert(_el$30, createComponent(Show, {
553
+ get when() {
554
+ return memo(() => !!open())() && filtered().length > 0;
555
+ },
556
+ get children() {
557
+ var _el$34 = _tmpl$22();
558
+ setAttribute(_el$34, "id", listId);
559
+ insert(_el$34, createComponent(For, {
560
+ get each() {
561
+ return filtered();
562
+ },
563
+ children: (option, i) => (() => {
564
+ var _el$37 = _tmpl$25();
565
+ _el$37.$$click = () => choose(option);
566
+ _el$37.$$mousedown = (e) => e.preventDefault();
567
+ insert(_el$37, () => option.label);
568
+ effect((_p$) => {
569
+ var _v$11 = selectedIds().includes(option.id), _v$12 = !!(i() === active());
570
+ _v$11 !== _p$.e && setAttribute(_el$37, "aria-selected", _p$.e = _v$11);
571
+ _v$12 !== _p$.t && _el$37.classList.toggle("bg-base-200", _p$.t = _v$12);
572
+ return _p$;
573
+ }, {
574
+ e: void 0,
575
+ t: void 0
576
+ });
577
+ return _el$37;
578
+ })()
579
+ }));
580
+ return _el$34;
581
+ }
582
+ }), null);
583
+ effect((_p$) => {
584
+ var _v$8 = props.name, _v$9 = open(), _v$0 = props.field.required && selectedIds().length === 0, _v$1 = props.field.admin?.readOnly, _v$10 = props.field.admin?.placeholder ?? "Search…";
585
+ _v$8 !== _p$.e && setAttribute(_el$32, "id", _p$.e = _v$8);
586
+ _v$9 !== _p$.t && setAttribute(_el$32, "aria-expanded", _p$.t = _v$9);
587
+ _v$0 !== _p$.a && (_el$32.required = _p$.a = _v$0);
588
+ _v$1 !== _p$.o && (_el$32.disabled = _p$.o = _v$1);
589
+ _v$10 !== _p$.i && setAttribute(_el$32, "placeholder", _p$.i = _v$10);
590
+ return _p$;
591
+ }, {
592
+ e: void 0,
593
+ t: void 0,
594
+ a: void 0,
595
+ o: void 0,
596
+ i: void 0
597
+ });
598
+ effect(() => _el$32.value = open() || isMulti() ? query() : singleLabel());
599
+ return _el$30;
320
600
  })();
321
601
  }
322
- function renderArrayInput(key, field, value, setField, ctx) {
323
- const items = () => Array.isArray(value) ? value : [];
324
- function updateItem(index, itemKey, itemValue) {
325
- const next = items().slice();
326
- next[index] = {
327
- ...next[index],
328
- [itemKey]: itemValue
329
- };
330
- setField(key, next);
602
+ function renderArray(form, ctx, name, field, label) {
603
+ return createComponent(form.Field, {
604
+ name,
605
+ mode: "array",
606
+ children: (fieldApi) => createComponent(BlockEditor, {
607
+ form,
608
+ ctx,
609
+ name,
610
+ field,
611
+ label,
612
+ fieldApi
613
+ })
614
+ });
615
+ }
616
+ function variantLabel(disc, variant) {
617
+ return disc.variantsAdmin?.[variant]?.label ?? humanize(variant);
618
+ }
619
+ function BlockEditor(props) {
620
+ const [collapsed, setCollapsed] = createSignal(/* @__PURE__ */ new Set());
621
+ const [menuOpen, setMenuOpen] = createSignal(false);
622
+ const disc = props.field.discriminator;
623
+ const variants = disc ? Object.keys(disc.variants) : [];
624
+ const items = () => Array.isArray(props.fieldApi().state.value) ? props.fieldApi().state.value : [];
625
+ function addBlock(variant) {
626
+ const seed = variant && disc ? { [disc.key]: variant } : {};
627
+ props.fieldApi().pushValue(seed);
628
+ setMenuOpen(false);
331
629
  }
332
- function addItem() {
333
- setField(key, [...items(), {}]);
630
+ function duplicate(index) {
631
+ props.fieldApi().insertValue(index + 1, { ...items()[index] });
334
632
  }
335
- function removeItem(index) {
336
- setField(key, items().filter((_, i) => i !== index));
633
+ function move(from, to) {
634
+ if (to < 0 || to >= items().length) return;
635
+ props.fieldApi().moveValue(from, to);
337
636
  }
338
- function fieldsForItem(item) {
339
- const base = Object.entries(field.fields);
340
- const discriminator = field.discriminator;
341
- if (!discriminator) return base;
342
- const variantValue = item[discriminator.key];
343
- const variantFields = typeof variantValue === "string" ? discriminator.variants[variantValue] : void 0;
344
- return variantFields ? [...base, ...Object.entries(variantFields)] : base;
637
+ function toggleCollapse(index) {
638
+ setCollapsed((prev) => {
639
+ const next = new Set(prev);
640
+ if (next.has(index)) next.delete(index);
641
+ else next.add(index);
642
+ return next;
643
+ });
644
+ }
645
+ function blockTitle(item) {
646
+ if (disc) {
647
+ const v = item[disc.key];
648
+ if (typeof v === "string") return variantLabel(disc, v);
649
+ }
650
+ return props.label;
651
+ }
652
+ function blockSummary(item) {
653
+ for (const [key, f] of fieldsForItem(props.field, item)) {
654
+ if (key === disc?.key) continue;
655
+ if ((f.type === "text" || f.type === "select") && item[key]) return String(item[key]);
656
+ }
657
+ return "";
345
658
  }
346
659
  return (() => {
347
- var _el$28 = _tmpl$18(), _el$29 = _el$28.firstChild;
348
- _el$29.firstChild;
349
- insert(_el$28, createComponent(For, {
660
+ var _el$38 = _tmpl$28(), _el$39 = _el$38.firstChild, _el$42 = _el$39.nextSibling;
661
+ insert(_el$39, () => props.label, null);
662
+ insert(_el$39, createComponent(Show, {
663
+ get when() {
664
+ return props.field.required;
665
+ },
666
+ get children() {
667
+ return _tmpl$9$1();
668
+ }
669
+ }), null);
670
+ insert(_el$38, createComponent(Show, {
671
+ get when() {
672
+ return props.field.admin?.description;
673
+ },
674
+ get children() {
675
+ var _el$41 = _tmpl$0$1();
676
+ insert(_el$41, () => props.field.admin?.description);
677
+ return _el$41;
678
+ }
679
+ }), _el$42);
680
+ insert(_el$42, createComponent(Index, {
350
681
  get each() {
351
682
  return items();
352
683
  },
353
- children: (item, index) => (() => {
354
- var _el$31 = _tmpl$19(), _el$32 = _el$31.firstChild;
355
- insert(_el$31, createComponent(For, {
356
- get each() {
357
- return fieldsForItem(item);
358
- },
359
- children: ([itemKey, itemField]) => {
360
- const inputId = `${key}.${index()}.${itemKey}`;
361
- return (() => {
362
- var _el$33 = _tmpl$8$1(), _el$34 = _el$33.firstChild;
363
- setAttribute(_el$34, "for", inputId);
364
- insert(_el$34, itemKey, null);
365
- insert(_el$34, createComponent(Show, {
366
- get when() {
367
- return itemField.required;
684
+ children: (item, index) => {
685
+ const isCollapsed = () => collapsed().has(index);
686
+ return (() => {
687
+ var _el$46 = _tmpl$31(), _el$47 = _el$46.firstChild, _el$48 = _el$47.firstChild, _el$49 = _el$48.firstChild, _el$50 = _el$49.nextSibling, _el$52 = _el$48.nextSibling, _el$53 = _el$52.firstChild, _el$54 = _el$53.nextSibling, _el$55 = _el$54.nextSibling, _el$56 = _el$55.nextSibling;
688
+ _el$48.$$click = () => toggleCollapse(index);
689
+ insert(_el$49, () => isCollapsed() ? "▸" : "▾");
690
+ insert(_el$50, () => blockTitle(item()));
691
+ insert(_el$47, createComponent(Show, {
692
+ get when() {
693
+ return memo(() => !!isCollapsed())() && blockSummary(item());
694
+ },
695
+ get children() {
696
+ var _el$51 = _tmpl$29();
697
+ insert(_el$51, () => blockSummary(item()));
698
+ return _el$51;
699
+ }
700
+ }), _el$52);
701
+ _el$53.$$click = () => move(index, index - 1);
702
+ _el$53.disabled = index === 0;
703
+ _el$54.$$click = () => move(index, index + 1);
704
+ _el$55.$$click = () => duplicate(index);
705
+ _el$56.$$click = () => props.fieldApi().removeValue(index);
706
+ insert(_el$46, createComponent(Show, {
707
+ get when() {
708
+ return !isCollapsed();
709
+ },
710
+ get children() {
711
+ var _el$57 = _tmpl$30();
712
+ insert(_el$57, createComponent(For, {
713
+ get each() {
714
+ return fieldsForItem(props.field, item());
368
715
  },
369
- get children() {
370
- return _tmpl$7$1();
371
- }
372
- }), null);
373
- insert(_el$33, () => renderInput(inputId, itemField, item[itemKey], (_, v) => updateItem(index(), itemKey, v), ctx), null);
374
- return _el$33;
375
- })();
716
+ children: ([itemKey, itemField]) => renderField(props.form, props.ctx, `${props.name}[${index}].${itemKey}`, itemField, labelFor(itemKey, itemField))
717
+ }));
718
+ return _el$57;
719
+ }
720
+ }), null);
721
+ effect((_p$) => {
722
+ var _v$13 = !isCollapsed(), _v$14 = index === items().length - 1;
723
+ _v$13 !== _p$.e && setAttribute(_el$48, "aria-expanded", _p$.e = _v$13);
724
+ _v$14 !== _p$.t && (_el$54.disabled = _p$.t = _v$14);
725
+ return _p$;
726
+ }, {
727
+ e: void 0,
728
+ t: void 0
729
+ });
730
+ return _el$46;
731
+ })();
732
+ }
733
+ }), null);
734
+ insert(_el$42, createComponent(Show, {
735
+ get when() {
736
+ return disc && variants.length > 0;
737
+ },
738
+ get fallback() {
739
+ return (() => {
740
+ var _el$58 = _tmpl$32();
741
+ _el$58.firstChild;
742
+ _el$58.$$click = () => addBlock();
743
+ insert(_el$58, () => props.label, null);
744
+ return _el$58;
745
+ })();
746
+ },
747
+ get children() {
748
+ var _el$43 = _tmpl$27(), _el$44 = _el$43.firstChild;
749
+ _el$44.$$click = () => setMenuOpen((o) => !o);
750
+ insert(_el$43, createComponent(Show, {
751
+ get when() {
752
+ return menuOpen();
753
+ },
754
+ get children() {
755
+ var _el$45 = _tmpl$26();
756
+ insert(_el$45, createComponent(For, {
757
+ each: variants,
758
+ children: (variant) => (() => {
759
+ var _el$60 = _tmpl$34();
760
+ _el$60.$$click = () => addBlock(variant);
761
+ insert(_el$60, createComponent(Show, {
762
+ get when() {
763
+ return disc?.variantsAdmin?.[variant]?.icon;
764
+ },
765
+ get children() {
766
+ var _el$61 = _tmpl$33();
767
+ effect(() => className(_el$61, disc?.variantsAdmin?.[variant]?.icon));
768
+ return _el$61;
769
+ }
770
+ }), null);
771
+ insert(_el$60, () => variantLabel(disc, variant), null);
772
+ return _el$60;
773
+ })()
774
+ }));
775
+ return _el$45;
376
776
  }
377
- }), _el$32);
378
- _el$32.$$click = () => removeItem(index());
379
- return _el$31;
380
- })()
381
- }), _el$29);
382
- _el$29.$$click = addItem;
383
- insert(_el$29, key, null);
384
- return _el$28;
777
+ }), null);
778
+ effect(() => setAttribute(_el$44, "aria-expanded", menuOpen()));
779
+ return _el$43;
780
+ }
781
+ }), null);
782
+ return _el$38;
385
783
  })();
386
784
  }
785
+ function fieldsForItem(field, item) {
786
+ const base = Object.entries(field.fields);
787
+ const discriminator = field.discriminator;
788
+ if (!discriminator) return base;
789
+ const variantValue = item[discriminator.key];
790
+ const variantFields = typeof variantValue === "string" ? discriminator.variants[variantValue] : void 0;
791
+ return variantFields ? [...base, ...Object.entries(variantFields)] : base;
792
+ }
387
793
  function formatDateValue(value) {
388
794
  if (!value) return "—";
389
795
  const date = value instanceof Date ? value : new Date(value);
390
796
  return Number.isNaN(date.getTime()) ? "—" : date.toLocaleString();
391
797
  }
392
- delegateEvents(["click", "input"]);
798
+ delegateEvents([
799
+ "click",
800
+ "input",
801
+ "keydown",
802
+ "mousedown"
803
+ ]);
393
804
  //#endregion
394
805
  //#region src/tanstack-start/create.tsx
395
806
  var _tmpl$$3 = /*#__PURE__*/ template(`<div class="flex flex-col gap-4"><h1 class="text-xl font-semibold">`);
@@ -578,7 +989,7 @@ function createCollectionEditPage(options) {
578
989
  delegateEvents(["click"]);
579
990
  //#endregion
580
991
  //#region src/CollectionList.tsx
581
- var _tmpl$$1 = /*#__PURE__*/ template(`<button type=button class="btn btn-outline btn-sm">`), _tmpl$2$1 = /*#__PURE__*/ template(`<div class=join><select aria-label="Sort by"class="select select-sm join-item"></select><select aria-label="Sort direction"class="select select-sm join-item"><option value=asc>Ascending</option><option value=desc>Descending`), _tmpl$3 = /*#__PURE__*/ template(`<th>`), _tmpl$4 = /*#__PURE__*/ template(`<table class="table hidden md:table"><thead><tr></tr></thead><tbody>`), _tmpl$5 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2 md:hidden">`), _tmpl$6 = /*#__PURE__*/ template(`<div class="bg-base-100 sticky bottom-0 flex items-center justify-between gap-2 border-t py-2"><button type=button class="btn btn-sm">Prev</button><span class="text-sm opacity-70">Page </span><button type=button class="btn btn-sm">Next`), _tmpl$7 = /*#__PURE__*/ template(`<div class="flex flex-col gap-3"><div class="flex flex-wrap items-center justify-between gap-2">`), _tmpl$8 = /*#__PURE__*/ template(`<option>`), _tmpl$9 = /*#__PURE__*/ template(`<p class="text-sm opacity-70">No <!> yet.`), _tmpl$0 = /*#__PURE__*/ template(`<td><input type=checkbox class="checkbox checkbox-sm">`), _tmpl$1 = /*#__PURE__*/ template(`<tr>`), _tmpl$10 = /*#__PURE__*/ template(`<td>`), _tmpl$11 = /*#__PURE__*/ template(`<input type=checkbox class="checkbox checkbox-sm mt-1">`), _tmpl$12 = /*#__PURE__*/ template(`<div class="card bg-base-200 cursor-pointer p-3"role=button tabindex=0><div class="flex items-start gap-3"><div class="flex flex-1 flex-col gap-1">`), _tmpl$13 = /*#__PURE__*/ template(`<div class="flex justify-between gap-2 text-sm"><span class=opacity-60></span><span class=text-right>`);
992
+ var _tmpl$$1 = /*#__PURE__*/ template(`<button type=button class="btn btn-outline btn-sm">`), _tmpl$2$1 = /*#__PURE__*/ template(`<div class=join><select aria-label="Sort by"class="select select-sm join-item"></select><select aria-label="Sort direction"class="select select-sm join-item"><option value=asc>Ascending</option><option value=desc>Descending`), _tmpl$3 = /*#__PURE__*/ template(`<table class="table hidden md:table"><thead></thead><tbody>`), _tmpl$4 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2 md:hidden">`), _tmpl$5 = /*#__PURE__*/ template(`<div class="bg-base-100 sticky bottom-0 flex items-center justify-between gap-2 border-t py-2"><button type=button class="btn btn-sm">Prev</button><span class="text-sm opacity-70">Page </span><button type=button class="btn btn-sm">Next`), _tmpl$6 = /*#__PURE__*/ template(`<div class="flex flex-col gap-3"><div class="flex flex-wrap items-center justify-between gap-2">`), _tmpl$7 = /*#__PURE__*/ template(`<option>`), _tmpl$8 = /*#__PURE__*/ template(`<p class="text-sm opacity-70">No <!> yet.`), _tmpl$9 = /*#__PURE__*/ template(`<th>`), _tmpl$0 = /*#__PURE__*/ template(`<tr>`), _tmpl$1 = /*#__PURE__*/ template(`<td><input type=checkbox class="checkbox checkbox-sm">`), _tmpl$10 = /*#__PURE__*/ template(`<td>`), _tmpl$11 = /*#__PURE__*/ template(`<input type=checkbox class="checkbox checkbox-sm mt-1">`), _tmpl$12 = /*#__PURE__*/ template(`<div class="card bg-base-200 cursor-pointer p-3"role=button tabindex=0><div class="flex items-start gap-3"><div class="flex flex-1 flex-col gap-1">`), _tmpl$13 = /*#__PURE__*/ template(`<div class="flex justify-between gap-2 text-sm"><span class=opacity-60></span><span class=text-right>`);
582
993
  function listableFields(config) {
583
994
  const excluded = new Set([
584
995
  "richText",
@@ -596,7 +1007,21 @@ function rowId(row) {
596
1007
  return typeof row.id === "number" ? row.id : void 0;
597
1008
  }
598
1009
  function CollectionList(props) {
599
- const columns = () => listableFields(props.config);
1010
+ const columns = () => listableFields(props.config).map(([key]) => ({
1011
+ id: key,
1012
+ accessorFn: (row) => row[key],
1013
+ header: key,
1014
+ cell: (info) => formatCellValue(info.getValue())
1015
+ }));
1016
+ const table = createSolidTable({
1017
+ get data() {
1018
+ return props.rows;
1019
+ },
1020
+ get columns() {
1021
+ return columns();
1022
+ },
1023
+ getCoreRowModel: getCoreRowModel()
1024
+ });
600
1025
  const [selectMode, setSelectMode] = createSignal(false);
601
1026
  function toggleSelected(id) {
602
1027
  const next = new Set(props.selectedIds ?? []);
@@ -613,7 +1038,7 @@ function CollectionList(props) {
613
1038
  props.onRowClick?.(row);
614
1039
  }
615
1040
  return (() => {
616
- var _el$ = _tmpl$7(), _el$2 = _el$.firstChild;
1041
+ var _el$ = _tmpl$6(), _el$2 = _el$.firstChild;
617
1042
  insert(_el$2, createComponent(Show, {
618
1043
  get when() {
619
1044
  return props.selectable;
@@ -634,16 +1059,16 @@ function CollectionList(props) {
634
1059
  _el$5.addEventListener("change", (e) => props.onSortChange?.(e.currentTarget.value, props.sortDirection ?? "asc"));
635
1060
  insert(_el$5, createComponent(For, {
636
1061
  get each() {
637
- return columns();
1062
+ return table.getAllColumns();
638
1063
  },
639
- children: ([key]) => (() => {
640
- var _el$16 = _tmpl$8();
641
- _el$16.value = key;
642
- insert(_el$16, key);
643
- return _el$16;
1064
+ children: (column) => (() => {
1065
+ var _el$14 = _tmpl$7();
1066
+ insert(_el$14, () => column.id);
1067
+ effect(() => _el$14.value = column.id);
1068
+ return _el$14;
644
1069
  })()
645
1070
  }));
646
- _el$6.addEventListener("change", (e) => props.onSortChange?.(props.sortField ?? columns()[0]?.[0] ?? "", e.currentTarget.value));
1071
+ _el$6.addEventListener("change", (e) => props.onSortChange?.(props.sortField ?? table.getAllColumns()[0]?.id ?? "", e.currentTarget.value));
647
1072
  effect(() => _el$5.value = props.sortField ?? "");
648
1073
  effect(() => _el$6.value = props.sortDirection ?? "asc");
649
1074
  return _el$4;
@@ -655,62 +1080,71 @@ function CollectionList(props) {
655
1080
  },
656
1081
  get fallback() {
657
1082
  return (() => {
658
- var _el$17 = _tmpl$9(), _el$20 = _el$17.firstChild.nextSibling;
659
- _el$20.nextSibling;
660
- insert(_el$17, () => props.config.slug, _el$20);
661
- return _el$17;
1083
+ var _el$15 = _tmpl$8(), _el$18 = _el$15.firstChild.nextSibling;
1084
+ _el$18.nextSibling;
1085
+ insert(_el$15, () => props.config.slug, _el$18);
1086
+ return _el$15;
662
1087
  })();
663
1088
  },
664
1089
  get children() {
665
1090
  return [(() => {
666
- var _el$7 = _tmpl$4(), _el$8 = _el$7.firstChild, _el$9 = _el$8.firstChild, _el$1 = _el$8.nextSibling;
667
- insert(_el$9, createComponent(Show, {
668
- get when() {
669
- return selectMode();
670
- },
671
- get children() {
672
- return _tmpl$3();
673
- }
674
- }), null);
675
- insert(_el$9, createComponent(For, {
1091
+ var _el$7 = _tmpl$3(), _el$8 = _el$7.firstChild, _el$9 = _el$8.nextSibling;
1092
+ insert(_el$8, createComponent(For, {
676
1093
  get each() {
677
- return columns();
1094
+ return table.getHeaderGroups();
678
1095
  },
679
- children: ([key]) => (() => {
680
- var _el$21 = _tmpl$3();
681
- insert(_el$21, key);
682
- return _el$21;
1096
+ children: (headerGroup) => (() => {
1097
+ var _el$19 = _tmpl$0();
1098
+ insert(_el$19, createComponent(Show, {
1099
+ get when() {
1100
+ return selectMode();
1101
+ },
1102
+ get children() {
1103
+ return _tmpl$9();
1104
+ }
1105
+ }), null);
1106
+ insert(_el$19, createComponent(For, {
1107
+ get each() {
1108
+ return headerGroup.headers;
1109
+ },
1110
+ children: (header) => (() => {
1111
+ var _el$21 = _tmpl$9();
1112
+ insert(_el$21, () => flexRender(header.column.columnDef.header, header.getContext()));
1113
+ return _el$21;
1114
+ })()
1115
+ }), null);
1116
+ return _el$19;
683
1117
  })()
684
- }), null);
685
- insert(_el$1, createComponent(For, {
1118
+ }));
1119
+ insert(_el$9, createComponent(For, {
686
1120
  get each() {
687
- return props.rows;
1121
+ return table.getRowModel().rows;
688
1122
  },
689
1123
  children: (row) => (() => {
690
- var _el$22 = _tmpl$1();
691
- _el$22.$$click = () => handleRowActivate(row);
1124
+ var _el$22 = _tmpl$0();
1125
+ _el$22.$$click = () => handleRowActivate(row.original);
692
1126
  insert(_el$22, createComponent(Show, {
693
1127
  get when() {
694
1128
  return selectMode();
695
1129
  },
696
1130
  get children() {
697
- var _el$23 = _tmpl$0(), _el$24 = _el$23.firstChild;
1131
+ var _el$23 = _tmpl$1(), _el$24 = _el$23.firstChild;
698
1132
  _el$24.addEventListener("change", () => {
699
- const id = rowId(row);
1133
+ const id = rowId(row.original);
700
1134
  if (id !== void 0) toggleSelected(id);
701
1135
  });
702
1136
  _el$24.$$click = (e) => e.stopPropagation();
703
- effect(() => _el$24.checked = rowId(row) !== void 0 && (props.selectedIds?.has(rowId(row)) ?? false));
1137
+ effect(() => _el$24.checked = rowId(row.original) !== void 0 && (props.selectedIds?.has(rowId(row.original)) ?? false));
704
1138
  return _el$23;
705
1139
  }
706
1140
  }), null);
707
1141
  insert(_el$22, createComponent(For, {
708
1142
  get each() {
709
- return columns();
1143
+ return row.getVisibleCells();
710
1144
  },
711
- children: ([key]) => (() => {
1145
+ children: (cell) => (() => {
712
1146
  var _el$25 = _tmpl$10();
713
- insert(_el$25, () => formatCellValue(row[key]));
1147
+ insert(_el$25, () => flexRender(cell.column.columnDef.cell, cell.getContext()));
714
1148
  return _el$25;
715
1149
  })()
716
1150
  }), null);
@@ -720,20 +1154,20 @@ function CollectionList(props) {
720
1154
  }));
721
1155
  return _el$7;
722
1156
  })(), (() => {
723
- var _el$10 = _tmpl$5();
724
- insert(_el$10, createComponent(For, {
1157
+ var _el$0 = _tmpl$4();
1158
+ insert(_el$0, createComponent(For, {
725
1159
  get each() {
726
- return props.rows;
1160
+ return table.getRowModel().rows;
727
1161
  },
728
1162
  children: (row) => (() => {
729
1163
  var _el$26 = _tmpl$12(), _el$27 = _el$26.firstChild, _el$29 = _el$27.firstChild;
730
1164
  _el$26.$$keydown = (e) => {
731
1165
  if (e.key === "Enter" || e.key === " ") {
732
1166
  e.preventDefault();
733
- handleRowActivate(row);
1167
+ handleRowActivate(row.original);
734
1168
  }
735
1169
  };
736
- _el$26.$$click = () => handleRowActivate(row);
1170
+ _el$26.$$click = () => handleRowActivate(row.original);
737
1171
  insert(_el$27, createComponent(Show, {
738
1172
  get when() {
739
1173
  return selectMode();
@@ -741,29 +1175,29 @@ function CollectionList(props) {
741
1175
  get children() {
742
1176
  var _el$28 = _tmpl$11();
743
1177
  _el$28.addEventListener("change", () => {
744
- const id = rowId(row);
1178
+ const id = rowId(row.original);
745
1179
  if (id !== void 0) toggleSelected(id);
746
1180
  });
747
1181
  _el$28.$$click = (e) => e.stopPropagation();
748
- effect(() => _el$28.checked = rowId(row) !== void 0 && (props.selectedIds?.has(rowId(row)) ?? false));
1182
+ effect(() => _el$28.checked = rowId(row.original) !== void 0 && (props.selectedIds?.has(rowId(row.original)) ?? false));
749
1183
  return _el$28;
750
1184
  }
751
1185
  }), _el$29);
752
1186
  insert(_el$29, createComponent(For, {
753
1187
  get each() {
754
- return columns();
1188
+ return row.getVisibleCells();
755
1189
  },
756
- children: ([key]) => (() => {
1190
+ children: (cell) => (() => {
757
1191
  var _el$30 = _tmpl$13(), _el$31 = _el$30.firstChild, _el$32 = _el$31.nextSibling;
758
- insert(_el$31, key);
759
- insert(_el$32, () => formatCellValue(row[key]));
1192
+ insert(_el$31, () => cell.column.id);
1193
+ insert(_el$32, () => flexRender(cell.column.columnDef.cell, cell.getContext()));
760
1194
  return _el$30;
761
1195
  })()
762
1196
  }));
763
1197
  return _el$26;
764
1198
  })()
765
1199
  }));
766
- return _el$10;
1200
+ return _el$0;
767
1201
  })()];
768
1202
  }
769
1203
  }), null);
@@ -772,22 +1206,22 @@ function CollectionList(props) {
772
1206
  return memo(() => props.page !== void 0)() && props.pageSize !== void 0;
773
1207
  },
774
1208
  get children() {
775
- var _el$11 = _tmpl$6(), _el$12 = _el$11.firstChild, _el$13 = _el$12.nextSibling;
776
- _el$13.firstChild;
777
- var _el$15 = _el$13.nextSibling;
778
- _el$12.$$click = () => props.onPageChange?.((props.page ?? 1) - 1);
779
- insert(_el$13, () => props.page, null);
780
- _el$15.$$click = () => props.onPageChange?.((props.page ?? 1) + 1);
1209
+ var _el$1 = _tmpl$5(), _el$10 = _el$1.firstChild, _el$11 = _el$10.nextSibling;
1210
+ _el$11.firstChild;
1211
+ var _el$13 = _el$11.nextSibling;
1212
+ _el$10.$$click = () => props.onPageChange?.((props.page ?? 1) - 1);
1213
+ insert(_el$11, () => props.page, null);
1214
+ _el$13.$$click = () => props.onPageChange?.((props.page ?? 1) + 1);
781
1215
  effect((_p$) => {
782
1216
  var _v$ = (props.page ?? 1) <= 1, _v$2 = props.totalCount !== void 0 ? (props.page ?? 1) * (props.pageSize ?? 0) >= props.totalCount : props.rows.length < (props.pageSize ?? 0);
783
- _v$ !== _p$.e && (_el$12.disabled = _p$.e = _v$);
784
- _v$2 !== _p$.t && (_el$15.disabled = _p$.t = _v$2);
1217
+ _v$ !== _p$.e && (_el$10.disabled = _p$.e = _v$);
1218
+ _v$2 !== _p$.t && (_el$13.disabled = _p$.t = _v$2);
785
1219
  return _p$;
786
1220
  }, {
787
1221
  e: void 0,
788
1222
  t: void 0
789
1223
  });
790
- return _el$11;
1224
+ return _el$1;
791
1225
  }
792
1226
  }), null);
793
1227
  return _el$;