@zeyos/zx 4.3.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +266 -1
  2. package/README.md +7 -3
  3. package/dist/types/components/activity-item/activity-item.d.ts +351 -0
  4. package/dist/types/components/activity-list/activity-list.d.ts +195 -0
  5. package/dist/types/components/app-sidebar/app-sidebar.d.ts +28 -0
  6. package/dist/types/components/button/button.d.ts +8 -0
  7. package/dist/types/components/calendar/calendar-model.d.ts +22 -0
  8. package/dist/types/components/calendar/calendar.d.ts +19 -0
  9. package/dist/types/components/card/card.d.ts +7 -0
  10. package/dist/types/components/card-view/card-view.d.ts +12 -4
  11. package/dist/types/components/card-view/record-card.d.ts +53 -5
  12. package/dist/types/components/code-editor/code-editor.d.ts +160 -0
  13. package/dist/types/components/code-editor/field-adapter.d.ts +5 -0
  14. package/dist/types/components/context-menu/context-menu.d.ts +18 -2
  15. package/dist/types/components/date-picker/date-picker.d.ts +8 -0
  16. package/dist/types/components/date-picker/time-picker.d.ts +7 -0
  17. package/dist/types/components/dialog/dialog.d.ts +29 -0
  18. package/dist/types/components/entity-ref/entity-ref.d.ts +331 -0
  19. package/dist/types/components/file-item/file-item.d.ts +234 -0
  20. package/dist/types/components/file-list/file-list.d.ts +171 -0
  21. package/dist/types/components/filter/filter.d.ts +91 -36
  22. package/dist/types/components/filter-panel/filter-panel.d.ts +449 -0
  23. package/dist/types/components/kanban-view/kanban-card.d.ts +138 -0
  24. package/dist/types/components/kanban-view/kanban-policy.d.ts +268 -0
  25. package/dist/types/components/kanban-view/kanban-view.d.ts +837 -26
  26. package/dist/types/components/launcher/launcher.d.ts +19 -12
  27. package/dist/types/components/list-toolbar/list-toolbar.d.ts +599 -0
  28. package/dist/types/components/menu-button/menu-button.d.ts +4 -37
  29. package/dist/types/components/message/message.d.ts +7 -0
  30. package/dist/types/components/modal/modal.d.ts +48 -0
  31. package/dist/types/components/navigation-bar/navigation-bar.d.ts +105 -21
  32. package/dist/types/components/panel/panel.d.ts +7 -0
  33. package/dist/types/components/search/search.d.ts +7 -0
  34. package/dist/types/components/select/select.d.ts +4 -0
  35. package/dist/types/components/sort-control/sort-control.d.ts +105 -0
  36. package/dist/types/components/stat-tile/stat-tile.d.ts +277 -0
  37. package/dist/types/components/tabbox/tabbox.d.ts +7 -0
  38. package/dist/types/components/table/table.d.ts +144 -0
  39. package/dist/types/components/table-view/table-view.d.ts +11 -5
  40. package/dist/types/components/timebox/timebox.d.ts +7 -0
  41. package/dist/types/components/value-list/value-list.d.ts +8 -0
  42. package/dist/types/components/view/record-view.d.ts +96 -5
  43. package/dist/types/core/component.d.ts +6 -1
  44. package/dist/types/core/icons.d.ts +17 -0
  45. package/dist/types/index.d.ts +13 -1
  46. package/dist/types/internal/app-rail.d.ts +10 -0
  47. package/dist/types/internal/menu-items.d.ts +134 -0
  48. package/dist/zx-zeyos.esm.js +651 -88
  49. package/dist/zx-zeyos.esm.min.js +8 -1
  50. package/dist/zx.css +6266 -3900
  51. package/dist/zx.esm.js +8487 -1805
  52. package/dist/zx.esm.min.js +10 -3
  53. package/dist/zx.global.js +8487 -1805
  54. package/dist/zx.global.min.js +10 -3
  55. package/dist/zx.min.css +1 -1
  56. package/docs/api.json +1811 -247
  57. package/docs/llms.md +345 -40
  58. package/docs/llms.txt +11 -7
  59. package/package.json +1 -2
  60. package/src/components/activity-item/activity-item.css +137 -0
  61. package/src/components/activity-item/activity-item.js +599 -0
  62. package/src/components/activity-list/activity-list.css +64 -0
  63. package/src/components/activity-list/activity-list.js +375 -0
  64. package/src/components/app-rail/app-rail.css +227 -19
  65. package/src/components/app-sidebar/app-sidebar.css +414 -24
  66. package/src/components/app-sidebar/app-sidebar.js +65 -5
  67. package/src/components/button/button.css +8 -0
  68. package/src/components/button/button.js +6 -1
  69. package/src/components/calendar/calendar-model.js +45 -0
  70. package/src/components/calendar/calendar.css +30 -10
  71. package/src/components/calendar/calendar.js +41 -13
  72. package/src/components/card/card.js +12 -1
  73. package/src/components/card-view/card-view.css +212 -9
  74. package/src/components/card-view/card-view.js +32 -16
  75. package/src/components/card-view/record-card.js +98 -21
  76. package/src/components/code-editor/code-editor.css +67 -0
  77. package/src/components/code-editor/code-editor.js +288 -0
  78. package/src/components/code-editor/field-adapter.js +34 -0
  79. package/src/components/context-menu/context-menu.css +80 -3
  80. package/src/components/context-menu/context-menu.js +22 -30
  81. package/src/components/date-picker/date-picker.js +22 -8
  82. package/src/components/date-picker/month-picker.js +3 -3
  83. package/src/components/date-picker/time-picker.js +20 -8
  84. package/src/components/dialog/dialog.js +88 -66
  85. package/src/components/dropdown/dropdown.js +2 -2
  86. package/src/components/entity-ref/entity-ref.css +182 -0
  87. package/src/components/entity-ref/entity-ref.js +496 -0
  88. package/src/components/file-item/file-item.css +88 -0
  89. package/src/components/file-item/file-item.js +371 -0
  90. package/src/components/file-list/file-list.css +51 -0
  91. package/src/components/file-list/file-list.js +320 -0
  92. package/src/components/filter/filter.css +27 -1
  93. package/src/components/filter/filter.js +199 -45
  94. package/src/components/filter-panel/filter-panel.css +104 -0
  95. package/src/components/filter-panel/filter-panel.js +964 -0
  96. package/src/components/kanban-view/kanban-card.js +239 -0
  97. package/src/components/kanban-view/kanban-policy.js +412 -0
  98. package/src/components/kanban-view/kanban-view.css +674 -36
  99. package/src/components/kanban-view/kanban-view.js +1762 -240
  100. package/src/components/launcher/launcher.js +59 -27
  101. package/src/components/list-toolbar/list-toolbar.css +189 -0
  102. package/src/components/list-toolbar/list-toolbar.js +851 -0
  103. package/src/components/menu-button/menu-button.css +80 -3
  104. package/src/components/menu-button/menu-button.js +21 -37
  105. package/src/components/message/message.css +14 -12
  106. package/src/components/message/message.js +13 -2
  107. package/src/components/modal/modal.css +15 -0
  108. package/src/components/modal/modal.js +141 -0
  109. package/src/components/navigation-bar/navigation-bar.css +77 -2
  110. package/src/components/navigation-bar/navigation-bar.js +171 -4
  111. package/src/components/panel/panel.js +13 -2
  112. package/src/components/search/search.js +17 -5
  113. package/src/components/select/field-adapter.js +4 -1
  114. package/src/components/select/select.js +3 -0
  115. package/src/components/sort-control/sort-control.css +17 -0
  116. package/src/components/sort-control/sort-control.js +140 -0
  117. package/src/components/stat-tile/stat-tile.css +213 -0
  118. package/src/components/stat-tile/stat-tile.js +590 -0
  119. package/src/components/tabbox/tabbox.js +12 -1
  120. package/src/components/table/table.css +51 -2
  121. package/src/components/table/table.js +298 -19
  122. package/src/components/table-view/table-view.css +8 -2
  123. package/src/components/table-view/table-view.js +21 -6
  124. package/src/components/tag-picker/tag-picker.css +3 -1
  125. package/src/components/timebox/timebox.js +18 -5
  126. package/src/components/value-list/value-list.js +22 -6
  127. package/src/components/view/record-view.css +5 -0
  128. package/src/components/view/record-view.js +100 -7
  129. package/src/core/component.js +8 -3
  130. package/src/core/icons.js +74 -5
  131. package/src/index.js +33 -3
  132. package/src/internal/app-rail.js +19 -1
  133. package/src/internal/menu-items.js +142 -0
  134. package/styles/print.css +192 -0
  135. package/styles/zx.css +11 -0
  136. package/DESIGN-SYSTEM.md +0 -182
