@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,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The token contract. Every grammar in this system produces this shape and
|
|
3
|
+
* nothing else — the highlighter, the editor overlay, the markdown renderer and
|
|
4
|
+
* the tests all read it.
|
|
5
|
+
*
|
|
6
|
+
* WHY A FLAT TOKEN LIST AND NOT AN HTML STRING. The obvious design (and the one
|
|
7
|
+
* the Vue original uses) is `highlight(code) -> "<span class=…>…"`, one function
|
|
8
|
+
* per language. It cannot do the two things this component exists to do:
|
|
9
|
+
*
|
|
10
|
+
* 1. EDITING. The editor is a transparent `<textarea>` sitting exactly on top
|
|
11
|
+
* of a `<pre>` of the same text. That only works if the rendered text is
|
|
12
|
+
* character-for-character the source — same characters, same order, same
|
|
13
|
+
* length. A list of offsets into the original string makes that checkable;
|
|
14
|
+
* a string of markup makes it a promise nobody can verify.
|
|
15
|
+
* 2. NESTING. A fenced code block inside markdown, or `<style>` inside a Vue
|
|
16
|
+
* SFC, is a region of one language inside another. With offsets, an inner
|
|
17
|
+
* grammar's tokens splice into the outer stream and everything downstream
|
|
18
|
+
* is unaware anything happened. With strings you are concatenating markup
|
|
19
|
+
* and hoping the escaping survives.
|
|
20
|
+
*
|
|
21
|
+
* The invariant that makes both work, asserted by `tokenize`'s own tests:
|
|
22
|
+
* tokens are non-overlapping, ascending, and cover the whole input with no
|
|
23
|
+
* gaps. `src.slice(t.start, t.end)` joined over every token IS the source.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Token categories. Deliberately a closed set: each one maps to exactly one CSS
|
|
27
|
+
* custom property in `src/styles/syntax.css`, so a language cannot invent a
|
|
28
|
+
* colour, and adding a category is a visible, one-place decision.
|
|
29
|
+
*
|
|
30
|
+
* Named for ROLE rather than for any one language's grammar — `property` covers
|
|
31
|
+
* a JSON key, a CSS declaration name and a JS object key, because all three are
|
|
32
|
+
* "the name on the left" and should read the same way in every language.
|
|
33
|
+
*/
|
|
34
|
+
export type TokenType = "text" | "comment" | "punctuation" | "operator" | "string" | "escape" | "number" | "boolean" | "null" | "regex" | "keyword" | "property" | "variable" | "function" | "type" | "constant" | "tag" | "attribute" | "selector" | "atrule" | "heading" | "emphasis" | "strong" | "strike" | "link" | "url" | "marker" | "quote" | "invalid";
|
|
35
|
+
/** A run of source text with one category. Half-open range: `[start, end)`. */
|
|
36
|
+
export interface Token {
|
|
37
|
+
/** Offset into the ORIGINAL source string, never into a nested substring. */
|
|
38
|
+
start: number;
|
|
39
|
+
end: number;
|
|
40
|
+
type: TokenType;
|
|
41
|
+
/**
|
|
42
|
+
* The grammar that produced this token. An embedded region carries the INNER
|
|
43
|
+
* language's name, which is what lets a consumer style a fenced block
|
|
44
|
+
* differently from the markdown around it — and what makes a nesting bug
|
|
45
|
+
* visible in a test rather than merely wrong on screen.
|
|
46
|
+
*/
|
|
47
|
+
lang: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* One scanning rule, tried in order at the current position.
|
|
51
|
+
*
|
|
52
|
+
* `match` MUST carry the sticky flag. A non-sticky regex searches forward from
|
|
53
|
+
* the position and can match text the scanner has not reached, silently
|
|
54
|
+
* swallowing the characters in between — the failure looks like "highlighting
|
|
55
|
+
* is slightly off" and is very hard to trace back. `defineGrammar` throws on a
|
|
56
|
+
* non-sticky pattern rather than letting that ship.
|
|
57
|
+
*/
|
|
58
|
+
export interface Rule {
|
|
59
|
+
match: RegExp;
|
|
60
|
+
/** Category for the entire match. Mutually exclusive with `groups`. */
|
|
61
|
+
token?: TokenType;
|
|
62
|
+
/**
|
|
63
|
+
* Category per capture group, for a rule that matches several things at once
|
|
64
|
+
* (`key` `:` in JSON, `<` `div` in HTML). `null` leaves a group as plain
|
|
65
|
+
* text. Anything between groups is emitted as `text`, so coverage holds.
|
|
66
|
+
*/
|
|
67
|
+
groups?: (TokenType | null)[];
|
|
68
|
+
/** Enter another state of the SAME grammar (a string body, a comment). */
|
|
69
|
+
push?: string;
|
|
70
|
+
/** Leave the current state. Applied after the token is emitted. */
|
|
71
|
+
pop?: true;
|
|
72
|
+
/**
|
|
73
|
+
* Enter ANOTHER grammar for the region that follows, until `until` matches.
|
|
74
|
+
* A string names it outright (`<style>` -> css); a function reads it off the
|
|
75
|
+
* match, which is how a fence takes its language from its own info string and
|
|
76
|
+
* how `<script lang="ts">` differs from `<script>`.
|
|
77
|
+
*
|
|
78
|
+
* Returning null (unknown language) is not an error — the region is scanned
|
|
79
|
+
* as plain text and still terminates correctly at `until`. An unrecognised
|
|
80
|
+
* language must never break the document containing it.
|
|
81
|
+
*/
|
|
82
|
+
embed?: string | ((match: RegExpExecArray) => string | null);
|
|
83
|
+
/** Required with `embed`: the pattern that ends the embedded region. */
|
|
84
|
+
until?: RegExp;
|
|
85
|
+
/** Category for the terminator itself. Defaults to `punctuation`. */
|
|
86
|
+
untilToken?: TokenType;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A language. `states.root` is the entry point; other states are pushed by
|
|
90
|
+
* rules. Most grammars need only `root` plus a state per multi-line construct.
|
|
91
|
+
*/
|
|
92
|
+
export interface Grammar {
|
|
93
|
+
name: string;
|
|
94
|
+
aliases?: readonly string[];
|
|
95
|
+
states: Record<string, Rule[]>;
|
|
96
|
+
/**
|
|
97
|
+
* Full override for a language the rule stack genuinely cannot express.
|
|
98
|
+
* Markdown is the only one: its structure is by BLOCK (a list item's content
|
|
99
|
+
* is decided by indentation relative to its marker, several lines later),
|
|
100
|
+
* which no positional rule stack can see. It parses properly and emits this
|
|
101
|
+
* same token shape, so every consumer stays unaware of the difference.
|
|
102
|
+
*
|
|
103
|
+
* A grammar with `tokenize` may leave `states` empty.
|
|
104
|
+
*/
|
|
105
|
+
tokenize?: (source: string, ctx: TokenizeContext) => Token[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Handed to a `tokenize` override so it can highlight regions of other
|
|
109
|
+
* languages — a fenced block, YAML front matter — without importing the
|
|
110
|
+
* registry itself and creating a cycle.
|
|
111
|
+
*/
|
|
112
|
+
export interface TokenizeContext {
|
|
113
|
+
/**
|
|
114
|
+
* Tokenize `source` as `language`, with every offset shifted by `offset` so
|
|
115
|
+
* the result splices into the caller's stream. An unknown language yields one
|
|
116
|
+
* `text` token, never an error.
|
|
117
|
+
*/
|
|
118
|
+
sub(source: string, language: string | null, offset: number): Token[];
|
|
119
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { AmbiguousTimeError, isoDateString, isoDateTimeString, type CalendarDuration, type Disambiguation, type Instant, type PlainDate, type PlainDateTime, type TimeZone, } from "./types";
|
|
2
|
+
export { addDuration, dayFraction, dayLengthMs, hoursInDay, instantAtFraction, instantToPlainDate, instantToPlainDateTime, nextDay, offsetAt, plainDateTimeToInstant, startOfDay, } from "./zone";
|
|
3
|
+
export { addDays, addMonths, atMidnight, atTime, comparePlainDate, dayOfWeek, daysBetween, daysInMonth, endOfMonth, isSameDate, monthGridDays, parsePlainDate, startOfMonth, startOfWeek, weekDays, } from "./plain";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { isoDateString, type PlainDate, type PlainDateTime } from "./types";
|
|
2
|
+
/** Days in `month` of `year`, leap years included. */
|
|
3
|
+
export declare function daysInMonth(year: number, month: number): number;
|
|
4
|
+
/** `date` moved by `days`, which may be negative, rolling months and years. */
|
|
5
|
+
export declare function addDays(date: PlainDate, days: number): PlainDate;
|
|
6
|
+
/**
|
|
7
|
+
* `date` moved by `months`, clamping the day to the target month's length.
|
|
8
|
+
*
|
|
9
|
+
* CLAMPING, NOT ROLLING: one month after the 31st of January is the 28th or
|
|
10
|
+
* 29th of February, never the 3rd of March. Rolling is what `Date.setMonth`
|
|
11
|
+
* does natively and it is why "next month" buttons skip February.
|
|
12
|
+
*/
|
|
13
|
+
export declare function addMonths(date: PlainDate, months: number): PlainDate;
|
|
14
|
+
/** Whole days from `a` to `b`; negative when `b` is earlier. */
|
|
15
|
+
export declare function daysBetween(a: PlainDate, b: PlainDate): number;
|
|
16
|
+
/** Negative when `a` is earlier, 0 when equal, positive when later. */
|
|
17
|
+
export declare function comparePlainDate(a: PlainDate, b: PlainDate): number;
|
|
18
|
+
export declare function isSameDate(a: PlainDate, b: PlainDate): boolean;
|
|
19
|
+
/** 0 = Sunday … 6 = Saturday, matching `Date.getUTCDay` and `Intl`'s weekday order. */
|
|
20
|
+
export declare function dayOfWeek(date: PlainDate): number;
|
|
21
|
+
/**
|
|
22
|
+
* The first day of the week `date` falls in.
|
|
23
|
+
*
|
|
24
|
+
* `weekStartsOn` IS A PARAMETER WITH NO DEFAULT ANYWHERE UP THE STACK, because
|
|
25
|
+
* there is no correct global answer: Sunday in the US and Japan, Monday across
|
|
26
|
+
* Europe and by ISO 8601, Saturday in much of the Middle East. A component that
|
|
27
|
+
* picks one silently is wrong for most of the world, so the calendar surfaces
|
|
28
|
+
* it and this function simply obeys.
|
|
29
|
+
*/
|
|
30
|
+
export declare function startOfWeek(date: PlainDate, weekStartsOn: number): PlainDate;
|
|
31
|
+
/** The 1st of `date`'s month. */
|
|
32
|
+
export declare function startOfMonth(date: PlainDate): PlainDate;
|
|
33
|
+
/** The last day of `date`'s month. */
|
|
34
|
+
export declare function endOfMonth(date: PlainDate): PlainDate;
|
|
35
|
+
/**
|
|
36
|
+
* Every day a month grid shows, INCLUDING the leading and trailing days that
|
|
37
|
+
* belong to the neighbouring months.
|
|
38
|
+
*
|
|
39
|
+
* Always whole weeks, so the result is a multiple of seven and the grid never
|
|
40
|
+
* has a ragged edge. The count varies — a 28-day February beginning on the
|
|
41
|
+
* week's first day needs four rows, and a 31-day month beginning on its last
|
|
42
|
+
* day needs six. Callers that assume six rows draw an empty one eleven months
|
|
43
|
+
* a year; callers that assume five are simply wrong twice a year.
|
|
44
|
+
*/
|
|
45
|
+
export declare function monthGridDays(date: PlainDate, weekStartsOn: number): PlainDate[];
|
|
46
|
+
/** The seven days of the week `date` falls in. */
|
|
47
|
+
export declare function weekDays(date: PlainDate, weekStartsOn: number): PlainDate[];
|
|
48
|
+
/**
|
|
49
|
+
* Parse `YYYY-MM-DD`.
|
|
50
|
+
*
|
|
51
|
+
* FAILS LOUDLY on anything else, including the shapes `Date` accepts and
|
|
52
|
+
* silently reinterprets. `new Date("2026-2-30")` yields the 2nd of March, which
|
|
53
|
+
* is a data error becoming a rendered event on the wrong day with nothing
|
|
54
|
+
* anywhere reporting a problem.
|
|
55
|
+
*/
|
|
56
|
+
export declare function parsePlainDate(iso: string): PlainDate;
|
|
57
|
+
export { isoDateString };
|
|
58
|
+
/** A `PlainDateTime` at midnight on `date` — the wall reading, not an instant. */
|
|
59
|
+
export declare function atMidnight(date: PlainDate): PlainDateTime;
|
|
60
|
+
/** A `PlainDateTime` at `hour`:`minute` on `date`. */
|
|
61
|
+
export declare function atTime(date: PlainDate, hour: number, minute?: number): PlainDateTime;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A point on the timeline, as milliseconds since the epoch.
|
|
3
|
+
*
|
|
4
|
+
* NOT a `Date`. A `Date` is a mutable object that prints itself in the host's
|
|
5
|
+
* local zone, and every calendar bug in the survey behind this component
|
|
6
|
+
* involved someone reading a `Date`'s local fields when they meant a specific
|
|
7
|
+
* zone's. A number cannot be misread that way — it has no fields to read.
|
|
8
|
+
*/
|
|
9
|
+
export type Instant = number;
|
|
10
|
+
/** An IANA time zone identifier, e.g. `"America/New_York"`. */
|
|
11
|
+
export type TimeZone = string;
|
|
12
|
+
/**
|
|
13
|
+
* A calendar day. No time, no zone, no offset — just which square on the wall.
|
|
14
|
+
*
|
|
15
|
+
* `month` IS ONE-BASED, matching `Temporal` and matching how every human writes
|
|
16
|
+
* a date. `Date`'s zero-based month is the single most common off-by-one in
|
|
17
|
+
* date code and it is not reproduced here.
|
|
18
|
+
*/
|
|
19
|
+
export interface PlainDate {
|
|
20
|
+
readonly year: number;
|
|
21
|
+
/** 1–12. */
|
|
22
|
+
readonly month: number;
|
|
23
|
+
/** 1–31. */
|
|
24
|
+
readonly day: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A wall-clock reading. What a clock on the wall says, with no claim about
|
|
28
|
+
* which wall.
|
|
29
|
+
*
|
|
30
|
+
* This is the type that makes the ambiguity explicit rather than accidental:
|
|
31
|
+
* `2026-11-01T01:30` in New York happened TWICE, and `2026-03-08T02:30` never
|
|
32
|
+
* happened at all. A `PlainDateTime` can represent both, which is precisely why
|
|
33
|
+
* turning one into an `Instant` requires saying what to do about it.
|
|
34
|
+
*/
|
|
35
|
+
export interface PlainDateTime extends PlainDate {
|
|
36
|
+
/** 0–23. */
|
|
37
|
+
readonly hour: number;
|
|
38
|
+
/** 0–59. */
|
|
39
|
+
readonly minute: number;
|
|
40
|
+
/** 0–59. */
|
|
41
|
+
readonly second: number;
|
|
42
|
+
/** 0–999. */
|
|
43
|
+
readonly millisecond: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* How much to move, in CALENDAR units rather than elapsed time.
|
|
47
|
+
*
|
|
48
|
+
* THE DISTINCTION IS THE WHOLE POINT, and getting it wrong is the bug in every
|
|
49
|
+
* library surveyed. "One day later" is not "86,400,000 ms later": across a
|
|
50
|
+
* spring-forward boundary it is 23 hours, and across a fall-back it is 25. A
|
|
51
|
+
* user dragging an event from Saturday to Sunday expects it to keep its
|
|
52
|
+
* wall-clock time, so the move has to be expressed as `{ days: 1 }` and
|
|
53
|
+
* resolved against the zone — never added as a number.
|
|
54
|
+
*
|
|
55
|
+
* `hours` and `minutes` ARE exact elapsed time, and that is correct: dragging
|
|
56
|
+
* an event down by two hours means two hours of real duration.
|
|
57
|
+
*/
|
|
58
|
+
export interface CalendarDuration {
|
|
59
|
+
readonly days?: number;
|
|
60
|
+
readonly hours?: number;
|
|
61
|
+
readonly minutes?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* What to do when a wall-clock reading does not name exactly one instant.
|
|
65
|
+
*
|
|
66
|
+
* Spelled as `Temporal.ZonedDateTime.from`'s option of the same name, with the
|
|
67
|
+
* same meanings, so this is one more thing that becomes a deletion later.
|
|
68
|
+
*
|
|
69
|
+
* - `compatible` — what every other date library does, and the default.
|
|
70
|
+
* In a GAP (spring forward) move forward by the size of the gap; in an
|
|
71
|
+
* OVERLAP (fall back) take the first of the two.
|
|
72
|
+
* - `earlier` / `later` — take that side explicitly.
|
|
73
|
+
* - `reject` — throw. For a parser or an import, where a time that never
|
|
74
|
+
* existed is a fact about bad input rather than something to paper over.
|
|
75
|
+
*/
|
|
76
|
+
export type Disambiguation = "compatible" | "earlier" | "later" | "reject";
|
|
77
|
+
/** Thrown by `reject` disambiguation, and never by anything else. */
|
|
78
|
+
export declare class AmbiguousTimeError extends Error {
|
|
79
|
+
readonly wall: PlainDateTime;
|
|
80
|
+
readonly zone: TimeZone;
|
|
81
|
+
readonly kind: "gap" | "overlap";
|
|
82
|
+
constructor(wall: PlainDateTime, zone: TimeZone, kind: "gap" | "overlap");
|
|
83
|
+
}
|
|
84
|
+
/** `2026-03-08T02:30:00.000` — used in errors, and by the ISO helpers. */
|
|
85
|
+
export declare function isoDateTimeString(wall: PlainDateTime): string;
|
|
86
|
+
/** `2026-03-08`. */
|
|
87
|
+
export declare function isoDateString(date: PlainDate): string;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { type Disambiguation, type Instant, type PlainDate, type PlainDateTime, type TimeZone } from "./types";
|
|
2
|
+
/** The wall-clock reading in `zone` at `instant`. */
|
|
3
|
+
export declare function instantToPlainDateTime(zone: TimeZone, instant: Instant): PlainDateTime;
|
|
4
|
+
/**
|
|
5
|
+
* `zone`'s offset from UTC at `instant`, in milliseconds. East is positive.
|
|
6
|
+
*
|
|
7
|
+
* THE ONE PRIMITIVE. Read by asking the browser what the wall clock says at
|
|
8
|
+
* that instant and subtracting: if it is 07:00 UTC and the clock in New York
|
|
9
|
+
* reads 02:00, the offset is −5 hours. No table, no parsing of a zone name, no
|
|
10
|
+
* assumption that an offset is a whole number of hours — `Pacific/Chatham` sits
|
|
11
|
+
* at +12:45, and `Asia/Kathmandu` at +5:45.
|
|
12
|
+
*/
|
|
13
|
+
export declare function offsetAt(zone: TimeZone, instant: Instant): number;
|
|
14
|
+
/**
|
|
15
|
+
* The instant at which `zone`'s clock reads `wall`.
|
|
16
|
+
*
|
|
17
|
+
* See `Disambiguation` for what happens when that is not exactly one instant.
|
|
18
|
+
* The default is `compatible`, which is what `Temporal` and every other date
|
|
19
|
+
* library do, so the surprising cases are the ones you have to ask for.
|
|
20
|
+
*/
|
|
21
|
+
export declare function plainDateTimeToInstant(zone: TimeZone, wall: PlainDateTime, disambiguation?: Disambiguation): Instant;
|
|
22
|
+
/** The calendar day `instant` falls on, in `zone`. */
|
|
23
|
+
export declare function instantToPlainDate(zone: TimeZone, instant: Instant): PlainDate;
|
|
24
|
+
/**
|
|
25
|
+
* The first instant of `date` in `zone`.
|
|
26
|
+
*
|
|
27
|
+
* NOT "midnight". In `America/Santiago` on 2026-09-06 the clock jumps from
|
|
28
|
+
* 00:00 to 01:00, so the day's first instant reads 01:00 — and a grid that
|
|
29
|
+
* assumes its own origin is midnight puts every event on that day an hour out.
|
|
30
|
+
* `America/Havana` and `Asia/Beirut` do the same thing on their own dates.
|
|
31
|
+
*
|
|
32
|
+
* Implemented by asking for midnight and, when the clock skipped it, walking
|
|
33
|
+
* forward a minute at a time until a reading exists. The walk is bounded: no
|
|
34
|
+
* transition in the IANA database exceeds two hours, so 180 iterations cannot
|
|
35
|
+
* be reached by real data, and the bound exists to fail loudly rather than spin
|
|
36
|
+
* if that ever stops being true.
|
|
37
|
+
*/
|
|
38
|
+
export declare function startOfDay(zone: TimeZone, date: PlainDate): Instant;
|
|
39
|
+
/** The day after `date` on the calendar, ignoring zones entirely. */
|
|
40
|
+
export declare function nextDay(date: PlainDate): PlainDate;
|
|
41
|
+
/**
|
|
42
|
+
* How long `date` actually lasts in `zone`, in milliseconds.
|
|
43
|
+
*
|
|
44
|
+
* Measured as the distance between one day's first instant and the next day's,
|
|
45
|
+
* which is true by construction for every case — 23 hours, 25 hours, the 30
|
|
46
|
+
* minutes of Lord Howe, and a day that starts at 01:00 — with no special case
|
|
47
|
+
* for any of them. That is the entire reason positions in the grid are a RATIO
|
|
48
|
+
* of this number rather than `hour × rowHeight`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function dayLengthMs(zone: TimeZone, date: PlainDate): number;
|
|
51
|
+
/**
|
|
52
|
+
* How many hours `date` lasts in `zone` — 23, 24, 25, or 23.5.
|
|
53
|
+
*
|
|
54
|
+
* Fractional by design. `Australia/Lord_Howe` shifts by thirty minutes, so a
|
|
55
|
+
* signature returning an integer would be lying about a real zone, and any
|
|
56
|
+
* caller branching on `=== 23` is already broken.
|
|
57
|
+
*/
|
|
58
|
+
export declare function hoursInDay(zone: TimeZone, date: PlainDate): number;
|
|
59
|
+
/**
|
|
60
|
+
* Where `instant` sits within `date`, as a fraction from 0 to 1.
|
|
61
|
+
*
|
|
62
|
+
* THE LOAD-BEARING FUNCTION. A 23-hour day compresses and a 25-hour day
|
|
63
|
+
* stretches with no branch anywhere, because the divisor is the day's real
|
|
64
|
+
* length. Values outside 0–1 mean the instant is not on this day and are
|
|
65
|
+
* returned rather than clamped — the layout core needs to know by how much in
|
|
66
|
+
* order to clip a multi-day span.
|
|
67
|
+
*/
|
|
68
|
+
export declare function dayFraction(zone: TimeZone, date: PlainDate, instant: Instant): number;
|
|
69
|
+
/**
|
|
70
|
+
* The exact inverse of `dayFraction`.
|
|
71
|
+
*
|
|
72
|
+
* IT MUST BE EXACT, and that is not a stylistic preference. Rendering maps an
|
|
73
|
+
* instant to a position and hit-testing maps a position back to an instant; if
|
|
74
|
+
* the two disagree by even a rounding step, an event lands one slot away from
|
|
75
|
+
* where it was dropped. FullCalendar's Australia selection bug is exactly this
|
|
76
|
+
* pair drifting apart. `dayFraction(z, d, instantAtFraction(z, d, f)) === f`
|
|
77
|
+
* for every zone in the corpus, and there is a test that says so.
|
|
78
|
+
*/
|
|
79
|
+
export declare function instantAtFraction(zone: TimeZone, date: PlainDate, fraction: number): Instant;
|
|
80
|
+
/**
|
|
81
|
+
* Move `instant` by a CALENDAR duration.
|
|
82
|
+
*
|
|
83
|
+
* Days are applied on the calendar and then re-anchored to the same wall-clock
|
|
84
|
+
* time, so an event dragged from Saturday to Sunday across a transition keeps
|
|
85
|
+
* reading 09:00 rather than becoming 08:00 or 10:00. Hours and minutes are
|
|
86
|
+
* applied afterwards as exact elapsed time, because dragging an event down the
|
|
87
|
+
* grid by two hours does mean two hours.
|
|
88
|
+
*
|
|
89
|
+
* ORDER MATTERS AND IS FIXED: days first, then time. The other order makes
|
|
90
|
+
* "one day and two hours later" depend on which side of a transition the
|
|
91
|
+
* intermediate value happened to land on.
|
|
92
|
+
*/
|
|
93
|
+
export declare function addDuration(zone: TimeZone, instant: Instant, duration: {
|
|
94
|
+
days?: number;
|
|
95
|
+
hours?: number;
|
|
96
|
+
minutes?: number;
|
|
97
|
+
}, disambiguation?: Disambiguation): Instant;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscribes to a CSS media query and re-renders when it changes.
|
|
3
|
+
*
|
|
4
|
+
* WHY A HOOK AND NOT A CSS CLASS. Almost everything responsive in this system
|
|
5
|
+
* belongs in CSS, where it costs nothing and works before hydration. This
|
|
6
|
+
* exists for the case CSS cannot reach: a layout whose measurements are written
|
|
7
|
+
* as INLINE STYLE from application state — a resizable panel group being the
|
|
8
|
+
* one that matters here. A utility class cannot override `style="flex-grow:3"`,
|
|
9
|
+
* so the component has to know the width to write a different value.
|
|
10
|
+
*
|
|
11
|
+
* Reach for a `lg:` variant first. This is the exception, not the pattern.
|
|
12
|
+
*
|
|
13
|
+
* `useSyncExternalStore` rather than `useState` + `useEffect`: it reads the
|
|
14
|
+
* value during render on the client and returns the server snapshot during SSR,
|
|
15
|
+
* so there is no first paint at the wrong breakpoint and no hydration mismatch
|
|
16
|
+
* warning. The effect version renders once with a guess and then corrects
|
|
17
|
+
* itself, which is a visible layout jump on exactly the devices this is for.
|
|
18
|
+
*/
|
|
19
|
+
export declare function useMediaQuery(query: string, serverFallback?: boolean): boolean;
|
|
20
|
+
/** Tailwind's own breakpoints, so a JS check and a `lg:` class agree. */
|
|
21
|
+
export declare const BREAKPOINTS: {
|
|
22
|
+
readonly sm: 640;
|
|
23
|
+
readonly md: 768;
|
|
24
|
+
readonly lg: 1024;
|
|
25
|
+
readonly xl: 1280;
|
|
26
|
+
};
|
|
27
|
+
export type Breakpoint = keyof typeof BREAKPOINTS;
|
|
28
|
+
/** True below the named breakpoint — the JS twin of `max-<bp>:`. */
|
|
29
|
+
export declare function useBelow(breakpoint: Breakpoint, serverFallback?: boolean): boolean;
|
package/package.json
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@danxbot/ui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Danxbot — a domain-agnostic React design system with motion as a first-class primitive.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Dan Newman",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/newms87/danxbot.git",
|
|
11
|
+
"directory": "design-system"
|
|
12
|
+
},
|
|
13
|
+
"bugs": "https://github.com/newms87/danxbot/issues",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react",
|
|
16
|
+
"design-system",
|
|
17
|
+
"component-library",
|
|
18
|
+
"tailwindcss",
|
|
19
|
+
"accessible",
|
|
20
|
+
"animation",
|
|
21
|
+
"ui"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
29
|
+
"module": "./dist/index.js",
|
|
30
|
+
"types": "./dist/types/index.d.ts",
|
|
31
|
+
"sideEffects": [
|
|
32
|
+
"*.css"
|
|
33
|
+
],
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/types/index.d.ts",
|
|
37
|
+
"import": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./styles.css": "./dist/styles.css",
|
|
40
|
+
"./fonts.css": "./dist/fonts.css",
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist"
|
|
45
|
+
],
|
|
46
|
+
"scripts": {
|
|
47
|
+
"gen:api": "node scripts/gen-api-manifest.mjs",
|
|
48
|
+
"predev": "npm run gen:api",
|
|
49
|
+
"pretypecheck": "npm run gen:api",
|
|
50
|
+
"pretest": "npm run gen:api",
|
|
51
|
+
"prebuild:demo": "npm run gen:api",
|
|
52
|
+
"dev": "vite",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"typecheck:previews": "tsc -p tsconfig.previews.json",
|
|
55
|
+
"audit:previews": "node scripts/audit-preview-classes.mjs",
|
|
56
|
+
"audit:cards": "node scripts/audit-card-theme.mjs",
|
|
57
|
+
"audit:hover": "node scripts/audit-hover.mjs",
|
|
58
|
+
"test": "vitest run",
|
|
59
|
+
"build:lib": "vite build --config vite.lib.config.ts && node scripts/postbuild-css.mjs && npm run build:types",
|
|
60
|
+
"fonts": "node scripts/fetch-fonts.mjs",
|
|
61
|
+
"icons": "node scripts/build-icons.mjs",
|
|
62
|
+
"build:types": "tsc -p tsconfig.build.json",
|
|
63
|
+
"build:demo": "vite build",
|
|
64
|
+
"build": "npm run build:lib && npm run build:demo",
|
|
65
|
+
"verify": "npm run typecheck && npm run test && npm run build && npm run typecheck:previews",
|
|
66
|
+
"preview": "vite preview",
|
|
67
|
+
"preview:built": "vite preview --outDir demo-dist --port 5801 --strictPort",
|
|
68
|
+
"gates": "npm run shoot && npm run a11y && node scripts/shoot-overlays.mjs && npm run probe",
|
|
69
|
+
"a11y": "node scripts/a11y-scan.mjs",
|
|
70
|
+
"shoot": "node scripts/shoot.mjs",
|
|
71
|
+
"probe": "node scripts/probe-scale.mjs && node scripts/probe-switch.mjs && node scripts/probe-panel.mjs && node scripts/probe-popover-width.mjs && node scripts/probe-api.mjs && node scripts/probe-api-live.mjs",
|
|
72
|
+
"sync": "node scripts/sync.mjs",
|
|
73
|
+
"visual": "node scripts/visual-docker.mjs",
|
|
74
|
+
"visual:update": "node scripts/visual-docker.mjs --update-snapshots",
|
|
75
|
+
"visual:host": "playwright test",
|
|
76
|
+
"visual:report": "playwright show-report",
|
|
77
|
+
"audit:arrows": "node scripts/audit-arrows.mjs",
|
|
78
|
+
"audit:motion": "node scripts/audit-motion.mjs",
|
|
79
|
+
"audit:responsive": "node scripts/audit-responsive.mjs",
|
|
80
|
+
"audit:dnd": "node scripts/audit-dnd.mjs && node scripts/probe-dnd-sensors.mjs && node scripts/probe-dnd-a11y.mjs",
|
|
81
|
+
"audit:axtree": "node scripts/audit-axtree.mjs",
|
|
82
|
+
"audit:mutations": "node scripts/audit-mutations.mjs",
|
|
83
|
+
"audit:palette": "node scripts/audit-palette.mjs",
|
|
84
|
+
"probe:calendar": "node scripts/probe-calendar.mjs",
|
|
85
|
+
"audit": "npm run audit:previews && npm run audit:cards && npm run audit:arrows && npm run audit:axtree && npm run audit:palette && npm run audit:motion && npm run audit:responsive && npm run audit:hover && npm run a11y && npm run probe:calendar && npm run probe:calendar-drag && npm run audit:dnd && npm run probe:markdown",
|
|
86
|
+
"probe:calendar-drag": "node scripts/probe-calendar-drag.mjs",
|
|
87
|
+
"audit:conventions": "node scripts/audit-conventions.mjs",
|
|
88
|
+
"audit:component-exports": "node scripts/audit-component-exports.mjs",
|
|
89
|
+
"probe:markdown": "node scripts/probe-markdown-caret.mjs && node scripts/probe-markdown-component.mjs && node scripts/probe-markdown-affordances.mjs",
|
|
90
|
+
"release": "node --no-deprecation scripts/publish.mjs"
|
|
91
|
+
},
|
|
92
|
+
"peerDependencies": {
|
|
93
|
+
"react": "^19",
|
|
94
|
+
"react-dom": "^19"
|
|
95
|
+
},
|
|
96
|
+
"dependencies": {
|
|
97
|
+
"@base-ui/react": "^1.7.0",
|
|
98
|
+
"@tanstack/react-table": "^8.21.3",
|
|
99
|
+
"clsx": "^2.1.1",
|
|
100
|
+
"tailwind-merge": "^3.3.1",
|
|
101
|
+
"tailwind-variants": "^3.3.1"
|
|
102
|
+
},
|
|
103
|
+
"devDependencies": {
|
|
104
|
+
"@axe-core/playwright": "^4.13.0",
|
|
105
|
+
"@playwright/test": "^1.62.1",
|
|
106
|
+
"@tailwindcss/vite": "^4.1.14",
|
|
107
|
+
"@testing-library/dom": "^10.4.1",
|
|
108
|
+
"@testing-library/react": "^16.3.2",
|
|
109
|
+
"@types/node": "^26.2.0",
|
|
110
|
+
"@types/react": "^19.2.2",
|
|
111
|
+
"@types/react-dom": "^19.2.1",
|
|
112
|
+
"@vitejs/plugin-react": "^5.0.4",
|
|
113
|
+
"axe-core": "^4.13.0",
|
|
114
|
+
"fumadocs-core": "^16.14.5",
|
|
115
|
+
"fumadocs-mdx": "^15.3.0",
|
|
116
|
+
"happy-dom": "^20.11.2",
|
|
117
|
+
"lucide-react": "^0.545.0",
|
|
118
|
+
"playwright": "^1.62.1",
|
|
119
|
+
"react": "^19.2.0",
|
|
120
|
+
"react-dom": "^19.2.0",
|
|
121
|
+
"tailwindcss": "^4.1.14",
|
|
122
|
+
"typescript": "^5.9.3",
|
|
123
|
+
"vite": "^7.1.9",
|
|
124
|
+
"vitest": "^4.1.11",
|
|
125
|
+
"zod": "^4.4.3"
|
|
126
|
+
},
|
|
127
|
+
"allowScripts": {
|
|
128
|
+
"esbuild@0.28.2": true
|
|
129
|
+
}
|
|
130
|
+
}
|