@vadem/ui 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vadem-ui-schedule.mjs","names":[],"sources":["../../../projects/ui/schedule/src/core/schedule.ts","../../../projects/ui/schedule/src/schedule.ts"],"sourcesContent":["/**\n * Framework-agnostic schedule logic. Times are local wall-clock strings without a time zone\n * (\"2026-10-21T14:30\"): the application converts from its storage zone. All arithmetic runs on\n * minutes counted as if UTC, so a day always has 1440 minutes and nothing shifts around DST.\n */\n\n/** \"YYYY-MM-DD\" calendar date. */\nexport type VdIsoDate = string;\n\nconst ISO_DATE = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nfunction parseDate(value: string): Date | null {\n const m = ISO_DATE.exec(value);\n if (!m) return null;\n const date = new Date(Date.UTC(+m[1], +m[2] - 1, +m[3]));\n return date.toISOString().slice(0, 10) === value ? date : null;\n}\n\nfunction addDays(date: VdIsoDate, days: number): VdIsoDate {\n const d = parseDate(date)!;\n d.setUTCDate(d.getUTCDate() + days);\n return d.toISOString().slice(0, 10);\n}\n\n/** Adds months, clamping the day (Jan 31 + 1 month = Feb 28/29). */\nfunction addMonths(date: VdIsoDate, months: number): VdIsoDate {\n const d = parseDate(date)!;\n const target = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + months, 1));\n const last = new Date(\n Date.UTC(target.getUTCFullYear(), target.getUTCMonth() + 1, 0),\n ).getUTCDate();\n target.setUTCDate(Math.min(d.getUTCDate(), last));\n return target.toISOString().slice(0, 10);\n}\n\n/** 0 = Sunday ... 6 = Saturday. */\nfunction weekday(date: VdIsoDate): number {\n return parseDate(date)!.getUTCDay();\n}\n\nfunction weekStart(date: VdIsoDate, firstDay: number): VdIsoDate {\n return addDays(date, -((weekday(date) - firstDay + 7) % 7));\n}\n\nexport type VdScheduleView = 'month' | 'week' | 'day' | 'agenda';\nexport type VdScheduleColor = 'accent' | 'neutral' | 'success' | 'warning' | 'danger' | 'info';\n\nexport interface VdScheduleEvent {\n readonly id: string;\n readonly title: string;\n /** Timed: \"YYYY-MM-DDTHH:mm\". All-day: \"YYYY-MM-DD\". */\n readonly start: string;\n /** Timed: exclusive end \"YYYY-MM-DDTHH:mm\". All-day: last day, inclusive, \"YYYY-MM-DD\". */\n readonly end: string;\n readonly allDay?: boolean;\n readonly color?: VdScheduleColor;\n}\n\n/** A requested change of an event's time (from dragging or resizing). Same formats as the event. */\nexport interface VdScheduleEventChange {\n readonly id: string;\n readonly start: string;\n readonly end: string;\n readonly allDay: boolean;\n readonly kind: 'move' | 'resize';\n}\n\n/** A normalized event: minutes since the epoch (wall clock), exclusive end. */\nexport interface VdScheduleItem<E extends VdScheduleEvent = VdScheduleEvent> {\n readonly event: E;\n readonly allDay: boolean;\n readonly startMin: number;\n readonly endMin: number;\n /** First and last day the event touches (inclusive). */\n readonly startDate: VdIsoDate;\n readonly endDate: VdIsoDate;\n}\n\nexport const VD_DAY_MINUTES = 1440;\nconst DATE_TIME = /^(\\d{4}-\\d{2}-\\d{2})T(\\d{2}):(\\d{2})$/;\n\n/** Minutes since the epoch for \"YYYY-MM-DD\" (midnight) or \"YYYY-MM-DDTHH:mm\"; null if invalid. */\nexport function vdScheduleMinutes(value: string): number | null {\n const m = DATE_TIME.exec(value);\n const date = parseDate(m ? m[1] : value);\n if (!date) return null;\n if (!m) return date.getTime() / 60000;\n const h = +m[2],\n min = +m[3];\n if (h > 23 || min > 59) return null;\n return date.getTime() / 60000 + h * 60 + min;\n}\n\nexport function vdScheduleDateTime(minutes: number): string {\n return new Date(minutes * 60000).toISOString().slice(0, 16);\n}\n\nexport function vdScheduleDate(minutes: number): VdIsoDate {\n return new Date(minutes * 60000).toISOString().slice(0, 10);\n}\n\n/** Minutes since midnight of the day that contains `minutes`. */\nexport function vdScheduleTimeOfDay(minutes: number): number {\n return ((minutes % VD_DAY_MINUTES) + VD_DAY_MINUTES) % VD_DAY_MINUTES;\n}\n\nexport function vdScheduleNormalize<E extends VdScheduleEvent>(event: E): VdScheduleItem<E> | null {\n if (event.allDay) {\n const start = vdScheduleMinutes(event.start.slice(0, 10));\n const last = vdScheduleMinutes(event.end.slice(0, 10));\n if (start === null || last === null || last < start) return null;\n return {\n event,\n allDay: true,\n startMin: start,\n endMin: last + VD_DAY_MINUTES,\n startDate: event.start.slice(0, 10),\n endDate: event.end.slice(0, 10),\n };\n }\n const start = vdScheduleMinutes(event.start);\n const end = vdScheduleMinutes(event.end);\n if (start === null || end === null || end <= start || !event.start.includes('T')) return null;\n return {\n event,\n allDay: false,\n startMin: start,\n endMin: end,\n startDate: vdScheduleDate(start),\n endDate: vdScheduleDate(end - 1),\n };\n}\n\n/** IDs unique and non-empty; every event parses and ends after it starts. */\nexport function vdScheduleValid(events: readonly VdScheduleEvent[]): boolean {\n const ids = new Set<string>();\n for (const event of events) {\n if (typeof event.id !== 'string' || !event.id.trim() || ids.has(event.id)) return false;\n if (!vdScheduleNormalize(event)) return false;\n ids.add(event.id);\n }\n return true;\n}\n\n/** Normalized events sorted by start, all-day first, then longer first. */\nexport function vdScheduleItems<E extends VdScheduleEvent>(\n events: readonly E[],\n): VdScheduleItem<E>[] {\n return events\n .map((e) => vdScheduleNormalize(e))\n .filter((i): i is VdScheduleItem<E> => !!i)\n .sort(\n (a, b) =>\n Number(b.allDay) - Number(a.allDay) ||\n a.startMin - b.startMin ||\n b.endMin - a.endMin ||\n a.event.title.localeCompare(b.event.title),\n );\n}\n\n/** Items touching `date`. */\nexport function vdScheduleOnDay<E extends VdScheduleEvent>(\n items: readonly VdScheduleItem<E>[],\n date: VdIsoDate,\n): VdScheduleItem<E>[] {\n return items.filter((i) => i.startDate <= date && i.endDate >= date);\n}\n\n/** The dates a view shows for an anchor date. Month: 6 full weeks. */\nexport function vdScheduleDays(\n view: VdScheduleView,\n date: VdIsoDate,\n firstDay: number,\n agendaDays = 14,\n): VdIsoDate[] {\n switch (view) {\n case 'month': {\n // Always 6 weeks, so the grid height never jumps between months.\n const start = weekStart(date.slice(0, 8) + '01', firstDay);\n return Array.from({ length: 42 }, (_, i) => addDays(start, i));\n }\n case 'week': {\n const start = weekStart(date, firstDay);\n return Array.from({ length: 7 }, (_, i) => addDays(start, i));\n }\n case 'day':\n return [date];\n case 'agenda':\n return Array.from({ length: Math.max(1, agendaDays) }, (_, i) => addDays(date, i));\n }\n}\n\n/** The anchor date one period earlier or later. */\nexport function vdScheduleStep(\n view: VdScheduleView,\n date: VdIsoDate,\n direction: 1 | -1,\n agendaDays = 14,\n): VdIsoDate {\n switch (view) {\n case 'month':\n return addMonths(date, direction);\n case 'week':\n return addDays(date, 7 * direction);\n case 'day':\n return addDays(date, direction);\n case 'agenda':\n return addDays(date, Math.max(1, agendaDays) * direction);\n }\n}\n\nexport interface VdSchedulePlacement<E extends VdScheduleEvent = VdScheduleEvent> {\n readonly item: VdScheduleItem<E>;\n /** Minutes from the visible range start, clipped to the range. */\n readonly top: number;\n readonly bottom: number;\n readonly column: number;\n readonly columns: number;\n /** The event continues before/after the visible part of this day. */\n readonly clippedStart: boolean;\n readonly clippedEnd: boolean;\n}\n\n/**\n * Lays out the timed events of one day between `fromMinute` and `toMinute` (minutes after\n * midnight). Overlapping events share the width: each cluster of transitively overlapping events\n * gets the smallest number of columns and every event takes the first free column.\n */\nexport function vdScheduleLayout<E extends VdScheduleEvent>(\n items: readonly VdScheduleItem<E>[],\n date: VdIsoDate,\n fromMinute = 0,\n toMinute = VD_DAY_MINUTES,\n): VdSchedulePlacement<E>[] {\n const dayStart = vdScheduleMinutes(date);\n if (dayStart === null) return [];\n const from = dayStart + fromMinute,\n to = dayStart + toMinute;\n const visible = items\n .filter((i) => !i.allDay && i.startMin < to && i.endMin > from)\n .sort((a, b) => a.startMin - b.startMin || b.endMin - a.endMin);\n const result: VdSchedulePlacement<E>[] = [];\n let cluster: { item: VdScheduleItem<E>; column: number }[] = [];\n let columnEnds: number[] = [];\n let clusterEnd = -Infinity;\n const flush = () => {\n for (const { item, column } of cluster) {\n const start = Math.max(item.startMin, from),\n end = Math.min(item.endMin, to);\n result.push({\n item,\n top: start - from,\n bottom: end - from,\n column,\n columns: columnEnds.length,\n clippedStart: item.startMin < from,\n clippedEnd: item.endMin > to,\n });\n }\n cluster = [];\n columnEnds = [];\n };\n for (const item of visible) {\n if (item.startMin >= clusterEnd) flush();\n let column = columnEnds.findIndex((end) => end <= item.startMin);\n if (column < 0) column = columnEnds.push(item.endMin) - 1;\n else columnEnds[column] = item.endMin;\n cluster.push({ item, column });\n clusterEnd = Math.max(clusterEnd === -Infinity ? item.endMin : clusterEnd, item.endMin);\n }\n flush();\n return result;\n}\n\nexport function vdScheduleSnap(minutes: number, step: number): number {\n return step > 0 ? Math.round(minutes / step) * step : minutes;\n}\n\n/** Moves an event by whole days (all-day) or minutes (timed), keeping its duration. */\nexport function vdScheduleMove(item: VdScheduleItem, deltaMinutes: number): VdScheduleEventChange {\n if (item.allDay) {\n const days = Math.round(deltaMinutes / VD_DAY_MINUTES);\n return {\n id: item.event.id,\n start: addDays(item.startDate, days),\n end: addDays(item.endDate, days),\n allDay: true,\n kind: 'move',\n };\n }\n return {\n id: item.event.id,\n start: vdScheduleDateTime(item.startMin + deltaMinutes),\n end: vdScheduleDateTime(item.endMin + deltaMinutes),\n allDay: false,\n kind: 'move',\n };\n}\n\n/** Sets a timed event's end, keeping at least `minimum` minutes of duration. */\nexport function vdScheduleResize(\n item: VdScheduleItem,\n endMin: number,\n minimum: number,\n): VdScheduleEventChange {\n return {\n id: item.event.id,\n start: item.event.start,\n end: vdScheduleDateTime(Math.max(endMin, item.startMin + Math.max(1, minimum))),\n allDay: false,\n kind: 'resize',\n };\n}\n\n/** Applies a change immutably; returns the same array when the event is not found. */\nexport function vdScheduleApplyChange<E extends VdScheduleEvent>(\n events: readonly E[],\n change: VdScheduleEventChange,\n): readonly E[] {\n if (!events.some((e) => e.id === change.id)) return events;\n return events.map((e) =>\n e.id === change.id ? { ...e, start: change.start, end: change.end, allDay: change.allDay } : e,\n );\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n LOCALE_ID,\n ViewEncapsulation,\n afterNextRender,\n afterRenderEffect,\n booleanAttribute,\n computed,\n effect,\n inject,\n input,\n model,\n numberAttribute,\n output,\n signal,\n} from '@angular/core';\nimport { VdButton } from '@vadem/ui/button';\nimport {\n vdCalendarKey,\n vdFirstDayOfWeek,\n vdFormatDate,\n vdToday,\n vdWeekdayNames,\n} from '@vadem/ui/calendar';\nimport { vdUniqueId } from '@vadem/ui/field';\nimport { VdIcon } from '@vadem/ui/icon';\nimport { vdTexts } from '@vadem/ui/locale';\nimport {\n VD_DAY_MINUTES,\n VdIsoDate,\n VdScheduleEvent,\n VdScheduleEventChange,\n VdScheduleItem,\n VdSchedulePlacement,\n VdScheduleView,\n vdScheduleDate,\n vdScheduleDays,\n vdScheduleItems,\n vdScheduleLayout,\n vdScheduleMinutes,\n vdScheduleMove,\n vdScheduleOnDay,\n vdScheduleResize,\n vdScheduleSnap,\n vdScheduleStep,\n vdScheduleTimeOfDay,\n vdScheduleValid,\n} from './core/schedule';\n\n/** A click on empty space: a day (month) or a day and snapped time (week/day). */\nexport interface VdScheduleSlot {\n readonly date: VdIsoDate;\n /** \"HH:mm\", or null for a whole day. */\n readonly time: string | null;\n}\n\ninterface Drag {\n pointer: number;\n element: HTMLElement;\n item: VdScheduleItem;\n kind: 'move' | 'resize';\n events: readonly VdScheduleEvent[];\n x: number;\n y: number;\n /** Date and minute (time grid) under the pointer when the drag started. */\n origin: { date: VdIsoDate; minute: number } | null;\n active: boolean;\n}\n\ninterface Preview {\n change: VdScheduleEventChange;\n item: VdScheduleItem;\n}\n\n/**\n * Month, week, day and agenda views of application-owned events. The schedule never edits\n * `events`: dragging or resizing emits `eventChange` requests that the application applies\n * (for example with `vdScheduleApplyChange`). Spec: specs/schedule.md\n */\n@Component({\n selector: 'vd-schedule',\n imports: [VdButton, VdIcon],\n template: `\n <div class=\"vd-schedule__toolbar\">\n <div class=\"vd-schedule__nav\">\n <button vdButton size=\"sm\" variant=\"secondary\" type=\"button\" (click)=\"goToday()\">\n {{ t().todayText }}\n </button>\n <button\n vdButton\n size=\"sm\"\n variant=\"ghost\"\n iconOnly\n type=\"button\"\n [attr.aria-label]=\"t().previousLabel\"\n (click)=\"step(-1)\"\n >\n <vd-icon name=\"chevron-left\" />\n </button>\n <button\n vdButton\n size=\"sm\"\n variant=\"ghost\"\n iconOnly\n type=\"button\"\n [attr.aria-label]=\"t().nextLabel\"\n (click)=\"step(1)\"\n >\n <vd-icon name=\"chevron-right\" />\n </button>\n <p class=\"vd-schedule__title\" [id]=\"baseId + '-title'\" aria-live=\"polite\">{{ title() }}</p>\n </div>\n @if (views().length > 1) {\n <div class=\"vd-schedule__views\" role=\"group\" [attr.aria-label]=\"t().viewLabel\">\n @for (option of views(); track option) {\n <button\n vdButton\n size=\"sm\"\n type=\"button\"\n [variant]=\"option === view() ? 'secondary' : 'ghost'\"\n [attr.aria-pressed]=\"option === view()\"\n (click)=\"view.set(option)\"\n >\n {{ viewText(option) }}\n </button>\n }\n </div>\n }\n </div>\n\n @if (!valid()) {\n <p class=\"vd-schedule__invalid\">{{ t().invalidText }}</p>\n } @else {\n @switch (view()) {\n @case ('month') {\n <table class=\"vd-schedule__month\" [attr.aria-labelledby]=\"baseId + '-title'\">\n <thead>\n <tr>\n @for (name of weekdays(); track $index) {\n <th scope=\"col\">\n <abbr [attr.title]=\"name.long\">{{ name.short }}</abbr>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (week of weeks(); track week[0]) {\n <tr>\n @for (day of week; track day) {\n <td\n class=\"vd-schedule__cell\"\n [attr.data-date]=\"day\"\n [attr.data-outside]=\"!sameMonth(day) ? '' : null\"\n [attr.data-today]=\"day === today() ? '' : null\"\n [attr.data-drop-target]=\"\n preview()?.change?.start?.slice(0, 10) === day ? '' : null\n \"\n >\n <button\n type=\"button\"\n class=\"vd-schedule__day\"\n [attr.tabindex]=\"day === focusDate() ? 0 : -1\"\n [attr.aria-label]=\"dayLabel(day)\"\n [attr.aria-current]=\"day === today() ? 'date' : null\"\n (click)=\"openDay(day)\"\n (focus)=\"focusDate.set(day)\"\n >\n {{ dayNumber(day) }}\n @if (month().has(day)) {\n <span class=\"vd-schedule__dot\" aria-hidden=\"true\"></span>\n }\n </button>\n @let cell = month().get(day);\n @if (cell) {\n <ul class=\"vd-schedule__chips\" role=\"list\">\n @for (item of cell.visible; track item.event.id) {\n <li>\n <button\n type=\"button\"\n class=\"vd-schedule__event\"\n [attr.tabindex]=\"day === focusDate() ? 0 : -1\"\n [attr.data-color]=\"item.event.color ?? 'accent'\"\n [attr.data-all-day]=\"item.allDay ? '' : null\"\n [attr.data-dragging]=\"draggingId() === item.event.id ? '' : null\"\n [attr.aria-label]=\"eventLabel(item)\"\n (click)=\"activate(item.event)\"\n (pointerdown)=\"dragStart($event, item, 'move')\"\n (pointermove)=\"dragMove($event)\"\n (pointerup)=\"dragEnd($event)\"\n (pointercancel)=\"dragCancel($event)\"\n (lostpointercapture)=\"dragCancel($event)\"\n >\n @if (!item.allDay && item.startDate === day) {\n <span class=\"vd-schedule__time\">{{ time(item.startMin) }}</span>\n }\n <span class=\"vd-schedule__name\">{{ item.event.title }}</span>\n </button>\n </li>\n }\n @if (cell.more) {\n <li>\n <button\n type=\"button\"\n class=\"vd-schedule__more\"\n [attr.tabindex]=\"day === focusDate() ? 0 : -1\"\n (click)=\"openDay(day)\"\n >\n {{ t().moreText(cell.more) }}\n </button>\n </li>\n }\n </ul>\n }\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n }\n @case ('agenda') {\n <div class=\"vd-schedule__agenda\" [attr.aria-labelledby]=\"baseId + '-title'\" role=\"region\">\n @for (group of agenda(); track group.date; let g = $index) {\n <section\n class=\"vd-schedule__agenda-day\"\n [attr.aria-labelledby]=\"baseId + '-agenda-' + g\"\n >\n <p\n class=\"vd-schedule__agenda-date\"\n [id]=\"baseId + '-agenda-' + g\"\n [attr.data-today]=\"group.date === today() ? '' : null\"\n >\n {{ longDate(group.date) }}\n </p>\n <ul class=\"vd-schedule__agenda-list\" role=\"list\">\n @for (item of group.items; track item.event.id) {\n <li>\n <button\n type=\"button\"\n class=\"vd-schedule__agenda-event\"\n [attr.data-color]=\"item.event.color ?? 'accent'\"\n (click)=\"activate(item.event)\"\n >\n <span class=\"vd-schedule__agenda-time\">{{\n rangeText(item, group.date)\n }}</span>\n <span class=\"vd-schedule__name\">{{ item.event.title }}</span>\n </button>\n </li>\n }\n </ul>\n </section>\n } @empty {\n <p class=\"vd-schedule__empty\">{{ t().emptyText }}</p>\n }\n </div>\n }\n @default {\n <div\n class=\"vd-schedule__timegrid\"\n [attr.data-view]=\"view()\"\n [style.--vd-schedule-days]=\"days().length\"\n >\n <div class=\"vd-schedule__head\">\n <span class=\"vd-schedule__gutter\"></span>\n @for (day of days(); track day) {\n <button\n type=\"button\"\n class=\"vd-schedule__colhead\"\n [attr.data-today]=\"day === today() ? '' : null\"\n [attr.aria-label]=\"dayLabel(day)\"\n [attr.aria-current]=\"day === today() ? 'date' : null\"\n (click)=\"openDay(day)\"\n >\n <span class=\"vd-schedule__weekday\">{{ weekdayShort(day) }}</span>\n <span class=\"vd-schedule__date\">{{ dayNumber(day) }}</span>\n </button>\n }\n </div>\n <div class=\"vd-schedule__allday\">\n <span class=\"vd-schedule__gutter vd-schedule__allday-label\">{{\n t().allDayText\n }}</span>\n @for (day of days(); track day) {\n <div\n class=\"vd-schedule__allday-cell\"\n [attr.data-date]=\"day\"\n [attr.data-drop-target]=\"\n preview()?.item?.allDay && preview()?.change?.start === day ? '' : null\n \"\n >\n @for (item of allDay(day); track item.event.id) {\n <button\n type=\"button\"\n class=\"vd-schedule__event\"\n data-all-day\n [attr.data-color]=\"item.event.color ?? 'accent'\"\n [attr.data-dragging]=\"draggingId() === item.event.id ? '' : null\"\n [attr.aria-label]=\"eventLabel(item)\"\n (click)=\"activate(item.event)\"\n (pointerdown)=\"dragStart($event, item, 'move')\"\n (pointermove)=\"dragMove($event)\"\n (pointerup)=\"dragEnd($event)\"\n (pointercancel)=\"dragCancel($event)\"\n (lostpointercapture)=\"dragCancel($event)\"\n >\n <span class=\"vd-schedule__name\">{{ item.event.title }}</span>\n </button>\n }\n </div>\n }\n </div>\n <div\n class=\"vd-schedule__scroll\"\n role=\"region\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"baseId + '-title'\"\n >\n <div class=\"vd-schedule__grid\" [style.--vd-schedule-hours]=\"hours().length\">\n <div class=\"vd-schedule__hours\" aria-hidden=\"true\">\n @for (hour of hours(); track hour) {\n <span class=\"vd-schedule__hour\">{{ hourLabel(hour) }}</span>\n }\n </div>\n @for (day of days(); track day) {\n <div\n class=\"vd-schedule__column\"\n [attr.data-date]=\"day\"\n [attr.data-today]=\"day === today() ? '' : null\"\n >\n @for (p of layout().get(day); track p.item.event.id) {\n <button\n type=\"button\"\n class=\"vd-schedule__block\"\n [attr.data-color]=\"p.item.event.color ?? 'accent'\"\n [attr.data-dragging]=\"draggingId() === p.item.event.id ? '' : null\"\n [attr.data-clipped-start]=\"p.clippedStart ? '' : null\"\n [attr.data-clipped-end]=\"p.clippedEnd ? '' : null\"\n [attr.data-short]=\"p.bottom - p.top < 45 ? '' : null\"\n [style.--vd-schedule-top]=\"p.top\"\n [style.--vd-schedule-span]=\"p.bottom - p.top\"\n [style.--vd-schedule-col]=\"p.column\"\n [style.--vd-schedule-cols]=\"p.columns\"\n [attr.aria-label]=\"eventLabel(p.item)\"\n (click)=\"activate(p.item.event)\"\n (pointerdown)=\"dragStart($event, p.item, 'move')\"\n (pointermove)=\"dragMove($event)\"\n (pointerup)=\"dragEnd($event)\"\n (pointercancel)=\"dragCancel($event)\"\n (lostpointercapture)=\"dragCancel($event)\"\n >\n <span class=\"vd-schedule__name\">{{ p.item.event.title }}</span>\n <span class=\"vd-schedule__time\">{{ rangeText(p.item, day) }}</span>\n @if (editable() && !p.clippedEnd) {\n <span\n class=\"vd-schedule__resize\"\n aria-hidden=\"true\"\n (pointerdown)=\"dragStart($event, p.item, 'resize')\"\n ></span>\n }\n </button>\n }\n @if (preview(); as pv) {\n @if (ghost(day); as g) {\n <span\n class=\"vd-schedule__preview\"\n aria-hidden=\"true\"\n [style.--vd-schedule-top]=\"g.top\"\n [style.--vd-schedule-span]=\"g.span\"\n >\n {{ time(g.startMin) }}\n </span>\n }\n }\n @if (nowLine(day); as line) {\n <span\n class=\"vd-schedule__now\"\n aria-hidden=\"true\"\n [style.--vd-schedule-top]=\"line\"\n ></span>\n }\n </div>\n }\n </div>\n </div>\n </div>\n }\n }\n }\n <p class=\"vd-visually-hidden\" role=\"status\" aria-atomic=\"true\">\n @for (message of messages(); track message.serial) {\n <span>{{ message.text }}</span>\n }\n </p>\n `,\n host: {\n class: 'vd-schedule',\n '[attr.data-view]': 'view()',\n '[attr.data-state]': '!valid() ? \"invalid\" : draggingId() ? \"dragging\" : \"idle\"',\n '(keydown)': 'key($event)',\n '(click)': 'emptyClick($event)',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class VdSchedule<E extends VdScheduleEvent = VdScheduleEvent> {\n readonly events = input<readonly E[]>([]);\n readonly view = model<VdScheduleView>('month');\n /** Any date inside the shown period (\"YYYY-MM-DD\"). Defaults to today. */\n readonly date = model<VdIsoDate>(vdToday());\n readonly views = input<readonly VdScheduleView[]>(['month', 'week', 'day', 'agenda']);\n /** BCP 47 locale for names, week start, dates and times. Defaults to the app's LOCALE_ID. */\n readonly locale = input<string>(inject(LOCALE_ID));\n /** 0 = Sunday ... 6 = Saturday. Defaults to the locale's week start. */\n readonly firstDayOfWeek = input<number | undefined>(undefined);\n /** Visible hours in week/day views. */\n readonly dayStartHour = input(0, { transform: numberAttribute });\n readonly dayEndHour = input(24, { transform: numberAttribute });\n /** Hour scrolled into view when a week/day view appears. */\n readonly scrollToHour = input(8, { transform: numberAttribute });\n /** Snapping step for dragging, resizing and empty-slot clicks, in minutes. */\n readonly slotMinutes = input(30, { transform: numberAttribute });\n readonly maxEventsPerDay = input(3, { transform: numberAttribute });\n readonly agendaDays = input(14, { transform: numberAttribute });\n /** Current local time \"YYYY-MM-DDTHH:mm\" for the now line; omit to hide it. */\n readonly now = input<string | null>(null);\n /** Allows dragging and resizing (pointer). Activation and slot clicks always work. */\n readonly editable = input(true, { transform: booleanAttribute });\n\n readonly label = input<string>();\n readonly todayText = input<string>();\n readonly previousLabel = input<string>();\n readonly nextLabel = input<string>();\n readonly viewLabel = input<string>();\n readonly monthText = input<string>();\n readonly weekText = input<string>();\n readonly dayText = input<string>();\n readonly agendaText = input<string>();\n readonly allDayText = input<string>();\n readonly emptyText = input<string>();\n readonly invalidText = input<string>();\n readonly moreText = input<(count: number) => string>();\n readonly eventsText = input<(count: number) => string>();\n readonly changedText = input<(title: string, when: string) => string>();\n readonly canceledText = input<(title: string) => string>();\n\n /** An event was clicked or activated with the keyboard (open it, edit it...). */\n readonly eventActivate = output<E>();\n /** Empty space was clicked (create an event there). */\n readonly slotActivate = output<VdScheduleSlot>();\n /** A drag or resize asks to change an event's time. Apply it to `events` or ignore it. */\n readonly eventChange = output<VdScheduleEventChange>();\n\n protected readonly t = vdTexts('schedule', {\n label: this.label,\n todayText: this.todayText,\n previousLabel: this.previousLabel,\n nextLabel: this.nextLabel,\n viewLabel: this.viewLabel,\n monthText: this.monthText,\n weekText: this.weekText,\n dayText: this.dayText,\n agendaText: this.agendaText,\n allDayText: this.allDayText,\n emptyText: this.emptyText,\n invalidText: this.invalidText,\n moreText: this.moreText,\n eventsText: this.eventsText,\n changedText: this.changedText,\n canceledText: this.canceledText,\n });\n\n protected readonly baseId = vdUniqueId('vd-schedule');\n protected readonly today = computed(() => this.now()?.slice(0, 10) ?? vdToday());\n protected readonly valid = computed(() => vdScheduleValid(this.events()));\n protected readonly items = computed(() => (this.valid() ? vdScheduleItems(this.events()) : []));\n protected readonly firstDay = computed(\n () => this.firstDayOfWeek() ?? vdFirstDayOfWeek(this.locale()),\n );\n protected readonly days = computed(() =>\n vdScheduleDays(this.view(), this.date(), this.firstDay(), this.agendaDays()),\n );\n protected readonly weeks = computed(() => {\n const days = this.days();\n return Array.from({ length: days.length / 7 }, (_, i) => days.slice(i * 7, i * 7 + 7));\n });\n protected readonly weekdays = computed(() => {\n const short = vdWeekdayNames(this.locale(), this.firstDay(), 'short');\n const long = vdWeekdayNames(this.locale(), this.firstDay(), 'long');\n return short.map((s, i) => ({ short: s, long: long[i] }));\n });\n protected readonly hours = computed(() => {\n const from = Math.max(0, Math.min(23, this.dayStartHour()));\n const to = Math.max(from + 1, Math.min(24, this.dayEndHour()));\n return Array.from({ length: to - from }, (_, i) => from + i);\n });\n /** Month cells: visible events and the overflow count per day. */\n protected readonly month = computed(() => {\n const map = new Map<VdIsoDate, { visible: VdScheduleItem<E>[]; more: number }>();\n if (this.view() !== 'month') return map;\n const max = Math.max(1, this.maxEventsPerDay());\n for (const day of this.days()) {\n const all = vdScheduleOnDay(this.items(), day);\n if (!all.length) continue;\n const visible = all.length > max ? all.slice(0, max - 1) : all;\n map.set(day, { visible, more: all.length - visible.length });\n }\n return map;\n });\n protected readonly layout = computed(() => {\n const map = new Map<VdIsoDate, VdSchedulePlacement<E>[]>();\n const from = this.hours()[0] * 60,\n to = (this.hours().at(-1)! + 1) * 60;\n for (const day of this.days()) map.set(day, vdScheduleLayout(this.items(), day, from, to));\n return map;\n });\n protected readonly agenda = computed(() =>\n this.days()\n .map((date) => ({ date, items: vdScheduleOnDay(this.items(), date) }))\n .filter((group) => group.items.length),\n );\n protected readonly title = computed(() => {\n const days = this.days(),\n locale = this.locale();\n switch (this.view()) {\n case 'month':\n return vdFormatDate(this.date(), locale, { month: 'long', year: 'numeric' });\n case 'day':\n return this.longDate(this.date());\n default: {\n const format = new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n timeZone: 'UTC',\n });\n return format.formatRange(new Date(days[0]), new Date(days.at(-1)!));\n }\n }\n });\n\n protected readonly focusDate = signal<VdIsoDate>(this.date());\n protected readonly draggingId = signal<string | null>(null);\n protected readonly preview = signal<Preview | null>(null);\n protected readonly messages = signal<readonly { serial: number; text: string }[]>([]);\n\n private readonly host: HTMLElement = inject(ElementRef).nativeElement;\n private drag: Drag | null = null;\n private moveFocus = false;\n private suppressClick = false;\n private serial = 0;\n private scrolledView: string | null = null;\n\n constructor() {\n // Keep the roving day inside the shown month.\n effect(() => {\n const days = this.days();\n const focus = this.focusDate();\n if (this.view() === 'month' && !days.includes(focus)) {\n this.focusDate.set(days.includes(this.date()) ? this.date() : days[7]);\n }\n });\n effect(() => {\n const events = this.events();\n if (this.drag && events !== this.drag.events) this.finish(true);\n });\n afterRenderEffect(() => {\n const focus = this.focusDate();\n if (!this.moveFocus) return;\n this.moveFocus = false;\n this.host\n .querySelector<HTMLElement>(`.vd-schedule__cell[data-date=\"${focus}\"] .vd-schedule__day`)\n ?.focus();\n });\n // Scroll the time grid to `scrollToHour` once per view/period.\n afterRenderEffect(() => {\n const key = this.view() + this.days()[0];\n if (this.view() !== 'week' && this.view() !== 'day') return;\n if (this.scrolledView === key) return;\n this.scrolledView = key;\n const scroller = this.host.querySelector<HTMLElement>('.vd-schedule__scroll');\n const grid = this.host.querySelector<HTMLElement>('.vd-schedule__grid');\n if (!scroller || !grid) return;\n const offset = Math.max(0, this.scrollToHour() - this.hours()[0]);\n scroller.scrollTop = (grid.scrollHeight / this.hours().length) * offset;\n });\n const destroyRef = inject(DestroyRef);\n destroyRef.onDestroy(() => this.finish(false));\n afterNextRender(() => {\n const click = (event: Event) => {\n if (!this.suppressClick) return;\n this.suppressClick = false;\n event.preventDefault();\n event.stopPropagation();\n };\n // A new press starts fresh, so a release outside the board never swallows a later click.\n const press = () => (this.suppressClick = false);\n this.host.addEventListener('click', click, true);\n this.host.addEventListener('pointerdown', press, true);\n destroyRef.onDestroy(() => {\n this.host.removeEventListener('click', click, true);\n this.host.removeEventListener('pointerdown', press, true);\n });\n });\n }\n\n // ------------------------------------------------------------------ navigation\n\n protected goToday(): void {\n this.date.set(this.today());\n this.focusDate.set(this.today());\n }\n\n protected step(direction: 1 | -1): void {\n const next = vdScheduleStep(this.view(), this.date(), direction, this.agendaDays());\n this.date.set(next);\n this.focusDate.set(next);\n }\n\n protected openDay(date: VdIsoDate): void {\n this.date.set(date);\n this.focusDate.set(date);\n if (this.views().includes('day')) this.view.set('day');\n }\n\n private monthKey(event: KeyboardEvent): void {\n const target = event.target as HTMLElement;\n if (!target.classList.contains('vd-schedule__day')) return;\n const rtl =\n this.host.ownerDocument.defaultView?.getComputedStyle(this.host).direction === 'rtl';\n const next = vdCalendarKey(event.key, this.focusDate(), {\n firstDay: this.firstDay(),\n rtl,\n shift: event.shiftKey,\n });\n if (!next) return;\n event.preventDefault();\n if (!this.days().includes(next)) this.date.set(next);\n this.focusDate.set(next);\n this.moveFocus = true;\n }\n\n // ---------------------------------------------------------------- activation\n\n protected activate(event: E): void {\n this.eventActivate.emit(event);\n }\n\n /**\n * Pointer convenience on empty space (keyboard users create events with the application's own\n * controls): a month cell or all-day cell gives a day, a time-grid column a snapped time.\n */\n protected emptyClick(event: MouseEvent): void {\n const target = event.target as Element;\n if (target.closest('button')) return;\n const cell = target.closest<HTMLElement>('.vd-schedule__cell, .vd-schedule__allday-cell');\n if (cell) {\n this.slotActivate.emit({ date: cell.dataset['date']!, time: null });\n return;\n }\n const column = target.closest<HTMLElement>('.vd-schedule__column');\n if (column) this.slotClick(event, column, column.dataset['date']!);\n }\n\n private slotClick(event: MouseEvent, column: HTMLElement, date: VdIsoDate): void {\n const minute = this.minuteAt(column, event.clientY);\n const snapped = Math.min(\n VD_DAY_MINUTES - this.slot(),\n Math.floor(minute / this.slot()) * this.slot(),\n );\n this.slotActivate.emit({ date, time: this.clock(snapped) });\n }\n\n // ------------------------------------------------------------------ dragging\n\n protected dragStart(event: PointerEvent, item: VdScheduleItem<E>, kind: 'move' | 'resize'): void {\n if (\n !this.editable() ||\n !event.isPrimary ||\n event.button !== 0 ||\n event.pointerType === 'touch' ||\n this.drag\n )\n return;\n if (kind === 'resize') event.stopPropagation();\n const element = (\n kind === 'resize'\n ? (event.currentTarget as HTMLElement).closest('.vd-schedule__block')\n : event.currentTarget\n ) as HTMLElement;\n try {\n element.setPointerCapture(event.pointerId);\n } catch {\n return;\n }\n event.preventDefault();\n this.drag = {\n pointer: event.pointerId,\n element,\n item,\n kind,\n events: this.events(),\n x: event.clientX,\n y: event.clientY,\n origin: this.pointAt(event.clientX, event.clientY, item.allDay),\n active: false,\n };\n }\n\n protected dragMove(event: PointerEvent): void {\n const drag = this.drag;\n if (!drag || drag.pointer !== event.pointerId) return;\n if (event.buttons === 0) {\n this.finish(false);\n return;\n }\n if (!drag.active && Math.hypot(event.clientX - drag.x, event.clientY - drag.y) < 4) return;\n if (!drag.active) {\n drag.active = true;\n if (!drag.element.contains(this.host.ownerDocument.activeElement))\n drag.element.focus({ preventScroll: true });\n this.draggingId.set(drag.item.event.id);\n }\n const change = this.changeAt(drag, event.clientX, event.clientY);\n this.preview.set(change ? { change, item: drag.item } : null);\n }\n\n protected dragEnd(event: PointerEvent): void {\n const drag = this.drag;\n if (!drag || drag.pointer !== event.pointerId) return;\n const change = drag.active ? this.changeAt(drag, event.clientX, event.clientY) : null;\n this.suppressClick = drag.active;\n this.finish(drag.active && !change);\n if (change) {\n this.announce(this.t().changedText(drag.item.event.title, this.whenText(change)));\n this.eventChange.emit(change);\n }\n }\n\n protected dragCancel(event: PointerEvent): void {\n if (event.pointerId === this.drag?.pointer) this.finish(!!this.drag?.active);\n }\n\n protected key(event: KeyboardEvent): void {\n if (!this.drag) {\n if (this.view() === 'month') this.monthKey(event);\n return;\n }\n if (event.isComposing) return;\n if (event.key === 'Escape' || event.key === 'Tab') {\n if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n }\n // The button release that follows must not create or open anything.\n this.suppressClick = this.drag.active;\n this.finish(true);\n }\n }\n\n /** The change a pointer position asks for, or null when it changes nothing. */\n private changeAt(drag: Drag, x: number, y: number): VdScheduleEventChange | null {\n const point = this.pointAt(x, y, drag.item.allDay);\n if (!point || !drag.origin) return null;\n const dayDelta =\n (vdScheduleMinutes(point.date)! - vdScheduleMinutes(drag.origin.date)!) / VD_DAY_MINUTES;\n let change: VdScheduleEventChange;\n if (drag.kind === 'resize') {\n const end = vdScheduleMinutes(point.date)! + vdScheduleSnap(point.minute, this.slot());\n change = vdScheduleResize(drag.item, end, this.slot());\n } else if (drag.item.allDay || this.view() === 'month') {\n change = vdScheduleMove(drag.item, dayDelta * VD_DAY_MINUTES);\n } else {\n const minutes = vdScheduleSnap(point.minute - drag.origin.minute, this.slot());\n change = vdScheduleMove(drag.item, dayDelta * VD_DAY_MINUTES + minutes);\n }\n return change.start === drag.item.event.start && change.end === drag.item.event.end\n ? null\n : change;\n }\n\n /** Date (and minute in time grids) under a viewport point. */\n private pointAt(\n x: number,\n y: number,\n allDay: boolean,\n ): { date: VdIsoDate; minute: number } | null {\n const selector =\n this.view() === 'month'\n ? '.vd-schedule__cell[data-date]'\n : allDay\n ? '.vd-schedule__allday-cell[data-date]'\n : '.vd-schedule__column[data-date]';\n for (const el of Array.from(this.host.querySelectorAll<HTMLElement>(selector))) {\n const r = el.getBoundingClientRect();\n const inside =\n x >= r.left &&\n x <= r.right &&\n (allDay || this.view() === 'month' ? y >= r.top && y <= r.bottom : true);\n if (!inside) continue;\n const minute = this.view() === 'month' || allDay ? 0 : this.minuteAt(el, y);\n return { date: el.dataset['date']!, minute };\n }\n return null;\n }\n\n /** Minute of the day for a y position inside a time-grid column. */\n private minuteAt(column: HTMLElement, y: number): number {\n const r = column.getBoundingClientRect();\n const from = this.hours()[0] * 60;\n const span = this.hours().length * 60;\n const ratio = Math.max(0, Math.min(1, (y - r.top) / r.height));\n return from + ratio * span;\n }\n\n private finish(announce: boolean): void {\n const drag = this.drag;\n this.drag = null;\n this.draggingId.set(null);\n this.preview.set(null);\n if (!drag) return;\n if (drag.element.hasPointerCapture?.(drag.pointer))\n drag.element.releasePointerCapture(drag.pointer);\n if (announce && drag.active) this.announce(this.t().canceledText(drag.item.event.title));\n }\n\n /** Dashed preview of a timed change inside a time-grid column. */\n protected ghost(day: VdIsoDate): { top: number; span: number; startMin: number } | null {\n const pv = this.preview();\n if (!pv || pv.change.allDay || this.view() === 'month') return null;\n const start = vdScheduleMinutes(pv.change.start)!,\n end = vdScheduleMinutes(pv.change.end)!;\n const dayStart = vdScheduleMinutes(day)!;\n const from = dayStart + this.hours()[0] * 60,\n to = dayStart + (this.hours().at(-1)! + 1) * 60;\n if (end <= from || start >= to) return null;\n const top = Math.max(start, from) - from;\n return { top, span: Math.min(end, to) - from - top, startMin: start };\n }\n\n protected nowLine(day: VdIsoDate): number | null {\n const now = this.now();\n if (!now || now.slice(0, 10) !== day) return null;\n const minute = vdScheduleMinutes(now);\n if (minute === null) return null;\n const offset = vdScheduleTimeOfDay(minute) - this.hours()[0] * 60;\n return offset >= 0 && offset <= this.hours().length * 60 ? offset : null;\n }\n\n protected allDay(day: VdIsoDate): VdScheduleItem<E>[] {\n return vdScheduleOnDay(this.items(), day).filter((i) => i.allDay);\n }\n\n // ---------------------------------------------------------------- formatting\n\n protected viewText(view: VdScheduleView): string {\n const t = this.t();\n return { month: t.monthText, week: t.weekText, day: t.dayText, agenda: t.agendaText }[view];\n }\n\n protected sameMonth(day: VdIsoDate): boolean {\n return day.slice(0, 7) === this.date().slice(0, 7);\n }\n\n protected dayNumber(day: VdIsoDate): string {\n return vdFormatDate(day, this.locale(), { day: 'numeric' });\n }\n\n protected weekdayShort(day: VdIsoDate): string {\n return vdFormatDate(day, this.locale(), { weekday: 'short' });\n }\n\n protected longDate(day: VdIsoDate): string {\n return vdFormatDate(day, this.locale(), {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n });\n }\n\n protected dayLabel(day: VdIsoDate): string {\n const count = vdScheduleOnDay(this.items(), day).length;\n return `${this.longDate(day)}, ${this.t().eventsText(count)}`;\n }\n\n protected time(minutes: number): string {\n return new Intl.DateTimeFormat(this.locale(), {\n hour: 'numeric',\n minute: '2-digit',\n timeZone: 'UTC',\n }).format(new Date(minutes * 60000));\n }\n\n protected hourLabel(hour: number): string {\n return new Intl.DateTimeFormat(this.locale(), { hour: 'numeric', timeZone: 'UTC' }).format(\n new Date(Date.UTC(2026, 0, 1, hour)),\n );\n }\n\n /** Time range shown for an event on a given day (\"All day\" for all-day events). */\n protected rangeText(item: VdScheduleItem, day: VdIsoDate): string {\n if (item.allDay) return this.t().allDayText;\n const start = item.startDate === day ? this.time(item.startMin) : '…';\n const end = vdScheduleDate(item.endMin - 1) === day ? this.time(item.endMin) : '…';\n return `${start} – ${end}`;\n }\n\n protected eventLabel(item: VdScheduleItem): string {\n const date = this.longDate(item.startDate);\n if (item.allDay) {\n const last = item.endDate !== item.startDate ? ` – ${this.longDate(item.endDate)}` : '';\n return `${item.event.title}, ${date}${last}, ${this.t().allDayText}`;\n }\n const end =\n item.endDate !== item.startDate\n ? `${this.longDate(item.endDate)} ${this.time(item.endMin)}`\n : this.time(item.endMin);\n return `${item.event.title}, ${date}, ${this.time(item.startMin)} – ${end}`;\n }\n\n private whenText(change: VdScheduleEventChange): string {\n if (change.allDay) return this.longDate(change.start);\n const start = vdScheduleMinutes(change.start)!;\n return `${this.longDate(change.start.slice(0, 10))}, ${this.time(start)}`;\n }\n\n private clock(minutes: number): string {\n const h = Math.floor(minutes / 60),\n m = Math.round(minutes % 60);\n return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;\n }\n\n private slot(): number {\n return Math.max(5, Math.min(120, this.slotMinutes()));\n }\n\n private announce(text: string): void {\n this.messages.set([{ serial: ++this.serial, text }]);\n }\n}\n"],"mappings":";;;;;;;AASA,MAAM,WAAW;AAEjB,SAAS,UAAU,OAAa;CAC9B,MAAM,IAAI,SAAS,KAAK,KAAK;CAC7B,IAAI,CAAC,GAAG,OAAO;CACf,MAAM,OAAO,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC;CACvD,OAAO,KAAK,YAAW,CAAE,CAAC,MAAM,GAAG,EAAE,MAAM,QAAQ,OAAO;AAC5D;AAEA,SAAS,QAAQ,MAAiB,MAAY;CAC5C,MAAM,IAAI,UAAU,IAAI;CACxB,EAAE,WAAW,EAAE,WAAU,IAAK,IAAI;CAClC,OAAO,EAAE,YAAW,CAAE,CAAC,MAAM,GAAG,EAAE;AACpC;AAGA,SAAS,UAAU,MAAiB,QAAc;CAChD,MAAM,IAAI,UAAU,IAAI;CACxB,MAAM,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,eAAc,GAAI,EAAE,YAAW,IAAK,QAAQ,CAAC,CAAC;CACjF,MAAM,OAAO,IAAI,KACf,KAAK,IAAI,OAAO,eAAc,GAAI,OAAO,YAAW,IAAK,GAAG,CAAC,CAAC,CAC/D,CAAC,WAAU;CACZ,OAAO,WAAW,KAAK,IAAI,EAAE,WAAU,GAAI,IAAI,CAAC;CAChD,OAAO,OAAO,YAAW,CAAE,CAAC,MAAM,GAAG,EAAE;AACzC;AAGA,SAAS,QAAQ,MAAe;CAC9B,OAAO,UAAU,IAAI,CAAE,CAAC,UAAS;AACnC;AAEA,SAAS,UAAU,MAAiB,UAAgB;CAClD,OAAO,QAAQ,MAAM,GAAG,QAAQ,IAAI,IAAI,WAAW,KAAK,EAAE;AAC5D;AAoCA,MAAa,iBAAiB;AAC9B,MAAM,YAAY;AAGlB,SAAgB,kBAAkB,OAAa;CAC7C,MAAM,IAAI,UAAU,KAAK,KAAK;CAC9B,MAAM,OAAO,UAAU,IAAI,EAAE,KAAK,KAAK;CACvC,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,CAAC,GAAG,OAAO,KAAK,QAAO,IAAK;CAChC,MAAM,IAAI,CAAC,EAAE,IACX,MAAM,CAAC,EAAE;CACX,IAAI,IAAI,MAAM,MAAM,IAAI,OAAO;CAC/B,OAAO,KAAK,QAAO,IAAK,MAAQ,IAAI,KAAK;AAC3C;AAEA,SAAgB,mBAAmB,SAAe;CAChD,wBAAO,IAAI,KAAK,UAAU,GAAK,EAAC,CAAC,YAAW,CAAE,CAAC,MAAM,GAAG,EAAE;AAC5D;AAEA,SAAgB,eAAe,SAAe;CAC5C,wBAAO,IAAI,KAAK,UAAU,GAAK,EAAC,CAAC,YAAW,CAAE,CAAC,MAAM,GAAG,EAAE;AAC5D;AAGA,SAAgB,oBAAoB,SAAe;CACjD,QAAS,UAAU,iBAAkB,kBAAkB;AACzD;AAEA,SAAgB,oBAA+C,OAAQ;CACrE,IAAI,MAAM,QAAQ;EAChB,MAAM,QAAQ,kBAAkB,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC;EACxD,MAAM,OAAO,kBAAkB,MAAM,IAAI,MAAM,GAAG,EAAE,CAAC;EACrD,IAAI,UAAU,QAAQ,SAAS,QAAQ,OAAO,OAAO,OAAO;EAC5D,OAAO;GACL;GACA,QAAQ;GACR,UAAU;GACV,QAAQ,OAAO;GACf,WAAW,MAAM,MAAM,MAAM,GAAG,EAAE;GAClC,SAAS,MAAM,IAAI,MAAM,GAAG,EAAE;EAC/B;CACH;CACA,MAAM,QAAQ,kBAAkB,MAAM,KAAK;CAC3C,MAAM,MAAM,kBAAkB,MAAM,GAAG;CACvC,IAAI,UAAU,QAAQ,QAAQ,QAAQ,OAAO,SAAS,CAAC,MAAM,MAAM,SAAS,GAAG,GAAG,OAAO;CACzF,OAAO;EACL;EACA,QAAQ;EACR,UAAU;EACV,QAAQ;EACR,WAAW,eAAe,KAAK;EAC/B,SAAS,eAAe,MAAM,CAAC;CAChC;AACH;AAGA,SAAgB,gBAAgB,QAAkC;CAChE,MAAM,sBAAM,IAAI,IAAG;CACnB,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,OAAO,MAAM,OAAO,YAAY,CAAC,MAAM,GAAG,KAAI,KAAM,IAAI,IAAI,MAAM,EAAE,GAAG,OAAO;EAClF,IAAI,CAAC,oBAAoB,KAAK,GAAG,OAAO;EACxC,IAAI,IAAI,MAAM,EAAE;CAClB;CACA,OAAO;AACT;AAGA,SAAgB,gBACd,QAAoB;CAEpB,OAAO,OACJ,KAAK,MAAM,oBAAoB,CAAC,CAAC,CAAC,CAClC,QAAQ,MAA8B,CAAC,CAAC,CAAC,CAAC,CAC1C,MACE,GAAG,MACF,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,KAClC,EAAE,WAAW,EAAE,YACf,EAAE,SAAS,EAAE,UACb,EAAE,MAAM,MAAM,cAAc,EAAE,MAAM,KAAK,CAAC;AAElD;AAGA,SAAgB,gBACd,OACA,MAAe;CAEf,OAAO,MAAM,QAAQ,MAAM,EAAE,aAAa,QAAQ,EAAE,WAAW,IAAI;AACrE;AAGA,SAAgB,eACd,MACA,MACA,UACA,aAAa,IAAE;CAEf,QAAQ,MAAR;EACE,KAAK,SAAS;GAEZ,MAAM,QAAQ,UAAU,KAAK,MAAM,GAAG,CAAC,IAAI,MAAM,QAAQ;GACzD,OAAO,MAAM,KAAK,EAAE,QAAQ,GAAE,IAAK,GAAG,MAAM,QAAQ,OAAO,CAAC,CAAC;EAC/D;EACA,KAAK,QAAQ;GACX,MAAM,QAAQ,UAAU,MAAM,QAAQ;GACtC,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAC,IAAK,GAAG,MAAM,QAAQ,OAAO,CAAC,CAAC;EAC9D;EACA,KAAK,OACH,OAAO,CAAC,IAAI;EACd,KAAK,UACH,OAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,UAAU,EAAC,IAAK,GAAG,MAAM,QAAQ,MAAM,CAAC,CAAC;CACrF;AACF;AAGA,SAAgB,eACd,MACA,MACA,WACA,aAAa,IAAE;CAEf,QAAQ,MAAR;EACE,KAAK,SACH,OAAO,UAAU,MAAM,SAAS;EAClC,KAAK,QACH,OAAO,QAAQ,MAAM,IAAI,SAAS;EACpC,KAAK,OACH,OAAO,QAAQ,MAAM,SAAS;EAChC,KAAK,UACH,OAAO,QAAQ,MAAM,KAAK,IAAI,GAAG,UAAU,IAAI,SAAS;CAC5D;AACF;AAmBA,SAAgB,iBACd,OACA,MACA,aAAa,GACb,WAAW,gBAAc;CAEzB,MAAM,WAAW,kBAAkB,IAAI;CACvC,IAAI,aAAa,MAAM,OAAO,CAAA;CAC9B,MAAM,OAAO,WAAW,YACtB,KAAK,WAAW;CAClB,MAAM,UAAU,MACb,QAAQ,MAAM,CAAC,EAAE,UAAU,EAAE,WAAW,MAAM,EAAE,SAAS,IAAI,CAAC,CAC9D,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM;CAChE,MAAM,SAAmC,CAAA;CACzC,IAAI,UAAyD,CAAA;CAC7D,IAAI,aAAuB,CAAA;CAC3B,IAAI,aAAa;CACjB,MAAM,cAAa;EACjB,KAAK,MAAM,EAAE,MAAM,YAAY,SAAS;GACtC,MAAM,QAAQ,KAAK,IAAI,KAAK,UAAU,IAAI,GACxC,MAAM,KAAK,IAAI,KAAK,QAAQ,EAAE;GAChC,OAAO,KAAK;IACV;IACA,KAAK,QAAQ;IACb,QAAQ,MAAM;IACd;IACA,SAAS,WAAW;IACpB,cAAc,KAAK,WAAW;IAC9B,YAAY,KAAK,SAAS;GAC3B,CAAA;EACH;EACA,UAAU,CAAA;EACV,aAAa,CAAA;CACf;CACA,KAAK,MAAM,QAAQ,SAAS;EAC1B,IAAI,KAAK,YAAY,YAAY,MAAK;EACtC,IAAI,SAAS,WAAW,WAAW,QAAQ,OAAO,KAAK,QAAQ;EAC/D,IAAI,SAAS,GAAG,SAAS,WAAW,KAAK,KAAK,MAAM,IAAI;OACnD,WAAW,UAAU,KAAK;EAC/B,QAAQ,KAAK;GAAE;GAAM;EAAM,CAAE;EAC7B,aAAa,KAAK,IAAI,eAAe,YAAY,KAAK,SAAS,YAAY,KAAK,MAAM;CACxF;CACA,MAAK;CACL,OAAO;AACT;AAEA,SAAgB,eAAe,SAAiB,MAAY;CAC1D,OAAO,OAAO,IAAI,KAAK,MAAM,UAAU,IAAI,IAAI,OAAO;AACxD;AAGA,SAAgB,eAAe,MAAsB,cAAoB;CACvE,IAAI,KAAK,QAAQ;EACf,MAAM,OAAO,KAAK,MAAM,eAAe,cAAc;EACrD,OAAO;GACL,IAAI,KAAK,MAAM;GACf,OAAO,QAAQ,KAAK,WAAW,IAAI;GACnC,KAAK,QAAQ,KAAK,SAAS,IAAI;GAC/B,QAAQ;GACR,MAAM;EACP;CACH;CACA,OAAO;EACL,IAAI,KAAK,MAAM;EACf,OAAO,mBAAmB,KAAK,WAAW,YAAY;EACtD,KAAK,mBAAmB,KAAK,SAAS,YAAY;EAClD,QAAQ;EACR,MAAM;CACP;AACH;AAGA,SAAgB,iBACd,MACA,QACA,SAAe;CAEf,OAAO;EACL,IAAI,KAAK,MAAM;EACf,OAAO,KAAK,MAAM;EAClB,KAAK,mBAAmB,KAAK,IAAI,QAAQ,KAAK,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC;EAC9E,QAAQ;EACR,MAAM;CACP;AACH;AAGA,SAAgB,sBACd,QACA,QAA6B;CAE7B,IAAI,CAAC,OAAO,MAAM,MAAM,EAAE,OAAO,OAAO,EAAE,GAAG,OAAO;CACpD,OAAO,OAAO,KAAK,MACjB,EAAE,OAAO,OAAO,KAAK;EAAE,GAAG;EAAG,OAAO,OAAO;EAAO,KAAK,OAAO;EAAK,QAAQ,OAAO;CAAM,IAAK,CAAC;AAElG;ACqFA,IAAa,aAAb,MAAa,WAAU;CACZ,SAAS,MAAoB,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CAChC,OAAO,MAAsB,SAAQ,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAErC,OAAO,MAAiB,QAAO,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAClC,QAAQ,MAAiC;EAAC;EAAS;EAAQ;EAAO;CAAQ,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAE5E,SAAS,MAAc,OAAO,SAAS,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CAEzC,iBAAiB,MAA0B,QAAU,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAErD,eAAe,MAAM,GAAC;EAAA,GAAA,YAAA,EAAA,WAAA,eAAA,+BAAA,CAAA;EAAI,WAAW;CAAe,CAAA;CACpD,aAAa,MAAM,IAAE;EAAA,GAAA,YAAA,EAAA,WAAA,aAAA,+BAAA,CAAA;EAAI,WAAW;CAAe,CAAA;CAEnD,eAAe,MAAM,GAAC;EAAA,GAAA,YAAA,EAAA,WAAA,eAAA,+BAAA,CAAA;EAAI,WAAW;CAAe,CAAA;CAEpD,cAAc,MAAM,IAAE;EAAA,GAAA,YAAA,EAAA,WAAA,cAAA,+BAAA,CAAA;EAAI,WAAW;CAAe,CAAA;CACpD,kBAAkB,MAAM,GAAC;EAAA,GAAA,YAAA,EAAA,WAAA,kBAAA,+BAAA,CAAA;EAAI,WAAW;CAAe,CAAA;CACvD,aAAa,MAAM,IAAE;EAAA,GAAA,YAAA,EAAA,WAAA,aAAA,+BAAA,CAAA;EAAI,WAAW;CAAe,CAAA;CAEnD,MAAM,MAAqB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CAEhC,WAAW,MAAM,MAAI;EAAA,GAAA,YAAA,EAAA,WAAA,WAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CAEpD,QAAQ,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACvB,YAAY,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC3B,gBAAgB,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAC/B,YAAY,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC3B,YAAY,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC3B,YAAY,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC3B,WAAW,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAC1B,UAAU,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACzB,aAAa,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,aAAa,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,YAAY,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC3B,cAAc,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAC7B,WAAW,MAAkC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAC7C,aAAa,MAAkC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC/C,cAAc,MAAgD,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAC9D,eAAe,MAAkC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAGjD,gBAAgB,OAAM;CAEtB,eAAe,OAAM;CAErB,cAAc,OAAM;CAEV,IAAI,QAAQ,YAAY;EACzC,OAAO,KAAK;EACZ,WAAW,KAAK;EAChB,eAAe,KAAK;EACpB,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,UAAU,KAAK;EACf,SAAS,KAAK;EACd,YAAY,KAAK;EACjB,YAAY,KAAK;EACjB,WAAW,KAAK;EAChB,aAAa,KAAK;EAClB,UAAU,KAAK;EACf,YAAY,KAAK;EACjB,aAAa,KAAK;EAClB,cAAc,KAAK;CACpB,CAAA;CAEkB,SAAS,WAAW,aAAa;CACjC,QAAQ,eAAe,KAAK,IAAG,CAAE,EAAE,MAAM,GAAG,EAAE,KAAK,QAAO,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAC7D,QAAQ,eAAe,gBAAgB,KAAK,OAAM,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACtD,QAAQ,eAAgB,KAAK,MAAK,IAAK,gBAAgB,KAAK,OAAM,CAAE,IAAI,CAAA,GAAI,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAC5E,WAAW,eACtB,KAAK,eAAc,KAAM,iBAAiB,KAAK,OAAM,CAAE,GAC9D,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACkB,OAAO,eACxB,eAAe,KAAK,KAAI,GAAI,KAAK,KAAI,GAAI,KAAK,SAAQ,GAAI,KAAK,WAAU,CAAE,GAC5E,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACkB,QAAQ,eAAc;EACvC,MAAM,OAAO,KAAK,KAAI;EACtB,OAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,SAAS,EAAC,IAAK,GAAG,MAAM,KAAK,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;CACvF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACiB,WAAW,eAAc;EAC1C,MAAM,QAAQ,eAAe,KAAK,OAAM,GAAI,KAAK,SAAQ,GAAI,OAAO;EACpE,MAAM,OAAO,eAAe,KAAK,OAAM,GAAI,KAAK,SAAQ,GAAI,MAAM;EAClE,OAAO,MAAM,KAAK,GAAG,OAAO;GAAE,OAAO;GAAG,MAAM,KAAK;EAAE,EAAG;CAC1D,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACiB,QAAQ,eAAc;EACvC,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,aAAY,CAAE,CAAC;EAC1D,MAAM,KAAK,KAAK,IAAI,OAAO,GAAG,KAAK,IAAI,IAAI,KAAK,WAAU,CAAE,CAAC;EAC7D,OAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,KAAI,IAAK,GAAG,MAAM,OAAO,CAAC;CAC7D,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAEiB,QAAQ,eAAc;EACvC,MAAM,sBAAM,IAAI,IAAG;EACnB,IAAI,KAAK,KAAI,MAAO,SAAS,OAAO;EACpC,MAAM,MAAM,KAAK,IAAI,GAAG,KAAK,gBAAe,CAAE;EAC9C,KAAK,MAAM,OAAO,KAAK,KAAI,GAAI;GAC7B,MAAM,MAAM,gBAAgB,KAAK,MAAK,GAAI,GAAG;GAC7C,IAAI,CAAC,IAAI,QAAQ;GACjB,MAAM,UAAU,IAAI,SAAS,MAAM,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI;GAC3D,IAAI,IAAI,KAAK;IAAE;IAAS,MAAM,IAAI,SAAS,QAAQ;GAAM,CAAE;EAC7D;EACA,OAAO;CACT,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACiB,SAAS,eAAc;EACxC,MAAM,sBAAM,IAAI,IAAG;EACnB,MAAM,OAAO,KAAK,MAAK,CAAE,CAAC,KAAK,IAC7B,MAAM,KAAK,MAAK,CAAE,CAAC,GAAG,EAAE,IAAK,KAAK;EACpC,KAAK,MAAM,OAAO,KAAK,KAAI,GAAI,IAAI,IAAI,KAAK,iBAAiB,KAAK,MAAK,GAAI,KAAK,MAAM,EAAE,CAAC;EACzF,OAAO;CACT,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACiB,SAAS,eAC1B,KAAK,KAAI,CAAE,CACR,KAAK,UAAU;EAAE;EAAM,OAAO,gBAAgB,KAAK,MAAK,GAAI,IAAI;CAAC,EAAG,CAAC,CACrE,QAAQ,UAAU,MAAM,MAAM,MAAM,GACxC,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACkB,QAAQ,eAAc;EACvC,MAAM,OAAO,KAAK,KAAI,GACpB,SAAS,KAAK,OAAM;EACtB,QAAQ,KAAK,KAAI,GAAjB;GACE,KAAK,SACH,OAAO,aAAa,KAAK,KAAI,GAAI,QAAQ;IAAE,OAAO;IAAQ,MAAM;GAAS,CAAE;GAC7E,KAAK,OACH,OAAO,KAAK,SAAS,KAAK,KAAI,CAAE;GAClC,SAOE,OAAO,IANY,KAAK,eAAe,QAAQ;IAC7C,KAAK;IACL,OAAO;IACP,MAAM;IACN,UAAU;GACX,CACM,CAAA,CAAO,YAAY,IAAI,KAAK,KAAK,EAAE,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAE,CAAC;EAEvE;CACF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAEiB,YAAY,OAAkB,KAAK,KAAI,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC1C,aAAa,OAAsB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CACxC,UAAU,OAAuB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACtC,WAAW,OAAoD,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAEpE,OAAoB,OAAO,UAAU,CAAC,CAAC;CAChD,OAAoB;CACpB,YAAY;CACZ,gBAAgB;CAChB,SAAS;CACT,eAA8B;CAEtC,cAAA;EAEE,aAAY;GACV,MAAM,OAAO,KAAK,KAAI;GACtB,MAAM,QAAQ,KAAK,UAAS;GAC5B,IAAI,KAAK,KAAI,MAAO,WAAW,CAAC,KAAK,SAAS,KAAK,GACjD,KAAK,UAAU,IAAI,KAAK,SAAS,KAAK,KAAI,CAAE,IAAI,KAAK,KAAI,IAAK,KAAK,EAAE;EAEzE,CAAC;EACD,aAAY;GACV,MAAM,SAAS,KAAK,OAAM;GAC1B,IAAI,KAAK,QAAQ,WAAW,KAAK,KAAK,QAAQ,KAAK,OAAO,IAAI;EAChE,CAAC;EACD,wBAAuB;GACrB,MAAM,QAAQ,KAAK,UAAS;GAC5B,IAAI,CAAC,KAAK,WAAW;GACrB,KAAK,YAAY;GACjB,KAAK,KACF,cAA2B,iCAAiC,MAAK,qBAAsB,CAAC,EACvF,MAAK;EACX,CAAC;EAED,wBAAuB;GACrB,MAAM,MAAM,KAAK,KAAI,IAAK,KAAK,KAAI,CAAE,CAAC;GACtC,IAAI,KAAK,KAAI,MAAO,UAAU,KAAK,KAAI,MAAO,OAAO;GACrD,IAAI,KAAK,iBAAiB,KAAK;GAC/B,KAAK,eAAe;GACpB,MAAM,WAAW,KAAK,KAAK,cAA2B,sBAAsB;GAC5E,MAAM,OAAO,KAAK,KAAK,cAA2B,oBAAoB;GACtE,IAAI,CAAC,YAAY,CAAC,MAAM;GACxB,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK,aAAY,IAAK,KAAK,MAAK,CAAE,CAAC,EAAE;GAChE,SAAS,YAAa,KAAK,eAAe,KAAK,MAAK,CAAE,CAAC,SAAU;EACnE,CAAC;EACD,MAAM,aAAa,OAAO,UAAU;EACpC,WAAW,gBAAgB,KAAK,OAAO,KAAK,CAAC;EAC7C,sBAAqB;GACnB,MAAM,SAAS,UAAgB;IAC7B,IAAI,CAAC,KAAK,eAAe;IACzB,KAAK,gBAAgB;IACrB,MAAM,eAAc;IACpB,MAAM,gBAAe;GACvB;GAEA,MAAM,cAAe,KAAK,gBAAgB;GAC1C,KAAK,KAAK,iBAAiB,SAAS,OAAO,IAAI;GAC/C,KAAK,KAAK,iBAAiB,eAAe,OAAO,IAAI;GACrD,WAAW,gBAAe;IACxB,KAAK,KAAK,oBAAoB,SAAS,OAAO,IAAI;IAClD,KAAK,KAAK,oBAAoB,eAAe,OAAO,IAAI;GAC1D,CAAC;EACH,CAAC;CACH;CAIU,UAAO;EACf,KAAK,KAAK,IAAI,KAAK,MAAK,CAAE;EAC1B,KAAK,UAAU,IAAI,KAAK,MAAK,CAAE;CACjC;CAEU,KAAK,WAAiB;EAC9B,MAAM,OAAO,eAAe,KAAK,KAAI,GAAI,KAAK,KAAI,GAAI,WAAW,KAAK,WAAU,CAAE;EAClF,KAAK,KAAK,IAAI,IAAI;EAClB,KAAK,UAAU,IAAI,IAAI;CACzB;CAEU,QAAQ,MAAe;EAC/B,KAAK,KAAK,IAAI,IAAI;EAClB,KAAK,UAAU,IAAI,IAAI;EACvB,IAAI,KAAK,MAAK,CAAE,CAAC,SAAS,KAAK,GAAG,KAAK,KAAK,IAAI,KAAK;CACvD;CAEQ,SAAS,OAAoB;EAEnC,IAAI,CADW,MAAM,OACT,UAAU,SAAS,kBAAkB,GAAG;EACpD,MAAM,MACJ,KAAK,KAAK,cAAc,aAAa,iBAAiB,KAAK,IAAI,CAAC,CAAC,cAAc;EACjF,MAAM,OAAO,cAAc,MAAM,KAAK,KAAK,UAAS,GAAI;GACtD,UAAU,KAAK,SAAQ;GACvB;GACA,OAAO,MAAM;EACd,CAAA;EACD,IAAI,CAAC,MAAM;EACX,MAAM,eAAc;EACpB,IAAI,CAAC,KAAK,KAAI,CAAE,CAAC,SAAS,IAAI,GAAG,KAAK,KAAK,IAAI,IAAI;EACnD,KAAK,UAAU,IAAI,IAAI;EACvB,KAAK,YAAY;CACnB;CAIU,SAAS,OAAQ;EACzB,KAAK,cAAc,KAAK,KAAK;CAC/B;CAMU,WAAW,OAAiB;EACpC,MAAM,SAAS,MAAM;EACrB,IAAI,OAAO,QAAQ,QAAQ,GAAG;EAC9B,MAAM,OAAO,OAAO,QAAqB,+CAA+C;EACxF,IAAI,MAAM;GACR,KAAK,aAAa,KAAK;IAAE,MAAM,KAAK,QAAQ;IAAU,MAAM;GAAI,CAAE;GAClE;EACF;EACA,MAAM,SAAS,OAAO,QAAqB,sBAAsB;EACjE,IAAI,QAAQ,KAAK,UAAU,OAAO,QAAQ,OAAO,QAAQ,OAAQ;CACnE;CAEQ,UAAU,OAAmB,QAAqB,MAAe;EACvE,MAAM,SAAS,KAAK,SAAS,QAAQ,MAAM,OAAO;EAClD,MAAM,UAAU,KAAK,IACnB,iBAAiB,KAAK,KAAI,GAC1B,KAAK,MAAM,SAAS,KAAK,KAAI,CAAE,IAAI,KAAK,KAAI,CAAE;EAEhD,KAAK,aAAa,KAAK;GAAE;GAAM,MAAM,KAAK,MAAM,OAAO;EAAC,CAAE;CAC5D;CAIU,UAAU,OAAqB,MAAyB,MAAuB;EACvF,IACE,CAAC,KAAK,SAAQ,KACd,CAAC,MAAM,aACP,MAAM,WAAW,KACjB,MAAM,gBAAgB,WACtB,KAAK,MAEL;EACF,IAAI,SAAS,UAAU,MAAM,gBAAe;EAC5C,MAAM,UACJ,SAAS,WACJ,MAAM,cAA8B,QAAQ,qBAAqB,IAClE,MAAM;EAEZ,IAAI;GACF,QAAQ,kBAAkB,MAAM,SAAS;EAC3C,QAAQ;GACN;EACF;EACA,MAAM,eAAc;EACpB,KAAK,OAAO;GACV,SAAS,MAAM;GACf;GACA;GACA;GACA,QAAQ,KAAK,OAAM;GACnB,GAAG,MAAM;GACT,GAAG,MAAM;GACT,QAAQ,KAAK,QAAQ,MAAM,SAAS,MAAM,SAAS,KAAK,MAAM;GAC9D,QAAQ;EACT;CACH;CAEU,SAAS,OAAmB;EACpC,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,QAAQ,KAAK,YAAY,MAAM,WAAW;EAC/C,IAAI,MAAM,YAAY,GAAG;GACvB,KAAK,OAAO,KAAK;GACjB;EACF;EACA,IAAI,CAAC,KAAK,UAAU,KAAK,MAAM,MAAM,UAAU,KAAK,GAAG,MAAM,UAAU,KAAK,CAAC,IAAI,GAAG;EACpF,IAAI,CAAC,KAAK,QAAQ;GAChB,KAAK,SAAS;GACd,IAAI,CAAC,KAAK,QAAQ,SAAS,KAAK,KAAK,cAAc,aAAa,GAC9D,KAAK,QAAQ,MAAM,EAAE,eAAe,KAAI,CAAE;GAC5C,KAAK,WAAW,IAAI,KAAK,KAAK,MAAM,EAAE;EACxC;EACA,MAAM,SAAS,KAAK,SAAS,MAAM,MAAM,SAAS,MAAM,OAAO;EAC/D,KAAK,QAAQ,IAAI,SAAS;GAAE;GAAQ,MAAM,KAAK;EAAI,IAAK,IAAI;CAC9D;CAEU,QAAQ,OAAmB;EACnC,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,QAAQ,KAAK,YAAY,MAAM,WAAW;EAC/C,MAAM,SAAS,KAAK,SAAS,KAAK,SAAS,MAAM,MAAM,SAAS,MAAM,OAAO,IAAI;EACjF,KAAK,gBAAgB,KAAK;EAC1B,KAAK,OAAO,KAAK,UAAU,CAAC,MAAM;EAClC,IAAI,QAAQ;GACV,KAAK,SAAS,KAAK,EAAC,CAAE,CAAC,YAAY,KAAK,KAAK,MAAM,OAAO,KAAK,SAAS,MAAM,CAAC,CAAC;GAChF,KAAK,YAAY,KAAK,MAAM;EAC9B;CACF;CAEU,WAAW,OAAmB;EACtC,IAAI,MAAM,cAAc,KAAK,MAAM,SAAS,KAAK,OAAO,CAAC,CAAC,KAAK,MAAM,MAAM;CAC7E;CAEU,IAAI,OAAoB;EAChC,IAAI,CAAC,KAAK,MAAM;GACd,IAAI,KAAK,KAAI,MAAO,SAAS,KAAK,SAAS,KAAK;GAChD;EACF;EACA,IAAI,MAAM,aAAa;EACvB,IAAI,MAAM,QAAQ,YAAY,MAAM,QAAQ,OAAO;GACjD,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAc;IACpB,MAAM,gBAAe;GACvB;GAEA,KAAK,gBAAgB,KAAK,KAAK;GAC/B,KAAK,OAAO,IAAI;EAClB;CACF;CAGQ,SAAS,MAAY,GAAW,GAAS;EAC/C,MAAM,QAAQ,KAAK,QAAQ,GAAG,GAAG,KAAK,KAAK,MAAM;EACjD,IAAI,CAAC,SAAS,CAAC,KAAK,QAAQ,OAAO;EACnC,MAAM,YACH,kBAAkB,MAAM,IAAI,IAAK,kBAAkB,KAAK,OAAO,IAAI,KAAM;EAC5E,IAAI;EACJ,IAAI,KAAK,SAAS,UAAU;GAC1B,MAAM,MAAM,kBAAkB,MAAM,IAAI,IAAK,eAAe,MAAM,QAAQ,KAAK,KAAI,CAAE;GACrF,SAAS,iBAAiB,KAAK,MAAM,KAAK,KAAK,KAAI,CAAE;EACvD,OAAO,IAAI,KAAK,KAAK,UAAU,KAAK,KAAI,MAAO,SAC7C,SAAS,eAAe,KAAK,MAAM,WAAW,cAAc;OACvD;GACL,MAAM,UAAU,eAAe,MAAM,SAAS,KAAK,OAAO,QAAQ,KAAK,KAAI,CAAE;GAC7E,SAAS,eAAe,KAAK,MAAM,WAAW,iBAAiB,OAAO;EACxE;EACA,OAAO,OAAO,UAAU,KAAK,KAAK,MAAM,SAAS,OAAO,QAAQ,KAAK,KAAK,MAAM,MAC5E,OACA;CACN;CAGQ,QACN,GACA,GACA,QAAe;EAEf,MAAM,WACJ,KAAK,KAAI,MAAO,UACZ,kCACA,SACE,yCACA;EACR,KAAK,MAAM,MAAM,MAAM,KAAK,KAAK,KAAK,iBAA8B,QAAQ,CAAC,GAAG;GAC9E,MAAM,IAAI,GAAG,sBAAqB;GAKlC,IAAI,EAHF,KAAK,EAAE,QACP,KAAK,EAAE,UACN,UAAU,KAAK,KAAI,MAAO,UAAU,KAAK,EAAE,OAAO,KAAK,EAAE,SAAS,QACxD;GACb,MAAM,SAAS,KAAK,KAAI,MAAO,WAAW,SAAS,IAAI,KAAK,SAAS,IAAI,CAAC;GAC1E,OAAO;IAAE,MAAM,GAAG,QAAQ;IAAU;GAAM;EAC5C;EACA,OAAO;CACT;CAGQ,SAAS,QAAqB,GAAS;EAC7C,MAAM,IAAI,OAAO,sBAAqB;EACtC,MAAM,OAAO,KAAK,MAAK,CAAE,CAAC,KAAK;EAC/B,MAAM,OAAO,KAAK,MAAK,CAAE,CAAC,SAAS;EAEnC,OAAO,OADO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,EAAE,OAAO,EAAE,MAAM,CAC9C,IAAQ;CACxB;CAEQ,OAAO,UAAiB;EAC9B,MAAM,OAAO,KAAK;EAClB,KAAK,OAAO;EACZ,KAAK,WAAW,IAAI,IAAI;EACxB,KAAK,QAAQ,IAAI,IAAI;EACrB,IAAI,CAAC,MAAM;EACX,IAAI,KAAK,QAAQ,oBAAoB,KAAK,OAAO,GAC/C,KAAK,QAAQ,sBAAsB,KAAK,OAAO;EACjD,IAAI,YAAY,KAAK,QAAQ,KAAK,SAAS,KAAK,EAAC,CAAE,CAAC,aAAa,KAAK,KAAK,MAAM,KAAK,CAAC;CACzF;CAGU,MAAM,KAAc;EAC5B,MAAM,KAAK,KAAK,QAAO;EACvB,IAAI,CAAC,MAAM,GAAG,OAAO,UAAU,KAAK,KAAI,MAAO,SAAS,OAAO;EAC/D,MAAM,QAAQ,kBAAkB,GAAG,OAAO,KAAK,GAC7C,MAAM,kBAAkB,GAAG,OAAO,GAAG;EACvC,MAAM,WAAW,kBAAkB,GAAG;EACtC,MAAM,OAAO,WAAW,KAAK,MAAK,CAAE,CAAC,KAAK,IACxC,KAAK,YAAY,KAAK,MAAK,CAAE,CAAC,GAAG,EAAE,IAAK,KAAK;EAC/C,IAAI,OAAO,QAAQ,SAAS,IAAI,OAAO;EACvC,MAAM,MAAM,KAAK,IAAI,OAAO,IAAI,IAAI;EACpC,OAAO;GAAE;GAAK,MAAM,KAAK,IAAI,KAAK,EAAE,IAAI,OAAO;GAAK,UAAU;EAAK;CACrE;CAEU,QAAQ,KAAc;EAC9B,MAAM,MAAM,KAAK,IAAG;EACpB,IAAI,CAAC,OAAO,IAAI,MAAM,GAAG,EAAE,MAAM,KAAK,OAAO;EAC7C,MAAM,SAAS,kBAAkB,GAAG;EACpC,IAAI,WAAW,MAAM,OAAO;EAC5B,MAAM,SAAS,oBAAoB,MAAM,IAAI,KAAK,MAAK,CAAE,CAAC,KAAK;EAC/D,OAAO,UAAU,KAAK,UAAU,KAAK,MAAK,CAAE,CAAC,SAAS,KAAK,SAAS;CACtE;CAEU,OAAO,KAAc;EAC7B,OAAO,gBAAgB,KAAK,MAAK,GAAI,GAAG,CAAC,CAAC,QAAQ,MAAM,EAAE,MAAM;CAClE;CAIU,SAAS,MAAoB;EACrC,MAAM,IAAI,KAAK,EAAC;EAChB,OAAO;GAAE,OAAO,EAAE;GAAW,MAAM,EAAE;GAAU,KAAK,EAAE;GAAS,QAAQ,EAAE;EAAU,EAAG;CACxF;CAEU,UAAU,KAAc;EAChC,OAAO,IAAI,MAAM,GAAG,CAAC,MAAM,KAAK,KAAI,CAAE,CAAC,MAAM,GAAG,CAAC;CACnD;CAEU,UAAU,KAAc;EAChC,OAAO,aAAa,KAAK,KAAK,OAAM,GAAI,EAAE,KAAK,UAAS,CAAE;CAC5D;CAEU,aAAa,KAAc;EACnC,OAAO,aAAa,KAAK,KAAK,OAAM,GAAI,EAAE,SAAS,QAAO,CAAE;CAC9D;CAEU,SAAS,KAAc;EAC/B,OAAO,aAAa,KAAK,KAAK,OAAM,GAAI;GACtC,SAAS;GACT,KAAK;GACL,OAAO;GACP,MAAM;EACP,CAAA;CACH;CAEU,SAAS,KAAc;EAC/B,MAAM,QAAQ,gBAAgB,KAAK,MAAK,GAAI,GAAG,CAAC,CAAC;EACjD,OAAO,GAAG,KAAK,SAAS,GAAG,EAAC,IAAK,KAAK,EAAC,CAAE,CAAC,WAAW,KAAK;CAC5D;CAEU,KAAK,SAAe;EAC5B,OAAO,IAAI,KAAK,eAAe,KAAK,OAAM,GAAI;GAC5C,MAAM;GACN,QAAQ;GACR,UAAU;EACX,CAAA,CAAC,CAAC,uBAAO,IAAI,KAAK,UAAU,GAAK,CAAC;CACrC;CAEU,UAAU,MAAY;EAC9B,OAAO,IAAI,KAAK,eAAe,KAAK,OAAM,GAAI;GAAE,MAAM;GAAW,UAAU;EAAK,CAAE,CAAC,CAAC,OAClF,IAAI,KAAK,KAAK,IAAI,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC;CAExC;CAGU,UAAU,MAAsB,KAAc;EACtD,IAAI,KAAK,QAAQ,OAAO,KAAK,EAAC,CAAE,CAAC;EAGjC,OAAO,GAFO,KAAK,cAAc,MAAM,KAAK,KAAK,KAAK,QAAQ,IAAI,IAEnD,KADH,eAAe,KAAK,SAAS,CAAC,MAAM,MAAM,KAAK,KAAK,KAAK,MAAM,IAAI;CAEjF;CAEU,WAAW,MAAoB;EACvC,MAAM,OAAO,KAAK,SAAS,KAAK,SAAS;EACzC,IAAI,KAAK,QAAQ;GACf,MAAM,OAAO,KAAK,YAAY,KAAK,YAAY,MAAM,KAAK,SAAS,KAAK,OAAO,MAAM;GACrF,OAAO,GAAG,KAAK,MAAM,MAAK,IAAK,OAAO,KAAI,IAAK,KAAK,EAAC,CAAE,CAAC;EAC1D;EACA,MAAM,MACJ,KAAK,YAAY,KAAK,YAClB,GAAG,KAAK,SAAS,KAAK,OAAO,EAAC,GAAI,KAAK,KAAK,KAAK,MAAM,MACvD,KAAK,KAAK,KAAK,MAAM;EAC3B,OAAO,GAAG,KAAK,MAAM,MAAK,IAAK,KAAI,IAAK,KAAK,KAAK,KAAK,QAAQ,EAAC,KAAM;CACxE;CAEQ,SAAS,QAA6B;EAC5C,IAAI,OAAO,QAAQ,OAAO,KAAK,SAAS,OAAO,KAAK;EACpD,MAAM,QAAQ,kBAAkB,OAAO,KAAK;EAC5C,OAAO,GAAG,KAAK,SAAS,OAAO,MAAM,MAAM,GAAG,EAAE,CAAC,EAAC,IAAK,KAAK,KAAK,KAAK;CACxE;CAEQ,MAAM,SAAe;EAC3B,MAAM,IAAI,KAAK,MAAM,UAAU,EAAE,GAC/B,IAAI,KAAK,MAAM,UAAU,EAAE;EAC7B,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,EAAC,GAAI,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;CACnE;CAEQ,OAAI;EACV,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,YAAW,CAAE,CAAC;CACtD;CAEQ,SAAS,MAAY;EAC3B,KAAK,SAAS,IAAI,CAAC;GAAE,QAAQ,EAAE,KAAK;GAAQ;EAAI,CAAE,CAAC;CACrD;CAthBW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAU,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAV,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAU,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,gBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,iBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,KAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,eAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA;GAAA,MAAA;GAAA,MAAA;GAAA,eAAA;GAAA,cAAA;GAAA,aAAA;EAAA;EAAA,MAAA;GAAA,WAAA;IAAA,WAAA;IAAA,SAAA;GAAA;GAAA,YAAA;IAAA,kBAAA;IAAA,mBAAA;GAAA;GAAA,gBAAA;EAAA;EAAA,UAAA;EAAA,UAnUX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwTT,UAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MAzTS;GAAQ,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAM,UAAA;GAAA,QAAA,CAAA,QAAA,OAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;EAAA,eAAA,GAAA,kBAAA;CAAA,CAAA;;AAoUf,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAU,YAAA,CAAA;EAtUtB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS,CAAC,UAAU,MAAM;GAC1B,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyTV,MAAM;IACJ,OAAO;IACP,oBAAoB;IACpB,qBAAqB;IACrB,aAAa;IACb,WAAW;GACZ;GACD,iBAAiB,wBAAwB;GACzC,eAAe,kBAAkB;EAClC,CAAA"}
@@ -1,4 +1,4 @@
1
- const VD_VERSION = "0.1.0";
1
+ const VD_VERSION = "0.2.0";
2
2
  export { VD_VERSION };
3
3
 
4
4
  //# sourceMappingURL=vadem-ui.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"vadem-ui.mjs","names":[],"sources":["../../../projects/ui/src/public-api.ts"],"sourcesContent":["/*\n * Public API surface of @vadem/ui (primary entry point).\n * Components live in secondary entry points: @vadem/ui/button, @vadem/ui/card, ...\n */\nexport const VD_VERSION = '0.1.0';\n"],"mappings":"AAIA,MAAa,aAAa"}
1
+ {"version":3,"file":"vadem-ui.mjs","names":[],"sources":["../../../projects/ui/src/public-api.ts"],"sourcesContent":["/*\n * Public API surface of @vadem/ui (primary entry point).\n * Components live in secondary entry points: @vadem/ui/button, @vadem/ui/card, ...\n */\nexport const VD_VERSION = '0.2.0';\n"],"mappings":"AAIA,MAAa,aAAa"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vadem/ui",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^22.2.0",
6
6
  "@angular/core": "^22.2.0",
@@ -150,6 +150,10 @@
150
150
  "types": "./types/vadem-ui-input.d.ts",
151
151
  "default": "./fesm2022/vadem-ui-input.mjs"
152
152
  },
153
+ "./kanban": {
154
+ "types": "./types/vadem-ui-kanban.d.ts",
155
+ "default": "./fesm2022/vadem-ui-kanban.mjs"
156
+ },
153
157
  "./kbd": {
154
158
  "types": "./types/vadem-ui-kbd.d.ts",
155
159
  "default": "./fesm2022/vadem-ui-kbd.mjs"
@@ -214,6 +218,10 @@
214
218
  "types": "./types/vadem-ui-reorder-list.d.ts",
215
219
  "default": "./fesm2022/vadem-ui-reorder-list.mjs"
216
220
  },
221
+ "./schedule": {
222
+ "types": "./types/vadem-ui-schedule.d.ts",
223
+ "default": "./fesm2022/vadem-ui-schedule.mjs"
224
+ },
217
225
  "./scroll-area": {
218
226
  "types": "./types/vadem-ui-scroll-area.d.ts",
219
227
  "default": "./fesm2022/vadem-ui-scroll-area.mjs"
@@ -56,8 +56,10 @@
56
56
  @import './autocomplete.css';
57
57
  @import './navigation-list.css';
58
58
  @import './sidebar.css';
59
+ @import './kanban.css';
59
60
  @import './kbd.css';
60
61
  @import './progress-ring.css';
62
+ @import './schedule.css';
61
63
  @import './search-input.css';
62
64
  @import './stat.css';
63
65
  @import './chart.css';
@@ -0,0 +1,220 @@
1
+ /* Kanban board - spec: specs/kanban.md */
2
+ @layer vd.components {
3
+ .vd-kanban {
4
+ --vd-kanban-gap: var(--vd-space-4);
5
+ --vd-kanban-column-width: 18rem;
6
+ --vd-kanban-column-padding: var(--vd-space-3);
7
+ --vd-kanban-column-radius: var(--vd-radius-surface);
8
+ --vd-kanban-column-bg: var(--vd-color-surface-sunken);
9
+ --vd-kanban-column-border: var(--vd-color-border);
10
+ --vd-kanban-card-gap: var(--vd-space-2);
11
+ --vd-kanban-card-padding: var(--vd-space-3);
12
+ --vd-kanban-card-radius: max(
13
+ var(--vd-radius-xs),
14
+ calc(var(--vd-kanban-column-radius) - var(--vd-kanban-column-padding))
15
+ );
16
+ --vd-kanban-card-bg: var(--vd-color-surface-raised);
17
+ --vd-kanban-card-border: var(--vd-color-border);
18
+ --vd-kanban-card-shadow: var(--vd-highlight-top);
19
+ --vd-kanban-muted: var(--vd-color-text-muted);
20
+ --vd-kanban-active-bg: var(--vd-color-action-subtle);
21
+ --vd-kanban-marker: var(--vd-color-focus);
22
+ --vd-kanban-ghost-shadow: var(--vd-shadow-lg);
23
+ --vd-kanban-ghost-tilt: 2deg;
24
+
25
+ display: block;
26
+ min-inline-size: 0;
27
+ color: var(--vd-color-text);
28
+ }
29
+
30
+ .vd-kanban__columns {
31
+ /* Containing block for visually hidden text, so it scrolls and clips with the columns. */
32
+ position: relative;
33
+ display: flex;
34
+ align-items: flex-start;
35
+ gap: var(--vd-kanban-gap);
36
+ overflow-x: auto;
37
+ overscroll-behavior-inline: contain;
38
+ padding-block-end: var(--vd-space-2);
39
+ }
40
+
41
+ .vd-kanban__column {
42
+ display: flex;
43
+ flex-direction: column;
44
+ flex: 0 0 var(--vd-kanban-column-width);
45
+ max-inline-size: 100%;
46
+ min-inline-size: 0;
47
+ gap: var(--vd-kanban-card-gap);
48
+ padding: var(--vd-kanban-column-padding);
49
+ border: var(--vd-border-width) solid var(--vd-kanban-column-border);
50
+ border-radius: var(--vd-kanban-column-radius);
51
+ background: var(--vd-kanban-column-bg);
52
+ }
53
+
54
+ .vd-kanban__column[data-drop-target] {
55
+ border-color: var(--vd-kanban-marker);
56
+ }
57
+
58
+ .vd-kanban__header {
59
+ display: grid;
60
+ gap: var(--vd-space-1);
61
+ padding-inline: var(--vd-space-1);
62
+ }
63
+
64
+ .vd-kanban__title {
65
+ display: flex;
66
+ align-items: baseline;
67
+ gap: var(--vd-space-2);
68
+ margin: 0;
69
+ font-family: var(--vd-font-mono);
70
+ font-size: var(--vd-text-xs);
71
+ font-weight: var(--vd-weight-semibold);
72
+ letter-spacing: var(--vd-tracking-caps);
73
+ text-transform: uppercase;
74
+ }
75
+
76
+ .vd-kanban__title bdi {
77
+ min-inline-size: 0;
78
+ overflow-wrap: anywhere;
79
+ }
80
+
81
+ .vd-kanban__count {
82
+ color: var(--vd-kanban-muted);
83
+ font-variant-numeric: tabular-nums;
84
+ }
85
+
86
+ .vd-kanban__header-extra {
87
+ color: var(--vd-kanban-muted);
88
+ font-size: var(--vd-text-sm);
89
+ }
90
+
91
+ .vd-kanban__cards {
92
+ display: flex;
93
+ flex-direction: column;
94
+ gap: var(--vd-kanban-card-gap);
95
+ margin: 0;
96
+ padding: 0;
97
+ list-style: none;
98
+ }
99
+
100
+ .vd-kanban__card {
101
+ position: relative;
102
+ display: grid;
103
+ grid-template-columns: minmax(0, 1fr) auto;
104
+ align-items: start;
105
+ gap: var(--vd-space-2);
106
+ padding: var(--vd-kanban-card-padding);
107
+ border: var(--vd-border-width) solid var(--vd-kanban-card-border);
108
+ border-radius: var(--vd-kanban-card-radius);
109
+ background: var(--vd-kanban-card-bg);
110
+ box-shadow: var(--vd-kanban-card-shadow);
111
+ cursor: grab;
112
+ user-select: none;
113
+ -webkit-touch-callout: none;
114
+ }
115
+
116
+ .vd-kanban__card:focus-visible {
117
+ outline: var(--vd-focus-ring-width) solid var(--vd-color-focus);
118
+ outline-offset: var(--vd-focus-ring-offset);
119
+ }
120
+
121
+ .vd-kanban__content {
122
+ min-inline-size: 0;
123
+ overflow-wrap: anywhere;
124
+ user-select: text;
125
+ }
126
+
127
+ .vd-kanban__move {
128
+ margin-block: calc(-1 * var(--vd-space-1));
129
+ margin-inline-end: calc(-1 * var(--vd-space-1));
130
+ }
131
+
132
+ /* The lifted card leaves a slot of the same size; its floating copy follows the pointer. */
133
+ .vd-kanban__card[data-dragging] {
134
+ border-style: dashed;
135
+ background: var(--vd-kanban-active-bg);
136
+ box-shadow: none;
137
+ }
138
+
139
+ .vd-kanban__card[data-dragging] > * {
140
+ visibility: hidden;
141
+ }
142
+
143
+ /* The slot holds focus only so Escape reaches the board; the lifted copy is the focus cue. */
144
+ .vd-kanban__card[data-dragging]:focus-visible {
145
+ outline: none;
146
+ }
147
+
148
+ /* Shown as a manual popover: the top layer keeps it above everything without z-index. */
149
+ .vd-kanban__ghost {
150
+ position: fixed;
151
+ inset-block: 0 auto;
152
+ inset-inline: 0 auto;
153
+ margin: 0;
154
+ overflow: visible;
155
+ color: inherit;
156
+ translate: var(--vd-kanban-ghost-x, 0) var(--vd-kanban-ghost-y, 0);
157
+ rotate: var(--vd-kanban-ghost-tilt);
158
+ box-shadow: var(--vd-kanban-ghost-shadow), var(--vd-kanban-card-shadow);
159
+ cursor: grabbing;
160
+ pointer-events: none;
161
+ }
162
+
163
+ [dir='rtl'] .vd-kanban__ghost,
164
+ .vd-kanban:dir(rtl) .vd-kanban__ghost {
165
+ rotate: calc(-1 * var(--vd-kanban-ghost-tilt));
166
+ }
167
+
168
+ /* Drop marker: a line in the gap; never changes card geometry. */
169
+ .vd-kanban__card[data-drop]::after {
170
+ content: '';
171
+ position: absolute;
172
+ inset-inline: 0;
173
+ block-size: var(--vd-focus-ring-width);
174
+ background: var(--vd-kanban-marker);
175
+ pointer-events: none;
176
+ }
177
+
178
+ .vd-kanban__card[data-drop='before']::after {
179
+ inset-block-start: calc(-1 * (var(--vd-kanban-card-gap) + var(--vd-focus-ring-width)) / 2);
180
+ }
181
+
182
+ .vd-kanban__card[data-drop='after']::after {
183
+ inset-block-end: calc(-1 * (var(--vd-kanban-card-gap) + var(--vd-focus-ring-width)) / 2);
184
+ }
185
+
186
+ .vd-kanban[data-state='disabled'] .vd-kanban__card {
187
+ cursor: default;
188
+ }
189
+
190
+ .vd-kanban__empty {
191
+ padding: var(--vd-kanban-card-padding);
192
+ border: var(--vd-border-width) dashed var(--vd-kanban-column-border);
193
+ border-radius: var(--vd-kanban-card-radius);
194
+ color: var(--vd-kanban-muted);
195
+ font-size: var(--vd-text-sm);
196
+ text-align: center;
197
+ }
198
+
199
+ .vd-kanban__invalid {
200
+ color: var(--vd-kanban-muted);
201
+ }
202
+
203
+ @media (forced-colors: active) {
204
+ .vd-kanban__column,
205
+ .vd-kanban__card {
206
+ border-color: CanvasText;
207
+ }
208
+ .vd-kanban__column[data-drop-target],
209
+ .vd-kanban__card[data-dragging] {
210
+ outline: var(--vd-border-width) solid Highlight;
211
+ outline-offset: calc(-1 * var(--vd-border-width));
212
+ }
213
+ .vd-kanban__card[data-drop]::after {
214
+ background: Highlight;
215
+ }
216
+ .vd-kanban__ghost {
217
+ border-color: Highlight;
218
+ }
219
+ }
220
+ }