@@ -1,9 +1,17 @@
1
+ import { ContextMenu } from '../context-menu/context-menu.js';
1
2
  import { RecordView } from '../view/record-view.js';
2
3
  export type KanbanRecord = Record<string, any>;
3
4
  export type RecordViewOptions = import('../view/record-view.js').RecordViewOptions;
4
5
  export type RecordCardPreview = import('../card-view/record-card.js').RecordCardPreview;
5
6
  export type RecordCardLink = import('../card-view/record-card.js').RecordCardLink;
6
7
  export type RecordCardAction = import('../card-view/record-card.js').RecordCardAction;
8
+ export type MenuItem = import('../menu-button/menu-button.js').MenuItem;
9
+ export type KanbanRule = import('./kanban-policy.js').KanbanRule;
10
+ export type KanbanIndicator = import('./kanban-card.js').KanbanIndicator;
11
+ export type KanbanIndicatorSource = string | KanbanIndicator | ((record: KanbanRecord, index: number) => KanbanIndicator | Node | unknown) | null;
12
+ export type KanbanAssignee = import('./kanban-card.js').KanbanAssignee;
13
+ export type KanbanRejectReason = import('./kanban-policy.js').KanbanRejectReason;
14
+ export type KanbanMoveEvaluation = import('./kanban-policy.js').KanbanMoveEvaluation;
7
15
  export type KanbanAccessor = string | ((record: KanbanRecord, index: number) => unknown) | null;
8
16
  export type KanbanCardField = string | ((record: KanbanRecord, index: number) => unknown) | null;
