@niivue/uikit 1.0.0-rc.2 → 1.0.0-rc.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +702 -8
- package/dist/button.d.ts +97 -0
- package/dist/buttonOverlay.d.ts +121 -0
- package/dist/colorControl.d.ts +130 -0
- package/dist/colorControlOverlay.d.ts +72 -0
- package/dist/controls.d.ts +151 -0
- package/dist/dialog.d.ts +138 -0
- package/dist/dialogOverlay.d.ts +115 -0
- package/dist/filePicker.d.ts +95 -0
- package/dist/filePickerOverlay.d.ts +75 -0
- package/dist/host.d.ts +87 -0
- package/dist/index.d.ts +61 -0
- package/dist/menu.d.ts +227 -0
- package/dist/menuOverlay.d.ts +149 -0
- package/dist/numberInput.d.ts +172 -0
- package/dist/numberInputOverlay.d.ts +131 -0
- package/dist/pointLabel.d.ts +68 -0
- package/dist/pointLabelOverlay.d.ts +39 -0
- package/dist/rect.d.ts +27 -0
- package/dist/rectOverlay.d.ts +13 -0
- package/dist/render/glRectRenderer.d.ts +13 -0
- package/dist/render/shaders.d.ts +3 -0
- package/dist/render/wgpuRectRenderer.d.ts +18 -0
- package/dist/scroll.d.ts +70 -0
- package/dist/segmented.d.ts +127 -0
- package/dist/segmentedOverlay.d.ts +87 -0
- package/dist/select.d.ts +66 -0
- package/dist/selectOverlay.d.ts +102 -0
- package/dist/slider.d.ts +152 -0
- package/dist/sliderOverlay.d.ts +92 -0
- package/dist/text/layout.d.ts +8 -0
- package/dist/textArea.d.ts +216 -0
- package/dist/textAreaOverlay.d.ts +145 -0
- package/dist/textEdit.d.ts +72 -0
- package/dist/textField.d.ts +33 -0
- package/dist/textInput.d.ts +123 -0
- package/dist/textInputOverlay.d.ts +139 -0
- package/dist/toggle.d.ts +115 -0
- package/dist/toggleOverlay.d.ts +80 -0
- package/dist/uikit.js +6269 -221
- package/package.json +3 -3
package/dist/dialog.d.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { ButtonStyle } from './button';
|
|
2
|
+
import { RectData } from './rect';
|
|
3
|
+
import { UIKitBox } from './scroll';
|
|
4
|
+
import { UIKitFontMetrics } from './text/font';
|
|
5
|
+
import { RGBA } from './text/layout';
|
|
6
|
+
import { UIKitTextItem } from './textOverlay';
|
|
7
|
+
/** Every visual knob on a dialog. All lengths are in canvas pixels. */
|
|
8
|
+
export interface DialogStyle {
|
|
9
|
+
/** Color laid over the whole canvas behind the panel. */
|
|
10
|
+
scrim: RGBA;
|
|
11
|
+
fill: RGBA;
|
|
12
|
+
border: RGBA;
|
|
13
|
+
borderWidth: number;
|
|
14
|
+
radius: number;
|
|
15
|
+
/** Panel width when the spec gives none. */
|
|
16
|
+
width: number;
|
|
17
|
+
/** Space between the panel edge and its contents. */
|
|
18
|
+
padding: number;
|
|
19
|
+
/** Vertical space between the title, message, content box and buttons. */
|
|
20
|
+
gap: number;
|
|
21
|
+
titleColor: RGBA;
|
|
22
|
+
titleSizePx: number;
|
|
23
|
+
textColor: RGBA;
|
|
24
|
+
textSizePx: number;
|
|
25
|
+
/** Message line height as a multiple of `textSizePx`. */
|
|
26
|
+
lineHeight: number;
|
|
27
|
+
/** Space between action buttons. */
|
|
28
|
+
buttonGap: number;
|
|
29
|
+
/** Style overrides for the action buttons. */
|
|
30
|
+
button: Partial<ButtonStyle>;
|
|
31
|
+
/** Further overrides for the button with the `default` role. */
|
|
32
|
+
defaultButton: Partial<ButtonStyle>;
|
|
33
|
+
}
|
|
34
|
+
export declare const DEFAULT_DIALOG_STYLE: DialogStyle;
|
|
35
|
+
export type DialogButtonRole = 'default' | 'cancel' | 'normal';
|
|
36
|
+
export interface DialogButtonSpec {
|
|
37
|
+
/** The result `onClose` reports when this button closes the dialog. */
|
|
38
|
+
id: string;
|
|
39
|
+
label: string;
|
|
40
|
+
/**
|
|
41
|
+
* `default` is what Enter presses (drawn in the accent style); `cancel` is
|
|
42
|
+
* what Escape presses. Default `normal`.
|
|
43
|
+
*/
|
|
44
|
+
role?: DialogButtonRole;
|
|
45
|
+
enabled?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** The panel's boxes the host needs to place widgets, in spec units. */
|
|
48
|
+
export interface DialogBoxes {
|
|
49
|
+
panel: UIKitBox;
|
|
50
|
+
/** The space reserved by `contentHeight`, between the message and the buttons. */
|
|
51
|
+
content: UIKitBox;
|
|
52
|
+
}
|
|
53
|
+
export interface DialogSpec {
|
|
54
|
+
/** Stable key: the handle for opening, closing and the callbacks. */
|
|
55
|
+
id: string;
|
|
56
|
+
title?: string;
|
|
57
|
+
/** Body text; wrapped to the panel width, with '\n' forcing a line break. */
|
|
58
|
+
message?: string;
|
|
59
|
+
/** Top-left corner of the panel. Omit both to center it in the canvas. */
|
|
60
|
+
x?: number;
|
|
61
|
+
y?: number;
|
|
62
|
+
/** Panel width. Default: the style's `width`. */
|
|
63
|
+
width?: number;
|
|
64
|
+
/** Height reserved for hosted widgets between the message and the buttons. */
|
|
65
|
+
contentHeight?: number;
|
|
66
|
+
/** Action buttons, drawn right-aligned in the order given. */
|
|
67
|
+
buttons?: readonly DialogButtonSpec[];
|
|
68
|
+
/** A press on the scrim closes the dialog with a null result. Default false. */
|
|
69
|
+
closeOnScrim?: boolean;
|
|
70
|
+
/** Per-dialog overrides of the overlay's default style. */
|
|
71
|
+
style?: Partial<DialogStyle>;
|
|
72
|
+
/**
|
|
73
|
+
* Fired when the panel is placed or moves (first draw, a canvas resize),
|
|
74
|
+
* with its boxes in spec units: position hosted widgets here.
|
|
75
|
+
*/
|
|
76
|
+
onLayout?: (boxes: DialogBoxes, id: string) => void;
|
|
77
|
+
/** Fired when the dialog closes: the button id, or null for Escape and the scrim. */
|
|
78
|
+
onClose?: (result: string | null, id: string) => void;
|
|
79
|
+
}
|
|
80
|
+
/** The dialog's boxes in canvas pixels. */
|
|
81
|
+
export interface DialogLayout {
|
|
82
|
+
panel: UIKitBox;
|
|
83
|
+
/** Title baseline, or null without a title. */
|
|
84
|
+
title: {
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
} | null;
|
|
88
|
+
/** Wrapped message lines with their baselines. */
|
|
89
|
+
lines: {
|
|
90
|
+
str: string;
|
|
91
|
+
x: number;
|
|
92
|
+
y: number;
|
|
93
|
+
}[];
|
|
94
|
+
content: UIKitBox;
|
|
95
|
+
/** Resting boxes for the action buttons, right-aligned. */
|
|
96
|
+
buttons: {
|
|
97
|
+
id: string;
|
|
98
|
+
box: UIKitBox;
|
|
99
|
+
}[];
|
|
100
|
+
}
|
|
101
|
+
/** What `layoutDialog` needs to know about each button: its resting size. */
|
|
102
|
+
export interface DialogButtonSize {
|
|
103
|
+
id: string;
|
|
104
|
+
width: number;
|
|
105
|
+
height: number;
|
|
106
|
+
}
|
|
107
|
+
export declare function resolveDialogStyle(base: DialogStyle, override?: Partial<DialogStyle>): DialogStyle;
|
|
108
|
+
/**
|
|
109
|
+
* Break `text` into lines no wider than `maxWidth`: at '\n', else at the last
|
|
110
|
+
* space that fits; a single word wider than the line stays whole.
|
|
111
|
+
*/
|
|
112
|
+
export declare function wrapText(metrics: UIKitFontMetrics, text: string, sizePx: number, maxWidth: number): string[];
|
|
113
|
+
/**
|
|
114
|
+
* The panel's boxes for a spec, centered in `bounds` unless the spec gives a
|
|
115
|
+
* position. `buttonSizes` are the action buttons' resting sizes in order.
|
|
116
|
+
*/
|
|
117
|
+
export declare function layoutDialog(spec: DialogSpec, style: DialogStyle, metrics: UIKitFontMetrics, buttonSizes: readonly DialogButtonSize[], bounds: {
|
|
118
|
+
width: number;
|
|
119
|
+
height: number;
|
|
120
|
+
}): DialogLayout;
|
|
121
|
+
/** Scale every length in a spec and style by `k` (CSS pixels to canvas pixels). */
|
|
122
|
+
export declare function scaleDialog(spec: DialogSpec, style: DialogStyle, k: number): {
|
|
123
|
+
spec: DialogSpec;
|
|
124
|
+
style: DialogStyle;
|
|
125
|
+
};
|
|
126
|
+
/** True when canvas point (px, py) lies inside the panel. */
|
|
127
|
+
export declare function dialogContains(layout: DialogLayout, px: number, py: number): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* The draw data for an open dialog: the scrim over `bounds`, the panel, the
|
|
130
|
+
* title and the message lines. The action buttons are a button overlay's.
|
|
131
|
+
*/
|
|
132
|
+
export declare function buildDialog(spec: DialogSpec, style: DialogStyle, layout: DialogLayout, bounds: {
|
|
133
|
+
width: number;
|
|
134
|
+
height: number;
|
|
135
|
+
}): {
|
|
136
|
+
rects: RectData[];
|
|
137
|
+
text: UIKitTextItem[];
|
|
138
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { UIKitOverlayFrame, UIKitOverlayRenderer } from '@niivue/niivue';
|
|
2
|
+
import { UIKitInteractive, UIKitKeyEvent, UIKitRedrawSource } from './controls';
|
|
3
|
+
import { DialogBoxes, DialogSpec, DialogStyle } from './dialog';
|
|
4
|
+
import { UIKitFont } from './text/font';
|
|
5
|
+
export interface UIKitDialogOverlayOptions {
|
|
6
|
+
/** Called whenever the overlay needs another frame. A control layer fills it in. */
|
|
7
|
+
requestRedraw?: () => void;
|
|
8
|
+
/** Default style for every dialog; a spec's `style` overrides per key. */
|
|
9
|
+
style?: Partial<DialogStyle>;
|
|
10
|
+
/**
|
|
11
|
+
* Interpret spec positions and style lengths as CSS pixels and scale them by
|
|
12
|
+
* the frame's device pixel ratio, instead of canvas pixels.
|
|
13
|
+
*/
|
|
14
|
+
cssUnits?: boolean;
|
|
15
|
+
/** Clock for the button press animation. Default `performance.now`. */
|
|
16
|
+
now?: () => number;
|
|
17
|
+
}
|
|
18
|
+
export declare class UIKitDialogOverlay implements UIKitOverlayRenderer, UIKitInteractive {
|
|
19
|
+
private readonly font;
|
|
20
|
+
private readonly rects;
|
|
21
|
+
private readonly labels;
|
|
22
|
+
private readonly entries;
|
|
23
|
+
private baseStyle;
|
|
24
|
+
private readonly cssUnits;
|
|
25
|
+
private readonly now;
|
|
26
|
+
private requestRedraw;
|
|
27
|
+
private layer;
|
|
28
|
+
private childLayer;
|
|
29
|
+
private inLayer;
|
|
30
|
+
private scale;
|
|
31
|
+
private bounds;
|
|
32
|
+
private geometryDirty;
|
|
33
|
+
private openId;
|
|
34
|
+
/** The member (a child or the button row) owning the pointer, and the focused one. */
|
|
35
|
+
private captured;
|
|
36
|
+
private focused;
|
|
37
|
+
private hovered;
|
|
38
|
+
constructor(font: UIKitFont, options?: UIKitDialogOverlayOptions);
|
|
39
|
+
/** CSS cursor: the captured or hovered member's, else the default over the panel. */
|
|
40
|
+
get hoverCursor(): string | undefined;
|
|
41
|
+
/** Replace the default style for every dialog (per-spec overrides still win). */
|
|
42
|
+
setDefaultStyle(style: Partial<DialogStyle>): void;
|
|
43
|
+
/** Add a dialog, or replace the one with the same id (keeping its children). */
|
|
44
|
+
addDialog(spec: DialogSpec): void;
|
|
45
|
+
removeDialog(id: string): void;
|
|
46
|
+
/** Patch one dialog's spec (title, message, buttons, position, ...). */
|
|
47
|
+
updateDialog(id: string, patch: Partial<Omit<DialogSpec, 'id'>>): void;
|
|
48
|
+
/** Host a widget in a dialog: routed and drawn while the dialog is open. */
|
|
49
|
+
addChild(id: string, child: UIKitInteractive): void;
|
|
50
|
+
removeChild(id: string, child: UIKitInteractive): void;
|
|
51
|
+
/** The ids of all dialogs. */
|
|
52
|
+
get ids(): string[];
|
|
53
|
+
/** The open dialog's id, if any. */
|
|
54
|
+
get openDialog(): string | null;
|
|
55
|
+
isOpen(id: string): boolean;
|
|
56
|
+
/** Open a dialog (closing any other with a null result). */
|
|
57
|
+
open(id: string): void;
|
|
58
|
+
/** Close the open dialog, reporting `result` through its `onClose`. */
|
|
59
|
+
close(result?: string | null): void;
|
|
60
|
+
/**
|
|
61
|
+
* Press an action button of the open dialog from code, as a click would:
|
|
62
|
+
* the dialog closes at once and fires `onClose` with the button's id.
|
|
63
|
+
*/
|
|
64
|
+
click(buttonId: string): void;
|
|
65
|
+
/** The open dialog's boxes in spec units, once it has been laid out. */
|
|
66
|
+
getBoxes(id: string): DialogBoxes | null;
|
|
67
|
+
/**
|
|
68
|
+
* The area the panel centers in, in canvas pixels. `drawOverlay` refreshes
|
|
69
|
+
* it from every frame; call it yourself when driving the overlay without one.
|
|
70
|
+
*/
|
|
71
|
+
setBounds(bounds: {
|
|
72
|
+
width: number;
|
|
73
|
+
height: number;
|
|
74
|
+
}): void;
|
|
75
|
+
isModal(): boolean;
|
|
76
|
+
/** A press or focus elsewhere in the page: the children lose focus, the dialog stays. */
|
|
77
|
+
dismiss(): void;
|
|
78
|
+
blur(): void;
|
|
79
|
+
/** The whole canvas while open (the dialog is modal), else nothing. */
|
|
80
|
+
hitTest(_x: number, _y: number): boolean;
|
|
81
|
+
pointerDown(x: number, y: number): boolean;
|
|
82
|
+
pointerMove(x: number, y: number): boolean;
|
|
83
|
+
pointerUp(x: number, y: number): boolean;
|
|
84
|
+
pointerCancel(): void;
|
|
85
|
+
/**
|
|
86
|
+
* A modal child sees the key first and keeps what it takes. Then the
|
|
87
|
+
* focused child keeps what it takes, unless it says the key submits the
|
|
88
|
+
* form (Enter in a text or number field, as in an HTML form). Otherwise
|
|
89
|
+
* Enter presses the default button and Escape the cancel button (or
|
|
90
|
+
* closes with null). Every other key is swallowed while open.
|
|
91
|
+
*/
|
|
92
|
+
keyDown(e: UIKitKeyEvent): boolean;
|
|
93
|
+
/** A modal child, else the child under the point, may scroll; the page never does. */
|
|
94
|
+
wheel(x: number, y: number, deltaX: number, deltaY: number): boolean;
|
|
95
|
+
bindLayer(layer: UIKitRedrawSource): void;
|
|
96
|
+
drawOverlay(frame: UIKitOverlayFrame): void;
|
|
97
|
+
/** Draw the open dialog; a control layer calls this after every widget. */
|
|
98
|
+
drawPopup(frame: UIKitOverlayFrame): void;
|
|
99
|
+
/** Release the surfaces, the action buttons and every hosted child. */
|
|
100
|
+
destroy(): void;
|
|
101
|
+
private invalidate;
|
|
102
|
+
private openEntry;
|
|
103
|
+
/** The routing order, topmost first: the button row, then the children last added first. */
|
|
104
|
+
private members;
|
|
105
|
+
private modalChild;
|
|
106
|
+
private setFocus;
|
|
107
|
+
private scaled;
|
|
108
|
+
private boxesOf;
|
|
109
|
+
/**
|
|
110
|
+
* Lay the panel out (sizing the buttons first), place the buttons, and
|
|
111
|
+
* report the boxes to `onLayout` when they changed. The button overlay
|
|
112
|
+
* shares the dialog's units, so it is fed spec-unit positions.
|
|
113
|
+
*/
|
|
114
|
+
private layoutOf;
|
|
115
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { ButtonLayout, ButtonStyle } from './button';
|
|
2
|
+
import { UIKitFontMetrics } from './text/font';
|
|
3
|
+
import { RGBA } from './text/layout';
|
|
4
|
+
import { UIKitTextItem } from './textOverlay';
|
|
5
|
+
/** Every visual knob on a file picker. All lengths are in canvas pixels. */
|
|
6
|
+
export interface FilePickerStyle {
|
|
7
|
+
/** Overrides for the "Choose file" button. */
|
|
8
|
+
button: Partial<ButtonStyle>;
|
|
9
|
+
/** Space between the button and the readout. */
|
|
10
|
+
gap: number;
|
|
11
|
+
/** Readout color once something was chosen. */
|
|
12
|
+
textColor: RGBA;
|
|
13
|
+
/** Readout color while nothing is chosen (the placeholder). */
|
|
14
|
+
emptyTextColor: RGBA;
|
|
15
|
+
disabledTextColor: RGBA;
|
|
16
|
+
/** Readout em size. */
|
|
17
|
+
textSizePx: number;
|
|
18
|
+
/** Halo outline width around the readout (it sits on the scene); 0 draws none. */
|
|
19
|
+
textOutlineWidth: number;
|
|
20
|
+
/** Halo color; null picks black or white against the readout color. */
|
|
21
|
+
textOutlineColor: RGBA | null;
|
|
22
|
+
/** Readout width when the spec gives no width. */
|
|
23
|
+
readoutWidth: number;
|
|
24
|
+
}
|
|
25
|
+
export declare const DEFAULT_FILE_PICKER_STYLE: FilePickerStyle;
|
|
26
|
+
export interface FilePickerSpec {
|
|
27
|
+
/** Stable key: the handle for updates and the callbacks. */
|
|
28
|
+
id: string;
|
|
29
|
+
/** Button label. Default "Choose file...". */
|
|
30
|
+
label?: string;
|
|
31
|
+
/** Top-left corner of the row, in canvas pixels. */
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
/** Width of the whole row; the readout gets what the button leaves. */
|
|
35
|
+
width?: number;
|
|
36
|
+
/** Readout while nothing is chosen. Default "No file chosen". */
|
|
37
|
+
placeholder?: string;
|
|
38
|
+
/** `accept` for the host chooser: ".nii,.nii.gz" or MIME types. */
|
|
39
|
+
accept?: string;
|
|
40
|
+
multiple?: boolean;
|
|
41
|
+
/** Choose a directory (every file inside it) instead of files. */
|
|
42
|
+
directory?: boolean;
|
|
43
|
+
/** A disabled picker draws dimmed and ignores the pointer. Default true. */
|
|
44
|
+
enabled?: boolean;
|
|
45
|
+
/** Per-picker overrides of the overlay's default style. */
|
|
46
|
+
style?: Partial<FilePickerStyle>;
|
|
47
|
+
/** Fired with the chosen files once the chooser closes with a choice. */
|
|
48
|
+
onPick?: (files: File[], id: string) => void;
|
|
49
|
+
/** Fired when the chooser closes without a choice. */
|
|
50
|
+
onCancel?: (id: string) => void;
|
|
51
|
+
}
|
|
52
|
+
export declare const DEFAULT_FILE_PICKER_LABEL = "Choose file...";
|
|
53
|
+
export declare const DEFAULT_FILE_PICKER_PLACEHOLDER = "No file chosen";
|
|
54
|
+
/** The resting boxes of a picker, in canvas pixels. */
|
|
55
|
+
export interface FilePickerLayout {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
button: ButtonLayout;
|
|
61
|
+
/** Left edge and baseline of the readout. */
|
|
62
|
+
textX: number;
|
|
63
|
+
baseline: number;
|
|
64
|
+
/** Space available to the readout. */
|
|
65
|
+
readoutWidth: number;
|
|
66
|
+
}
|
|
67
|
+
export interface FilePickerVisual {
|
|
68
|
+
/** Names of the chosen files; empty shows the placeholder. */
|
|
69
|
+
names: readonly string[];
|
|
70
|
+
enabled: boolean;
|
|
71
|
+
}
|
|
72
|
+
export declare function resolveFilePickerStyle(base: FilePickerStyle, override?: Partial<FilePickerStyle>): FilePickerStyle;
|
|
73
|
+
/** The button style a picker's button is laid out and drawn with. */
|
|
74
|
+
export declare function filePickerButtonStyle(style: FilePickerStyle): ButtonStyle;
|
|
75
|
+
/** What the readout says for a set of chosen names. */
|
|
76
|
+
export declare function filePickerSummary(names: readonly string[], placeholder?: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Trim a string to `maxWidth` at `sizePx`, keeping its tail (a file's
|
|
79
|
+
* extension is the informative end) behind a leading "...".
|
|
80
|
+
*/
|
|
81
|
+
export declare function ellipsizeStart(metrics: UIKitFontMetrics, str: string, sizePx: number, maxWidth: number): string;
|
|
82
|
+
export declare function layoutFilePicker(spec: FilePickerSpec, style: FilePickerStyle, metrics: UIKitFontMetrics): FilePickerLayout;
|
|
83
|
+
/**
|
|
84
|
+
* Scale a spec and style by `k` (CSS to device pixels). The button overrides
|
|
85
|
+
* come back as a full button style, so a layout of the result agrees with a
|
|
86
|
+
* button overlay scaling the same picker.
|
|
87
|
+
*/
|
|
88
|
+
export declare function scaleFilePicker(spec: FilePickerSpec, style: FilePickerStyle, k: number): {
|
|
89
|
+
spec: FilePickerSpec;
|
|
90
|
+
style: FilePickerStyle;
|
|
91
|
+
};
|
|
92
|
+
/** The readout text of a picker; its button is drawn by a button overlay. */
|
|
93
|
+
export declare function buildFilePicker(spec: FilePickerSpec, style: FilePickerStyle, layout: FilePickerLayout, metrics: UIKitFontMetrics, visual: FilePickerVisual): {
|
|
94
|
+
text: UIKitTextItem[];
|
|
95
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { UIKitOverlayFrame, UIKitOverlayRenderer } from '@niivue/niivue';
|
|
2
|
+
import { UIKitInteractive, UIKitKeyEvent, UIKitRedrawSource } from './controls';
|
|
3
|
+
import { FilePickerLayout, FilePickerSpec, FilePickerStyle } from './filePicker';
|
|
4
|
+
import { FilePickerBridge } from './host';
|
|
5
|
+
import { UIKitFont } from './text/font';
|
|
6
|
+
export interface UIKitFilePickerOverlayOptions {
|
|
7
|
+
/** Called whenever the overlay needs another frame. A control layer fills it in. */
|
|
8
|
+
requestRedraw?: () => void;
|
|
9
|
+
/** Default style for every picker; a spec's `style` overrides per key. */
|
|
10
|
+
style?: Partial<FilePickerStyle>;
|
|
11
|
+
/**
|
|
12
|
+
* Interpret spec positions and style lengths as CSS pixels and scale them by
|
|
13
|
+
* the frame's device pixel ratio, instead of canvas pixels.
|
|
14
|
+
*/
|
|
15
|
+
cssUnits?: boolean;
|
|
16
|
+
/** The host's file chooser. Defaults to a hidden `<input type="file">`. */
|
|
17
|
+
pickFiles?: FilePickerBridge;
|
|
18
|
+
}
|
|
19
|
+
export declare class UIKitFilePickerOverlay implements UIKitOverlayRenderer, UIKitInteractive {
|
|
20
|
+
readonly hoverCursor = "pointer";
|
|
21
|
+
private readonly font;
|
|
22
|
+
private readonly buttons;
|
|
23
|
+
private readonly labels;
|
|
24
|
+
private readonly entries;
|
|
25
|
+
private baseStyle;
|
|
26
|
+
private readonly cssUnits;
|
|
27
|
+
private requestRedraw;
|
|
28
|
+
private pickFiles;
|
|
29
|
+
private scale;
|
|
30
|
+
private geometryDirty;
|
|
31
|
+
constructor(font: UIKitFont, options?: UIKitFilePickerOverlayOptions);
|
|
32
|
+
/** Replace the default style for every picker (per-spec overrides still win). */
|
|
33
|
+
setDefaultStyle(style: Partial<FilePickerStyle>): void;
|
|
34
|
+
/** Add a picker, or replace the one with the same id (keeping its files). */
|
|
35
|
+
addFilePicker(spec: FilePickerSpec): void;
|
|
36
|
+
setFilePickers(specs: readonly FilePickerSpec[]): void;
|
|
37
|
+
removeFilePicker(id: string): void;
|
|
38
|
+
/** Patch one picker's spec (label, position, accept, callbacks, ...). */
|
|
39
|
+
updateFilePicker(id: string, patch: Partial<Omit<FilePickerSpec, 'id'>>): void;
|
|
40
|
+
setEnabled(id: string, enabled: boolean): void;
|
|
41
|
+
/** Show these files (or names) as chosen without firing callbacks. */
|
|
42
|
+
setFiles(id: string, files: readonly (File | string)[]): void;
|
|
43
|
+
/** The names a picker shows as chosen. */
|
|
44
|
+
getFiles(id: string): string[] | undefined;
|
|
45
|
+
get ids(): string[];
|
|
46
|
+
/** A picker's boxes in spec units, or null for an unknown id. */
|
|
47
|
+
getLayout(id: string): FilePickerLayout | null;
|
|
48
|
+
/** True while the host chooser is open for the picker. */
|
|
49
|
+
isPending(id: string): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Open the host chooser for a picker as if its button were pressed. Call it
|
|
52
|
+
* from a pointer or key handler: browsers only open a chooser inside a user
|
|
53
|
+
* activation.
|
|
54
|
+
*/
|
|
55
|
+
open(id: string): void;
|
|
56
|
+
hitTest(x: number, y: number): boolean;
|
|
57
|
+
pointerDown(x: number, y: number): boolean;
|
|
58
|
+
pointerMove(x: number, y: number): boolean;
|
|
59
|
+
pointerUp(x: number, y: number): boolean;
|
|
60
|
+
pointerCancel(): void;
|
|
61
|
+
/** Enter or Space presses the last-pressed button. */
|
|
62
|
+
keyDown(e: UIKitKeyEvent): boolean;
|
|
63
|
+
blur(): void;
|
|
64
|
+
bindLayer(layer: UIKitRedrawSource): void;
|
|
65
|
+
drawOverlay(frame: UIKitOverlayFrame): void;
|
|
66
|
+
/** Release GPU resources on both backends. */
|
|
67
|
+
destroy(): void;
|
|
68
|
+
private invalidate;
|
|
69
|
+
private rebuild;
|
|
70
|
+
private layoutOf;
|
|
71
|
+
/** Create or move a picker's button, in spec units. */
|
|
72
|
+
private placeButton;
|
|
73
|
+
/** Ask the host for files and report the outcome to the picker's callbacks. */
|
|
74
|
+
private pick;
|
|
75
|
+
}
|
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/** What a file picker asks the host for, mirroring `<input type="file">`. */
|
|
2
|
+
export interface FilePickerOptions {
|
|
3
|
+
/** Comma-separated extensions or MIME types, as the `accept` attribute. */
|
|
4
|
+
accept?: string;
|
|
5
|
+
multiple?: boolean;
|
|
6
|
+
/** Pick a directory (every file inside it) instead of files. */
|
|
7
|
+
directory?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Open the host's file chooser and resolve with the files picked, or with an
|
|
11
|
+
* empty array when the user cancels. Call it synchronously from a pointer or
|
|
12
|
+
* key handler: browsers only open a chooser inside a user activation.
|
|
13
|
+
*/
|
|
14
|
+
export type FilePickerBridge = (options: FilePickerOptions) => Promise<File[]>;
|
|
15
|
+
/** Save a blob to the host under a file name (a browser "download"). */
|
|
16
|
+
export type DownloadBridge = (blob: Blob, filename: string) => void;
|
|
17
|
+
/** The subset of a Document the browser file picker uses. */
|
|
18
|
+
export interface FilePickerDocument {
|
|
19
|
+
createElement(tagName: 'input'): HTMLInputElement;
|
|
20
|
+
body: Pick<HTMLElement, 'appendChild' | 'removeChild'>;
|
|
21
|
+
}
|
|
22
|
+
/** The subset of a Window the browser bridges use: timers and focus. */
|
|
23
|
+
export interface BridgeWindow {
|
|
24
|
+
setTimeout(handler: () => void, ms: number): number;
|
|
25
|
+
clearTimeout(id: number): void;
|
|
26
|
+
addEventListener(type: 'focus', listener: () => void): void;
|
|
27
|
+
removeEventListener(type: 'focus', listener: () => void): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* How long after the window regains focus a chooser with neither a `change`
|
|
31
|
+
* nor a `cancel` event counts as cancelled. A pick's `change` can trail the
|
|
32
|
+
* focus, so this leaves it room.
|
|
33
|
+
*/
|
|
34
|
+
export declare const FILE_PICKER_CANCEL_GRACE_MS = 1000;
|
|
35
|
+
/**
|
|
36
|
+
* How long a download keeps its object URL: revoking it in the tick that
|
|
37
|
+
* clicks the anchor can cancel the download before it starts.
|
|
38
|
+
*/
|
|
39
|
+
export declare const DOWNLOAD_REVOKE_DELAY_MS = 40000;
|
|
40
|
+
/**
|
|
41
|
+
* A file picker that drives a hidden `<input type="file">`. The input is
|
|
42
|
+
* attached to the body while the chooser is open (some browsers ignore a
|
|
43
|
+
* detached input) and removed once it settles. Cancelling resolves to an
|
|
44
|
+
* empty array through the input's `cancel` event or, where there is none
|
|
45
|
+
* (Safari before 16.4, Chrome before 113), once the window has had focus
|
|
46
|
+
* back for `FILE_PICKER_CANCEL_GRACE_MS` with no pick. `directory` sets
|
|
47
|
+
* `webkitdirectory`, which every current engine honours.
|
|
48
|
+
*/
|
|
49
|
+
export declare function createBrowserFilePicker(doc?: FilePickerDocument, win?: BridgeWindow): FilePickerBridge;
|
|
50
|
+
/** The subset of a Document and URL the browser download uses. */
|
|
51
|
+
export interface DownloadDocument {
|
|
52
|
+
createElement(tagName: 'a'): HTMLAnchorElement;
|
|
53
|
+
body: Pick<HTMLElement, 'appendChild' | 'removeChild'>;
|
|
54
|
+
}
|
|
55
|
+
export interface DownloadUrlFactory {
|
|
56
|
+
createObjectURL(blob: Blob): string;
|
|
57
|
+
revokeObjectURL(url: string): void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A download that clicks a temporary anchor with a `download` name over an
|
|
61
|
+
* object URL of the blob, then revokes the URL `DOWNLOAD_REVOKE_DELAY_MS`
|
|
62
|
+
* later.
|
|
63
|
+
*/
|
|
64
|
+
export declare function createBrowserDownload(doc?: DownloadDocument, urls?: DownloadUrlFactory, win?: Pick<BridgeWindow, 'setTimeout'>): DownloadBridge;
|
|
65
|
+
/** A `.ext` list or MIME list from file extensions, for `FilePickerOptions.accept`. */
|
|
66
|
+
export declare function acceptExtensions(extensions: readonly string[]): string;
|
|
67
|
+
/**
|
|
68
|
+
* The clipboard a text widget copies to and pastes from. `write` puts text
|
|
69
|
+
* on it; `read` resolves with its text, or with an empty string when it
|
|
70
|
+
* holds none or the host refuses. Browsers grant both only inside a user
|
|
71
|
+
* activation, so the widgets call them synchronously from a key handler.
|
|
72
|
+
*/
|
|
73
|
+
export interface ClipboardBridge {
|
|
74
|
+
write(text: string): void;
|
|
75
|
+
read(): Promise<string>;
|
|
76
|
+
}
|
|
77
|
+
/** The subset of `navigator.clipboard` the browser clipboard bridge uses. */
|
|
78
|
+
export interface ClipboardSource {
|
|
79
|
+
readText(): Promise<string>;
|
|
80
|
+
writeText(text: string): Promise<void>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A clipboard bridge over the async clipboard API. Without a source (an
|
|
84
|
+
* insecure context, or no navigator) writes are dropped and reads resolve
|
|
85
|
+
* empty; a refused read also resolves empty.
|
|
86
|
+
*/
|
|
87
|
+
export declare function createBrowserClipboard(source?: ClipboardSource | undefined): ClipboardBridge;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,80 @@
|
|
|
1
1
|
export type { AnnotationGeometryOptions } from './annotationOverlay';
|
|
2
2
|
export { buildAnnotationGeometry, UIKitAnnotationOverlay, } from './annotationOverlay';
|
|
3
|
+
export type { ButtonLayout, ButtonSpec, ButtonStyle, ButtonVisual, } from './button';
|
|
4
|
+
export { DEFAULT_BUTTON_STYLE } from './button';
|
|
5
|
+
export type { UIKitButtonHost, UIKitButtonOverlayOptions, } from './buttonOverlay';
|
|
6
|
+
export { UIKitButtonOverlay } from './buttonOverlay';
|
|
7
|
+
export type { ColorChannel, ColorControlLayout, ColorControlSpec, ColorControlStyle, ColorControlVisual, ColorSwatch, } from './colorControl';
|
|
8
|
+
export { DEFAULT_COLOR_CONTROL_STYLE } from './colorControl';
|
|
9
|
+
export type { UIKitColorControlOverlayOptions } from './colorControlOverlay';
|
|
10
|
+
export { UIKitColorControlOverlay } from './colorControlOverlay';
|
|
11
|
+
export type { UIKitControlsOptions, UIKitHost, UIKitInteractive, UIKitKeyEvent, UIKitRedrawSource, } from './controls';
|
|
12
|
+
export { UIKitControls } from './controls';
|
|
3
13
|
export type { CrosshairGeometry, CrosshairSpec } from './crosshair';
|
|
4
14
|
export { buildCrosshair } from './crosshair';
|
|
5
15
|
export type { CrosshairPlacement } from './crosshairOverlay';
|
|
6
16
|
export { UIKitCrosshairOverlay } from './crosshairOverlay';
|
|
17
|
+
export type { DialogBoxes, DialogButtonRole, DialogButtonSize, DialogButtonSpec, DialogLayout, DialogSpec, DialogStyle, } from './dialog';
|
|
18
|
+
export { DEFAULT_DIALOG_STYLE } from './dialog';
|
|
19
|
+
export type { UIKitDialogOverlayOptions } from './dialogOverlay';
|
|
20
|
+
export { UIKitDialogOverlay } from './dialogOverlay';
|
|
21
|
+
export type { FilePickerLayout, FilePickerSpec, FilePickerStyle, FilePickerVisual, } from './filePicker';
|
|
22
|
+
export { DEFAULT_FILE_PICKER_LABEL, DEFAULT_FILE_PICKER_PLACEHOLDER, DEFAULT_FILE_PICKER_STYLE, } from './filePicker';
|
|
23
|
+
export type { UIKitFilePickerOverlayOptions } from './filePickerOverlay';
|
|
24
|
+
export { UIKitFilePickerOverlay } from './filePickerOverlay';
|
|
25
|
+
export type { BridgeWindow, ClipboardBridge, ClipboardSource, DownloadBridge, DownloadDocument, DownloadUrlFactory, FilePickerBridge, FilePickerDocument, FilePickerOptions, } from './host';
|
|
26
|
+
export { acceptExtensions, createBrowserClipboard, createBrowserDownload, createBrowserFilePicker, DOWNLOAD_REVOKE_DELAY_MS, FILE_PICKER_CANCEL_GRACE_MS, } from './host';
|
|
7
27
|
export type { LineData, LineTerminators } from './line';
|
|
8
28
|
export { buildLine, buildTerminatedLine, LineTerminator } from './line';
|
|
9
29
|
export { UIKitLineOverlay } from './lineOverlay';
|
|
30
|
+
export type { MenuBounds, MenuButtonSpec, MenuButtonVisual, MenuItemKind, MenuItemSpec, MenuPopupLayout, MenuRowLayout, MenuStyle, } from './menu';
|
|
31
|
+
export { DEFAULT_MENU_BUTTON_STYLE, DEFAULT_MENU_STYLE, } from './menu';
|
|
32
|
+
export type { UIKitMenuOverlayOptions } from './menuOverlay';
|
|
33
|
+
export { UIKitMenuOverlay } from './menuOverlay';
|
|
34
|
+
export type { NumberInputLayout, NumberInputSpec, NumberInputStyle, NumberInputVisual, } from './numberInput';
|
|
35
|
+
export { DEFAULT_NUMBER_INPUT_STYLE } from './numberInput';
|
|
36
|
+
export type { UIKitNumberInputOverlayOptions } from './numberInputOverlay';
|
|
37
|
+
export { UIKitNumberInputOverlay } from './numberInputOverlay';
|
|
38
|
+
export type { PointLabelBounds, PointLabelGeometry, PointLabelSpec, } from './pointLabel';
|
|
39
|
+
export { buildPointLabel } from './pointLabel';
|
|
40
|
+
export type { MMPoint, MMProjector, PointLabelPlacement, } from './pointLabelOverlay';
|
|
41
|
+
export { UIKitPointLabelOverlay } from './pointLabelOverlay';
|
|
42
|
+
export type { RectData, RectSpec } from './rect';
|
|
43
|
+
export { buildRect } from './rect';
|
|
44
|
+
export { UIKitRectOverlay } from './rectOverlay';
|
|
10
45
|
export type { RulerGeometry, RulerSpec, Vec2 } from './ruler';
|
|
11
46
|
export { buildRuler } from './ruler';
|
|
12
47
|
export { UIKitRulerOverlay } from './rulerOverlay';
|
|
48
|
+
export type { ScrollRange, ScrollStripStyle, ScrollWindow, UIKitBox, } from './scroll';
|
|
49
|
+
export type { SegmentedLayout, SegmentedSpec, SegmentedStyle, SegmentedVisual, SegmentLayout, SegmentSpec, } from './segmented';
|
|
50
|
+
export { DEFAULT_SEGMENTED_STYLE } from './segmented';
|
|
51
|
+
export type { UIKitSegmentedOverlayOptions } from './segmentedOverlay';
|
|
52
|
+
export { UIKitSegmentedOverlay } from './segmentedOverlay';
|
|
53
|
+
export type { SelectOption, SelectSpec } from './select';
|
|
54
|
+
export type { UIKitSelectOverlayOptions } from './selectOverlay';
|
|
55
|
+
export { UIKitSelectOverlay } from './selectOverlay';
|
|
56
|
+
export type { SliderLayout, SliderSpec, SliderStyle, SliderVisual, } from './slider';
|
|
57
|
+
export { DEFAULT_SLIDER_STYLE } from './slider';
|
|
58
|
+
export type { UIKitSliderOverlayOptions } from './sliderOverlay';
|
|
59
|
+
export { UIKitSliderOverlay } from './sliderOverlay';
|
|
13
60
|
export { loadDefaultFont } from './text/defaultFont';
|
|
14
61
|
export type { RawFontFile, UIKitFont, UIKitFontMetrics, UIKitGlyph, } from './text/font';
|
|
15
62
|
export { parseFont, screenPxRange } from './text/font';
|
|
16
63
|
export type { RGBA, TextLayoutOptions } from './text/layout';
|
|
17
64
|
export { autoOutlineColor, layoutText, measureWidth, readableAngle, } from './text/layout';
|
|
65
|
+
export type { TextAreaLayout, TextAreaSpec, TextAreaStyle, TextAreaVisual, TextRow, } from './textArea';
|
|
66
|
+
export { DEFAULT_TEXT_AREA_STYLE } from './textArea';
|
|
67
|
+
export type { UIKitTextAreaOverlayOptions } from './textAreaOverlay';
|
|
68
|
+
export { UIKitTextAreaOverlay } from './textAreaOverlay';
|
|
69
|
+
export type { TextEditState } from './textEdit';
|
|
70
|
+
export type { TextFieldStyle } from './textField';
|
|
71
|
+
export type { TextInputLayout, TextInputSpec, TextInputStyle, TextInputVisual, } from './textInput';
|
|
72
|
+
export { DEFAULT_TEXT_INPUT_STYLE } from './textInput';
|
|
73
|
+
export type { UIKitTextInputOverlayOptions } from './textInputOverlay';
|
|
74
|
+
export { UIKitTextInputOverlay } from './textInputOverlay';
|
|
18
75
|
export type { UIKitTextItem } from './textOverlay';
|
|
19
76
|
export { UIKitTextOverlay } from './textOverlay';
|
|
77
|
+
export type { ToggleLayout, ToggleSpec, ToggleStyle, ToggleVisual, } from './toggle';
|
|
78
|
+
export { DEFAULT_TOGGLE_STYLE } from './toggle';
|
|
79
|
+
export type { UIKitToggleOverlayOptions } from './toggleOverlay';
|
|
80
|
+
export { UIKitToggleOverlay } from './toggleOverlay';
|