@dskripchenko/ui 1.19.1 → 1.21.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.
package/README.md CHANGED
@@ -91,7 +91,7 @@ A short selection — the full catalog is in [Storybook](https://dskripchenko.gi
91
91
 
92
92
  **Navigation:** Tabs, Breadcrumb, Link, Pagination (+ Cursor / LoadMore / InfiniteScroll / PageSize), BackTop, Affix, Anchor
93
93
 
94
- **Data display:** Card, Avatar, AvatarGroup, Tag, Divider, Accordion, Table, VirtualList, Stat, DescriptionList, Timeline, TreeView, Code, Watermark, Carousel, Calendar, NotificationBadge
94
+ **Data display:** Card, Avatar, AvatarGroup, Tag, Divider, Accordion, Table, VirtualList, Stat, DescriptionList, Timeline, TreeView, Code, Watermark, Carousel, Calendar, EventCalendar, Board, Kanban, NotificationBadge
95
95
 
96
96
  **Layout helpers:** Stack, Grid, Container, Splitter
97
97
 
@@ -111,7 +111,7 @@ A short selection — the full catalog is in [Storybook](https://dskripchenko.gi
111
111
 
112
112
  User docs are translated into four languages — pick yours:
113
113
 
114
- - 🇬🇧 **English** (default): [getting-started](./docs/en/getting-started.md), [theming](./docs/en/theming.md), [tokens](./docs/en/tokens.md), [icons](./docs/en/icons.md), [patterns](./docs/en/patterns.md), [validation](./docs/en/validation.md), [charts](./docs/en/charts.md), [markdown](./docs/en/markdown.md), [video](./docs/en/video.md), [audio](./docs/en/audio.md), [i18n](./docs/en/i18n.md)
114
+ - 🇬🇧 **English** (default): [getting-started](./docs/en/getting-started.md), [theming](./docs/en/theming.md), [tokens](./docs/en/tokens.md), [icons](./docs/en/icons.md), [patterns](./docs/en/patterns.md), [validation](./docs/en/validation.md), [charts](./docs/en/charts.md), [markdown](./docs/en/markdown.md), [board](./docs/en/board.md), [calendar](./docs/en/calendar.md), [kanban](./docs/en/kanban.md), [event calendar](./docs/en/event-calendar.md), [video](./docs/en/video.md), [audio](./docs/en/audio.md), [i18n](./docs/en/i18n.md)
115
115
  - 🇷🇺 **Русский**: [docs/ru/](./docs/ru/)
116
116
  - 🇩🇪 **Deutsch**: [docs/de/](./docs/de/)
117
117
  - 🇨🇳 **中文**: [docs/zh/](./docs/zh/)
@@ -4,11 +4,23 @@ export interface BoardCardTag {
4
4
  label: string;
5
5
  tone?: Tone | 'default';
6
6
  }
7
+ /** Who a card is assigned to: a name, or a name with an avatar picture or colour. */
8
+ export type BoardAssignee = string | {
9
+ name: string;
10
+ avatar?: string;
11
+ color?: string;
12
+ };
7
13
  export interface BoardCard {
8
14
  key: BoardKey;
9
15
  title: string;
10
16
  subtitle?: string;
11
17
  tags?: BoardCardTag[];
18
+ /** Shown in the card's footer as initials or the avatar picture. */
19
+ assignee?: BoardAssignee;
20
+ /** `YYYY-MM-DD`: the due date, shown formatted; before `today` (and not `done`) it is overdue. */
21
+ due?: string;
22
+ /** A finished card: muted, and never overdue. */
23
+ done?: boolean;
12
24
  /** The swimlane the card sits in, when the board has lanes. */
13
25
  lane?: BoardKey;
14
26
  /** Columns the card may move to; omitted — any column. */
@@ -18,6 +30,8 @@ export interface BoardColumn {
18
30
  key: BoardKey;
19
31
  title: string;
20
32
  cards: BoardCard[];
33
+ /** The real number of cards when only some are loaded; the count and WIP check use it. */
34
+ total?: number;
21
35
  /** Work-in-progress limit; the header warns when the column holds more. */
22
36
  wip?: number | null;
23
37
  }
@@ -40,6 +54,8 @@ export interface UidBoardProps {
40
54
  /** Freeze the board while a move is being saved. */
41
55
  busy?: boolean;
42
56
  readonly?: boolean;
57
+ /** `YYYY-MM-DD`: a card `due` before it is overdue. The local date by default. */
58
+ today?: string;
43
59
  }
44
60
  declare function __VLS_template(): {
45
61
  attrs: Partial<{}>;
@@ -53,6 +69,10 @@ declare function __VLS_template(): {
53
69
  count: number;
54
70
  over: boolean;
55
71
  }): unknown;
72
+ /** The bottom of a column, below its cards (with lanes — below the last lane). */
73
+ 'column-footer'?(props: {
74
+ column: BoardColumn;
75
+ }): unknown;
56
76
  }> & {
57
77
  card?(props: {
58
78
  card: BoardCard;
@@ -63,6 +83,10 @@ declare function __VLS_template(): {
63
83
  count: number;
64
84
  over: boolean;
65
85
  }): unknown;
86
+ /** The bottom of a column, below its cards (with lanes — below the last lane). */
87
+ 'column-footer'?(props: {
88
+ column: BoardColumn;
89
+ }): unknown;
66
90
  };
67
91
  refs: {};
68
92
  rootEl: HTMLDivElement;
@@ -78,6 +102,7 @@ declare const __VLS_component: import('vue').DefineComponent<UidBoardProps, {},
78
102
  readonly: boolean;
79
103
  lanes: BoardLane[];
80
104
  busy: boolean;
105
+ today: string;
81
106
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
82
107
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
83
108
  export default _default;
@@ -1,2 +1,2 @@
1
1
  export { default as UidBoard } from './UidBoard.vue';
2
- export type { UidBoardProps, BoardCard, BoardCardTag, BoardColumn, BoardLane, BoardMove, BoardKey } from './UidBoard.vue';
2
+ export type { UidBoardProps, BoardCard, BoardCardTag, BoardColumn, BoardLane, BoardMove, BoardKey, BoardAssignee } from './UidBoard.vue';
@@ -1,5 +1,6 @@
1
1
  import { CalendarEvent, CalendarRange, CalendarView } from './calendarModel';
2
2
  export type { CalendarEvent, CalendarRange, CalendarView } from './calendarModel';
3
+ /** `event-move`: a move gives the new date (and times); a resize gives the new `endTime` (time grid) or inclusive `endDate` (month, all-day row). */
3
4
  export interface CalendarEventMove {
4
5
  event: CalendarEvent;
5
6
  date: string;
@@ -7,6 +8,7 @@ export interface CalendarEventMove {
7
8
  time?: string;
8
9
  endTime?: string;
9
10
  }
11
+ /** The payload of `slot-click`: an empty slot — a time in the day/week grid, a day in the all-day row. */
10
12
  export interface CalendarSlot {
11
13
  date: string;
12
14
  time?: string;
@@ -20,6 +22,8 @@ export interface UidCalendarProps {
20
22
  todayLabel?: string;
21
23
  views?: CalendarView[];
22
24
  editable?: boolean;
25
+ /** Emit `slot-click` for clicks on empty slots. Defaults to `editable`. */
26
+ selectable?: boolean;
23
27
  hourHeight?: number;
24
28
  scrollToHour?: number;
25
29
  }
@@ -57,11 +61,12 @@ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {
57
61
  "onUpdate:view"?: ((value: CalendarView) => any) | undefined;
58
62
  "onUpdate:anchor"?: ((value: string | null) => any) | undefined;
59
63
  }>, {
64
+ selectable: boolean;
60
65
  compact: boolean;
66
+ editable: boolean;
61
67
  events: CalendarEvent[];
62
68
  maxEventsPerDay: number;
63
69
  views: CalendarView[];
64
- editable: boolean;
65
70
  hourHeight: number;
66
71
  scrollToHour: number;
67
72
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
@@ -7,6 +7,8 @@ export interface CalendarEvent {
7
7
  endTime?: string;
8
8
  title: string;
9
9
  color?: string;
10
+ /** `false` — never dragged or resized, even in an editable calendar; omitted — follows the calendar. */
11
+ editable?: boolean;
10
12
  }
11
13
  export interface CalendarRange {
12
14
  view: CalendarView;
@@ -37,4 +39,6 @@ export interface TimedBlock {
37
39
  cols: number;
38
40
  }
39
41
  export declare function layoutDay(events: readonly CalendarEvent[], iso: string): TimedBlock[];
42
+ /** The event stretched to end on `end` (inclusive, never before the start), times kept. */
43
+ export declare function resized(e: CalendarEvent, end: string): Pick<CalendarEvent, 'date' | 'endDate' | 'time' | 'endTime'>;
40
44
  export declare function moved(e: CalendarEvent, date: string, time?: string): Pick<CalendarEvent, 'date' | 'endDate' | 'time' | 'endTime'>;
@@ -1,2 +1,2 @@
1
1
  export { default as UidCalendar } from './UidCalendar.vue';
2
- export type { UidCalendarProps, CalendarEvent } from './UidCalendar.vue';
2
+ export type { UidCalendarProps, CalendarEvent, CalendarEventMove, CalendarSlot, CalendarRange, CalendarView } from './UidCalendar.vue';
@@ -0,0 +1,43 @@
1
+ import { CalendarRange, CalendarView } from '../Calendar/calendarModel';
2
+ export interface UidEventCalendarProps {
3
+ /** The calendar's markup. */
4
+ source?: string;
5
+ /** Drag and resize, the event builder, the source tab. */
6
+ editable?: boolean;
7
+ /** Read-only, whatever `editable` says. */
8
+ locked?: boolean;
9
+ /** Show the lock button (it emits `lock`). */
10
+ lockable?: boolean;
11
+ /** The view shown first; empty — the markup's `view:`, else the month. */
12
+ view?: CalendarView | '';
13
+ /** The date shown first (`YYYY-MM-DD`); empty — the markup's `date:`, else today. */
14
+ date?: string;
15
+ /** The views offered. */
16
+ views?: CalendarView[];
17
+ }
18
+ /** The payload of `open`: the event (the series for a repeat) and the date opened. */
19
+ export interface EventCalendarOpen {
20
+ id: string;
21
+ date: string;
22
+ title: string;
23
+ }
24
+ declare const _default: import('vue').DefineComponent<UidEventCalendarProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
25
+ range: (range: CalendarRange) => any;
26
+ change: (source: string) => any;
27
+ lock: (locked: boolean) => any;
28
+ open: (event: EventCalendarOpen) => any;
29
+ }, string, import('vue').PublicProps, Readonly<UidEventCalendarProps> & Readonly<{
30
+ onRange?: ((range: CalendarRange) => any) | undefined;
31
+ onChange?: ((source: string) => any) | undefined;
32
+ onLock?: ((locked: boolean) => any) | undefined;
33
+ onOpen?: ((event: EventCalendarOpen) => any) | undefined;
34
+ }>, {
35
+ source: string;
36
+ view: CalendarView | "";
37
+ date: string;
38
+ editable: boolean;
39
+ views: CalendarView[];
40
+ locked: boolean;
41
+ lockable: boolean;
42
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
43
+ export default _default;
@@ -0,0 +1,18 @@
1
+ import { EventCalendarDraft } from './eventCalendarDraft';
2
+ type __VLS_PublicProps = {
3
+ 'draft': EventCalendarDraft;
4
+ };
5
+ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
6
+ cancel: () => any;
7
+ remove: () => any;
8
+ save: () => any;
9
+ skip: () => any;
10
+ "update:draft": (value: EventCalendarDraft) => any;
11
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
12
+ onCancel?: (() => any) | undefined;
13
+ onRemove?: (() => any) | undefined;
14
+ onSave?: (() => any) | undefined;
15
+ onSkip?: (() => any) | undefined;
16
+ "onUpdate:draft"?: ((value: EventCalendarDraft) => any) | undefined;
17
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLFormElement>;
18
+ export default _default;
@@ -0,0 +1,31 @@
1
+ import { EventCalendarFields, EventCalendarFreq, EventCalendarItem, EventCalendarRule } from './eventCalendarMarkup';
2
+ export interface EventCalendarDraft {
3
+ itemId: string | null;
4
+ /** The occurrence of a repeat that was opened. */
5
+ occurrence: string | null;
6
+ scope: 'one' | 'all';
7
+ title: string;
8
+ allDay: boolean;
9
+ date: string;
10
+ endDate: string | null;
11
+ time: string;
12
+ endTime: string;
13
+ freq: 'none' | EventCalendarFreq;
14
+ interval: number;
15
+ byDay: number[];
16
+ monthMode: 'day' | 'nth' | 'last';
17
+ monthDay: number;
18
+ nth: number;
19
+ nthDay: number;
20
+ ends: 'never' | 'until' | 'count';
21
+ until: string | null;
22
+ count: number;
23
+ except: string[];
24
+ tags: string[];
25
+ where: string;
26
+ extra: string;
27
+ }
28
+ export declare function newDraft(date: string, time?: string): EventCalendarDraft;
29
+ export declare function draftOf(item: EventCalendarItem, occurrence: string | null): EventCalendarDraft;
30
+ export declare function ruleOf(d: EventCalendarDraft): EventCalendarRule | null;
31
+ export declare function fieldsOf(d: EventCalendarDraft, single?: boolean): EventCalendarFields;
@@ -0,0 +1,82 @@
1
+ import { MarkupProps } from '../Kanban/kanbanMarkup';
2
+ export type EventCalendarFreq = 'daily' | 'weekly' | 'monthly' | 'yearly';
3
+ export interface EventCalendarByDay {
4
+ /** 0 = Monday … 6 = Sunday. */
5
+ day: number;
6
+ /** The n-th weekday of the month (1…4, -1 = last); undefined — every such weekday. */
7
+ nth?: number;
8
+ }
9
+ export interface EventCalendarRule {
10
+ freq: EventCalendarFreq;
11
+ interval: number;
12
+ byDay: EventCalendarByDay[];
13
+ /** Days of the month (-1 = the last day). */
14
+ byMonthDay: number[];
15
+ /** Months 1…12. */
16
+ byMonth: number[];
17
+ from: string | null;
18
+ until: string | null;
19
+ count: number | null;
20
+ except: string[];
21
+ }
22
+ export interface EventCalendarItem {
23
+ id: string;
24
+ line: number;
25
+ title: string;
26
+ tags: string[];
27
+ props: MarkupProps;
28
+ date: string | null;
29
+ endDate: string | null;
30
+ time: string | null;
31
+ endTime: string | null;
32
+ rule: EventCalendarRule | null;
33
+ }
34
+ export interface EventCalendarProblem {
35
+ line: number;
36
+ message: string;
37
+ }
38
+ export interface EventCalendarDoc {
39
+ title: string | null;
40
+ settings: MarkupProps;
41
+ tagTones: Record<string, string>;
42
+ items: EventCalendarItem[];
43
+ problems: EventCalendarProblem[];
44
+ }
45
+ /** `FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,FR;UNTIL=20261228` → a rule. */
46
+ export declare function parseEventRRule(text: string): EventCalendarRule | null;
47
+ export declare function parseEventCalendar(source: string): EventCalendarDoc;
48
+ /** One event line → an item, or the reason it is not one. */
49
+ export declare function parseEventLine(text: string, line?: number, id?: string): EventCalendarItem | string;
50
+ /** The dates a rule produces between `start` and `end` (inclusive). */
51
+ export declare function eventOccurrences(rule: EventCalendarRule, start: string, end: string, limit?: number): string[];
52
+ export interface EventCalendarOccurrence {
53
+ /** `<item id>` or `<item id>@<date>` for a repeat. */
54
+ id: string;
55
+ item: EventCalendarItem;
56
+ date: string;
57
+ endDate?: string;
58
+ time?: string;
59
+ endTime?: string;
60
+ }
61
+ /** Every event and repeat occurrence that touches the days `start`…`end`. */
62
+ export declare function expandEventCalendar(doc: EventCalendarDoc, start: string, end: string): EventCalendarOccurrence[];
63
+ export declare function eventRuleText(rule: EventCalendarRule): string;
64
+ export interface EventCalendarFields {
65
+ title: string;
66
+ date?: string | null;
67
+ endDate?: string | null;
68
+ time?: string | null;
69
+ endTime?: string | null;
70
+ tags?: string[];
71
+ props?: MarkupProps;
72
+ rule?: EventCalendarRule | null;
73
+ }
74
+ export declare function serializeCalendarEvent(e: EventCalendarFields): string;
75
+ export declare function addCalendarEvent(source: string, e: EventCalendarFields): string;
76
+ export declare function updateCalendarEvent(source: string, id: string, e: EventCalendarFields): string;
77
+ export declare function removeCalendarEvent(source: string, id: string): string;
78
+ /**
79
+ * One occurrence of a repeat changed (moved, or edited "this one only"): the
80
+ * series skips that date and a single event takes its place.
81
+ */
82
+ export declare function detachCalendarOccurrence(source: string, id: string, date: string, single: EventCalendarFields): string;
@@ -0,0 +1,4 @@
1
+ export { default as UidEventCalendar } from './UidEventCalendar.vue';
2
+ export type { UidEventCalendarProps, EventCalendarOpen } from './UidEventCalendar.vue';
3
+ export { parseEventCalendar, parseEventLine, parseEventRRule, expandEventCalendar, eventOccurrences, eventRuleText, serializeCalendarEvent, addCalendarEvent, updateCalendarEvent, removeCalendarEvent, detachCalendarOccurrence, } from './eventCalendarMarkup';
4
+ export type { EventCalendarDoc, EventCalendarItem, EventCalendarProblem, EventCalendarRule, EventCalendarFreq, EventCalendarByDay, EventCalendarOccurrence, EventCalendarFields, } from './eventCalendarMarkup';
@@ -0,0 +1,34 @@
1
+ export interface UidKanbanProps {
2
+ /** The board's markup. */
3
+ source?: string;
4
+ /** Allow moves, new and changed cards and the source tab. */
5
+ editable?: boolean;
6
+ /** Read-only, whatever `editable` says. */
7
+ locked?: boolean;
8
+ /** Show the lock button (it emits `lock`). */
9
+ lockable?: boolean;
10
+ /** `YYYY-MM-DD`: a due date before it is overdue. Today (UTC) by default. */
11
+ today?: string;
12
+ }
13
+ /** The payload of `open`: the card and the title of its column. */
14
+ export interface KanbanOpen {
15
+ id: string;
16
+ title: string;
17
+ column: string;
18
+ }
19
+ declare const _default: import('vue').DefineComponent<UidKanbanProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
20
+ change: (source: string) => any;
21
+ lock: (locked: boolean) => any;
22
+ open: (card: KanbanOpen) => any;
23
+ }, string, import('vue').PublicProps, Readonly<UidKanbanProps> & Readonly<{
24
+ onChange?: ((source: string) => any) | undefined;
25
+ onLock?: ((locked: boolean) => any) | undefined;
26
+ onOpen?: ((card: KanbanOpen) => any) | undefined;
27
+ }>, {
28
+ source: string;
29
+ today: string;
30
+ editable: boolean;
31
+ locked: boolean;
32
+ lockable: boolean;
33
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
34
+ export default _default;
@@ -0,0 +1,4 @@
1
+ export { default as UidKanban } from './UidKanban.vue';
2
+ export type { UidKanbanProps, KanbanOpen } from './UidKanban.vue';
3
+ export { parseKanban, addKanbanCard, moveKanbanCard, updateKanbanCard, removeKanbanCard, addKanbanColumn, serializeKanbanCard, kanbanInlineMarkdown, parseMarkupProps, serializeMarkupProps, splitMarkupProps, } from './kanbanMarkup';
4
+ export type { KanbanDoc, KanbanCard, KanbanColumn, KanbanProblem, KanbanPriority, KanbanCardFields, MarkupProps, } from './kanbanMarkup';
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The kanban markup:
3
+ *
4
+ * # Board title
5
+ * lanes: Payments, Refunds
6
+ *
7
+ * ## Column {wip: 3}
8
+ * - Card title #tag !high {lane: Payments, who: Anna, due: 2026-11-15}
9
+ * Description, indented.
10
+ *
11
+ * Parsing keeps each column's and card's line range, so an edit (moving a
12
+ * card, changing one) rewrites only its own lines and leaves comments, blank
13
+ * lines and the rest of the text as they were.
14
+ */
15
+ /**
16
+ * `{key: value, flag, list: a, b}` — the properties at the end of a kanban
17
+ * card, column or calendar event line. A part without a colon is a flag
18
+ * (`done`) when it reads like a name, otherwise the next item of the
19
+ * previous value (`except: 2026-11-30, 2026-12-07`). Flags map to ''.
20
+ */
21
+ export type MarkupProps = Map<string, string>;
22
+ export declare function parseMarkupProps(inner: string): MarkupProps;
23
+ export declare function serializeMarkupProps(props: MarkupProps): string;
24
+ /** `Title {a: 1, b}` → the text and its props (the braces at the end of a line). */
25
+ export declare function splitMarkupProps(text: string): {
26
+ text: string;
27
+ props: MarkupProps;
28
+ };
29
+ export type KanbanPriority = 'high' | 'low';
30
+ export interface KanbanCard {
31
+ id: string;
32
+ title: string;
33
+ tags: string[];
34
+ priority: KanbanPriority | null;
35
+ props: MarkupProps;
36
+ description: string;
37
+ /** Lines of the card: its own line and the description under it. */
38
+ start: number;
39
+ end: number;
40
+ }
41
+ export interface KanbanColumn {
42
+ id: string;
43
+ title: string;
44
+ props: MarkupProps;
45
+ wip: number | null;
46
+ done: boolean;
47
+ cards: KanbanCard[];
48
+ start: number;
49
+ end: number;
50
+ }
51
+ export interface KanbanProblem {
52
+ line: number;
53
+ message: string;
54
+ }
55
+ export interface KanbanDoc {
56
+ title: string | null;
57
+ settings: MarkupProps;
58
+ lanes: string[];
59
+ tagTones: Record<string, string>;
60
+ columns: KanbanColumn[];
61
+ problems: KanbanProblem[];
62
+ }
63
+ export declare function parseKanban(source: string): KanbanDoc;
64
+ export interface KanbanCardFields {
65
+ title: string;
66
+ tags?: string[];
67
+ priority?: KanbanPriority | null;
68
+ props?: MarkupProps;
69
+ description?: string;
70
+ }
71
+ /** A card as markup lines: its own line, then the description indented under it. */
72
+ export declare function serializeKanbanCard(card: KanbanCardFields): string[];
73
+ /** Moves a card into a column, before another card or (null) to its end; `lane` changes its swimlane. */
74
+ export declare function moveKanbanCard(source: string, cardId: string, toColumnId: string, beforeCardId: string | null, lane?: string | null): string;
75
+ export declare function addKanbanCard(source: string, columnId: string, card: KanbanCardFields): string;
76
+ export declare function updateKanbanCard(source: string, cardId: string, card: KanbanCardFields): string;
77
+ export declare function removeKanbanCard(source: string, cardId: string): string;
78
+ export declare function addKanbanColumn(source: string, title: string): string;
79
+ /** A card title's inline markdown as HTML: links, code, bold, italics. The text is escaped first. */
80
+ export declare function kanbanInlineMarkdown(text: string): string;