9
17
  export type KanbanMovePoint = {
@@ -56,9 +64,22 @@ export type KanbanColumn = {
56
64
  */
57
65
  value?: unknown;
58
66
  /**
59
- * Advisory work-in-progress limit.
67
+ * Work-in-progress limit across every lane.
60
68
  */
61
69
  limit?: number | null;
70
+ /**
71
+ * Per-lane limits inside this column.
72
+ */
73
+ laneLimits?: Record<string, number>;
74
+ /**
75
+ * Overrides the board `wipPolicy` for this column.
76
+ */
77
+ wipPolicy?: 'warn' | 'block';
78
+ /**
79
+ * Origin column ids allowed to move in. `null`, an absent
80
+ * value, or `['*']` admits any origin; a move that stays in the column is never restricted.
81
+ */
82
+ from?: string[] | null;
62
83
  /**
63
84
  * Eligibility
64
85
  * predicate. Returning false rejects the move before the cancelable event is emitted.
@@ -78,6 +99,14 @@ export type KanbanSwimlane = {
78
99
  * Value written by local moves; defaults to `id`.
79
100
  */
80
101
  value?: unknown;
102
+ /**
103
+ * Work-in-progress limit across every column in the lane.
104
+ */
105
+ limit?: number | null;
106
+ /**
107
+ * Origin lane ids allowed to move in.
108
+ */
109
+ from?: string[] | null;
81
110
  /**
82
111
  * Eligibility
83
112
  * predicate. Returning false rejects the move before the cancelable event is emitted.
@@ -135,6 +164,70 @@ export type KanbanViewState = {
135
164
  */
136
165
  collapsedSwimlanes: string[];
137
166
  };
167
+ export type KanbanCardContext = {
168
+ /**
169
+ * Record being rendered.
170
+ */
171
+ record: KanbanRecord;
172
+ /**
173
+ * Record id.
174
+ */
175
+ id: unknown;
176
+ /**
177
+ * Display index in the current record order.
178
+ */
179
+ index: number;
180
+ /**
181
+ * Column id.
182
+ */
183
+ column: string;
184
+ /**
185
+ * Lane id, or null when lanes are disabled.
186
+ */
187
+ lane: string | null;
188
+ /**
189
+ * Rules matching this record, in configured order.
190
+ */
191
+ rules: KanbanRule[];
192
+ /**
193
+ * Whether the record is selected.
194
+ */
195
+ selected: boolean;
196
+ };
197
+ export type KanbanHeaderContext = {
198
+ /**
199
+ * Column being rendered.
200
+ */
201
+ column?: KanbanColumn;
202
+ /**
203
+ * Lane being rendered, or the lane a column belongs to.
204
+ */
205
+ swimlane?: KanbanSwimlane | null;
206
+ /**
207
+ * Records rendered in this section.
208
+ */
209
+ count: number;
210
+ /**
211
+ * Records this section holds before search and filters.
212
+ */
213
+ total: number;
214
+ /**
215
+ * Records in the whole column, across lanes.
216
+ */
217
+ columnTotal: number;
218
+ /**
219
+ * Applicable work-in-progress limit.
220
+ */
221
+ limit: number | null;
222
+ /**
223
+ * Capacity state.
224
+ */
225
+ wip: 'none' | 'within' | 'limit' | 'exceeded';
226
+ /**
227
+ * Whether the section is collapsed.
228
+ */
229
+ collapsed: boolean;
230
+ };
138
231
  export type KanbanViewOptions = {
139
232
  /**
140
233
  * Shared field descriptors.
@@ -163,6 +256,10 @@ export type KanbanViewOptions = {
163
256
  * Shared selection mode.
164
257
  */
165
258
  selectable?: false | 'single' | 'multi';
259
+ /**
260
+ * Select through a checkbox or the non-interactive card surface.
261
+ */
262
+ selectionTrigger?: 'checkbox' | 'card';
166
263
  /**
167
264
  * Initial record ids.
168
265
  */
@@ -176,9 +273,10 @@ export type KanbanViewOptions = {
176
273
  */
177
274
  hiddenFields?: string[];
178
275
  /**
179
- * Show shared field controls.
276
+ * Show shared field controls. Redeclared narrower than `RecordViewOptions` it fails declaration
277
+ * emit, because the two option types are intersected.
180
278
  */
181
- fieldControls?: boolean;
279
+ fieldControls?: boolean | import('../view/record-view.js').ViewFieldControlsConfig;
182
280
  /**
183
281
  * Empty-board content.
184
282
  */
@@ -227,6 +325,147 @@ export type KanbanViewOptions = {
227
325
  * Whether accepted moves update local data.
228
326
  */
229
327
  moveMode?: 'local' | 'external';
328
+ /**
329
+ * Whether the whole card or only its handle starts a
330
+ * pointer drag. Touch drags from the card body require a long press so the board still scrolls.
331
+ */
332
+ dragFrom?: 'card' | 'handle';
333
+ /**
334
+ * Move-handle presentation. `keyboard`
335
+ * keeps it announced and tabbable but out of sight until it takes focus, because the card itself
336
+ * is already the pointer drag source; `always` shows it alongside the card's other controls.
337
+ * `dragFrom:'handle'` overrides this — a drag source a pointer user cannot see is not a control.
338
+ */
339
+ moveHandle?: 'keyboard' | 'always';
340
+ /**
341
+ * Icon
342
+ * naming what the record is, drawn before the identifier.
343
+ */
344
+ entityIcon?: string | ((record: KanbanRecord, index: number) => string | null) | null;
345
+ /**
346
+ * Stable record key shown on the card head.
347
+ */
348
+ identifier?: KanbanCardField;
349
+ /**
350
+ * Status indicator source.
351
+ */
352
+ status?: KanbanIndicatorSource;
353
+ /**
354
+ * Maps a status value to a semantic tone.
355
+ */
356
+ statusTones?: Record<string, string>;
357
+ /**
358
+ * Priority indicator source.
359
+ */
360
+ priority?: KanbanIndicatorSource;
361
+ /**
362
+ * Maps a priority value to a semantic tone.
363
+ */
364
+ priorityTones?: Record<string, string>;
365
+ /**
366
+ * Completion source; a number or `{value,max,label}`.
367
+ */
368
+ progress?: KanbanCardField;
369
+ /**
370
+ * Amount that counts as finished.
371
+ */
372
+ progressMax?: number;
373
+ /**
374
+ * Responsible people; a name, a list, or descriptors.
375
+ */
376
+ assignees?: KanbanCardField;
377
+ /**
378
+ * Faces drawn before the overflow chip.
379
+ */
380
+ maxAvatars?: number;
381
+ /**
382
+ * Move the whole selection when a selected card is picked up.
383
+ */
384
+ multiMove?: boolean;
385
+ /**
386
+ * Scroll the board and columns while dragging near an edge.
387
+ */
388
+ autoScroll?: boolean;
389
+ /**
390
+ * Whether exceeding a limit warns or refuses.
391
+ */
392
+ wipPolicy?: 'warn' | 'block';
393
+ /**
394
+ * Ordered visual card rules.
395
+ */
396
+ rules?: KanbanRule[];
397
+ /**
398
+ * Board search text.
399
+ */
400
+ search?: string;
401
+ /**
402
+ * Field ids searched; null searches visible fields
403
+ * plus the title and subtitle sources.
404
+ */
405
+ searchFields?: string[] | null;
406
+ /**
407
+ * Extra card predicate.
408
+ */
409
+ filter?: ((record: KanbanRecord, index: number) => boolean) | null;
410
+ /**
411
+ * Render the built-in board search control.
412
+ */
413
+ searchControl?: boolean;
414
+ /**
415
+ * Record committed local moves for undo and redo.
416
+ */
417
+ history?: boolean;
418
+ /**
419
+ * Maximum remembered move steps.
420
+ */
421
+ historyLimit?: number;
422
+ /**
423
+ * Render built-in undo and redo controls.
424
+ */
425
+ historyControls?: boolean;
426
+ /**
427
+ * CSS length turning each column into a scroll region.
428
+ */
429
+ columnHeight?: string | null;
430
+ /**
431
+ * Render a per-column add control that emits `recordadd`.
432
+ */
433
+ allowAdd?: boolean | ((column: KanbanColumn, swimlane: KanbanSwimlane | null) => boolean);
434
+ /**
435
+ * Card context menu. `true` offers move commands; an array or function appends application items.
436
+ */
437
+ contextMenu?: boolean | MenuItem[] | ((context: KanbanCardContext) => MenuItem[]);
438
+ /**
439
+ * Replaces the
440
+ * shared record-card content — eyebrow, titles, and metadata. The preview, selection control,
441
+ * action group, move handle, rule badges, and any configured card head and footer still render,
442
+ * because each of those answers to its own option; clear those options to remove them.
443
+ */
444
+ renderCard?: ((context: KanbanCardContext) => Node | null | undefined) | null;
445
+ /**
446
+ * Replaces column header content.
447
+ */
448
+ renderColumnHeader?: ((context: KanbanHeaderContext) => Node | null | undefined) | null;
449
+ /**
450
+ * Replaces lane header content.
451
+ */
452
+ renderSwimlaneHeader?: ((context: KanbanHeaderContext) => Node | null | undefined) | null;
453
+ /**
454
+ * Empty-column placeholder.
455
+ */
456
+ renderColumnEmpty?: ((context: KanbanHeaderContext) => Node | null | undefined) | null;
457
+ /**
458
+ * Replaces the floating drag preview.
459
+ */
460
+ renderDragPreview?: ((context: {
461
+ records: KanbanRecord[];
462
+ ids: unknown[];
463
+ count: number;
464
+ }) => Node | null | undefined) | null;
465
+ /**
466
+ * Overrides for every visible and announced string.
467
+ */
468
+ labels?: Record<string, string>;
230
469
  /**
231
470
  * Preferred column order.
232
471
  */
@@ -260,7 +499,20 @@ export type KanbanViewOptions = {
260
499
  */
261
500
  label?: string;
262
501
  onrecordmove?: (event: CustomEvent<Record<string, unknown>>) => void;
502
+ onmovereject?: (event: CustomEvent<Record<string, unknown>>) => void;
263
503
  onrecordaction?: (event: CustomEvent<Record<string, unknown>>) => void;
504
+ onrecordadd?: (event: CustomEvent<Record<string, unknown>>) => void;
505
+ onsearchchange?: (event: CustomEvent<{
506
+ search: string;
507
+ }>) => void;
508
+ onhistorychange?: (event: CustomEvent<{
509
+ canUndo: boolean;
510
+ canRedo: boolean;
511
+ depth: {
512
+ undo: number;
513
+ redo: number;
514
+ };
515
+ }>) => void;
264
516
  };
265
517
  export type KanbanCardMeta = {
266
518
  record: KanbanRecord;
@@ -275,16 +527,121 @@ export type KanbanSectionMeta = {
275
527
  list: HTMLElement;
276
528
  };
277
529
  export type KanbanKeyboardMove = {
278
- id: unknown;
530
+ ids: unknown[];
279
531
  from: KanbanMovePoint;
280
532
  to: KanbanMovePoint;
281
533
  };
534
+ export type KanbanCardReader = ((record: KanbanRecord, index: number) => unknown) | null;
535
+ export type KanbanCardSources = {
536
+ /**
537
+ * Record-key reader.
538
+ */
539
+ identifier: KanbanCardReader;
540
+ /**
541
+ * Status reader.
542
+ */
543
+ status: KanbanCardReader;
544
+ /**
545
+ * Priority reader.
546
+ */
547
+ priority: KanbanCardReader;
548
+ /**
549
+ * Completion reader.
550
+ */
551
+ progress: KanbanCardReader;
552
+ /**
553
+ * Responsible-people reader.
554
+ */
555
+ assignees: KanbanCardReader;
556
+ /**
557
+ * Entity-icon reader.
558
+ */
559
+ entityIcon: KanbanCardReader;
560
+ /**
561
+ * Field ids the anatomy consumes.
562
+ */
563
+ fieldIds: Set<string>;
564
+ /**
565
+ * Whether any source is configured.
566
+ */
567
+ any: boolean;
568
+ };
569
+ /**
570
+ * Every user-visible and announced string, so a host can translate the board without patching it.
571
+ * Values run through `printf`, so named placeholders may be reordered or dropped by a translation.
572
+ */
573
+ declare const DEFAULT_LABELS: Readonly<{
574
+ fields: "Fields";
575
+ search: "Search board";
576
+ searchPlaceholder: "Search cards";
577
+ clearSearch: "Clear search";
578
+ searchSummary: "%count% of %total% cards match.";
579
+ undo: "Undo";
580
+ redo: "Redo";
581
+ add: "Add card";
582
+ addTo: "Add card to %target%";
583
+ move: "Move %name%";
584
+ moveMultiple: "Move %count% selected cards";
585
+ collapseColumn: "Collapse column %label%";
586
+ expandColumn: "Expand column %label%";
587
+ collapseLane: "Collapse swim lane %label%";
588
+ expandLane: "Expand swim lane %label%";
589
+ count: "%count% records";
590
+ countFiltered: "%count% of %total% records";
591
+ countLimit: "%count% records, work-in-progress limit %limit%";
592
+ countLimitInLane: "%count% records in this lane, %total% of work-in-progress limit %limit% in the column";
593
+ empty: "No records";
594
+ columnEmpty: "Drop a card here";
595
+ identifier: "Record";
596
+ priorityLabel: "Priority";
597
+ statusLabel: "Status";
598
+ progress: "Progress";
599
+ progressValue: "%percent%%";
600
+ assignees: "Assigned to %names%";
601
+ assigneeOverflow: "+%count%";
602
+ selected: "Selected";
603
+ notSelected: "Not selected";
604
+ noMatches: "No cards match the current search.";
605
+ record: "record";
606
+ grabbed: "Grabbed %name%. Use left and right for columns, up and down for position, and Alt plus up or down for swim lanes.";
607
+ grabbedMultiple: "Grabbed %count% cards. Use left and right for columns, up and down for position, and Alt plus up or down for swim lanes.";
608
+ target: "Target %target%, position %position% of %total%.";
609
+ moved: "Moved %name% to %target%.%wip%";
610
+ movedMultiple: "Moved %count% cards to %target%.%wip%";
611
+ moveRequested: "Move requested for %name% to %target%.%wip%";
612
+ moveCanceled: "Move canceled for %name%.";
613
+ moveCanceledPlain: "Move canceled.";
614
+ limitReached: " Work-in-progress limit %limit% reached.";
615
+ limitExceeded: " Work-in-progress limit %limit% exceeded.";
616
+ rejectAccept: "Move rejected: %target% does not accept %name%.";
617
+ rejectTransition: "Move rejected: %target% does not accept cards from %origin%.";
618
+ rejectWip: "Move rejected: %target% is at its work-in-progress limit of %limit%.";
619
+ rejectDestination: "Move rejected: the destination is not available.";
620
+ rejectGrouping: "Move rejected: callback grouping requires external move mode.";
621
+ undone: "Move undone.";
622
+ redone: "Move redone.";
623
+ nothingToUndo: "Nothing to undo.";
624
+ nothingToRedo: "Nothing to redo.";
625
+ menuMoveTo: "Move to %target%";
626
+ menuMoveToLane: "Move to lane %target%";
627
+ dragPreview: "%count% cards";
628
+ }>;
282
629
  /**
283
- * Configurable record board with semantic columns, optional swim lanes, and equivalent pointer and
284
- * keyboard movement. Local moves clone records; callback grouping remains fully usable for display
285
- * and external moves but cannot be written safely by local cross-axis moves.
630
+ * A field consumed by the card head or footer — the `identifier`, `status`, `priority`,
631
+ * `progress`, or `assignees` source — is dropped from the shared metadata list so the same value
632
+ * is never shown twice. `field.duplicate === true` opts it back in, extending the rule the shared
633
+ * record card already applies to title and subtitle fields.
634
+ *
635
+ * Configurable record board with semantic columns, optional swim lanes, and equivalent pointer,
636
+ * touch, keyboard, context-menu, and programmatic movement. Local moves clone records; callback
637
+ * grouping remains fully usable for display and external moves but cannot be written safely by
638
+ * local cross-axis moves.
286
639
  * @fires KanbanView#recordmove
640
+ * @fires KanbanView#movereject
287
641
  * @fires KanbanView#recordaction
642
+ * @fires KanbanView#recordadd
643
+ * @fires KanbanView#searchchange
644
+ * @fires KanbanView#historychange
288
645
  * @extends {RecordView}
289
646
  */
290
647
  export declare class KanbanView extends RecordView {
@@ -296,8 +653,12 @@ export declare class KanbanView extends RecordView {
296
653
  _kanbanSwimlaneOrder: string[];
297
654
  _collapsedColumns: Set<string>;
298
655
  _collapsedSwimlanes: Set<string>;
656
+ _kanbanRules: import("./kanban-policy.js").KanbanRule[];
657
+ _kanbanSearch: any;
658
+ _kanbanFilter: ((record: KanbanRecord, index: number) => boolean) | ((record: KanbanRecord, index: number) => boolean);
659
+ _kanbanHistory: import("./kanban-policy.js").KanbanHistory;
299
660
  _keyboardMove: KanbanKeyboardMove | {
300
- id: unknown;
661
+ ids: unknown[];
301
662
  from: {
302
663
  column: string;
303
664
  lane: string | null;
@@ -309,12 +670,66 @@ export declare class KanbanView extends RecordView {
309
670
  index: number;
310
671
  };
311
672
  };
312
- _dragId: unknown;
313
- _dragDestination: KanbanMovePoint;
673
+ _dragIds: any[] | unknown[];
674
+ _dragDestination: KanbanMovePoint | {
675
+ column: any;
676
+ lane: any;
677
+ index: number;
678
+ };
679
+ _pointerStart: {
680
+ x: number;
681
+ y: number;
682
+ id: number;
683
+ ids: unknown[];
684
+ touch: boolean;
685
+ } | {
686
+ x: number;
687
+ y: number;
688
+ id: number;
689
+ ids: unknown[];
690
+ touch: boolean;
691
+ };
692
+ _pointerHold: number;
693
+ _dragFrame: number;
694
+ _dragPreview: HTMLElement;
695
+ _dragPointer: number;
696
+ _dragCaptured: boolean;
697
+ _searchTimer: number;
698
+ _dragPoint: {
699
+ x: number;
700
+ y: number;
701
+ } | {
702
+ x: number;
703
+ y: number;
704
+ } | {
705
+ x: number;
706
+ y: number;
707
+ } | {
708
+ x: number;
709
+ y: number;
710
+ } | {
711
+ x: number;
712
+ y: number;
713
+ };
714
+ _suppressClick: boolean;
314
715
  _announcementToken: number;
315
716
  _cardMeta: WeakMap<object, any>;
316
717
  _sectionMeta: WeakMap<object, any>;
317
718
  _cardsById: Map<any, any>;
719
+ _visibleIds: Set<any>;
720
+ _cardSources: KanbanCardSources;
721
+ _fieldIndex: Map<string, any> | Map<string, import("../view/record-view.js").ViewField>;
722
+ _cardFields: {
723
+ all: any[];
724
+ metadata: any[];
725
+ } | {
726
+ all: import("../view/record-view.js").ViewField[];
727
+ metadata: import("../view/record-view.js").ViewField[];
728
+ };
729
+ _kanbanMenu: ContextMenu;
730
+ _searchInput: HTMLInputElement;
731
+ _undoButton: HTMLButtonElement;
732
+ _redoButton: HTMLButtonElement;
318
733
  _toolbar: HTMLElement;
319
734
  _board: HTMLElement;
320
735
  _live: HTMLElement;
@@ -412,15 +827,82 @@ export declare class KanbanView extends RecordView {
412
827
  /** Toggles a lane. @param {string} id Lane id. @returns {this} */
413
828
  toggleSwimlane(id: string): this;
414
829
  /**
415
- * Proposes and, in local mode, commits a record move. Destination acceptance is checked before
416
- * a cancelable `recordmove` event. WIP limits are reported but remain advisory.
830
+ * Proposes and, in local mode, commits a record move. Equivalent to `moveRecords([id], …)`.
417
831
  * @param {unknown} id Record id.
418
832
  * @param {KanbanDestination} destination Destination.
419
833
  * @returns {this}
420
834
  * @fires KanbanView#recordmove
835
+ * @fires KanbanView#movereject
421
836
  * @fires RecordView#datachange
422
837
  */
423
838
  moveRecord(id: unknown, destination: KanbanDestination): this;
839
+ /**
840
+ * Proposes and, in local mode, commits an atomic move of one or more records. Destination
841
+ * eligibility, transition rules, and work-in-progress policy are all checked before a single
842
+ * cancelable `recordmove` event; the move commits completely or not at all, and the moving
843
+ * records keep their relative order at the destination.
844
+ * @param {unknown[]} ids Record ids, in any order.
845
+ * @param {KanbanDestination} destination Destination.
846
+ * @returns {this}
847
+ * @fires KanbanView#recordmove
848
+ * @fires KanbanView#movereject
849
+ * @fires RecordView#datachange
850
+ */
851
+ moveRecords(ids: unknown[], destination: KanbanDestination): this;
852
+ /** Whether a committed local move can be reverted. @returns {boolean} */
853
+ canUndo(): boolean;
854
+ /** Whether a reverted local move can be reapplied. @returns {boolean} */
855
+ canRedo(): boolean;
856
+ /**
857
+ * Reverts the last committed local move, restoring the exact record order and selection.
858
+ * @returns {this}
859
+ * @fires RecordView#datachange
860
+ * @fires KanbanView#historychange
861
+ */
862
+ undo(): this;
863
+ /**
864
+ * Reapplies the last reverted local move.
865
+ * @returns {this}
866
+ * @fires RecordView#datachange
867
+ * @fires KanbanView#historychange
868
+ */
869
+ redo(): this;
870
+ /** Empties both history stacks. @returns {this} @fires KanbanView#historychange */
871
+ clearHistory(): this;
872
+ /** Returns the current board search text. @returns {string} */
873
+ getSearch(): string;
874
+ /**
875
+ * Narrows visible cards to those matching a search. Hidden records keep their position in the
876
+ * data, so a card dropped between two visible cards still lands between them.
877
+ * @param {string} search Search text.
878
+ * @param {{silent?:boolean}} [options={}] Event behavior.
879
+ * @returns {this}
880
+ * @fires KanbanView#searchchange
881
+ */
882
+ setSearch(search: string, options?: {
883
+ silent?: boolean;
884
+ }): this;
885
+ /**
886
+ * Replaces the extra card predicate. Pass null to clear it.
887
+ * @param {((record:KanbanRecord,index:number)=>boolean)|null} filter Predicate.
888
+ * @returns {this}
889
+ */
890
+ setFilter(filter: ((record: KanbanRecord, index: number) => boolean) | null): this;
891
+ /** Returns the records currently rendered, in board order. @returns {KanbanRecord[]} */
892
+ getVisibleRecords(): KanbanRecord[];
893
+ /**
894
+ * Replaces every record. History is dropped because its snapshots describe records the host has
895
+ * just replaced, and reinstating them would resurrect data the application no longer owns.
896
+ * @param {KanbanRecord[]} records New records.
897
+ * @returns {this}
898
+ */
899
+ setData(records: KanbanRecord[]): this;
900
+ /** @param {KanbanRecord[]} records Records to append. @returns {this} */
901
+ addData(records: KanbanRecord[]): this;
902
+ /** @param {unknown} id Existing record id. @param {KanbanRecord} record Replacement. @returns {this} */
903
+ updateRecord(id: unknown, record: KanbanRecord): this;
904
+ /** @param {unknown} id Record id. @returns {this} */
905
+ removeRecord(id: unknown): this;
424
906
  /** Returns common plus board-specific serializable configuration. @returns {KanbanViewState} */
425
907
  getViewState(): KanbanViewState;
426
908
  /**
@@ -453,8 +935,95 @@ export declare class KanbanView extends RecordView {
453
935
  }[], hasLanes: boolean): HTMLElement;
454
936
  /** @param {KanbanRecord} record @param {number} index @param {string} column @param {string|null} lane @param {boolean} hasLanes @returns {HTMLLIElement} */
455
937
  _renderCard(record: KanbanRecord, index: number, column: string, lane: string | null, hasLanes: boolean): HTMLLIElement;
456
- /** @returns {HTMLElement} */
457
- _emptyContent(): HTMLElement;
938
+ /**
939
+ * Builds the two field arrays every card needs, once per refresh.
940
+ * @returns {{all:import('../view/record-view.js').ViewField[],metadata:import('../view/record-view.js').ViewField[]}}
941
+ */
942
+ _resolvedCardFields(): {
943
+ all: import('../view/record-view.js').ViewField[];
944
+ metadata: import('../view/record-view.js').ViewField[];
945
+ };
946
+ /**
947
+ * Returns the fields the shared metadata list may show. A field the card head or footer already
948
+ * projects is dropped, because repeating it as a labelled row is the same value twice; a field
949
+ * marked `duplicate` opts back in, matching how title and subtitle already behave.
950
+ * @returns {import('../view/record-view.js').ViewField[]} Metadata fields.
951
+ */
952
+ _cardMetadataFields(): import('../view/record-view.js').ViewField[];
953
+ /**
954
+ * Resolves the card-anatomy readers once per refresh. A field id would otherwise be looked up
955
+ * through `getFields()` — which clones every descriptor — once per source per card, so a board
956
+ * with six anatomy sources rebuilt the whole field array six times for every card it drew.
957
+ * @returns {void}
958
+ */
959
+ _resolveCardSources(): void;
960
+ /**
961
+ * Adds the two Kanban-owned regions that bracket the shared record-card anatomy: a head naming
962
+ * what the record is and how urgent it is, and a footer carrying completion and the people
963
+ * responsible. Each part is omitted when its option is unset, so a board that configures none of
964
+ * them renders exactly the card it rendered before.
965
+ * @param {HTMLElement} card Card element.
966
+ * @param {KanbanRecord} record Record.
967
+ * @param {number} index Display index.
968
+ * @returns {void}
969
+ */
970
+ _applyCardAnatomy(card: HTMLElement, record: KanbanRecord, index: number): void;
971
+ /**
972
+ * Resolves one indicator from an already-resolved reader. A reader may return a ready-made
973
+ * `Node`, which is adopted rather than described, so an application keeps full control.
974
+ * @param {((record:KanbanRecord,index:number)=>unknown)|null} source Resolved reader.
975
+ * @param {unknown} tones Value-to-tone map.
976
+ * @param {KanbanRecord} record Record.
977
+ * @param {number} index Display index.
978
+ * @returns {KanbanIndicator|Node|null} Indicator, node, or null.
979
+ */
980
+ _cardIndicator(source: ((record: KanbanRecord, index: number) => unknown) | null, tones: unknown, record: KanbanRecord, index: number): KanbanIndicator | Node | null;
981
+ /**
982
+ * Hands card content to `renderCard` while keeping the managed shell: the list item, its
983
+ * selection control, the action group, and the move handle are never given away, because they
984
+ * carry the drop, focus, and movement semantics the board is responsible for.
985
+ * @param {HTMLElement} card Card built from the shared anatomy.
986
+ * @param {KanbanCardContext} context Card context.
987
+ * @returns {void}
988
+ */
989
+ _applyCardContent(card: HTMLElement, context: KanbanCardContext): void;
990
+ /**
991
+ * Applies ordered card rules. The first match owns the marker tone; every match with a label adds
992
+ * a badge, and rule descriptions join the accessible description so the marker is never the only
993
+ * carrier of the meaning.
994
+ * @param {HTMLElement} card Card element.
995
+ * @param {KanbanRule[]} rules Matching rules.
996
+ * @returns {void}
997
+ */
998
+ _applyCardRules(card: HTMLElement, rules: KanbanRule[]): void;
999
+ /**
1000
+ * Composes one card's accessible description from its selection state and its rules, so that
1001
+ * refreshing selection cannot quietly drop what a rule contributed.
1002
+ * @param {HTMLElement} card Card element.
1003
+ * @param {unknown} id Record id.
1004
+ * @returns {void}
1005
+ */
1006
+ _applyCardDescription(card: HTMLElement, id: unknown): void;
1007
+ /** @param {string} text Board-level empty message. @returns {HTMLElement} */
1008
+ _emptyContent(text: string): HTMLElement;
1009
+ /** @returns {string} Per-column placeholder text, or an empty string for none. */
1010
+ _placeholderText(): string;
1011
+ /**
1012
+ * @param {number} count Visible records.
1013
+ * @param {number} total Records before search and filters.
1014
+ * @param {number|null} limit Applicable limit.
1015
+ * @returns {HTMLElement}
1016
+ */
1017
+ _countIndicator(count: number, total: number, limit: number | null): HTMLElement;
1018
+ /**
1019
+ * @param {number} count Visible records in this column and lane.
1020
+ * @param {number} total Records in this column and lane before search and filters.
1021
+ * @param {number} columnTotal Records across the whole column.
1022
+ * @param {number|null} limit Applicable limit.
1023
+ * @param {boolean} columnScoped Whether the limit counts the column rather than this lane.
1024
+ * @returns {HTMLElement}
1025
+ */
1026
+ _columnIndicator(count: number, total: number, columnTotal: number, limit: number | null, columnScoped: boolean): HTMLElement;
458
1027
  /** @returns {KanbanColumn[]} */
459
1028
  _rawColumns(): KanbanColumn[];
460
1029
  /** @returns {KanbanColumn[]} */
@@ -465,6 +1034,14 @@ export declare class KanbanView extends RecordView {
465
1034
  _resolvedSwimlanes(): KanbanSwimlane[];
466
1035
  /** @param {KanbanAccessor} accessor @param {KanbanRecord} record @param {number} index @returns {unknown} */
467
1036
  _readAxis(accessor: KanbanAccessor, record: KanbanRecord, index: number): unknown;
1037
+ /**
1038
+ * Resolves one field descriptor by id through a per-refresh index. `getFields()` rebuilds a Map
1039
+ * and clones every descriptor on each call, and a string column or lane accessor is read once
1040
+ * per record per column per lane — which made this the most expensive line in a board render.
1041
+ * @param {string} id Field id.
1042
+ * @returns {import('../view/record-view.js').ViewField|undefined} Descriptor, if any.
1043
+ */
1044
+ _axisField(id: string): import('../view/record-view.js').ViewField | undefined;
468
1045
  /** @param {string} column @param {string|null} lane @returns {{record:KanbanRecord,index:number}[]} */
469
1046
  _recordsIn(column: string, lane: string | null): {
470
1047
  record: KanbanRecord;
@@ -472,33 +1049,204 @@ export declare class KanbanView extends RecordView {
472
1049
  }[];
473
1050
  /** @param {unknown} id @returns {KanbanMovePoint|null} */
474
1051
  _recordLocation(id: unknown): KanbanMovePoint | null;
1052
+ /**
1053
+ * Recomputes which records survive the search and the filter predicate.
1054
+ * @returns {void}
1055
+ */
1056
+ _resolveVisibility(): void;
1057
+ /**
1058
+ * Resolves what a search looks at, once. `searchFields` names them explicitly; otherwise the
1059
+ * visible fields are searched, plus the title and subtitle sources — a card is findable by the
1060
+ * name it shows even when that field is hidden from the metadata list.
1061
+ * @returns {{fields:import('../view/record-view.js').ViewField[],readers:((record:KanbanRecord,index:number)=>unknown)[]}}
1062
+ */
1063
+ _searchSources(): {
1064
+ fields: import('../view/record-view.js').ViewField[];
1065
+ readers: ((record: KanbanRecord, index: number) => unknown)[];
1066
+ };
1067
+ /**
1068
+ * Builds the text one record is searched through. Field `render` output is deliberately ignored:
1069
+ * it may be a DOM node, and matching what a formatter produced rather than what the record holds
1070
+ * would make the same query behave differently in two views over the same data.
1071
+ * @param {KanbanRecord} record Record.
1072
+ * @param {number} index Display index.
1073
+ * @param {{fields:import('../view/record-view.js').ViewField[],readers:((record:KanbanRecord,index:number)=>unknown)[]}} sources Resolved sources.
1074
+ * @returns {string} Searchable text.
1075
+ */
1076
+ _searchableText(record: KanbanRecord, index: number, sources: {
1077
+ fields: import('../view/record-view.js').ViewField[];
1078
+ readers: ((record: KanbanRecord, index: number) => unknown)[];
1079
+ }): string;
1080
+ /**
1081
+ * Translates a position among rendered cards into a position among all records in one bucket.
1082
+ * @param {string} column Column id.
1083
+ * @param {string|null} lane Lane id.
1084
+ * @param {number} visibleIndex Position among visible cards.
1085
+ * @param {Set<unknown>} excluded Ids being moved, which the visible list already omits.
1086
+ * @returns {number} Absolute position.
1087
+ */
1088
+ _absoluteIndex(column: string, lane: string | null, visibleIndex: number, excluded: Set<unknown>): number;
475
1089
  /**
476
1090
  * @param {KanbanRecord} record @param {KanbanMovePoint} from @param {KanbanMovePoint} to
477
1091
  * @param {KanbanColumn} column @param {KanbanSwimlane|null} lane @returns {KanbanRecord|null}
478
1092
  */
479
1093
  _localMovedRecord(record: KanbanRecord, from: KanbanMovePoint, to: KanbanMovePoint, column: KanbanColumn, lane: KanbanSwimlane | null): KanbanRecord | null;
1094
+ /**
1095
+ * Runs transition, eligibility, and capacity policy for a whole move. Every distinct origin is
1096
+ * checked, so a multi-card move drawn from two columns cannot slip past a transition rule that
1097
+ * only the second origin violates.
1098
+ * @param {KanbanRecord[]} records Moving records.
1099
+ * @param {KanbanMovePoint[]} origins Their origins.
1100
+ * @param {KanbanColumn} column Destination column.
1101
+ * @param {KanbanSwimlane|null} lane Destination lane.
1102
+ * @param {KanbanMovePoint} to Destination point.
1103
+ * @param {KanbanMoveContext} context Predicate context.
1104
+ * @param {Set<unknown>} excluded Moving ids, excluded from destination counts.
1105
+ * @returns {KanbanMoveEvaluation} Decision.
1106
+ */
1107
+ _evaluateMove(records: KanbanRecord[], origins: KanbanMovePoint[], column: KanbanColumn, lane: KanbanSwimlane | null, to: KanbanMovePoint, context: KanbanMoveContext, excluded: Set<unknown>): KanbanMoveEvaluation;
1108
+ /**
1109
+ * Announces and reports a refused move. Nothing is written and no `recordmove` is emitted, so a
1110
+ * listener can neither observe nor undo a move that never happened.
1111
+ * @param {KanbanRejectReason} reason Refusal reason.
1112
+ * @param {{ids:unknown[],records:KanbanRecord[],from:KanbanMovePoint|null,to:KanbanMovePoint|null,column:KanbanColumn|null,swimlane:KanbanSwimlane|null,evaluation?:KanbanMoveEvaluation}} detail Context.
1113
+ * @returns {void}
1114
+ * @fires KanbanView#movereject
1115
+ */
1116
+ _rejectMove(reason: KanbanRejectReason, detail: {
1117
+ ids: unknown[];
1118
+ records: KanbanRecord[];
1119
+ from: KanbanMovePoint | null;
1120
+ to: KanbanMovePoint | null;
1121
+ column: KanbanColumn | null;
1122
+ swimlane: KanbanSwimlane | null;
1123
+ evaluation?: KanbanMoveEvaluation;
1124
+ }): void;
1125
+ /**
1126
+ * Installs a committed local record order, remembering the previous one for undo.
1127
+ * @param {KanbanRecord[]} records Next record order.
1128
+ * @returns {void}
1129
+ */
1130
+ _commitLocalRecords(records: KanbanRecord[]): void;
1131
+ /**
1132
+ * @param {'undo'|'redo'} direction Travel direction.
1133
+ * @returns {this}
1134
+ */
1135
+ _travelHistory(direction: 'undo' | 'redo'): this;
1136
+ /** Drops both stacks without announcing, for host-driven data replacement. @returns {void} */
1137
+ _resetHistory(): void;
1138
+ /** @returns {void} */
1139
+ _emitHistory(): void;
1140
+ /** @returns {void} */
1141
+ _syncHistoryControls(): void;
1142
+ /** @returns {HTMLElement} Built-in search control. */
1143
+ _createSearchControl(): HTMLElement;
1144
+ /** @returns {HTMLElement} Built-in history controls. */
1145
+ _createHistoryControls(): HTMLElement;
1146
+ /** Attaches the card context menu. @returns {void} */
1147
+ _createContextMenu(): void;
1148
+ /**
1149
+ * Builds the menu for one card: every destination the same policy path would accept, plus any
1150
+ * application items. Destinations the board would refuse are shown disabled rather than hidden,
1151
+ * so a rule is discoverable instead of silently removing a command.
1152
+ * @param {Element|null} context Card element the menu opened on.
1153
+ * @returns {(MenuItem|'-')[]} Menu entries.
1154
+ */
1155
+ _menuItems(context: Element | null): (MenuItem | '-')[];
1156
+ /**
1157
+ * @param {{value:unknown,item:MenuItem,context:Element|null}} detail Selection detail.
1158
+ * @returns {void}
1159
+ */
1160
+ _handleMenuSelect(detail: {
1161
+ value: unknown;
1162
+ item: MenuItem;
1163
+ context: Element | null;
1164
+ }): void;
1165
+ /**
1166
+ * Dry-runs the policy path for a destination without emitting or committing anything.
1167
+ * @param {unknown[]} ids Moving ids.
1168
+ * @param {KanbanDestination} destination Destination.
1169
+ * @returns {boolean} Whether the move would be allowed.
1170
+ */
1171
+ _canMove(ids: unknown[], destination: KanbanDestination): boolean;
1172
+ /**
1173
+ * Resolves the ids one gesture moves: the whole selection when the grabbed card belongs to it,
1174
+ * otherwise just that card. Picking up an unselected card never drags the selection along.
1175
+ * @param {unknown} id Grabbed record id.
1176
+ * @returns {unknown[]} Ids to move, in board order.
1177
+ */
1178
+ _movingIds(id: unknown): unknown[];
1179
+ /** @param {unknown[]} ids Requested ids. @returns {unknown[]} Existing ids in board order. */
1180
+ _orderedIds(ids: unknown[]): unknown[];
480
1181
  /** @param {MouseEvent} event @returns {void} */
481
1182
  _handleBoardClick(event: MouseEvent): void;
482
1183
  /** @param {MouseEvent} event @returns {void} */
483
1184
  _handleBoardDoubleClick(event: MouseEvent): void;
484
1185
  /** @param {KeyboardEvent} event @returns {void} */
485
1186
  _handleBoardKeydown(event: KeyboardEvent): void;
1187
+ /**
1188
+ * @param {KeyboardEvent} event Keyboard event.
1189
+ * @param {Element|null} target Event target.
1190
+ * @returns {boolean} Whether the event was handled as a history command.
1191
+ */
1192
+ _handleHistoryKeydown(event: KeyboardEvent, target: Element | null): boolean;
486
1193
  /** @param {KeyboardEvent} event @param {HTMLElement} handle @param {KanbanCardMeta} meta @returns {void} */
487
1194
  _handleMoveKeydown(event: KeyboardEvent, handle: HTMLElement, meta: KanbanCardMeta): void;
488
1195
  /** @param {Event} event @returns {void} */
489
1196
  _handlePreviewError(event: Event): void;
490
- /** @param {DragEvent} event @returns {void} */
491
- _handleDragStart(event: DragEvent): void;
492
- /** @param {DragEvent} event @returns {void} */
493
- _handleDragOver(event: DragEvent): void;
494
- /** @param {DragEvent} event @returns {void} */
495
- _handleDrop(event: DragEvent): void;
496
- /** @param {DragEvent} event @param {KanbanSectionMeta} section @returns {KanbanMovePoint} */
497
- _pointerDestination(event: DragEvent, section: KanbanSectionMeta): KanbanMovePoint;
1197
+ /**
1198
+ * Records a candidate drag. Nothing moves yet: a press that never travels stays a click, and a
1199
+ * touch on the card body stays a scroll until the long press elapses.
1200
+ * @param {PointerEvent} event Pointer event.
1201
+ * @returns {void}
1202
+ */
1203
+ _handlePointerDown(event: PointerEvent): void;
1204
+ /** @param {PointerEvent} event @returns {void} */
1205
+ _handlePointerMove(event: PointerEvent): void;
1206
+ /** @param {PointerEvent} event @returns {void} */
1207
+ _handlePointerUp(event: PointerEvent): void;
1208
+ /**
1209
+ * Starts a pointer drag: the floating preview appears, the board stops selecting text, and the
1210
+ * auto-scroll loop begins.
1211
+ * @param {number} x Pointer client x.
1212
+ * @param {number} y Pointer client y.
1213
+ * @returns {void}
1214
+ */
1215
+ _beginDrag(x: number, y: number): void;
1216
+ /** @returns {HTMLElement} Floating drag preview. */
1217
+ _createDragPreview(): HTMLElement;
1218
+ /** @returns {void} */
1219
+ _positionDragPreview(): void;
1220
+ /**
1221
+ * Resolves and marks the drop destination under the pointer. Pointer capture retargets events to
1222
+ * the board, so the element under the pointer is looked up rather than read off the event.
1223
+ * @param {number} x Pointer client x.
1224
+ * @param {number} y Pointer client y.
1225
+ * @returns {void}
1226
+ */
1227
+ _updateDropTarget(x: number, y: number): void;
1228
+ /** @returns {void} */
1229
+ _scheduleAutoScroll(): void;
1230
+ /** Scrolls the board horizontally and the hovered column vertically near their edges. @returns {void} */
1231
+ _autoScroll(): void;
1232
+ /**
1233
+ * Commits a move whose index came from rendered cards. Search and filters hide records without
1234
+ * removing them, so the visible position is translated back before anything is proposed.
1235
+ * @param {unknown[]} ids Moving ids.
1236
+ * @param {KanbanMovePoint} point Destination in visible-card space.
1237
+ * @returns {void}
1238
+ */
1239
+ _commitInteractionMove(ids: unknown[], point: KanbanMovePoint): void;
498
1240
  /** @returns {void} */
499
1241
  _clearDrag(): void;
500
1242
  /** @returns {void} */
501
1243
  _clearDropMarkers(): void;
1244
+ /** @param {HTMLElement} list Card list. @returns {HTMLElement[]} Cards excluding the ones in flight. */
1245
+ _draggableCards(list: HTMLElement): HTMLElement[];
1246
+ /** @param {string} column @param {string|null} lane @param {Set<unknown>} excluded @returns {number} */
1247
+ _visibleCount(column: string, lane: string | null, excluded: Set<unknown>): number;
1248
+ /** @param {unknown} id Record id. @returns {number} Position among visible cards in its bucket. */
1249
+ _visibleIndex(id: unknown): number;
502
1250
  /** @returns {void} */
503
1251
  _syncKeyboardTarget(): void;
504
1252
  /** @returns {void} */
@@ -507,10 +1255,39 @@ export declare class KanbanView extends RecordView {
507
1255
  _metaForTarget(target: EventTarget | null): KanbanCardMeta | null;
508
1256
  /** @param {unknown} id @returns {HTMLElement|null} */
509
1257
  _moveHandle(id: unknown): HTMLElement | null;
1258
+ /**
1259
+ * Resolves a collapse control after a board refresh, retaining the same lane copy for columns.
1260
+ * @param {'column'|'swimlane'} axis Collapse axis.
1261
+ * @param {string} id Descriptor id.
1262
+ * @param {string|null} [lane=null] Column copy's lane.
1263
+ * @returns {HTMLElement|null}
1264
+ */
1265
+ _collapseControl(axis: 'column' | 'swimlane', id: string, lane?: string | null): HTMLElement | null;
1266
+ /**
1267
+ * Runs one presentation hook, ignoring anything that is not a node so a hook cannot smuggle
1268
+ * markup in as a string.
1269
+ * @param {'renderCard'|'renderColumnHeader'|'renderSwimlaneHeader'|'renderColumnEmpty'|'renderDragPreview'} name Hook name.
1270
+ * @param {any} context Hook context.
1271
+ * @returns {Node|null} Node to adopt, or null for the default presentation.
1272
+ */
1273
+ _renderHook(name: 'renderCard' | 'renderColumnHeader' | 'renderSwimlaneHeader' | 'renderColumnEmpty' | 'renderDragPreview', context: any): Node | null;
1274
+ /** @param {KanbanColumn} column @param {KanbanSwimlane|null} lane @returns {boolean} */
1275
+ _allowsAdd(column: KanbanColumn, lane: KanbanSwimlane | null): boolean;
510
1276
  /** @param {KanbanRecord} record @param {number} index @returns {string} */
511
1277
  _recordName(record: KanbanRecord, index: number): string;
1278
+ /** @param {KanbanRecord[]} records Moving records. @returns {string} */
1279
+ _movingName(records: KanbanRecord[]): string;
512
1280
  /** @param {KanbanMovePoint} point @returns {string} */
513
1281
  _targetName(point: KanbanMovePoint): string;
1282
+ /** @param {KanbanMoveEvaluation} evaluation Capacity report. @returns {string} */
1283
+ _wipAnnouncement(evaluation: KanbanMoveEvaluation): string;
1284
+ /**
1285
+ * Resolves one localizable string.
1286
+ * @param {keyof typeof DEFAULT_LABELS|string} key Label key.
1287
+ * @param {Record<string, unknown>} [args] Placeholder values.
1288
+ * @returns {string} Resolved text.
1289
+ */
1290
+ _text(key: keyof typeof DEFAULT_LABELS | string, args?: Record<string, unknown>): string;
514
1291
  /** @param {string} message @returns {void} */
515
1292
  _announce(message: string): void;
516
1293
  /** @param {string} reason @returns {void} */
@@ -542,8 +1319,20 @@ export declare function reconcileKanbanOrder(descriptors: {
542
1319
  id: string;
543
1320
  }[], order: unknown): string[];
544
1321
  /**
545
- * Reorders records around an already-cloned moved record. The input array and every input record
546
- * remain untouched; destination index is relative to records in that one column/lane.
1322
+ * Reconciles the visible descriptor order while optionally retaining preferences for derived axes
1323
+ * that are absent from the current result set. This lets saved state be applied before an async
1324
+ * query supplies the records from which columns or lanes are derived.
1325
+ * @param {{id:string}[]} descriptors Available descriptors.
1326
+ * @param {unknown} order Preferred order.
1327
+ * @param {boolean} [preserveUnknown=false] Retain temporarily unavailable ids.
1328
+ * @returns {string[]}
1329
+ */
1330
+ export declare function reconcileKanbanPreference(descriptors: {
1331
+ id: string;
1332
+ }[], order: unknown, preserveUnknown?: boolean): string[];
1333
+ /**
1334
+ * Reorders records around one already-cloned moved record. Retained as the single-record form of
1335
+ * `reorderKanbanRecords`; the input array and every input record remain untouched.
547
1336
  * @param {KanbanRecord[]} records Records.
548
1337
  * @param {unknown} id Moving record id.
549
1338
  * @param {KanbanRecord} movedRecord Cloned record carrying its destination axis values.
@@ -560,13 +1349,35 @@ export declare function reorderKanbanData(records: KanbanRecord[], id: unknown,
560
1349
  from: KanbanMovePoint;
561
1350
  to: KanbanMovePoint;
562
1351
  } | null;
1352
+ export {};
563
1353
  /**
564
- * Record movement event emitted before a local commit or external request.
1354
+ * Record movement event emitted before a local commit or external request. `record`, `id`, and
1355
+ * `from` describe the primary record; `records`, `ids`, and `moves` describe the whole atomic move.
565
1356
  * @event KanbanView#recordmove
566
- * @type {CustomEvent<{record:KanbanRecord,id:unknown,from:KanbanMovePoint,to:KanbanMovePoint,column:KanbanColumn,swimlane:KanbanSwimlane|null,limitExceeded:boolean}>}
1357
+ * @type {CustomEvent<{record:KanbanRecord,id:unknown,records:KanbanRecord[],ids:unknown[],moves:{id:unknown,from:KanbanMovePoint}[],from:KanbanMovePoint,to:KanbanMovePoint,column:KanbanColumn,swimlane:KanbanSwimlane|null,limitExceeded:boolean}>}
1358
+ */
1359
+ /**
1360
+ * Refused movement event. Nothing was written and no `recordmove` was emitted.
1361
+ * @event KanbanView#movereject
1362
+ * @type {CustomEvent<{reason:KanbanRejectReason,ids:unknown[],records:KanbanRecord[],from:KanbanMovePoint|null,to:KanbanMovePoint|null,column:KanbanColumn|null,swimlane:KanbanSwimlane|null,limit:number|null,count:number,message:string}>}
567
1363
  */
568
1364
  /**
569
1365
  * Secondary card action event.
570
1366
  * @event KanbanView#recordaction
571
1367
  * @type {CustomEvent<{record:KanbanRecord,id:unknown,action:unknown,actionId:string|undefined,event:Event}>}
572
1368
  */
1369
+ /**
1370
+ * Request to create a record in one column and lane. The board never creates records itself.
1371
+ * @event KanbanView#recordadd
1372
+ * @type {CustomEvent<{column:KanbanColumn|null,swimlane:KanbanSwimlane|null,columnId:string,laneId:string|null,event:Event}>}
1373
+ */
1374
+ /**
1375
+ * Board search change from the built-in control.
1376
+ * @event KanbanView#searchchange
1377
+ * @type {CustomEvent<{search:string}>}
1378
+ */
1379
+ /**
1380
+ * Undo and redo availability after a committed, reverted, or discarded local move.
1381
+ * @event KanbanView#historychange
1382
+ * @type {CustomEvent<{canUndo:boolean,canRedo:boolean,depth:{undo:number,redo:number}}>}
1383
+ */