@danxbot/ui 1.0.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/LICENSE +21 -0
- package/README.md +126 -0
- package/dist/fonts/bricolage-grotesque-0.woff2 +0 -0
- package/dist/fonts/bricolage-grotesque-1.woff2 +0 -0
- package/dist/fonts/bricolage-grotesque-2.woff2 +0 -0
- package/dist/fonts/figtree-0.woff2 +0 -0
- package/dist/fonts/figtree-1.woff2 +0 -0
- package/dist/fonts/figtree-2.woff2 +0 -0
- package/dist/fonts/figtree-3.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-0.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-1.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-10.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-11.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-2.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-3.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-4.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-5.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-6.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-7.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-8.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-9.woff2 +0 -0
- package/dist/fonts.css +187 -0
- package/dist/index.js +42425 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +190 -0
- package/dist/types/components/Accordion.d.ts +15 -0
- package/dist/types/components/AppShell.d.ts +58 -0
- package/dist/types/components/Avatar.d.ts +154 -0
- package/dist/types/components/Badge.d.ts +73 -0
- package/dist/types/components/Button.d.ts +103 -0
- package/dist/types/components/Card.d.ts +193 -0
- package/dist/types/components/Choice.d.ts +112 -0
- package/dist/types/components/CodeEditor.d.ts +86 -0
- package/dist/types/components/Combobox.d.ts +37 -0
- package/dist/types/components/CommandPalette.d.ts +33 -0
- package/dist/types/components/DatePicker.d.ts +20 -0
- package/dist/types/components/Dialog.d.ts +117 -0
- package/dist/types/components/DragDrop.d.ts +60 -0
- package/dist/types/components/ErrorBoundary.d.ts +16 -0
- package/dist/types/components/Field.d.ts +37 -0
- package/dist/types/components/FileUpload.d.ts +22 -0
- package/dist/types/components/Icon.d.ts +40 -0
- package/dist/types/components/Input.d.ts +120 -0
- package/dist/types/components/Loading.d.ts +83 -0
- package/dist/types/components/MarkdownEditor.d.ts +24 -0
- package/dist/types/components/Menu.d.ts +57 -0
- package/dist/types/components/Navigation.d.ts +46 -0
- package/dist/types/components/NumberInput.d.ts +88 -0
- package/dist/types/components/OTPInput.d.ts +11 -0
- package/dist/types/components/Panel.d.ts +94 -0
- package/dist/types/components/Popover.d.ts +64 -0
- package/dist/types/components/Progress.d.ts +178 -0
- package/dist/types/components/Select.d.ts +53 -0
- package/dist/types/components/Slider.d.ts +203 -0
- package/dist/types/components/Spinner.d.ts +29 -0
- package/dist/types/components/Stat.d.ts +98 -0
- package/dist/types/components/StatusSelect.d.ts +23 -0
- package/dist/types/components/Surface.d.ts +110 -0
- package/dist/types/components/Table.d.ts +46 -0
- package/dist/types/components/Tabs.d.ts +84 -0
- package/dist/types/components/ThemeMenu.d.ts +4 -0
- package/dist/types/components/Toast.d.ts +46 -0
- package/dist/types/components/Toggle.d.ts +65 -0
- package/dist/types/components/Tree.d.ts +20 -0
- package/dist/types/components/calendar/CalendarMonth.d.ts +33 -0
- package/dist/types/components/calendar/CalendarTimeGrid.d.ts +75 -0
- package/dist/types/components/calendar/EventActions.d.ts +17 -0
- package/dist/types/components/calendar/format.d.ts +43 -0
- package/dist/types/components/calendar/index.d.ts +9 -0
- package/dist/types/components/calendar/palette.d.ts +17 -0
- package/dist/types/components/calendar/use-calendar-drag.d.ts +54 -0
- package/dist/types/components/calendar/use-event-keyboard.d.ts +24 -0
- package/dist/types/components/calendar/use-grid-navigation.d.ts +47 -0
- package/dist/types/components/calendar/use-now.d.ts +20 -0
- package/dist/types/components/chat/Attachment.d.ts +49 -0
- package/dist/types/components/chat/Chat.d.ts +60 -0
- package/dist/types/components/chat/Composer.d.ts +29 -0
- package/dist/types/components/chat/ContextMeter.d.ts +55 -0
- package/dist/types/components/chat/EffortControl.d.ts +23 -0
- package/dist/types/components/chat/Markdown.d.ts +22 -0
- package/dist/types/components/chat/Message.d.ts +59 -0
- package/dist/types/components/chat/MessageScroller.d.ts +13 -0
- package/dist/types/components/chat/ModelSelector.d.ts +44 -0
- package/dist/types/components/chat/types.d.ts +155 -0
- package/dist/types/components/code-editor/context.d.ts +32 -0
- package/dist/types/components/code-editor/editing.d.ts +39 -0
- package/dist/types/components/code-editor/highlight.d.ts +20 -0
- package/dist/types/components/code-editor/recipe.d.ts +109 -0
- package/dist/types/components/code-editor/state.d.ts +14 -0
- package/dist/types/components/drag-drop/context.d.ts +45 -0
- package/dist/types/components/drag-drop/recipe.d.ts +121 -0
- package/dist/types/components/drag-drop/shift.d.ts +66 -0
- package/dist/types/components/markdown/Affordances.d.ts +76 -0
- package/dist/types/components/rbac/AccountMenu.d.ts +8 -0
- package/dist/types/components/rbac/DevToolsPopover.d.ts +5 -0
- package/dist/types/components/rbac/ProfilePage.d.ts +1 -0
- package/dist/types/components/rbac/RBACProvider.d.ts +64 -0
- package/dist/types/components/rbac/RolePermissionMatrix.d.ts +6 -0
- package/dist/types/components/rbac/RolesPermissionsPage.d.ts +1 -0
- package/dist/types/components/rbac/index.d.ts +7 -0
- package/dist/types/components/rbac/types.d.ts +26 -0
- package/dist/types/components/roadmap/PhaseManager.d.ts +19 -0
- package/dist/types/components/roadmap/RoadmapItemCard.d.ts +45 -0
- package/dist/types/components/roadmap/RoadmapPage.d.ts +9 -0
- package/dist/types/components/roadmap/RoadmapSwimlaneBoard.d.ts +9 -0
- package/dist/types/components/roadmap/UseCaseCard.d.ts +14 -0
- package/dist/types/components/roadmap/UseCaseLedgerPage.d.ts +21 -0
- package/dist/types/components/roadmap/chip-tones.d.ts +2 -0
- package/dist/types/components/roadmap/derive.d.ts +12 -0
- package/dist/types/components/roadmap/index.d.ts +9 -0
- package/dist/types/components/roadmap/types.d.ts +54 -0
- package/dist/types/icons/data.d.ts +1318 -0
- package/dist/types/index.d.ts +97 -0
- package/dist/types/lib/calendar/band-packer.d.ts +53 -0
- package/dist/types/lib/calendar/drag.d.ts +125 -0
- package/dist/types/lib/calendar/index.d.ts +4 -0
- package/dist/types/lib/calendar/lane-packer.d.ts +88 -0
- package/dist/types/lib/calendar/segments.d.ts +91 -0
- package/dist/types/lib/calendar/types.d.ts +166 -0
- package/dist/types/lib/cn.d.ts +7 -0
- package/dist/types/lib/dnd/announce.d.ts +132 -0
- package/dist/types/lib/dnd/autoscroll.d.ts +88 -0
- package/dist/types/lib/dnd/geometry.d.ts +78 -0
- package/dist/types/lib/dnd/index.d.ts +16 -0
- package/dist/types/lib/dnd/sensors/gesture.d.ts +37 -0
- package/dist/types/lib/dnd/sensors/keyboard.d.ts +50 -0
- package/dist/types/lib/dnd/sensors/pointer.d.ts +59 -0
- package/dist/types/lib/dnd/session.d.ts +99 -0
- package/dist/types/lib/dnd/types.d.ts +162 -0
- package/dist/types/lib/dnd/use-drag.d.ts +56 -0
- package/dist/types/lib/icons.d.ts +40 -0
- package/dist/types/lib/markdown/caret-map.d.ts +48 -0
- package/dist/types/lib/markdown/caret.d.ts +6 -0
- package/dist/types/lib/markdown/commands.d.ts +170 -0
- package/dist/types/lib/markdown/convert.d.ts +82 -0
- package/dist/types/lib/markdown/dom.d.ts +67 -0
- package/dist/types/lib/markdown/edit.d.ts +16 -0
- package/dist/types/lib/markdown/history.d.ts +47 -0
- package/dist/types/lib/markdown/hotkeys.d.ts +39 -0
- package/dist/types/lib/markdown/input.d.ts +15 -0
- package/dist/types/lib/markdown/keys.d.ts +34 -0
- package/dist/types/lib/markdown/paste.d.ts +9 -0
- package/dist/types/lib/markdown/position.d.ts +43 -0
- package/dist/types/lib/markdown/project.d.ts +88 -0
- package/dist/types/lib/markdown/reconcile.d.ts +63 -0
- package/dist/types/lib/markdown/surface.d.ts +177 -0
- package/dist/types/lib/persist.d.ts +40 -0
- package/dist/types/lib/preferences.d.ts +80 -0
- package/dist/types/lib/sim/createSimStore.d.ts +18 -0
- package/dist/types/lib/sim/index.d.ts +5 -0
- package/dist/types/lib/sim/latency.d.ts +10 -0
- package/dist/types/lib/sim/registry.d.ts +14 -0
- package/dist/types/lib/sim/settings.d.ts +11 -0
- package/dist/types/lib/sim/types.d.ts +3 -0
- package/dist/types/lib/syntax/index.d.ts +16 -0
- package/dist/types/lib/syntax/languages/bash.d.ts +1 -0
- package/dist/types/lib/syntax/languages/css.d.ts +1 -0
- package/dist/types/lib/syntax/languages/html.d.ts +17 -0
- package/dist/types/lib/syntax/languages/index.d.ts +33 -0
- package/dist/types/lib/syntax/languages/javascript.d.ts +22 -0
- package/dist/types/lib/syntax/languages/json.d.ts +1 -0
- package/dist/types/lib/syntax/languages/mongodb.d.ts +1 -0
- package/dist/types/lib/syntax/languages/plain.d.ts +9 -0
- package/dist/types/lib/syntax/languages/sql.d.ts +4 -0
- package/dist/types/lib/syntax/languages/vue.d.ts +1 -0
- package/dist/types/lib/syntax/languages/yaml.d.ts +1 -0
- package/dist/types/lib/syntax/markdown/frames.d.ts +145 -0
- package/dist/types/lib/syntax/markdown/grammar.d.ts +1 -0
- package/dist/types/lib/syntax/markdown/index.d.ts +4 -0
- package/dist/types/lib/syntax/markdown/inline.d.ts +21 -0
- package/dist/types/lib/syntax/markdown/parse.d.ts +11 -0
- package/dist/types/lib/syntax/markdown/render.d.ts +19 -0
- package/dist/types/lib/syntax/markdown/spans.d.ts +84 -0
- package/dist/types/lib/syntax/markdown/types.d.ts +108 -0
- package/dist/types/lib/syntax/registry.d.ts +37 -0
- package/dist/types/lib/syntax/tokenize.d.ts +17 -0
- package/dist/types/lib/syntax/types.d.ts +119 -0
- package/dist/types/lib/time/index.d.ts +3 -0
- package/dist/types/lib/time/plain.d.ts +61 -0
- package/dist/types/lib/time/types.d.ts +87 -0
- package/dist/types/lib/time/zone.d.ts +97 -0
- package/dist/types/lib/use-media-query.d.ts +29 -0
- package/package.json +130 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Danxbot — public library surface.
|
|
3
|
+
*
|
|
4
|
+
* This single entry is the contract for BOTH build targets: the ESM package
|
|
5
|
+
* that applications import, and the compiled global bundle that Claude Design
|
|
6
|
+
* loads. A component that is not exported here exists in neither.
|
|
7
|
+
*
|
|
8
|
+
* Every props interface is named `<Name>Props` — the design agent reads those
|
|
9
|
+
* type names directly, and consumers get predictable imports.
|
|
10
|
+
*/
|
|
11
|
+
import "./styles/index.css";
|
|
12
|
+
export { Icon, type IconProps, type IconSize, type IconName } from "./components/Icon";
|
|
13
|
+
export { registerIcon, registerIcons, getIcon, hasIcon, iconNames, type IconNode, type IconNodeChild, } from "./lib/icons";
|
|
14
|
+
export { coreIcons, type CoreIconName } from "./icons/data";
|
|
15
|
+
export { Button, buttonVariants, type ButtonProps } from "./components/Button";
|
|
16
|
+
export { Badge, badgeVariants, type BadgeProps } from "./components/Badge";
|
|
17
|
+
export { Spinner, type SpinnerProps } from "./components/Spinner";
|
|
18
|
+
export { Skeleton, SkeletonText, LoadingOverlay, type SkeletonProps, type SkeletonTextProps, type LoadingOverlayProps, } from "./components/Loading";
|
|
19
|
+
export { ErrorBoundary } from "./components/ErrorBoundary";
|
|
20
|
+
export { Field, FieldSet, type FieldProps, type FieldSetProps } from "./components/Field";
|
|
21
|
+
export { Input, Textarea, type InputProps, type TextareaProps } from "./components/Input";
|
|
22
|
+
export { Checkbox, Switch, Radio, RadioGroup, CheckboxField, SwitchField, RadioField, RadioCard, type CheckboxProps, type SwitchProps, type RadioProps, type RadioGroupProps, type CheckboxFieldProps, type SwitchFieldProps, type RadioFieldProps, type RadioCardProps, } from "./components/Choice";
|
|
23
|
+
export { Dialog, DialogClose, AlertDialog, type DialogProps, type AlertDialogProps, } from "./components/Dialog";
|
|
24
|
+
export { Popover, PopoverClose, Tooltip, TooltipProvider, type PopoverProps, type TooltipProps, } from "./components/Popover";
|
|
25
|
+
export { Toaster, ToastProvider, useToast, type ToasterProps, type ToastProviderProps, type ToastOptions, type ToastTone, } from "./components/Toast";
|
|
26
|
+
export { Menu, MenuItem, MenuGroup, MenuRadioGroup, MenuRadioItem, MenuSeparator, type MenuProps, type MenuItemProps, type MenuGroupProps, type MenuRadioGroupProps, type MenuRadioItemProps, } from "./components/Menu";
|
|
27
|
+
export { ThemeMenu, type ThemeMenuProps } from "./components/ThemeMenu";
|
|
28
|
+
export { AppShell, type AppShellProps, type NavItem, type NavSection, } from "./components/AppShell";
|
|
29
|
+
export { FileUpload, type FileUploadProps, type UploadFile } from "./components/FileUpload";
|
|
30
|
+
export { DatePicker, type DatePickerProps, type DateRange } from "./components/DatePicker";
|
|
31
|
+
export { Tree, type TreeProps, type TreeNode } from "./components/Tree";
|
|
32
|
+
export { CommandPalette, useCommandPalette, type CommandPaletteProps, type CommandItem, } from "./components/CommandPalette";
|
|
33
|
+
export { Slider, type SliderProps, type SliderMark } from "./components/Slider";
|
|
34
|
+
export { NumberInput, type NumberInputProps } from "./components/NumberInput";
|
|
35
|
+
export { OTPInput, type OTPInputProps } from "./components/OTPInput";
|
|
36
|
+
export { Combobox, ComboboxItem, ComboboxGroup, MultiCombobox, type ComboboxProps, type ComboboxItemProps, type ComboboxGroupProps, type MultiComboboxProps, } from "./components/Combobox";
|
|
37
|
+
export { Select, SelectItem, SelectGroup, SelectSeparator, type SelectProps, type SelectItemProps, type SelectGroupProps, } from "./components/Select";
|
|
38
|
+
export { StatusSelect, type StatusSelectProps, type StatusOption } from "./components/StatusSelect";
|
|
39
|
+
export { Card, CardHeader, CardFooter, type CardProps, type CardHeaderProps, } from "./components/Card";
|
|
40
|
+
export { Tabs, TabList, Tab, TabPanel, type TabsProps, type TabListProps, type TabProps, type TabPanelProps, } from "./components/Tabs";
|
|
41
|
+
export { Accordion, AccordionItem, type AccordionProps, type AccordionItemProps, } from "./components/Accordion";
|
|
42
|
+
export { Breadcrumb, Pagination, type BreadcrumbProps, type PaginationProps, type Crumb, } from "./components/Navigation";
|
|
43
|
+
export { Toggle, ToggleGroup, Toolbar, ToolbarSeparator, type ToggleProps, type ToggleGroupProps, type ToolbarProps, } from "./components/Toggle";
|
|
44
|
+
export { Separator, ScrollArea, Collapsible, EmptyState, Timeline, type SeparatorProps, type ScrollAreaProps, type CollapsibleProps, type EmptyStateProps, type TimelineProps, type TimelineItem, } from "./components/Surface";
|
|
45
|
+
export { PanelGroup, Panel, PanelResizer, type PanelGroupProps, type PanelProps, type PanelResizerProps, type PanelDirection, type PanelNarrowMode, } from "./components/Panel";
|
|
46
|
+
export { Avatar, AvatarGroup, type AvatarProps, type AvatarGroupProps, type AvatarStatus, } from "./components/Avatar";
|
|
47
|
+
export { Progress, Meter, ProgressRing, type ProgressProps, type MeterProps, type ProgressRingProps, } from "./components/Progress";
|
|
48
|
+
export { Stat, Sparkline, type StatProps, type SparklineProps, type StatTrend, type StatSentiment, } from "./components/Stat";
|
|
49
|
+
export { DataTable, TableEmptyState, CellStack, type DataTableProps, type TableDensity, } from "./components/Table";
|
|
50
|
+
export { CodeEditor, CodeEditorToolbar, CodeEditorCaption, CodeEditorCopyButton, CodeEditorWrapToggle, CodeEditorViewSwitch, type CodeEditorProps, type CodeEditorToolbarProps, type CodeEditorView, } from "./components/CodeEditor";
|
|
51
|
+
export { MarkdownEditor, type MarkdownEditorProps } from "./components/MarkdownEditor";
|
|
52
|
+
export { MarkdownSurface, type SurfaceOptions, type Splice } from "./lib/markdown/surface";
|
|
53
|
+
export { project, projectedText, ProjectionError } from "./lib/markdown/project";
|
|
54
|
+
export type { Projection, PNode, PText, PElement } from "./lib/markdown/project";
|
|
55
|
+
export { attachInput, type InputOptions } from "./lib/markdown/input";
|
|
56
|
+
export { HOTKEYS, hotkeyFor, chordsOf, type Hotkey, type HotkeyGroup } from "./lib/markdown/hotkeys";
|
|
57
|
+
export { htmlFragmentToMarkdown } from "./lib/markdown/paste";
|
|
58
|
+
export { lineAt, stepOffset } from "./lib/markdown/caret";
|
|
59
|
+
export { caretMap, nearestStop, stepStop, graphemeBefore, graphemeAfter, lineStartStop, type CaretMap, } from "./lib/markdown/caret-map";
|
|
60
|
+
export { deleteVisible, deleteVisibleBefore, deleteVisibleAfter } from "./lib/markdown/edit";
|
|
61
|
+
export { resolveKey, type KeyIntent, type KeyContext } from "./lib/markdown/keys";
|
|
62
|
+
export { blockAt, convertBlock, setFenceLanguage, constructAt, editConstruct, unwrapConstruct, type BlockKind, type BlockInfo, type ConstructInfo, } from "./lib/markdown/convert";
|
|
63
|
+
export { readSelection, writeSelection, sourceOffsetAt, domPointAt, type SourceSelection, type DomPoint, type Association, } from "./lib/markdown/position";
|
|
64
|
+
export type { Command, Edit } from "./lib/markdown/commands";
|
|
65
|
+
export { toggleBold, toggleItalic, toggleCode, toggleStrike, toggleInline, setHeading, adjustHeading, headingLevel, toggleList, toggleTask, indentLines, outdentLines, toggleQuote, toggleCodeBlock, fenceAround, insertRule, insertImage, insertLink, insertTable, insertRow, insertColumn, deleteRow, deleteColumn, deleteTable, alignColumn, tableAround, cellsOf, cellAt, tableTab, smartEnter, smartTab, smartShiftTab, } from "./lib/markdown/commands";
|
|
66
|
+
export { tokenize, listLanguages, resolveLanguage, defineGrammar, registerGrammar, checkCoverage, type Token, type TokenType, type Grammar, type Rule, } from "./lib/syntax";
|
|
67
|
+
export { parseMarkdown, MarkdownNodes, sanitizeHref, type MdNode, type MdInline, type MdCodeRenderer, } from "./lib/syntax/markdown";
|
|
68
|
+
export { DragDrop, DragDropContainer, DragDropItem, DragDropHandle, DragDropOverlay, type DragDropProps, type DragDropContainerProps, type DragDropItemProps, type DragDropHandleProps, type DragDropOverlayProps, } from "./components/DragDrop";
|
|
69
|
+
export { DEFAULT_DRAG_STRINGS, DRAG_INSTRUCTIONS_ID, DragInstructions, DragLiveRegion, DragSession, DragSessionProvider, applyMove, attachAutoScroll, attachKeyboardSensor, attachPointerSensor, attachSessionWindowListeners, isNoOp, resolveTarget, sameTarget, scrollVelocity, useCreateDragSession, useDragAnnouncements, useDragSession, useDragState, useDraggable, useDropContainer, type ContainerId, type DragAxis, type DragCancelEvent, type DragEndEvent, type DragId, type DragMode, type DragPhase, type DragSessionCallbacks, type DragStartEvent, type DragState, type AutoScrollOptions, type DragAnnouncementContext, type DragAnnouncementOptions, type DragAnnouncements, type DragInstructionsProps, type DragLiveRegionProps, type DragStrings, type DropTarget, type KeyboardSensorOptions, type PointerActivation, } from "./lib/dnd";
|
|
70
|
+
export type { MessageRole, MessagePart, MessagePartType, TextPart, CodePart, ReasoningPart, ToolPart, ToolStatus, FilePart, ComponentPart, ChatFile, ChatMessage, RenderContext, PartRenderer, PartRenderers, ChatComponentRenderer, ChatComponents, } from "./components/chat/types";
|
|
71
|
+
export { Chat, ChatPopover, type ChatProps, type ChatPopoverProps, type ChatSurface, } from "./components/chat/Chat";
|
|
72
|
+
export { Message, MessagePartView, ToolCall, ChatMarker, type MessageProps, type MessageAction, type MessagePartViewProps, type ToolCallProps, type ChatMarkerProps, } from "./components/chat/Message";
|
|
73
|
+
export { MessageScroller, type MessageScrollerProps, } from "./components/chat/MessageScroller";
|
|
74
|
+
export { Composer, type ComposerProps } from "./components/chat/Composer";
|
|
75
|
+
export { Markdown, CodeBlock, type MarkdownProps, type CodeBlockProps } from "./components/chat/Markdown";
|
|
76
|
+
export { Attachment, AttachmentList, AttachmentPreview, formatBytes, type AttachmentProps, type AttachmentListProps, type AttachmentPreviewProps, type AttachmentLayout, } from "./components/chat/Attachment";
|
|
77
|
+
export { ModelSelector, type ModelSelectorProps, type ChatModel, } from "./components/chat/ModelSelector";
|
|
78
|
+
export { EffortControl, DEFAULT_EFFORT_LEVELS, type EffortControlProps, type EffortLevel, } from "./components/chat/EffortControl";
|
|
79
|
+
export { ContextMeter, ChatStatus, formatTokens, type ContextMeterProps, type ContextSegment, type UsageLimit, type ChatStatusProps, } from "./components/chat/ContextMeter";
|
|
80
|
+
export { cn } from "./lib/cn";
|
|
81
|
+
export { useTheme, useUiScale, useContrast, useMotionPreference, type Theme, type UiScale, type ContrastPreference, type MotionPreference, } from "./lib/preferences";
|
|
82
|
+
export { usePersistedState, readStored, writeStored, clearStored, storageKey, type PersistedStateOptions, } from "./lib/persist";
|
|
83
|
+
export { CalendarMonth, type CalendarMonthProps } from "./components/calendar/CalendarMonth";
|
|
84
|
+
export { CalendarTimeGrid, type CalendarTimeGridProps, } from "./components/calendar/CalendarTimeGrid";
|
|
85
|
+
export { useNow, type UseNowOptions } from "./components/calendar/use-now";
|
|
86
|
+
export { EventActions, type EventActionsProps } from "./components/calendar/EventActions";
|
|
87
|
+
export { useCalendarDrag, type CalendarDragOptions, type CalendarDragState, } from "./components/calendar/use-calendar-drag";
|
|
88
|
+
export { useEventKeyboard, type EventKeyboardOptions, type EventKeyboardState, } from "./components/calendar/use-event-keyboard";
|
|
89
|
+
export { applyCalendarDelta, calendarDragResult, createdEvent, describeTarget, resolveCalendarTarget, snapInstant, MIN_DURATION_MINUTES, type CalendarDragOrigin, type CalendarDragResult, type CalendarTarget, type ColumnRect, } from "./lib/calendar/drag";
|
|
90
|
+
export { EVENT_PALETTE, DEFAULT_PALETTE_KEY, isPaletteKey, paletteFor, } from "./components/calendar/palette";
|
|
91
|
+
export { cellLabel, eventLabel, formatDateRange, longDate, monthTitle, timeOfDay, weekdayName, zoneLabel, } from "./components/calendar/format";
|
|
92
|
+
export { initialFocusDay, isInMonth, nextDayForKey, useGridNavigation, type GridNavigation, type GridNavigationOptions, } from "./components/calendar/use-grid-navigation";
|
|
93
|
+
export { AmbiguousTimeError, addDays, addDuration, addMonths, atMidnight, atTime, comparePlainDate, dayFraction, dayLengthMs, dayOfWeek, daysBetween, daysInMonth, endOfMonth, hoursInDay, instantAtFraction, instantToPlainDate, instantToPlainDateTime, isSameDate, isoDateString, isoDateTimeString, monthGridDays, nextDay, offsetAt, parsePlainDate, plainDateTimeToInstant, startOfDay, startOfMonth, startOfWeek, weekDays, type CalendarDuration, type Disambiguation, type Instant, type PlainDate, type PlainDateTime, type TimeZone, } from "./lib/time";
|
|
94
|
+
export { allDayBandSegment, dayKey, daySlots, isAllDay, packBand, packLanes, snapFractionToInstant, timeSegments, timedBandSegment, type AllDayEvent, type BandInput, type BandOptions, type BandPlacement, type BandResult, type BandSegment, type CalendarEvent, type CalendarEventId, type CalendarView, type DaySlot, type DragKind, type EventDraft, type EventPalette, type LaneInput, type LaneOptions, type LanePlacement, type PaletteEntry, type TimeSegment, type TimedEvent, type VisibleRange, } from "./lib/calendar";
|
|
95
|
+
export { RBACProvider, useRBAC, AccountMenu, DevToolsPopover, RolePermissionMatrix, ProfilePage, RolesPermissionsPage, type RBACProviderProps, type RBACHookResult, type AccountMenuProps, type DevToolsPopoverProps, type RolePermissionMatrixProps, type Permission, type Role, type User, type Team, type TeamMembership, } from "./components/rbac";
|
|
96
|
+
export { UseCaseCard, RoadmapItemCard, RoadmapSwimlaneBoard, UseCaseLedgerPage, RoadmapPage, PhaseManager, deriveRoadmapItemStatus, toneForIndex, CATEGORY_TONES, type Domain, type Phase, type RoadmapItem, type RoadmapItemStatus, type UseCase, type UseCaseStatus, type UseCaseDecision, type UseCaseCardProps, type RoadmapItemCardProps, type RoadmapSwimlaneBoardProps, type UseCaseLedgerPageProps, type RoadmapPageProps, type PhaseManagerProps, } from "./components/roadmap";
|
|
97
|
+
export { createSimStore, resetSimStores, useSimSettings, setSimSettings, getNetworkSpeed, getDataSource, simulateLatency, SimNetworkError, type SimStore, type SimStoreOptions, type SimSettings, type NetworkSpeed, type DataSource, type SimNamespace, } from "./lib/sim";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** A contiguous run of columns within one row of the grid. Both ends inclusive. */
|
|
2
|
+
export interface BandInput {
|
|
3
|
+
readonly key: string;
|
|
4
|
+
readonly startColumn: number;
|
|
5
|
+
readonly endColumn: number;
|
|
6
|
+
/**
|
|
7
|
+
* Ordering weight. Lower sorts earlier, so pinned items keep their place as
|
|
8
|
+
* neighbours come and go. Ties fall through to span length, then key.
|
|
9
|
+
*/
|
|
10
|
+
readonly priority?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface BandPlacement extends BandInput {
|
|
13
|
+
/** 0-based row within the band. */
|
|
14
|
+
readonly row: number;
|
|
15
|
+
}
|
|
16
|
+
export interface BandResult {
|
|
17
|
+
/** Everything that fits, in row order. */
|
|
18
|
+
readonly placed: readonly BandPlacement[];
|
|
19
|
+
/** Everything pushed past the limit, in the same order it would have had. */
|
|
20
|
+
readonly hidden: readonly BandInput[];
|
|
21
|
+
/** Per column, how many hidden items cover it — the "+N more" count. */
|
|
22
|
+
readonly overflow: readonly number[];
|
|
23
|
+
/** Rows actually used by `placed`. */
|
|
24
|
+
readonly rows: number;
|
|
25
|
+
}
|
|
26
|
+
export interface BandOptions {
|
|
27
|
+
/** How many columns the row has. Required — it sizes the overflow tally. */
|
|
28
|
+
readonly columns: number;
|
|
29
|
+
/**
|
|
30
|
+
* Most rows the band may occupy, INCLUDING the row the "+N more" affordance
|
|
31
|
+
* takes.
|
|
32
|
+
*
|
|
33
|
+
* Counting the affordance is what stops the classic off-by-one where the
|
|
34
|
+
* overflow link is drawn on top of the last event. When items do not fit,
|
|
35
|
+
* events get `maxRows - 1` rows and the last is reserved — which is
|
|
36
|
+
* FullCalendar's `dayMaxEventRows` semantics, and the only version that
|
|
37
|
+
* leaves room for the thing it just decided to draw.
|
|
38
|
+
*
|
|
39
|
+
* Omit for no limit. The all-day band MUST pass one: an uncapped band eats
|
|
40
|
+
* the container and makes the time grid unreachable — an open FullCalendar
|
|
41
|
+
* bug, and react-big-calendar's default is literally `Infinity`.
|
|
42
|
+
*/
|
|
43
|
+
readonly maxRows?: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Assign each item the first row where every column it covers is free.
|
|
47
|
+
*
|
|
48
|
+
* Greedy first-fit. Not optimal in the sense of minimising rows — that is
|
|
49
|
+
* NP-hard and nobody wants it anyway, because the optimal packing reshuffles
|
|
50
|
+
* every event's row whenever one is added, and a calendar whose events jump
|
|
51
|
+
* rows as you type is worse than one that uses an extra row.
|
|
52
|
+
*/
|
|
53
|
+
export declare function packBand(inputs: readonly BandInput[], options: BandOptions): BandResult;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { type Instant, type PlainDate, type TimeZone } from "@/lib/time";
|
|
2
|
+
import type { CalendarDuration } from "@/lib/time";
|
|
3
|
+
import type { DragKind, TimedEvent } from "./types";
|
|
4
|
+
/** A day column, as the view measured it. */
|
|
5
|
+
export interface ColumnRect {
|
|
6
|
+
readonly day: PlainDate;
|
|
7
|
+
readonly left: number;
|
|
8
|
+
readonly right: number;
|
|
9
|
+
readonly top: number;
|
|
10
|
+
readonly bottom: number;
|
|
11
|
+
}
|
|
12
|
+
/** Where a pointer is, in calendar terms. */
|
|
13
|
+
export interface CalendarTarget {
|
|
14
|
+
readonly dayIndex: number;
|
|
15
|
+
readonly day: PlainDate;
|
|
16
|
+
/** Snapped to `snapMinutes`, measured from that day's own first instant. */
|
|
17
|
+
readonly instant: Instant;
|
|
18
|
+
}
|
|
19
|
+
export interface ResolveOptions {
|
|
20
|
+
readonly zone: TimeZone;
|
|
21
|
+
readonly columns: readonly ColumnRect[];
|
|
22
|
+
readonly snapMinutes: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Which day and which time a point is over.
|
|
26
|
+
*
|
|
27
|
+
* `null` outside every column — and the caller KEEPS THE LAST NON-NULL TARGET
|
|
28
|
+
* rather than treating that as "no drop". A pointer leaves the columns
|
|
29
|
+
* constantly while dragging toward the edge of the grid, and an event that
|
|
30
|
+
* snapped back to its origin every time the finger crossed the gutter would be
|
|
31
|
+
* unusable.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveCalendarTarget(point: {
|
|
34
|
+
x: number;
|
|
35
|
+
y: number;
|
|
36
|
+
}, options: ResolveOptions): CalendarTarget | null;
|
|
37
|
+
/**
|
|
38
|
+
* Snap an instant to the nearest `snapMinutes`, measured from the DAY'S OWN
|
|
39
|
+
* first instant.
|
|
40
|
+
*
|
|
41
|
+
* Not from midnight and not from the epoch. On a day that begins at 01:00 —
|
|
42
|
+
* Havana in March — snapping to the epoch puts every slot boundary an hour away
|
|
43
|
+
* from the rails the grid drew, in exactly the zones where a user is least able
|
|
44
|
+
* to explain what they are seeing.
|
|
45
|
+
*/
|
|
46
|
+
export declare function snapInstant(zone: TimeZone, day: PlainDate, instant: Instant, snapMinutes: number): Instant;
|
|
47
|
+
export interface CalendarDragOrigin {
|
|
48
|
+
readonly event: TimedEvent;
|
|
49
|
+
readonly kind: DragKind;
|
|
50
|
+
/** The target under the pointer when the gesture activated. */
|
|
51
|
+
readonly from: CalendarTarget;
|
|
52
|
+
}
|
|
53
|
+
export interface CalendarDragResult {
|
|
54
|
+
/**
|
|
55
|
+
* The change, as a CALENDAR duration — never milliseconds.
|
|
56
|
+
*
|
|
57
|
+
* "One day later" is 23 hours across a spring-forward boundary and 25 across
|
|
58
|
+
* a fall-back. A user dragging an event from Saturday to Sunday expects it to
|
|
59
|
+
* keep its wall-clock time, and a millisecond delta cannot express that. It
|
|
60
|
+
* is the bug in every library surveyed.
|
|
61
|
+
*/
|
|
62
|
+
readonly delta: CalendarDuration;
|
|
63
|
+
/** False when the gesture would leave the event exactly where it was. */
|
|
64
|
+
readonly moved: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Set when a resize would produce a zero or negative duration.
|
|
67
|
+
*
|
|
68
|
+
* REJECTED, NOT CLAMPED. FullCalendar returns no mutation at all;
|
|
69
|
+
* react-big-calendar clamps, and asymmetrically — its bottom-edge rule can
|
|
70
|
+
* produce a ZERO-DURATION event, which then renders as an invisible sliver
|
|
71
|
+
* the user cannot grab to fix. Refusing the gesture leaves the event where it
|
|
72
|
+
* was, which the user can see and try again from.
|
|
73
|
+
*/
|
|
74
|
+
readonly invalid?: "too-short";
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The minimum an event may be resized to, in minutes.
|
|
78
|
+
*
|
|
79
|
+
* One snap step. Anything smaller cannot be expressed by the gesture that made
|
|
80
|
+
* it, so it could never be undone by the same gesture.
|
|
81
|
+
*/
|
|
82
|
+
export declare const MIN_DURATION_MINUTES = 15;
|
|
83
|
+
/**
|
|
84
|
+
* What a gesture from `origin` to `target` means.
|
|
85
|
+
*
|
|
86
|
+
* DAYS AND MINUTES SEPARATELY, and that separation is the whole point. The day
|
|
87
|
+
* component is a CALENDAR move — re-anchored to the same wall-clock time on the
|
|
88
|
+
* new day. The minute component is EXACT elapsed time — dragging down two hours
|
|
89
|
+
* means two hours. Both are true at once, and collapsing them into one number
|
|
90
|
+
* loses whichever property the collapse did not preserve.
|
|
91
|
+
*/
|
|
92
|
+
export declare function calendarDragResult(origin: CalendarDragOrigin, target: CalendarTarget, zone: TimeZone, minDurationMinutes?: number): CalendarDragResult;
|
|
93
|
+
/**
|
|
94
|
+
* The event as it would be after `delta`, for the live preview.
|
|
95
|
+
*
|
|
96
|
+
* COMPOSED ONTO THE EVENT AT CALL TIME, never onto a snapshot taken at
|
|
97
|
+
* pointer-down. Two real failures from other calendars' trackers: a re-render
|
|
98
|
+
* replaces the event store mid-drag and the drag is left holding an instance
|
|
99
|
+
* from the dead one; and a concurrent server update during a drag DUPLICATES
|
|
100
|
+
* the times, because a snapshot was composited on top of data that had moved
|
|
101
|
+
* underneath it. Recomputing from whatever the event says now makes a change
|
|
102
|
+
* arriving mid-gesture compose rather than clobber.
|
|
103
|
+
*/
|
|
104
|
+
export declare function applyCalendarDelta(event: TimedEvent, kind: DragKind, delta: CalendarDuration, zone: TimeZone): TimedEvent;
|
|
105
|
+
/**
|
|
106
|
+
* The event a drag-to-create gesture would produce.
|
|
107
|
+
*
|
|
108
|
+
* The two ends are ordered, so dragging upward creates the same event as
|
|
109
|
+
* dragging downward across the same span — which is what every calendar does
|
|
110
|
+
* and what a user expects from a rubber-band gesture.
|
|
111
|
+
*/
|
|
112
|
+
export declare function createdEvent(anchor: CalendarTarget, target: CalendarTarget, minDurationMinutes?: number): {
|
|
113
|
+
start: Instant;
|
|
114
|
+
endExclusive: Instant;
|
|
115
|
+
day: PlainDate;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* A human description of the position, for the live region.
|
|
119
|
+
*
|
|
120
|
+
* "Moved to 2:30 PM, Wednesday" — the SLOT, not the fact that something moved.
|
|
121
|
+
* "Moved" alone tells a screen-reader user nothing they can act on.
|
|
122
|
+
*/
|
|
123
|
+
export declare function describeTarget(target: CalendarTarget, zone: TimeZone, locale?: string): string;
|
|
124
|
+
/** Where in the grid a fraction sits, for the preview. Inverse of the resolve. */
|
|
125
|
+
export declare function fractionOf(zone: TimeZone, day: PlainDate, instant: Instant): number;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { isAllDay, type AllDayEvent, type CalendarEvent, type CalendarEventId, type CalendarView, type DragKind, type EventDraft, type EventPalette, type PaletteEntry, type TimedEvent, type VisibleRange, } from "./types";
|
|
2
|
+
export { packLanes, type LaneInput, type LaneOptions, type LanePlacement } from "./lane-packer";
|
|
3
|
+
export { packBand, type BandInput, type BandOptions, type BandPlacement, type BandResult } from "./band-packer";
|
|
4
|
+
export { allDayBandSegment, dayKey, daySlots, snapFractionToInstant, timeSegments, timedBandSegment, type BandSegment, type DaySlot, type TimeSegment, } from "./segments";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** A half-open interval `[start, end)` in column fractions, with an identity. */
|
|
2
|
+
export interface LaneInput {
|
|
3
|
+
readonly key: string;
|
|
4
|
+
readonly start: number;
|
|
5
|
+
readonly end: number;
|
|
6
|
+
}
|
|
7
|
+
export interface LanePlacement {
|
|
8
|
+
readonly key: string;
|
|
9
|
+
/** As laid out — possibly inflated past the input by `minSpan`. */
|
|
10
|
+
readonly start: number;
|
|
11
|
+
readonly end: number;
|
|
12
|
+
/** 0-based lane within this event's collision batch. */
|
|
13
|
+
readonly column: number;
|
|
14
|
+
/** Lanes in that batch. Uniform across every member of it — see below. */
|
|
15
|
+
readonly lanes: number;
|
|
16
|
+
/** Fraction of the container's width, from its leading edge. */
|
|
17
|
+
readonly left: number;
|
|
18
|
+
readonly width: number;
|
|
19
|
+
/** Later columns paint over earlier ones. Equal to `column`. */
|
|
20
|
+
readonly zIndex: number;
|
|
21
|
+
}
|
|
22
|
+
export interface LaneOptions {
|
|
23
|
+
/**
|
|
24
|
+
* `cascade` — every event runs to the container's trailing edge and later
|
|
25
|
+
* columns paint over earlier ones. **This is the Google look and the
|
|
26
|
+
* default.** `split` — the batch divides the width evenly and nothing
|
|
27
|
+
* overlaps.
|
|
28
|
+
*
|
|
29
|
+
* Three products, three different cascade multipliers: Schedule-X runs to the
|
|
30
|
+
* edge, FullCalendar doubles the lane width capped at 1, and
|
|
31
|
+
* react-big-calendar uses 1.7x — arbitrary and unexplained anywhere in its
|
|
32
|
+
* source. Running to the edge is the only one of the three that is a rule
|
|
33
|
+
* rather than a number someone liked.
|
|
34
|
+
*/
|
|
35
|
+
readonly mode?: "cascade" | "split";
|
|
36
|
+
/**
|
|
37
|
+
* The smallest span an event may occupy, as a column fraction.
|
|
38
|
+
*
|
|
39
|
+
* A 5-minute event on a 12-hour column is 0.7% of it — unclickable, and
|
|
40
|
+
* unreadable long before that. So it is inflated to a floor.
|
|
41
|
+
*
|
|
42
|
+
* **THE INFLATED SPAN IS WHAT COLLISION USES TOO**, which is the part that is
|
|
43
|
+
* easy to get wrong. Two 5-minute events a minute apart do not overlap as
|
|
44
|
+
* intervals, but they overlap ON SCREEN once both are inflated to a clickable
|
|
45
|
+
* height — so laying them in the same lane stacks one on the other. Detecting
|
|
46
|
+
* collisions on the true interval and drawing the inflated one is how a
|
|
47
|
+
* calendar ends up with events sitting invisibly behind each other.
|
|
48
|
+
*/
|
|
49
|
+
readonly minSpan?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Cap on lanes per batch. Beyond it, events STACK in the last lane rather
|
|
52
|
+
* than disappear.
|
|
53
|
+
*
|
|
54
|
+
* A week column is around 120px; a fifth lane in it is 24px and unreadable.
|
|
55
|
+
* But hiding an event in a time grid is worse than overlapping one — the user
|
|
56
|
+
* can see and click something that overlaps, and cannot do either with
|
|
57
|
+
* something that is not there. So the cap limits the DIVISION, not the
|
|
58
|
+
* membership. Day view passes no cap.
|
|
59
|
+
*/
|
|
60
|
+
readonly maxLanes?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Floor on the rendered width, as a fraction.
|
|
63
|
+
*
|
|
64
|
+
* Guards the width-0 collapse — an open FullCalendar bug where enough
|
|
65
|
+
* concurrent events divide the column into nothing and the whole batch
|
|
66
|
+
* becomes invisible. A floor makes a crowded column ugly instead of empty.
|
|
67
|
+
*/
|
|
68
|
+
readonly minWidth?: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Lay out overlapping events across lanes.
|
|
72
|
+
*
|
|
73
|
+
* Four steps, and the third is the colouring:
|
|
74
|
+
*
|
|
75
|
+
* 1. Sort by the total order above.
|
|
76
|
+
* 2. Sweep into COLLISION BATCHES — a batch closes when the next event starts
|
|
77
|
+
* at or after the maximum end of everything accumulated so far. Two events
|
|
78
|
+
* in different batches provably cannot overlap, so lane counts never leak
|
|
79
|
+
* between them and one crowded hour does not narrow the whole day.
|
|
80
|
+
* 3. Within a batch, give each event the SMALLEST lane index not taken by an
|
|
81
|
+
* earlier member it overlaps. That is greedy colouring of an interval
|
|
82
|
+
* graph, and on interval graphs greedy in start order is OPTIMAL — it uses
|
|
83
|
+
* exactly the number of lanes the maximum concurrency requires.
|
|
84
|
+
* 4. `lanes = maxColumn + 1`, computed ONCE PER BATCH and applied uniformly to
|
|
85
|
+
* every member. Per-event lane counts are what make two side-by-side
|
|
86
|
+
* events different widths for no visible reason.
|
|
87
|
+
*/
|
|
88
|
+
export declare function packLanes(inputs: readonly LaneInput[], options?: LaneOptions): LanePlacement[];
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { isoDateString, type Instant, type PlainDate, type TimeZone } from "@/lib/time";
|
|
2
|
+
import type { AllDayEvent, CalendarEvent, TimedEvent } from "./types";
|
|
3
|
+
/** One day's worth of a timed event, positioned within that day's column. */
|
|
4
|
+
export interface TimeSegment {
|
|
5
|
+
readonly event: TimedEvent;
|
|
6
|
+
readonly day: PlainDate;
|
|
7
|
+
/** Index into the range's `days`, so a view can address a column directly. */
|
|
8
|
+
readonly dayIndex: number;
|
|
9
|
+
/** Fraction down the column, 0 at the day's first instant, 1 at the next day's. */
|
|
10
|
+
readonly top: number;
|
|
11
|
+
readonly bottom: number;
|
|
12
|
+
/** False when the event began before this day — draw the top edge as cut. */
|
|
13
|
+
readonly isStart: boolean;
|
|
14
|
+
/** False when the event continues past this day. */
|
|
15
|
+
readonly isEnd: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** A run of whole days, for the month grid or the all-day band. */
|
|
18
|
+
export interface BandSegment {
|
|
19
|
+
readonly event: CalendarEvent;
|
|
20
|
+
/** Inclusive column index within the row. */
|
|
21
|
+
readonly startColumn: number;
|
|
22
|
+
readonly endColumn: number;
|
|
23
|
+
readonly isStart: boolean;
|
|
24
|
+
readonly isEnd: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Cut a timed event into one segment per day it touches.
|
|
28
|
+
*
|
|
29
|
+
* `days` is a contiguous run — a week, or a single day. Days the event does not
|
|
30
|
+
* touch produce nothing.
|
|
31
|
+
*/
|
|
32
|
+
export declare function timeSegments(zone: TimeZone, days: readonly PlainDate[], event: TimedEvent): TimeSegment[];
|
|
33
|
+
/**
|
|
34
|
+
* Where an all-day event sits within a row of days.
|
|
35
|
+
*
|
|
36
|
+
* `null` when it does not reach this row at all. Both `endColumn` and the
|
|
37
|
+
* event's own end are handled here so no caller ever does the ±1: the model is
|
|
38
|
+
* half-open (`endExclusive` is the first day NOT in the event) and a column
|
|
39
|
+
* index is inclusive, so the conversion happens once, here.
|
|
40
|
+
*/
|
|
41
|
+
export declare function allDayBandSegment(rowDays: readonly PlainDate[], event: AllDayEvent): BandSegment | null;
|
|
42
|
+
/**
|
|
43
|
+
* Where a TIMED event sits within a row of days, as whole columns.
|
|
44
|
+
*
|
|
45
|
+
* The month grid draws timed events as chips in a day cell, so a timed event
|
|
46
|
+
* that crosses midnight occupies both cells and needs the same clipping
|
|
47
|
+
* booleans an all-day bar does.
|
|
48
|
+
*/
|
|
49
|
+
export declare function timedBandSegment(zone: TimeZone, rowDays: readonly PlainDate[], event: TimedEvent): BandSegment | null;
|
|
50
|
+
/** One horizontal rail in the time grid, and the wall time it is labelled by. */
|
|
51
|
+
export interface DaySlot {
|
|
52
|
+
readonly instant: Instant;
|
|
53
|
+
/** Position down the column, 0–1. */
|
|
54
|
+
readonly fraction: number;
|
|
55
|
+
/** 0–23. On a fall-back day one value appears TWICE — see below. */
|
|
56
|
+
readonly hour: number;
|
|
57
|
+
readonly minute: number;
|
|
58
|
+
/** True for the second of a repeated reading, so a view can mark it. */
|
|
59
|
+
readonly repeated: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The rails for one day, generated by WALKING WALL-CLOCK TIME through the zone.
|
|
63
|
+
*
|
|
64
|
+
* NOT by dividing the column into 24. That is the difference between a
|
|
65
|
+
* fall-back day showing **25 rails with 1 AM twice** — which is what the clock
|
|
66
|
+
* on the wall actually did — and showing 24 evenly spaced labels that are each
|
|
67
|
+
* an hour wrong after 02:00.
|
|
68
|
+
*
|
|
69
|
+
* Walking forward by real elapsed time and reading the clock at each step is
|
|
70
|
+
* also what makes the 30-minute zone fall out for free: Lord Howe's short day
|
|
71
|
+
* produces 23 hourly rails and a half-hour remainder, with no branch.
|
|
72
|
+
*/
|
|
73
|
+
export declare function daySlots(zone: TimeZone, day: PlainDate, slotMinutes?: number): DaySlot[];
|
|
74
|
+
/**
|
|
75
|
+
* The instant a pointer at `fraction` down `day`'s column is over, snapped.
|
|
76
|
+
*
|
|
77
|
+
* SNAP IS A HIT-CHANGE, NOT COORDINATE ROUNDING, and the difference is what the
|
|
78
|
+
* gesture feels like. Resolving which slot the pointer is IN and only reacting
|
|
79
|
+
* when that slot changes makes the preview jump discretely between positions,
|
|
80
|
+
* and **that discreteness IS the feedback** — a preview that tracks the pointer
|
|
81
|
+
* continuously and rounds on drop reads as mushy and imprecise.
|
|
82
|
+
*
|
|
83
|
+
* `snapMinutes` is deliberately independent of the rail spacing. FullCalendar,
|
|
84
|
+
* react-big-calendar and Schedule-X all couple them; Google and Mobiscroll do
|
|
85
|
+
* not, and **Google is 15-minute snap on 60-minute rails**, which is the
|
|
86
|
+
* combination that feels right. Retrofitting the split is a rewrite, so the two
|
|
87
|
+
* are separate values from the first commit.
|
|
88
|
+
*/
|
|
89
|
+
export declare function snapFractionToInstant(zone: TimeZone, day: PlainDate, fraction: number, snapMinutes: number): Instant;
|
|
90
|
+
/** Stable key for a day, for maps and React keys. */
|
|
91
|
+
export declare const dayKey: typeof isoDateString;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { CalendarDuration, Instant, PlainDate, TimeZone } from "@/lib/time/types";
|
|
2
|
+
export type CalendarEventId = string;
|
|
3
|
+
interface EventCommon {
|
|
4
|
+
readonly id: CalendarEventId;
|
|
5
|
+
readonly title: string;
|
|
6
|
+
/**
|
|
7
|
+
* Which series this occurrence belongs to, if any.
|
|
8
|
+
*
|
|
9
|
+
* PRESENT FROM THE FIRST COMMIT ALTHOUGH RECURRENCE SHIPS LATER, because
|
|
10
|
+
* this is the half that cannot be added afterwards. The moment any real data
|
|
11
|
+
* exists, backfilling series identity onto rows that never had it is a
|
|
12
|
+
* migration nobody can write correctly — there is no way to tell, later,
|
|
13
|
+
* which of two identical Tuesday stand-ups belonged to which series.
|
|
14
|
+
*/
|
|
15
|
+
readonly seriesId?: string;
|
|
16
|
+
/**
|
|
17
|
+
* A short human label for the calendar this event came from, rendered ON the
|
|
18
|
+
* chip.
|
|
19
|
+
*
|
|
20
|
+
* NOT decoration, and not satisfied by a legend. Colour-coding is only
|
|
21
|
+
* conforming when the information it carries is also available another way,
|
|
22
|
+
* and the remedy has to sit on the coded item itself — a key elsewhere on the
|
|
23
|
+
* page requires the reader to hold a colour in their head and go looking.
|
|
24
|
+
*/
|
|
25
|
+
readonly calendarLabel?: string;
|
|
26
|
+
/** A key into the calendar's palette. Never a raw colour — see `EventPalette`. */
|
|
27
|
+
readonly paletteKey?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Whether this event may be dragged, resized, or otherwise moved.
|
|
30
|
+
*
|
|
31
|
+
* Defaults to editable at the calendar level, not here: an undefined value
|
|
32
|
+
* means "ask the calendar", and only an explicit `false` pins one event down
|
|
33
|
+
* while its neighbours stay live.
|
|
34
|
+
*/
|
|
35
|
+
readonly editable?: boolean;
|
|
36
|
+
/** Anything the consumer wants back in a render prop or an event handler. */
|
|
37
|
+
readonly data?: unknown;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* An event with a time of day, anchored to a real instant.
|
|
41
|
+
*
|
|
42
|
+
* Both ends are `Instant`s, so the event means the same moment regardless of
|
|
43
|
+
* which zone renders it. A meeting at 09:00 in New York is at 14:00 in London
|
|
44
|
+
* and both are the same event; storing wall-clock fields instead makes it two
|
|
45
|
+
* different events that happen to be spelled alike.
|
|
46
|
+
*/
|
|
47
|
+
export interface TimedEvent extends EventCommon {
|
|
48
|
+
readonly allDay: false;
|
|
49
|
+
readonly start: Instant;
|
|
50
|
+
/**
|
|
51
|
+
* The first instant NOT in the event. Half-open: `start <= t < endExclusive`.
|
|
52
|
+
*
|
|
53
|
+
* THE NAME IS THE DOCUMENTATION, deliberately. Half-open intervals make
|
|
54
|
+
* `duration = end - start` correct, make adjacent events provably
|
|
55
|
+
* non-overlapping, and make every algorithm in the layout core fall out
|
|
56
|
+
* without a `+1` anywhere — overlap is `aStart < bEnd && bStart < aEnd`, with
|
|
57
|
+
* no special case for two events that merely touch.
|
|
58
|
+
*
|
|
59
|
+
* The cost is the most-reported bug in calendar interoperability: a
|
|
60
|
+
* one-day event stored as 23rd → 24th renders as two days in any consumer
|
|
61
|
+
* that reads the end as inclusive. So the ±1 conversion happens in exactly
|
|
62
|
+
* TWO places — the display formatter and the date-picker binding — and the
|
|
63
|
+
* field is named so that nobody has to remember which convention this is.
|
|
64
|
+
*/
|
|
65
|
+
readonly endExclusive: Instant;
|
|
66
|
+
/**
|
|
67
|
+
* The start this occurrence had when the series first produced it.
|
|
68
|
+
*
|
|
69
|
+
* THE PERMANENT JOIN KEY FOR AN OVERRIDE, and the single most common
|
|
70
|
+
* recurrence-model mistake is keying by the CURRENT start instead. Do that
|
|
71
|
+
* and the override becomes unjoinable the moment somebody drags the event:
|
|
72
|
+
* the series still generates an occurrence at the original time, the
|
|
73
|
+
* override now claims a different one, and the calendar shows both.
|
|
74
|
+
*
|
|
75
|
+
* Set once, never updated. Absent on an event that is not part of a series.
|
|
76
|
+
*/
|
|
77
|
+
readonly originalStart?: Instant;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* An event that occupies whole days.
|
|
81
|
+
*
|
|
82
|
+
* IT CARRIES NO ZONE, AND THAT IS THE POINT. A birthday is on the 4th of March
|
|
83
|
+
* everywhere; model it as an instant and it moves to the 3rd for anyone far
|
|
84
|
+
* enough west. `PlainDate` has no offset to be wrong about.
|
|
85
|
+
*/
|
|
86
|
+
export interface AllDayEvent extends EventCommon {
|
|
87
|
+
readonly allDay: true;
|
|
88
|
+
readonly start: PlainDate;
|
|
89
|
+
/** The first day NOT in the event — same half-open rule as `TimedEvent`. */
|
|
90
|
+
readonly endExclusive: PlainDate;
|
|
91
|
+
/** See `TimedEvent.originalStart`. A date, because an all-day event has no time. */
|
|
92
|
+
readonly originalStart?: PlainDate;
|
|
93
|
+
}
|
|
94
|
+
export type CalendarEvent = TimedEvent | AllDayEvent;
|
|
95
|
+
/** Narrowing helper, so consumers never test `allDay` by hand. */
|
|
96
|
+
export declare function isAllDay(event: CalendarEvent): event is AllDayEvent;
|
|
97
|
+
/** Which part of an event a gesture is moving. */
|
|
98
|
+
export type DragKind = "move" | "resize-start" | "resize-end" | "create";
|
|
99
|
+
/**
|
|
100
|
+
* A gesture in progress, as a DELTA against the committed event.
|
|
101
|
+
*
|
|
102
|
+
* NEVER A REWRITTEN COPY OF THE EVENT, and never a reference to one. Two real
|
|
103
|
+
* failures from other calendars' trackers, both of which this shape makes
|
|
104
|
+
* impossible:
|
|
105
|
+
*
|
|
106
|
+
* A re-render replaces the event store mid-drag, and the drag is left holding
|
|
107
|
+
* an instance from the store that no longer exists — so the drop writes stale
|
|
108
|
+
* values over fresh ones.
|
|
109
|
+
*
|
|
110
|
+
* A concurrent update arrives from a server during a drag and the times end
|
|
111
|
+
* up DUPLICATED, because a snapshot taken at pointer-down was composited on
|
|
112
|
+
* top of data that had moved underneath it.
|
|
113
|
+
*
|
|
114
|
+
* A delta keyed by id composes instead of clobbering: whatever the event says
|
|
115
|
+
* at the moment of the drop, the gesture's meaning is "two hours later than
|
|
116
|
+
* that", and a change arriving underneath is respected rather than overwritten.
|
|
117
|
+
*
|
|
118
|
+
* `delta` IS A CALENDAR DURATION, not a number of milliseconds — see
|
|
119
|
+
* `CalendarDuration`. Dragging across a spring-forward boundary must preserve
|
|
120
|
+
* the wall-clock time, and a millisecond delta cannot express that.
|
|
121
|
+
*/
|
|
122
|
+
export interface EventDraft {
|
|
123
|
+
readonly id: CalendarEventId;
|
|
124
|
+
readonly kind: DragKind;
|
|
125
|
+
readonly delta: CalendarDuration;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* One swatch, with its text colour ALREADY PAIRED and verified.
|
|
129
|
+
*
|
|
130
|
+
* WHY NOT COMPUTE THE TEXT COLOUR. The familiar trick — measure the fill's
|
|
131
|
+
* luminance and flip to black or white — fails in a band in the middle where
|
|
132
|
+
* NEITHER clears AA against the fill. The threshold is also not 0.5: it is
|
|
133
|
+
* around 0.38, and implementations that use 0.5 pick white on colours that
|
|
134
|
+
* needed black. Google ships two entire palettes ("white text" and "black
|
|
135
|
+
* text") rather than compute a flip, which is the same conclusion arrived at
|
|
136
|
+
* from the other direction.
|
|
137
|
+
*
|
|
138
|
+
* So the palette is curated, each pair is measured, and a consumer supplying
|
|
139
|
+
* arbitrary hex gets a documented refusal rather than an unreadable chip.
|
|
140
|
+
*/
|
|
141
|
+
export interface PaletteEntry {
|
|
142
|
+
readonly key: string;
|
|
143
|
+
/** Human name, used in the accessible label so colour is never the only cue. */
|
|
144
|
+
readonly label: string;
|
|
145
|
+
readonly fill: string;
|
|
146
|
+
readonly text: string;
|
|
147
|
+
/** Border and left-edge accent; darker than `fill`, still AA against it. */
|
|
148
|
+
readonly edge: string;
|
|
149
|
+
}
|
|
150
|
+
export type EventPalette = readonly PaletteEntry[];
|
|
151
|
+
export type CalendarView = "day" | "week" | "month";
|
|
152
|
+
/**
|
|
153
|
+
* The days a view is currently showing, and the zone it is showing them in.
|
|
154
|
+
*
|
|
155
|
+
* `days` is EXPLICIT rather than a start/end pair, because a month grid's days
|
|
156
|
+
* are not a contiguous range in any useful sense — they cross two month
|
|
157
|
+
* boundaries and the layout core needs to address them positionally.
|
|
158
|
+
*/
|
|
159
|
+
export interface VisibleRange {
|
|
160
|
+
readonly view: CalendarView;
|
|
161
|
+
readonly zone: TimeZone;
|
|
162
|
+
readonly days: readonly PlainDate[];
|
|
163
|
+
/** 0 = Sunday. Carried on the range so the packers never have to guess. */
|
|
164
|
+
readonly weekStartsOn: number;
|
|
165
|
+
}
|
|
166
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ClassValue } from "clsx";
|
|
2
|
+
/**
|
|
3
|
+
* Merge conditional class names, resolving Tailwind conflicts last-wins.
|
|
4
|
+
* Every component funnels its class composition through this so a consumer's
|
|
5
|
+
* `className` always beats the component's own defaults.
|
|
6
|
+
*/
|
|
7
|
+
export declare function cn(...inputs: ClassValue[]): string;
|