@orvain/utils 0.0.0-stage → 0.1.1
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 +64 -0
- package/README.md +48 -2
- package/dist/a11y.d.cts +102 -0
- package/dist/a11y.d.ts +103 -0
- package/dist/breakpoints.d.cts +36 -0
- package/dist/breakpoints.d.ts +37 -0
- package/dist/calendar.d.cts +127 -0
- package/dist/calendar.d.ts +128 -0
- package/dist/chart/color.d.cts +72 -0
- package/dist/chart/color.d.ts +73 -0
- package/dist/chart/index.d.cts +2 -0
- package/dist/chart/index.d.ts +3 -0
- package/dist/chart/math.d.cts +66 -0
- package/dist/chart/math.d.ts +67 -0
- package/dist/chart-items/index.d.cts +64 -0
- package/dist/chart-items/index.d.ts +65 -0
- package/dist/codeTokenizer.d.cts +29 -0
- package/dist/codeTokenizer.d.ts +30 -0
- package/dist/cssModule.d.cts +12 -0
- package/dist/cssModule.d.ts +13 -0
- package/dist/dismiss.d.cts +40 -0
- package/dist/dismiss.d.ts +41 -0
- package/dist/floating.d.cts +137 -0
- package/dist/floating.d.ts +138 -0
- package/dist/formField.d.cts +58 -0
- package/dist/formField.d.ts +59 -0
- package/dist/helpers.d.cts +17 -0
- package/dist/helpers.d.ts +18 -0
- package/dist/index.cjs +11 -0
- package/dist/index.d.cts +17 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +2819 -0
- package/dist/kanbanDnd.d.cts +71 -0
- package/dist/kanbanDnd.d.ts +72 -0
- package/dist/listNavigation.d.cts +36 -0
- package/dist/listNavigation.d.ts +37 -0
- package/dist/richText/blockquote.d.cts +11 -0
- package/dist/richText/blockquote.d.ts +12 -0
- package/dist/richText/editor.d.cts +117 -0
- package/dist/richText/editor.d.ts +118 -0
- package/dist/richText/index.d.cts +3 -0
- package/dist/richText/index.d.ts +4 -0
- package/dist/richText/model.d.cts +161 -0
- package/dist/richText/model.d.ts +162 -0
- package/dist/slider.d.cts +18 -0
- package/dist/slider.d.ts +19 -0
- package/dist/tree.d.cts +78 -0
- package/dist/tree.d.ts +79 -0
- package/dist/types.d.cts +22 -0
- package/dist/types.d.ts +23 -0
- package/package.json +56 -3
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rich-text document model shared by the React and Vue `TextAreaWithToolbar`.
|
|
3
|
+
*
|
|
4
|
+
* Every HTML string that enters the editor (a `value`, a paste, a drop, the
|
|
5
|
+
* live DOM after native typing) is read into this model and written back out
|
|
6
|
+
* by `serializeRichText`. Output is only ever produced from the model, so the
|
|
7
|
+
* allow-list is structural: text is escaped, and the only markup that can come
|
|
8
|
+
* out is `<blockquote>` around quoted paragraphs, `<p>` (optional `text-align`
|
|
9
|
+
* and a 24px `margin-left` indent), `<br>`, `<strong>`, `<em>`, `<u>` and
|
|
10
|
+
* `<span>` with validated `color` / `font-family` / `font-size`. Scripts,
|
|
11
|
+
* event handlers, URLs and every other tag or style are dropped on the way in.
|
|
12
|
+
*/
|
|
13
|
+
export type RichTextMark = 'bold' | 'italic' | 'underline';
|
|
14
|
+
export type RichTextStyle = 'color' | 'fontFamily' | 'fontSize';
|
|
15
|
+
export type RichTextAlign = 'left' | 'center' | 'right';
|
|
16
|
+
/** Formatting carried by a run of text. Absent = off / inherited default. */
|
|
17
|
+
export interface RichTextMarks {
|
|
18
|
+
bold?: true;
|
|
19
|
+
italic?: true;
|
|
20
|
+
underline?: true;
|
|
21
|
+
color?: string;
|
|
22
|
+
fontFamily?: string;
|
|
23
|
+
fontSize?: string;
|
|
24
|
+
}
|
|
25
|
+
/** A change to marks: `false` / `null` removes a mark or style. */
|
|
26
|
+
export interface RichTextMarkPatch {
|
|
27
|
+
bold?: boolean;
|
|
28
|
+
italic?: boolean;
|
|
29
|
+
underline?: boolean;
|
|
30
|
+
color?: string | null;
|
|
31
|
+
fontFamily?: string | null;
|
|
32
|
+
fontSize?: string | null;
|
|
33
|
+
}
|
|
34
|
+
export interface RichTextRun {
|
|
35
|
+
/** Text; `\n` is a line break (`<br>`). */
|
|
36
|
+
text: string;
|
|
37
|
+
marks: RichTextMarks;
|
|
38
|
+
}
|
|
39
|
+
export interface RichTextBlock {
|
|
40
|
+
align: RichTextAlign;
|
|
41
|
+
runs: RichTextRun[];
|
|
42
|
+
/** Inside a block quote. Absent = not quoted. */
|
|
43
|
+
quote?: true;
|
|
44
|
+
/** Indent steps of {@link RICH_TEXT_INDENT_STEP}px (0 to {@link RICH_TEXT_MAX_INDENT}). Absent = 0. */
|
|
45
|
+
indent?: number;
|
|
46
|
+
}
|
|
47
|
+
/** One indent step, in px (`spacing.24`). */
|
|
48
|
+
export declare const RICH_TEXT_INDENT_STEP = 24;
|
|
49
|
+
/** Deepest indent the editor produces; the model keeps a number so more levels can follow. */
|
|
50
|
+
export declare const RICH_TEXT_MAX_INDENT = 1;
|
|
51
|
+
export type RichTextDoc = RichTextBlock[];
|
|
52
|
+
/** A caret position: block index + character offset inside the block. */
|
|
53
|
+
export interface RichTextPos {
|
|
54
|
+
block: number;
|
|
55
|
+
offset: number;
|
|
56
|
+
}
|
|
57
|
+
/** What the toolbar shows for the current selection. */
|
|
58
|
+
export interface RichTextFormat {
|
|
59
|
+
bold: boolean;
|
|
60
|
+
italic: boolean;
|
|
61
|
+
underline: boolean;
|
|
62
|
+
align: RichTextAlign;
|
|
63
|
+
/** Every paragraph the selection touches is quoted. */
|
|
64
|
+
quote: boolean;
|
|
65
|
+
/** The smallest indent among the paragraphs the selection touches. */
|
|
66
|
+
indent: number;
|
|
67
|
+
/** `undefined` when the selection has no explicit value or mixes several. */
|
|
68
|
+
color: string | undefined;
|
|
69
|
+
fontFamily: string | undefined;
|
|
70
|
+
fontSize: string | undefined;
|
|
71
|
+
}
|
|
72
|
+
/** A CSS colour from the allow-list (hex, rgb[a](), a bare keyword), normalised, or `undefined`. */
|
|
73
|
+
export declare function cleanRichTextColor(value: string): string | undefined;
|
|
74
|
+
/** A font-family list made only of names, quotes, commas and hyphens, or `undefined`. */
|
|
75
|
+
export declare function cleanRichTextFontFamily(value: string): string | undefined;
|
|
76
|
+
/** A font size with a unit (px, pt, em, rem, %) inside sane bounds, or `undefined`. */
|
|
77
|
+
export declare function cleanRichTextFontSize(value: string): string | undefined;
|
|
78
|
+
export declare function applyMarkPatch(marks: RichTextMarks, patch: RichTextMarkPatch): RichTextMarks;
|
|
79
|
+
export interface RichTextReadOptions {
|
|
80
|
+
/**
|
|
81
|
+
* Clipboard / drag-and-drop content from elsewhere: keep only bold, italic,
|
|
82
|
+
* underline and paragraphs (foreign colours, fonts and sizes are dropped)
|
|
83
|
+
* and collapse source-code whitespace the way a browser renders it.
|
|
84
|
+
*/
|
|
85
|
+
foreign?: boolean;
|
|
86
|
+
}
|
|
87
|
+
/** Where a DOM node landed in the model; used to map selections. */
|
|
88
|
+
export interface RichTextDomItem<N> {
|
|
89
|
+
node: N;
|
|
90
|
+
kind: 'text' | 'br' | 'placeholder' | 'block';
|
|
91
|
+
block: number;
|
|
92
|
+
start: number;
|
|
93
|
+
length: number;
|
|
94
|
+
}
|
|
95
|
+
/** Merges equal neighbouring runs and drops empty ones. */
|
|
96
|
+
export declare function normalizeDoc(doc: RichTextDoc): RichTextDoc;
|
|
97
|
+
/** Reads an HTML string (a value, or clipboard HTML with `foreign`) into the model. */
|
|
98
|
+
export declare function parseRichText(html: string, options?: RichTextReadOptions): RichTextDoc;
|
|
99
|
+
/** Reads the live editor DOM into the model, with where each node landed. */
|
|
100
|
+
export declare function readRichTextDom(root: Node): {
|
|
101
|
+
doc: RichTextDoc;
|
|
102
|
+
items: RichTextDomItem<Node>[];
|
|
103
|
+
};
|
|
104
|
+
/** Builds output nodes of any kind (an HTML string, framework vnodes) from the model. */
|
|
105
|
+
export interface RichTextRenderer<T> {
|
|
106
|
+
element(tag: RichTextTag, style: string | undefined, children: T[]): T;
|
|
107
|
+
text(text: string): T;
|
|
108
|
+
}
|
|
109
|
+
export type RichTextTag = 'blockquote' | 'p' | 'br' | 'strong' | 'em' | 'u' | 'span';
|
|
110
|
+
/**
|
|
111
|
+
* The editor's paragraphs as renderer nodes: always at least one (empty)
|
|
112
|
+
* paragraph. An empty line needs a <br> to have height; so does a paragraph
|
|
113
|
+
* ending in a line break. Neighbouring quoted paragraphs share one
|
|
114
|
+
* `<blockquote>`.
|
|
115
|
+
*/
|
|
116
|
+
export declare function renderRichText<T>(doc: RichTextDoc, r: RichTextRenderer<T>): T[];
|
|
117
|
+
/** The markup the editor renders: always at least one (empty) paragraph. */
|
|
118
|
+
export declare function serializeRichText(doc: RichTextDoc): string;
|
|
119
|
+
/** The public value: the serialized document, or `''` when there is no content. */
|
|
120
|
+
export declare function richTextValue(doc: RichTextDoc): string;
|
|
121
|
+
export declare function isRichTextEmpty(doc: RichTextDoc): boolean;
|
|
122
|
+
/** Sanitizes an HTML string to the editor's allow-list. */
|
|
123
|
+
export declare function sanitizeRichText(html: string, options?: RichTextReadOptions): string;
|
|
124
|
+
/** Plain text of an HTML value: one line per paragraph, `<br>` as a newline. */
|
|
125
|
+
export declare function richTextToPlainText(html: string): string;
|
|
126
|
+
export declare function richTextDocText(doc: RichTextDoc): string;
|
|
127
|
+
export declare const emptyBlock: (align?: RichTextAlign) => RichTextBlock;
|
|
128
|
+
export declare function blockText(b: RichTextBlock): string;
|
|
129
|
+
export declare function blockLength(b: RichTextBlock | undefined): number;
|
|
130
|
+
/** Positions as one number: block boundaries count as one character. */
|
|
131
|
+
export declare function toGlobal(doc: RichTextDoc, pos: RichTextPos): number;
|
|
132
|
+
export declare function fromGlobal(doc: RichTextDoc, g: number): RichTextPos;
|
|
133
|
+
export declare function docLength(doc: RichTextDoc): number;
|
|
134
|
+
/** The content between two global positions, as a document fragment. */
|
|
135
|
+
export declare function sliceDoc(doc: RichTextDoc, from: number, to: number): RichTextDoc;
|
|
136
|
+
/**
|
|
137
|
+
* Replaces the range with a fragment. A one-block fragment goes inline; more
|
|
138
|
+
* blocks split the paragraph. Returns the new document and the caret after
|
|
139
|
+
* the inserted content.
|
|
140
|
+
*/
|
|
141
|
+
export declare function replaceRange(doc: RichTextDoc, from: number, to: number, fragment: RichTextDoc): {
|
|
142
|
+
doc: RichTextDoc;
|
|
143
|
+
caret: number;
|
|
144
|
+
};
|
|
145
|
+
/** Applies `change` to the marks of every character in the range. */
|
|
146
|
+
export declare function formatRange(doc: RichTextDoc, from: number, to: number, change: (marks: RichTextMarks) => RichTextMarks): RichTextDoc;
|
|
147
|
+
/** Sets the alignment of every block the range touches. */
|
|
148
|
+
export declare function alignRange(doc: RichTextDoc, from: number, to: number, align: RichTextAlign): RichTextDoc;
|
|
149
|
+
/** Quotes (or unquotes) every block the range touches. */
|
|
150
|
+
export declare function quoteRange(doc: RichTextDoc, from: number, to: number, on: boolean): RichTextDoc;
|
|
151
|
+
/**
|
|
152
|
+
* Sets the indent of every block the range touches, to `level` or to what
|
|
153
|
+
* `level(current)` returns; clamped to 0…{@link RICH_TEXT_MAX_INDENT}.
|
|
154
|
+
*/
|
|
155
|
+
export declare function indentRange(doc: RichTextDoc, from: number, to: number, level: number | ((current: number) => number)): RichTextDoc;
|
|
156
|
+
/** Marks typed text would take at a caret: the character before it, else the first one. */
|
|
157
|
+
export declare function marksAt(doc: RichTextDoc, g: number): RichTextMarks;
|
|
158
|
+
/** The format of a selection: a mark is on only if every selected character has it. */
|
|
159
|
+
export declare function formatOf(doc: RichTextDoc, anchor: number, focus: number, pending?: RichTextMarkPatch | null): RichTextFormat;
|
|
160
|
+
/** The toolbar format for a value before the editor is mounted: the caret at the end. */
|
|
161
|
+
export declare function richTextFormat(html: string, pending?: RichTextMarkPatch | null): RichTextFormat;
|
|
162
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-neutral helpers for "draggable progress bars" (website
|
|
3
|
+
* match): Compression / Spending / Intensity progress bars become WAI-ARIA
|
|
4
|
+
* APG sliders when the consumer opts in (React `onValueChange`, Vue
|
|
5
|
+
* `interactive`). Pointer position → value, and the APG keyboard model.
|
|
6
|
+
*/
|
|
7
|
+
/** Rounds `value` to the nearest `step` above `min` and clamps it to [min, max]. */
|
|
8
|
+
export declare function snapSliderValue(value: number, min: number, max: number, step: number): number;
|
|
9
|
+
/** Value under a horizontal pointer position inside `rect` (left = min). */
|
|
10
|
+
export declare function sliderValueFromPointer(clientX: number, rect: {
|
|
11
|
+
left: number;
|
|
12
|
+
width: number;
|
|
13
|
+
}, min: number, max: number, step: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* APG slider keys: ←/↓ −step, →/↑ +step, PageDown / PageUp ∓10 steps,
|
|
16
|
+
* Home → min, End → max. Returns `null` for any other key.
|
|
17
|
+
*/
|
|
18
|
+
export declare function sliderValueFromKey(key: string, value: number, min: number, max: number, step: number): number | null;
|
package/dist/slider.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-neutral helpers for "draggable progress bars" (website
|
|
3
|
+
* match): Compression / Spending / Intensity progress bars become WAI-ARIA
|
|
4
|
+
* APG sliders when the consumer opts in (React `onValueChange`, Vue
|
|
5
|
+
* `interactive`). Pointer position → value, and the APG keyboard model.
|
|
6
|
+
*/
|
|
7
|
+
/** Rounds `value` to the nearest `step` above `min` and clamps it to [min, max]. */
|
|
8
|
+
export declare function snapSliderValue(value: number, min: number, max: number, step: number): number;
|
|
9
|
+
/** Value under a horizontal pointer position inside `rect` (left = min). */
|
|
10
|
+
export declare function sliderValueFromPointer(clientX: number, rect: {
|
|
11
|
+
left: number;
|
|
12
|
+
width: number;
|
|
13
|
+
}, min: number, max: number, step: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* APG slider keys: ←/↓ −step, →/↑ +step, PageDown / PageUp ∓10 steps,
|
|
16
|
+
* Home → min, End → max. Returns `null` for any other key.
|
|
17
|
+
*/
|
|
18
|
+
export declare function sliderValueFromKey(key: string, value: number, min: number, max: number, step: number): number | null;
|
|
19
|
+
//# sourceMappingURL=slider.d.ts.map
|
package/dist/tree.d.cts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-free tree helpers for the TreeView component (React + Vue).
|
|
3
|
+
*
|
|
4
|
+
* They implement the data side of the WAI-ARIA APG Tree View pattern
|
|
5
|
+
* (https://www.w3.org/WAI/ARIA/apg/patterns/treeview/): the list of visible
|
|
6
|
+
* rows with their aria-level / aria-setsize / aria-posinset, and the
|
|
7
|
+
* keyboard model (arrows, Home/End, `*`, typeahead). The components only
|
|
8
|
+
* render and apply the returned actions.
|
|
9
|
+
*/
|
|
10
|
+
export interface TreeNodeLike<T> {
|
|
11
|
+
id: string;
|
|
12
|
+
label: string;
|
|
13
|
+
children?: T[];
|
|
14
|
+
}
|
|
15
|
+
/** One visible row. `kind: 'add'` is the optional trailing "add child" row of an open branch. */
|
|
16
|
+
export interface VisibleTreeRow<T> {
|
|
17
|
+
kind: 'node' | 'add';
|
|
18
|
+
/** Node id, or `<parentId>::add` for an add row. */
|
|
19
|
+
id: string;
|
|
20
|
+
/** The node (for an add row: its parent). */
|
|
21
|
+
node: T;
|
|
22
|
+
parentId: string | null;
|
|
23
|
+
/** aria-level, 1-based. */
|
|
24
|
+
level: number;
|
|
25
|
+
/** aria-posinset, 1-based. */
|
|
26
|
+
posinset: number;
|
|
27
|
+
/** aria-setsize. */
|
|
28
|
+
setsize: number;
|
|
29
|
+
expandable: boolean;
|
|
30
|
+
expanded: boolean;
|
|
31
|
+
/** `aria-disabled`: the row is skipped by the keyboard and cannot be activated or toggled. */
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface FlattenTreeOptions<T> {
|
|
35
|
+
/** Whether a node can be expanded (renders `aria-expanded`). */
|
|
36
|
+
isExpandable: (node: T) => boolean;
|
|
37
|
+
/** Whether an open branch ends with an "add child" row. */
|
|
38
|
+
hasAddRow?: (node: T) => boolean;
|
|
39
|
+
/** Whether a node is disabled (skipped by the keyboard). */
|
|
40
|
+
isDisabled?: (node: T) => boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Visible rows, depth-first, skipping the children of collapsed branches. */
|
|
43
|
+
export declare function flattenVisibleTree<T extends TreeNodeLike<T>>(nodes: readonly T[], expanded: ReadonlySet<string>, options: FlattenTreeOptions<T>): VisibleTreeRow<T>[];
|
|
44
|
+
/** Every node id in the tree, depth-first (used for stable DOM ids). */
|
|
45
|
+
export declare function collectTreeIds<T extends TreeNodeLike<T>>(nodes: readonly T[]): string[];
|
|
46
|
+
/** What a key press asks the tree to do. */
|
|
47
|
+
export interface TreeKeyAction {
|
|
48
|
+
/** Move focus to this row id. */
|
|
49
|
+
focus?: string;
|
|
50
|
+
/** Expand these node ids. */
|
|
51
|
+
expand?: string[];
|
|
52
|
+
/** Collapse this node id. */
|
|
53
|
+
collapse?: string;
|
|
54
|
+
/** Activate this row (select a node, or trigger an add row). */
|
|
55
|
+
activate?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* APG Tree View keyboard model. Returns `null` when the key is not handled
|
|
59
|
+
* (let it through). Typeahead is handled separately by `createTreeTypeahead`.
|
|
60
|
+
* Disabled rows (`row.disabled`) are skipped: focus never lands on them and
|
|
61
|
+
* they are never expanded, collapsed or activated.
|
|
62
|
+
*/
|
|
63
|
+
export declare function treeKeyAction<T>(key: string, focusedId: string, rows: readonly VisibleTreeRow<T>[]): TreeKeyAction | null;
|
|
64
|
+
/**
|
|
65
|
+
* Typeahead: returns a function that takes a printable character and the
|
|
66
|
+
* current rows, and returns the id of the next row whose label starts with
|
|
67
|
+
* the typed string (searching after the focused row, wrapping), or null.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createTreeTypeahead(timeout?: number): <T extends {
|
|
70
|
+
label: string;
|
|
71
|
+
}>(char: string, focusedId: string, rows: readonly VisibleTreeRow<T>[], labelOf?: (row: VisibleTreeRow<T>) => string) => string | null;
|
|
72
|
+
/** True for a key that should feed typeahead (one printable char, no modifier). */
|
|
73
|
+
export declare function isTypeaheadKey(e: {
|
|
74
|
+
key: string;
|
|
75
|
+
ctrlKey: boolean;
|
|
76
|
+
metaKey: boolean;
|
|
77
|
+
altKey: boolean;
|
|
78
|
+
}): boolean;
|
package/dist/tree.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-free tree helpers for the TreeView component (React + Vue).
|
|
3
|
+
*
|
|
4
|
+
* They implement the data side of the WAI-ARIA APG Tree View pattern
|
|
5
|
+
* (https://www.w3.org/WAI/ARIA/apg/patterns/treeview/): the list of visible
|
|
6
|
+
* rows with their aria-level / aria-setsize / aria-posinset, and the
|
|
7
|
+
* keyboard model (arrows, Home/End, `*`, typeahead). The components only
|
|
8
|
+
* render and apply the returned actions.
|
|
9
|
+
*/
|
|
10
|
+
export interface TreeNodeLike<T> {
|
|
11
|
+
id: string;
|
|
12
|
+
label: string;
|
|
13
|
+
children?: T[];
|
|
14
|
+
}
|
|
15
|
+
/** One visible row. `kind: 'add'` is the optional trailing "add child" row of an open branch. */
|
|
16
|
+
export interface VisibleTreeRow<T> {
|
|
17
|
+
kind: 'node' | 'add';
|
|
18
|
+
/** Node id, or `<parentId>::add` for an add row. */
|
|
19
|
+
id: string;
|
|
20
|
+
/** The node (for an add row: its parent). */
|
|
21
|
+
node: T;
|
|
22
|
+
parentId: string | null;
|
|
23
|
+
/** aria-level, 1-based. */
|
|
24
|
+
level: number;
|
|
25
|
+
/** aria-posinset, 1-based. */
|
|
26
|
+
posinset: number;
|
|
27
|
+
/** aria-setsize. */
|
|
28
|
+
setsize: number;
|
|
29
|
+
expandable: boolean;
|
|
30
|
+
expanded: boolean;
|
|
31
|
+
/** `aria-disabled`: the row is skipped by the keyboard and cannot be activated or toggled. */
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface FlattenTreeOptions<T> {
|
|
35
|
+
/** Whether a node can be expanded (renders `aria-expanded`). */
|
|
36
|
+
isExpandable: (node: T) => boolean;
|
|
37
|
+
/** Whether an open branch ends with an "add child" row. */
|
|
38
|
+
hasAddRow?: (node: T) => boolean;
|
|
39
|
+
/** Whether a node is disabled (skipped by the keyboard). */
|
|
40
|
+
isDisabled?: (node: T) => boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Visible rows, depth-first, skipping the children of collapsed branches. */
|
|
43
|
+
export declare function flattenVisibleTree<T extends TreeNodeLike<T>>(nodes: readonly T[], expanded: ReadonlySet<string>, options: FlattenTreeOptions<T>): VisibleTreeRow<T>[];
|
|
44
|
+
/** Every node id in the tree, depth-first (used for stable DOM ids). */
|
|
45
|
+
export declare function collectTreeIds<T extends TreeNodeLike<T>>(nodes: readonly T[]): string[];
|
|
46
|
+
/** What a key press asks the tree to do. */
|
|
47
|
+
export interface TreeKeyAction {
|
|
48
|
+
/** Move focus to this row id. */
|
|
49
|
+
focus?: string;
|
|
50
|
+
/** Expand these node ids. */
|
|
51
|
+
expand?: string[];
|
|
52
|
+
/** Collapse this node id. */
|
|
53
|
+
collapse?: string;
|
|
54
|
+
/** Activate this row (select a node, or trigger an add row). */
|
|
55
|
+
activate?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* APG Tree View keyboard model. Returns `null` when the key is not handled
|
|
59
|
+
* (let it through). Typeahead is handled separately by `createTreeTypeahead`.
|
|
60
|
+
* Disabled rows (`row.disabled`) are skipped: focus never lands on them and
|
|
61
|
+
* they are never expanded, collapsed or activated.
|
|
62
|
+
*/
|
|
63
|
+
export declare function treeKeyAction<T>(key: string, focusedId: string, rows: readonly VisibleTreeRow<T>[]): TreeKeyAction | null;
|
|
64
|
+
/**
|
|
65
|
+
* Typeahead: returns a function that takes a printable character and the
|
|
66
|
+
* current rows, and returns the id of the next row whose label starts with
|
|
67
|
+
* the typed string (searching after the focused row, wrapping), or null.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createTreeTypeahead(timeout?: number): <T extends {
|
|
70
|
+
label: string;
|
|
71
|
+
}>(char: string, focusedId: string, rows: readonly VisibleTreeRow<T>[], labelOf?: (row: VisibleTreeRow<T>) => string) => string | null;
|
|
72
|
+
/** True for a key that should feed typeahead (one printable char, no modifier). */
|
|
73
|
+
export declare function isTypeaheadKey(e: {
|
|
74
|
+
key: string;
|
|
75
|
+
ctrlKey: boolean;
|
|
76
|
+
metaKey: boolean;
|
|
77
|
+
altKey: boolean;
|
|
78
|
+
}): boolean;
|
|
79
|
+
//# sourceMappingURL=tree.d.ts.map
|
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one size vocabulary every component uses on its `size` prop (and on
|
|
3
|
+
* sub-part props such as `headerSize`). Each component spells out the steps it
|
|
4
|
+
* draws as a literal union (so the docs list the values); a type test keeps
|
|
5
|
+
* every such union inside `Size`. Figma axis values translate as
|
|
6
|
+
* 2X-Small → `2xs`, X-Small / Extra-Small → `xs`, Small → `sm`, Medium → `md`,
|
|
7
|
+
* Large → `lg`, X-Large → `xl`, 2X-Large → `2xl`. Components whose Figma Size
|
|
8
|
+
* axis is in pixels (Avatar, Pagination, …) take pixel numbers instead.
|
|
9
|
+
*/
|
|
10
|
+
export type Size = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
11
|
+
export type Variant = 'primary' | 'secondary' | 'ghost' | 'destructive' | 'outline';
|
|
12
|
+
export type ColorScheme = 'light' | 'dark';
|
|
13
|
+
export type Intent = 'default' | 'success' | 'warning' | 'error' | 'info';
|
|
14
|
+
/** Base props every component accepts */
|
|
15
|
+
export interface ComponentBaseProps {
|
|
16
|
+
/** Additional CSS class names */
|
|
17
|
+
class?: string;
|
|
18
|
+
/** Inline styles */
|
|
19
|
+
style?: string | Record<string, string>;
|
|
20
|
+
/** Test ID for automated testing */
|
|
21
|
+
'data-testid'?: string;
|
|
22
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one size vocabulary every component uses on its `size` prop (and on
|
|
3
|
+
* sub-part props such as `headerSize`). Each component spells out the steps it
|
|
4
|
+
* draws as a literal union (so the docs list the values); a type test keeps
|
|
5
|
+
* every such union inside `Size`. Figma axis values translate as
|
|
6
|
+
* 2X-Small → `2xs`, X-Small / Extra-Small → `xs`, Small → `sm`, Medium → `md`,
|
|
7
|
+
* Large → `lg`, X-Large → `xl`, 2X-Large → `2xl`. Components whose Figma Size
|
|
8
|
+
* axis is in pixels (Avatar, Pagination, …) take pixel numbers instead.
|
|
9
|
+
*/
|
|
10
|
+
export type Size = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
11
|
+
export type Variant = 'primary' | 'secondary' | 'ghost' | 'destructive' | 'outline';
|
|
12
|
+
export type ColorScheme = 'light' | 'dark';
|
|
13
|
+
export type Intent = 'default' | 'success' | 'warning' | 'error' | 'info';
|
|
14
|
+
/** Base props every component accepts */
|
|
15
|
+
export interface ComponentBaseProps {
|
|
16
|
+
/** Additional CSS class names */
|
|
17
|
+
class?: string;
|
|
18
|
+
/** Inline styles */
|
|
19
|
+
style?: string | Record<string, string>;
|
|
20
|
+
/** Test ID for automated testing */
|
|
21
|
+
'data-testid'?: string;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orvain/utils",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Orvain Design System — shared utilities, types and a11y helpers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"!dist/**/*.map",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"rimraf": "^6.0.1",
|
|
34
|
+
"typescript": "^5.5.4",
|
|
35
|
+
"vite": "^5.4.0",
|
|
36
|
+
"@orvain/tokens": "^0.1.1"
|
|
37
|
+
},
|
|
38
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/Ozzy-UI/orvain.git",
|
|
42
|
+
"directory": "packages/utils"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/Ozzy-UI/orvain/tree/main/packages/utils#readme",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/Ozzy-UI/orvain/issues"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"design-system",
|
|
50
|
+
"utilities",
|
|
51
|
+
"accessibility"
|
|
52
|
+
],
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "vite build && tsc --emitDeclarationOnly --outDir dist && node ../../scripts/fix-declarations.mjs dist",
|
|
55
|
+
"dev": "vite build --watch",
|
|
56
|
+
"lint": "eslint src",
|
|
57
|
+
"clean": "rimraf dist"
|
|
58
|
+
}
|
|
6
59
|
}
|