@zeyos/zx 4.3.0 → 4.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +111 -1
- package/README.md +0 -3
- package/dist/types/components/calendar/calendar-model.d.ts +22 -0
- package/dist/types/components/card-view/card-view.d.ts +1 -1
- package/dist/types/components/card-view/record-card.d.ts +47 -5
- package/dist/types/components/kanban-view/kanban-policy.d.ts +268 -0
- package/dist/types/components/kanban-view/kanban-view.d.ts +669 -24
- package/dist/types/core/component.d.ts +6 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/zx-zeyos.esm.js +35 -11
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +597 -78
- package/dist/zx.esm.js +1758 -238
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +1758 -238
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +214 -2
- package/docs/llms.md +30 -30
- package/docs/llms.txt +0 -2
- package/package.json +1 -2
- package/src/components/calendar/calendar-model.js +45 -0
- package/src/components/calendar/calendar.css +30 -10
- package/src/components/calendar/calendar.js +8 -10
- package/src/components/card-view/card-view.css +211 -9
- package/src/components/card-view/card-view.js +7 -7
- package/src/components/card-view/record-card.js +92 -19
- package/src/components/kanban-view/kanban-policy.js +412 -0
- package/src/components/kanban-view/kanban-view.css +480 -36
- package/src/components/kanban-view/kanban-view.js +1514 -235
- package/src/components/message/message.css +9 -10
- package/src/core/component.js +8 -3
- package/src/index.js +8 -3
- package/DESIGN-SYSTEM.md +0 -182
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,116 @@ and friends remain the complete record.
|
|
|
8
8
|
|
|
9
9
|
## Unreleased
|
|
10
10
|
|
|
11
|
+
## 4.3.4 — 2026-08-31
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Kanban boards became workflow boards.** `KanbanView` now moves cards by pointer, touch,
|
|
16
|
+
keyboard, context menu, and public API through one policy and one commit path.
|
|
17
|
+
- **Pointer and touch dragging.** Native HTML5 drag-and-drop is replaced by Pointer Events, so
|
|
18
|
+
the same code path serves mouse, pen, and touch. A drag from the card body needs a small
|
|
19
|
+
travel (or a long press on touch, so the board still scrolls); a drag from the move handle
|
|
20
|
+
starts immediately. A floating drag preview follows the pointer, the board and any scrollable
|
|
21
|
+
column auto-scroll near their edges, and Escape aborts without moving anything.
|
|
22
|
+
`dragFrom: 'card' | 'handle'` chooses the drag source.
|
|
23
|
+
- **Atomic multi-card moves.** Picking up a card that belongs to the current multi-selection
|
|
24
|
+
moves the whole selection as one step, preserving relative order — one `recordmove`, one
|
|
25
|
+
policy decision, one history entry. `moveRecords(ids, destination)` is the public form.
|
|
26
|
+
- **Enforceable workflow policy.** Columns gain `laneLimits`, `wipPolicy`, and a `from`
|
|
27
|
+
transition allow-list; lanes gain `limit` and `from`. The board-level `wipPolicy` still
|
|
28
|
+
defaults to `'warn'`, and `'block'` refuses a move before the cancelable event. Every refusal
|
|
29
|
+
announces its reason and emits the new cancel-free `movereject` event.
|
|
30
|
+
- **Ordered card rules.** `rules` marks cards with an inline tone marker, badges, and an
|
|
31
|
+
accessible description, so a rule is never communicated by colour alone.
|
|
32
|
+
- **Undo and redo** of committed local moves, with `undo()`, `redo()`, `canUndo()`, `canRedo()`,
|
|
33
|
+
`clearHistory()`, a bounded `historyLimit`, the `historychange` event, optional toolbar
|
|
34
|
+
controls, and Ctrl/Cmd+Z and Ctrl/Cmd+Shift+Z on the board.
|
|
35
|
+
- **Board search and filtering.** `search`, `searchFields`, `filter`, `setSearch`, `setFilter`,
|
|
36
|
+
an optional built-in search control, and the `searchchange` event. Hidden records keep their
|
|
37
|
+
position in the data, so a card dropped between two visible cards lands between them.
|
|
38
|
+
- **Replaceable presentation.** `renderCard`, `renderColumnHeader`, `renderSwimlaneHeader`,
|
|
39
|
+
`renderColumnEmpty`, and `renderDragPreview` replace content while the board keeps the managed
|
|
40
|
+
shell: list item, selection control, action group, move handle, drop targets, and collapse
|
|
41
|
+
control never change hands.
|
|
42
|
+
- **Card context menu, per-column scroll regions, and an add affordance.** `contextMenu` offers
|
|
43
|
+
move commands filtered by the same policy path, `columnHeight` turns each column into its own
|
|
44
|
+
scroll region, and `allowAdd` emits `recordadd` for the application to act on.
|
|
45
|
+
- **A complete `labels` map**, so every visible and announced string can be translated without
|
|
46
|
+
patching the component.
|
|
47
|
+
|
|
48
|
+
## 4.3.3 — 2026-08-26
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- **Kanban boards use a lighter rail hierarchy.** The board and columns no longer stack filled,
|
|
53
|
+
bordered panels around every lane. Compact headers, quiet semantic WIP counts, wider rail gaps,
|
|
54
|
+
and restrained card radii make record cards the primary surfaces while preserving horizontal
|
|
55
|
+
scrolling, empty drop targets, swim lanes, and every existing interaction.
|
|
56
|
+
- **Calendar grids use square structural edges.** The outer calendar, day headings, and time slots
|
|
57
|
+
align as one continuous grid, while the view picker becomes a compact segmented control with a
|
|
58
|
+
raised active view.
|
|
59
|
+
- **Floating messages keep severity visible on glass.** Toasts use a coloured leading inset over
|
|
60
|
+
the shared overlay material and retain deterministic severity backgrounds when transparency is
|
|
61
|
+
reduced or unsupported.
|
|
62
|
+
- The public landing page and Theme Studio no longer duplicate documentation search in their
|
|
63
|
+
headers. Dated 4.3 promotional sections were removed from the landing page and documentation
|
|
64
|
+
introduction, and the landing hero typography was rebalanced around the simplified header.
|
|
65
|
+
|
|
66
|
+
## 4.3.2 — 2026-08-26
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- **Shared card field slots.** A visible field may opt into the shared record-card anatomy with
|
|
71
|
+
`view.card.slot: 'eyebrow-start' | 'eyebrow-end' | 'title-prefix'`, producing a semantic eyebrow
|
|
72
|
+
row or labelled content immediately before — but outside — the title heading and primary link.
|
|
73
|
+
Absent, malformed, and unknown slots fall back to ordinary labelled metadata, and field
|
|
74
|
+
visibility and order remain authoritative.
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
- **CardView and KanbanView read as collections, not documents.** CardView clamps titles to two
|
|
79
|
+
lines, keeps previews at thumbnail scale, and renders visible fields as compact metadata chips.
|
|
80
|
+
Kanban columns use a stable 20rem rail with native horizontal overflow, compact headings and
|
|
81
|
+
counts, tighter card padding, an optional square thumbnail, and move/action controls that reveal
|
|
82
|
+
on hover, focus, selection, or grab while staying visible on touch. Both views keep the same
|
|
83
|
+
markup, semantics, and delegated interaction hooks.
|
|
84
|
+
- The landing page hero is lit by the shipped `Aurora` component rather than a bespoke gradient,
|
|
85
|
+
and gains a "Latest release" band covering Calendar, the record views, Aurora, Sheet and Dock,
|
|
86
|
+
the glass materials, and application identity.
|
|
87
|
+
- The documentation Introduction gains a "New in 4.3" section linking the newest component pages.
|
|
88
|
+
Aurora stays documented through its supported component examples and API reference; the
|
|
89
|
+
standalone showcase route is no longer part of the public site.
|
|
90
|
+
- The landing page now carries documentation search, restores the ZeyOS copyright identity in the
|
|
91
|
+
shared footer, and transitions its initially transparent navigation to the established glass
|
|
92
|
+
material after scrolling, with reduced-motion and reduced-transparency fallbacks.
|
|
93
|
+
- Public site and package assembly now exclude non-product contributor material and design audits,
|
|
94
|
+
with release checks that reject private paths in deployable output.
|
|
95
|
+
|
|
96
|
+
### Fixed
|
|
97
|
+
|
|
98
|
+
- **Calendar month and year paging no longer overflows a month-end anchor.** From 31 January,
|
|
99
|
+
`next()` reached 3 March and skipped February entirely; from 31 March, `prev()` landed back
|
|
100
|
+
inside March, so the button appeared dead. Both steps now clamp the day of month into the target
|
|
101
|
+
month via the new `calendarPageDate()` / `addCalendarMonths()` model helpers.
|
|
102
|
+
- `Calendar.updateEvent()` honours the configured `dateUnit` again. It normalized without it, so a
|
|
103
|
+
numeric `start`/`end` change was read as milliseconds on a calendar configured for Unix seconds.
|
|
104
|
+
- The Calendar toolbar no longer overlaps itself. The end-justified view/new controls kept their
|
|
105
|
+
min-content width inside a narrower `1fr` track and bled back over the centred heading, hiding
|
|
106
|
+
the first view button; the heading is now the only elastic track and ellipsizes instead.
|
|
107
|
+
- Kanban announces a reached or exceeded work-in-progress limit with the move it belongs to, and
|
|
108
|
+
keeps focus on a collapse control across a board refresh — including when a programmatic
|
|
109
|
+
collapse hides the card that had focus.
|
|
110
|
+
- Kanban preserves saved order and collapse preferences for data-derived columns and swim lanes
|
|
111
|
+
when state is restored before asynchronous records arrive. Canceling the bubbling
|
|
112
|
+
`zx-recordmove` event now vetoes the move, and a manual local move clears a conflicting local
|
|
113
|
+
sort so serialized state matches visible order.
|
|
114
|
+
- Selectable record cards retain valid list-item semantics with a global selection description,
|
|
115
|
+
and preview media no longer accepts local `file:` URLs.
|
|
116
|
+
- The four system-architecture cards on the landing page align their links again, and ~60 lines of
|
|
117
|
+
dead `.release-band`/`.release-notes` site CSS with no remaining markup were removed.
|
|
118
|
+
- Documentation search no longer collides with primary navigation: responsive headers move the
|
|
119
|
+
centered field to its own row before their chrome can overlap.
|
|
120
|
+
|
|
11
121
|
## 4.3.0 — 2026-08-26
|
|
12
122
|
|
|
13
123
|
### Added
|
|
@@ -67,7 +177,7 @@ and friends remain the complete record.
|
|
|
67
177
|
- **Aurora surfaces.** `Aurora` adds a dependency-free, one- to four-colour ambient-light layer
|
|
68
178
|
with six geometries, bounded palettes and intensity, CSS-only composition, and deterministic
|
|
69
179
|
reduced-motion, reduced-transparency, and forced-colour fallbacks. The documentation includes a
|
|
70
|
-
live application composition and
|
|
180
|
+
live application composition and examples for all six supported geometries.
|
|
71
181
|
|
|
72
182
|
### Changed
|
|
73
183
|
|
package/README.md
CHANGED
|
@@ -6,9 +6,6 @@ and application layouts in plain ES2022 modules. Source modules run directly in
|
|
|
6
6
|
distribution also provides ESM and classic-script bundles. Xenon originated at ZeyOS, while its
|
|
7
7
|
components and contracts remain product- and framework-agnostic.
|
|
8
8
|
|
|
9
|
-
The [design-system audit](./DESIGN-SYSTEM.md) records current ZeyOS coverage, missing shell
|
|
10
|
-
patterns, the adoption boundary, transaction-grid follow-ups, and chart-engine candidates.
|
|
11
|
-
|
|
12
9
|
## Quick start
|
|
13
10
|
|
|
14
11
|
Use the ESM bundle when the application already uses modules:
|
|
@@ -128,6 +128,28 @@ export declare function calendarRange(view: CalendarView, anchor: Date, options?
|
|
|
128
128
|
start: Date;
|
|
129
129
|
end: Date;
|
|
130
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Returns the anchor date one visible period away from `anchor`.
|
|
133
|
+
*
|
|
134
|
+
* Month and year steps clamp the day of month into the target month instead of letting it
|
|
135
|
+
* overflow: `setMonth()` alone turns 31 January into 3 March, which makes February unreachable
|
|
136
|
+
* from a month-end anchor and leaves `prev()` on 31 March landing back inside March.
|
|
137
|
+
* @param {CalendarView} view Current view.
|
|
138
|
+
* @param {Date} anchor Current anchor date.
|
|
139
|
+
* @param {number} direction -1 for the previous period, 1 for the next.
|
|
140
|
+
* @param {{agendaDays?: number}} [options={}] Paging options.
|
|
141
|
+
* @returns {Date}
|
|
142
|
+
*/
|
|
143
|
+
export declare function calendarPageDate(view: CalendarView, anchor: Date, direction: number, options?: {
|
|
144
|
+
agendaDays?: number;
|
|
145
|
+
}): Date;
|
|
146
|
+
/**
|
|
147
|
+
* Adds whole months, clamping the day of month to the last day the target month actually has.
|
|
148
|
+
* @param {Date} value Local date.
|
|
149
|
+
* @param {number} months Months to add.
|
|
150
|
+
* @returns {Date}
|
|
151
|
+
*/
|
|
152
|
+
export declare function addCalendarMonths(value: Date, months: number): Date;
|
|
131
153
|
/**
|
|
132
154
|
* Normalizes caller records atomically into the Calendar event contract.
|
|
133
155
|
* @param {Record<string, any>[]} records Source records.
|
|
@@ -190,7 +190,7 @@ export type CardRecordGroup = {
|
|
|
190
190
|
* @property {string|((record:ViewRecord,index:number)=>unknown)|null} [groupBy=null]
|
|
191
191
|
* Field id or local group resolver.
|
|
192
192
|
* @property {unknown[]} [groupOrder=[]] Preferred group ids; missing ids render as empty groups.
|
|
193
|
-
* @property {number|string} [minCardWidth='
|
|
193
|
+
* @property {number|string} [minCardWidth='15rem'] Responsive minimum card width.
|
|
194
194
|
* @property {number|null} [maxColumns=null] Maximum cards per row; null is unconstrained.
|
|
195
195
|
* @property {'outlined'|'raised'|'filled'} [variant='outlined'] Card surface treatment.
|
|
196
196
|
* @property {number} [loadingCount=6] Skeleton cards shown while loading.
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
export type ViewRecord = Record<string, any>;
|
|
2
2
|
export type ViewField = import('../view/record-view.js').ViewField;
|
|
3
3
|
export type RecordCardValueSource = string | ((record: ViewRecord, index: number) => unknown) | null;
|
|
4
|
+
export type RecordCardFieldSlot = 'eyebrow-start' | 'eyebrow-end' | 'title-prefix';
|
|
5
|
+
export type RecordCardFieldGroups = {
|
|
6
|
+
/**
|
|
7
|
+
* Fields shown at the logical start of the eyebrow row.
|
|
8
|
+
*/
|
|
9
|
+
eyebrowStart: ViewField[];
|
|
10
|
+
/**
|
|
11
|
+
* Fields shown at the logical end of the eyebrow row.
|
|
12
|
+
*/
|
|
13
|
+
eyebrowEnd: ViewField[];
|
|
14
|
+
/**
|
|
15
|
+
* Fields shown immediately before, but outside, the heading.
|
|
16
|
+
*/
|
|
17
|
+
titlePrefix: ViewField[];
|
|
18
|
+
/**
|
|
19
|
+
* Remaining labelled metadata fields.
|
|
20
|
+
*/
|
|
21
|
+
metadata: ViewField[];
|
|
22
|
+
};
|
|
4
23
|
export type RecordCardPreviewDescriptor = {
|
|
5
24
|
/**
|
|
6
25
|
* Image URL.
|
|
@@ -142,6 +161,14 @@ export type ResolvedRecordPreview = {
|
|
|
142
161
|
/** @typedef {Record<string, any>} ViewRecord */
|
|
143
162
|
/** @typedef {import('../view/record-view.js').ViewField} ViewField */
|
|
144
163
|
/** @typedef {string|((record:ViewRecord,index:number)=>unknown)|null} RecordCardValueSource */
|
|
164
|
+
/** @typedef {'eyebrow-start'|'eyebrow-end'|'title-prefix'} RecordCardFieldSlot */
|
|
165
|
+
/**
|
|
166
|
+
* @typedef {Object} RecordCardFieldGroups
|
|
167
|
+
* @property {ViewField[]} eyebrowStart Fields shown at the logical start of the eyebrow row.
|
|
168
|
+
* @property {ViewField[]} eyebrowEnd Fields shown at the logical end of the eyebrow row.
|
|
169
|
+
* @property {ViewField[]} titlePrefix Fields shown immediately before, but outside, the heading.
|
|
170
|
+
* @property {ViewField[]} metadata Remaining labelled metadata fields.
|
|
171
|
+
*/
|
|
145
172
|
/**
|
|
146
173
|
* @typedef {Object} RecordCardPreviewDescriptor
|
|
147
174
|
* @property {string} src Image URL.
|
|
@@ -200,11 +227,12 @@ export type ResolvedRecordPreview = {
|
|
|
200
227
|
* becomes text, URLs are normalized before reaching native attributes, and actions expose stable
|
|
201
228
|
* data attributes for a component-owned delegated listener.
|
|
202
229
|
*
|
|
203
|
-
* The returned `<li>` belongs in a semantic `<ul>`/`<ol>`. When selectable
|
|
204
|
-
* `aria-
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
230
|
+
* The returned `<li>` belongs in a semantic `<ul>`/`<ol>`. When selectable its global
|
|
231
|
+
* `aria-description` announces selection without applying the unsupported `aria-selected` state
|
|
232
|
+
* to a listitem; multi-selection also adds a native checkbox. It deliberately remains a listitem
|
|
233
|
+
* rather than becoming an ARIA option because cards may contain native links and buttons, which
|
|
234
|
+
* the listbox pattern does not permit inside an option. Preview images are paired with a stable
|
|
235
|
+
* fallback. The owning component listens for image `error` and marks the fallback.
|
|
208
236
|
*
|
|
209
237
|
* @param {ViewRecord} record Record to render.
|
|
210
238
|
* @param {number} index Current display index.
|
|
@@ -212,6 +240,20 @@ export type ResolvedRecordPreview = {
|
|
|
212
240
|
* @returns {HTMLLIElement} Semantic record card list item.
|
|
213
241
|
*/
|
|
214
242
|
export declare function createRecordCard(record: ViewRecord, index: number, options?: RecordCardOptions): HTMLLIElement;
|
|
243
|
+
/**
|
|
244
|
+
* Partitions ordered visible fields into the shared record-card slots. A recognized
|
|
245
|
+
* `field.view.card.slot` moves the field to that semantic region; absent or unknown values remain
|
|
246
|
+
* ordinary metadata. Title and subtitle fields retain the existing no-duplication rule.
|
|
247
|
+
*
|
|
248
|
+
* The input array and descriptors are never mutated. Each field appears in at most one result
|
|
249
|
+
* array, and the order within every result follows the supplied visible-field order.
|
|
250
|
+
*
|
|
251
|
+
* @param {ViewField[]} fields Ordered visible fields.
|
|
252
|
+
* @param {RecordCardValueSource} [titleSource=null] Active title field or resolver.
|
|
253
|
+
* @param {RecordCardValueSource} [subtitleSource=null] Active subtitle field or resolver.
|
|
254
|
+
* @returns {RecordCardFieldGroups} Partitioned fields.
|
|
255
|
+
*/
|
|
256
|
+
export declare function partitionRecordCardFields(fields: ViewField[], titleSource?: RecordCardValueSource, subtitleSource?: RecordCardValueSource): RecordCardFieldGroups;
|
|
215
257
|
/**
|
|
216
258
|
* Resolves a preview without touching the DOM. Unsafe, malformed, and non-image URL schemes are
|
|
217
259
|
* rejected into the same descriptor shape so callers can still render the stable fallback.
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
export type KanbanRecord = Record<string, any>;
|
|
2
|
+
export type KanbanColumn = import('./kanban-view.js').KanbanColumn;
|
|
3
|
+
export type KanbanSwimlane = import('./kanban-view.js').KanbanSwimlane;
|
|
4
|
+
export type KanbanMovePoint = import('./kanban-view.js').KanbanMovePoint;
|
|
5
|
+
export type KanbanAccessor = import('./kanban-view.js').KanbanAccessor;
|
|
6
|
+
export type KanbanRule = {
|
|
7
|
+
/**
|
|
8
|
+
* Stable rule id, written to the card's `data-rule` list.
|
|
9
|
+
*/
|
|
10
|
+
id: string;
|
|
11
|
+
/**
|
|
12
|
+
* Predicate deciding whether the rule applies to one record.
|
|
13
|
+
*/
|
|
14
|
+
when: (record: KanbanRecord, context: {
|
|
15
|
+
index: number;
|
|
16
|
+
column: string;
|
|
17
|
+
lane: string | null;
|
|
18
|
+
}) => boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Visual intent.
|
|
21
|
+
* The first matching rule paints the card marker; later matches only contribute badges.
|
|
22
|
+
*/
|
|
23
|
+
tone?: 'neutral' | 'accent' | 'success' | 'warning' | 'danger' | 'info';
|
|
24
|
+
/**
|
|
25
|
+
* Badge text. A rule without a label is marker-only.
|
|
26
|
+
*/
|
|
27
|
+
label?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Optional badge icon name.
|
|
30
|
+
*/
|
|
31
|
+
icon?: string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Text joined into the card's accessible description so a
|
|
34
|
+
* rule is never communicated by colour alone.
|
|
35
|
+
*/
|
|
36
|
+
description?: string;
|
|
37
|
+
};
|
|
38
|
+
export type KanbanMoveEvaluation = {
|
|
39
|
+
/**
|
|
40
|
+
* Whether the move may proceed to the cancelable event.
|
|
41
|
+
*/
|
|
42
|
+
allowed: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Refusal reason, or null when allowed.
|
|
45
|
+
*/
|
|
46
|
+
reason: KanbanRejectReason | null;
|
|
47
|
+
/**
|
|
48
|
+
* The limit the destination count was measured against.
|
|
49
|
+
*/
|
|
50
|
+
limit: number | null;
|
|
51
|
+
/**
|
|
52
|
+
* Resulting record count in the constrained scope.
|
|
53
|
+
*/
|
|
54
|
+
count: number;
|
|
55
|
+
/**
|
|
56
|
+
* Whether an applicable limit would be exceeded.
|
|
57
|
+
*/
|
|
58
|
+
limitExceeded: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Whether an applicable limit would be met exactly.
|
|
61
|
+
*/
|
|
62
|
+
limitReached: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Effective work-in-progress policy.
|
|
65
|
+
*/
|
|
66
|
+
policy: 'warn' | 'block';
|
|
67
|
+
};
|
|
68
|
+
export type KanbanRejectReason = 'accept' | 'transition' | 'wip' | 'lane-accept' | 'lane-transition' | 'lane-wip' | 'destination' | 'grouping';
|
|
69
|
+
export type KanbanHistoryEntry = {
|
|
70
|
+
/**
|
|
71
|
+
* Record order before or after one committed move.
|
|
72
|
+
*/
|
|
73
|
+
records: KanbanRecord[];
|
|
74
|
+
/**
|
|
75
|
+
* Selected record ids at that moment.
|
|
76
|
+
*/
|
|
77
|
+
selection: unknown[];
|
|
78
|
+
/**
|
|
79
|
+
* Human-readable description of the step.
|
|
80
|
+
*/
|
|
81
|
+
label?: string;
|
|
82
|
+
};
|
|
83
|
+
export type KanbanHistory = {
|
|
84
|
+
/**
|
|
85
|
+
* Records a step and drops the redo stack.
|
|
86
|
+
*/
|
|
87
|
+
push: (entry: KanbanHistoryEntry) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Steps back.
|
|
90
|
+
*/
|
|
91
|
+
undo: (current: KanbanHistoryEntry) => KanbanHistoryEntry | null;
|
|
92
|
+
/**
|
|
93
|
+
* Steps forward.
|
|
94
|
+
*/
|
|
95
|
+
redo: (current: KanbanHistoryEntry) => KanbanHistoryEntry | null;
|
|
96
|
+
/**
|
|
97
|
+
* Whether a step back exists.
|
|
98
|
+
*/
|
|
99
|
+
canUndo: () => boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Whether a step forward exists.
|
|
102
|
+
*/
|
|
103
|
+
canRedo: () => boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Empties both stacks.
|
|
106
|
+
*/
|
|
107
|
+
clear: () => void;
|
|
108
|
+
/**
|
|
109
|
+
* Current stack depths.
|
|
110
|
+
*/
|
|
111
|
+
depth: () => {
|
|
112
|
+
undo: number;
|
|
113
|
+
redo: number;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Validates and clones ordered card rules. Rules are pure presentation: they never change a
|
|
118
|
+
* record, a move, or a policy decision.
|
|
119
|
+
* @param {unknown} rules Configured rules.
|
|
120
|
+
* @returns {KanbanRule[]} Normalized rules.
|
|
121
|
+
*/
|
|
122
|
+
export declare function normalizeKanbanRules(rules: unknown): KanbanRule[];
|
|
123
|
+
/**
|
|
124
|
+
* Returns the rules matching one record, in configured order. A predicate that throws is treated
|
|
125
|
+
* as "does not apply" so one broken rule cannot take the board down.
|
|
126
|
+
* @param {KanbanRule[]} rules Normalized rules.
|
|
127
|
+
* @param {KanbanRecord} record Record.
|
|
128
|
+
* @param {{index:number,column:string,lane:string|null}} context Position context.
|
|
129
|
+
* @returns {KanbanRule[]} Matching rules.
|
|
130
|
+
*/
|
|
131
|
+
export declare function resolveKanbanRules(rules: KanbanRule[], record: KanbanRecord, context: {
|
|
132
|
+
index: number;
|
|
133
|
+
column: string;
|
|
134
|
+
lane: string | null;
|
|
135
|
+
}): KanbanRule[];
|
|
136
|
+
/**
|
|
137
|
+
* Decides whether a proposed move may proceed, and reports the work-in-progress consequence either
|
|
138
|
+
* way. Checks run in a fixed order — transition, eligibility, then capacity — so a refusal always
|
|
139
|
+
* names the first constraint the move violates rather than an arbitrary one.
|
|
140
|
+
*
|
|
141
|
+
* Counts exclude the moving records, so a reorder inside one column is measured against the column
|
|
142
|
+
* it is already in rather than being told it doubles the load.
|
|
143
|
+
*
|
|
144
|
+
* @param {Object} input Evaluation input.
|
|
145
|
+
* @param {KanbanRecord[]} input.records Records being moved together.
|
|
146
|
+
* @param {KanbanColumn} input.column Destination column descriptor.
|
|
147
|
+
* @param {KanbanSwimlane|null} input.swimlane Destination lane descriptor, or null.
|
|
148
|
+
* @param {import('./kanban-view.js').KanbanMoveContext} input.context Context passed to `accept`.
|
|
149
|
+
* @param {KanbanMovePoint} input.from Origin of the primary record.
|
|
150
|
+
* @param {number} input.columnCount Records already in the destination column, movers excluded.
|
|
151
|
+
* @param {number} input.laneCount Records already in the destination lane, movers excluded.
|
|
152
|
+
* @param {number} input.cellCount Records already in the destination column and lane, movers excluded.
|
|
153
|
+
* @param {'warn'|'block'} [input.policy='warn'] Board work-in-progress policy.
|
|
154
|
+
* @returns {KanbanMoveEvaluation} Decision and capacity report.
|
|
155
|
+
*/
|
|
156
|
+
export declare function evaluateKanbanMove(input: {
|
|
157
|
+
records: KanbanRecord[];
|
|
158
|
+
column: KanbanColumn;
|
|
159
|
+
swimlane: KanbanSwimlane | null;
|
|
160
|
+
context: import('./kanban-view.js').KanbanMoveContext;
|
|
161
|
+
from: KanbanMovePoint;
|
|
162
|
+
columnCount: number;
|
|
163
|
+
laneCount: number;
|
|
164
|
+
cellCount: number;
|
|
165
|
+
policy?: 'warn' | 'block';
|
|
166
|
+
}): KanbanMoveEvaluation;
|
|
167
|
+
/**
|
|
168
|
+
* Reports which transition allow-list, if any, refuses one origin. A move that stays on an axis is
|
|
169
|
+
* never judged by that axis's rule: reordering inside a column is not a transition into it.
|
|
170
|
+
* @param {KanbanColumn} column Destination column.
|
|
171
|
+
* @param {KanbanSwimlane|null} swimlane Destination lane, or null.
|
|
172
|
+
* @param {KanbanMovePoint} from Origin.
|
|
173
|
+
* @returns {'transition'|'lane-transition'|null} Refusing rule, or null when the origin is admitted.
|
|
174
|
+
*/
|
|
175
|
+
export declare function allowsKanbanTransition(column: KanbanColumn, swimlane: KanbanSwimlane | null, from: KanbanMovePoint): 'transition' | 'lane-transition' | null;
|
|
176
|
+
/**
|
|
177
|
+
* Splits a search string into lowercase terms. Quoted groups stay together so `"needs review"`
|
|
178
|
+
* matches a phrase rather than two independent words.
|
|
179
|
+
* @param {unknown} search Raw search string.
|
|
180
|
+
* @returns {string[]} Lowercase terms.
|
|
181
|
+
*/
|
|
182
|
+
export declare function kanbanSearchTerms(search: unknown): string[];
|
|
183
|
+
/**
|
|
184
|
+
* Reports whether searchable text contains every term.
|
|
185
|
+
* @param {string} text Concatenated searchable text.
|
|
186
|
+
* @param {string[]} terms Lowercase terms.
|
|
187
|
+
* @returns {boolean} Whether the record matches.
|
|
188
|
+
*/
|
|
189
|
+
export declare function matchesKanbanSearch(text: string, terms: string[]): boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Bounded undo/redo stack over whole record-order snapshots. Snapshots are shallow arrays of the
|
|
192
|
+
* very record objects the board already holds, so a step costs one array rather than a deep clone;
|
|
193
|
+
* this is safe precisely because a Kanban move clones the record it changes and never mutates one.
|
|
194
|
+
* @param {number} [limit=50] Maximum remembered steps.
|
|
195
|
+
* @returns {KanbanHistory} History controller.
|
|
196
|
+
*/
|
|
197
|
+
export declare function createKanbanHistory(limit?: number): KanbanHistory;
|
|
198
|
+
/**
|
|
199
|
+
* Reorders records around one or more already-cloned moved records. The input array and every
|
|
200
|
+
* input record remain untouched. Movers keep their relative order and land contiguously, so a
|
|
201
|
+
* multi-card move reads on the board exactly as it read before it was picked up.
|
|
202
|
+
*
|
|
203
|
+
* The destination index is relative to the records remaining in the destination column and lane
|
|
204
|
+
* after the movers are lifted out — the same frame of reference a user sees while dragging.
|
|
205
|
+
*
|
|
206
|
+
* @param {KanbanRecord[]} records Current records.
|
|
207
|
+
* @param {{id:unknown,record:KanbanRecord}[]} entries Moving ids paired with their cloned records.
|
|
208
|
+
* @param {{recordId:string|((record:KanbanRecord)=>unknown),columnBy:KanbanAccessor,swimlaneBy:KanbanAccessor,destination:KanbanMovePoint}} options Accessors and destination.
|
|
209
|
+
* @returns {{records:KanbanRecord[],moves:{id:unknown,from:KanbanMovePoint}[],to:KanbanMovePoint}|null}
|
|
210
|
+
*/
|
|
211
|
+
export declare function reorderKanbanRecords(records: KanbanRecord[], entries: {
|
|
212
|
+
id: unknown;
|
|
213
|
+
record: KanbanRecord;
|
|
214
|
+
}[], options: {
|
|
215
|
+
recordId: string | ((record: KanbanRecord) => unknown);
|
|
216
|
+
columnBy: KanbanAccessor;
|
|
217
|
+
swimlaneBy: KanbanAccessor;
|
|
218
|
+
destination: KanbanMovePoint;
|
|
219
|
+
}): {
|
|
220
|
+
records: KanbanRecord[];
|
|
221
|
+
moves: {
|
|
222
|
+
id: unknown;
|
|
223
|
+
from: KanbanMovePoint;
|
|
224
|
+
}[];
|
|
225
|
+
to: KanbanMovePoint;
|
|
226
|
+
} | null;
|
|
227
|
+
/**
|
|
228
|
+
* Resolves one record's column, lane, and position within its bucket.
|
|
229
|
+
* @param {KanbanRecord[]} records Records.
|
|
230
|
+
* @param {number} index Position in `records`.
|
|
231
|
+
* @param {{recordId:string|((record:KanbanRecord)=>unknown),columnBy:KanbanAccessor,swimlaneBy:KanbanAccessor}} options Accessors.
|
|
232
|
+
* @returns {KanbanMovePoint} Location.
|
|
233
|
+
*/
|
|
234
|
+
export declare function locateKanbanRecord(records: KanbanRecord[], index: number, options: {
|
|
235
|
+
recordId: string | ((record: KanbanRecord) => unknown);
|
|
236
|
+
columnBy: KanbanAccessor;
|
|
237
|
+
swimlaneBy: KanbanAccessor;
|
|
238
|
+
}): KanbanMovePoint;
|
|
239
|
+
/**
|
|
240
|
+
* Translates a position among *rendered* cards into a position among all records in the same
|
|
241
|
+
* column and lane. Search and filters hide records without removing them, and a drop between two
|
|
242
|
+
* visible cards must land between them in the underlying data rather than at the same ordinal.
|
|
243
|
+
* @param {boolean[]} visibility Per-record visibility inside the bucket, in record order.
|
|
244
|
+
* @param {number} visibleIndex Zero-based position among the visible records.
|
|
245
|
+
* @returns {number} Zero-based position among all records in the bucket.
|
|
246
|
+
*/
|
|
247
|
+
export declare function absoluteKanbanIndex(visibility: boolean[], visibleIndex: number): number;
|
|
248
|
+
/**
|
|
249
|
+
* Reads a grouping accessor without touching field descriptors.
|
|
250
|
+
* @param {KanbanRecord} record Record.
|
|
251
|
+
* @param {number} index Display index.
|
|
252
|
+
* @param {KanbanAccessor} accessor Accessor.
|
|
253
|
+
* @returns {unknown} Raw value.
|
|
254
|
+
*/
|
|
255
|
+
export declare function readKanbanAccessor(record: KanbanRecord, index: number, accessor: KanbanAccessor): unknown;
|
|
256
|
+
/**
|
|
257
|
+
* Normalizes any grouping value to its stable string id.
|
|
258
|
+
* @param {unknown} value Raw value.
|
|
259
|
+
* @returns {string} Axis id.
|
|
260
|
+
*/
|
|
261
|
+
export declare function normalizeAxisId(value: unknown): string;
|
|
262
|
+
/**
|
|
263
|
+
* Clamps a requested position into an insertable range, treating anything unusable as "append".
|
|
264
|
+
* @param {unknown} value Requested index.
|
|
265
|
+
* @param {number} maximum Highest insertable position.
|
|
266
|
+
* @returns {number} Clamped index.
|
|
267
|
+
*/
|
|
268
|
+
export declare function clampKanbanIndex(value: unknown, maximum: number): number;
|