@effindomv2/fui-as 0.1.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.md +7 -0
- package/browser/src/common-harness/host-imports.ts +430 -0
- package/browser/src/common-harness/interop.ts +39 -0
- package/browser/src/common-harness/managed-harness-bitmap-host.ts +92 -0
- package/browser/src/common-harness/managed-harness-fetch-host.ts +201 -0
- package/browser/src/common-harness/managed-harness-file-host.ts +1101 -0
- package/browser/src/common-harness/managed-harness-file-payloads.ts +143 -0
- package/browser/src/common-harness/managed-harness-file-types.ts +106 -0
- package/browser/src/common-harness/managed-harness-session.ts +15 -0
- package/browser/src/common-harness/managed-harness.ts +1323 -0
- package/browser/src/common-harness/managed-history.ts +168 -0
- package/browser/src/common-harness/persisted-restore-policy.ts +50 -0
- package/browser/src/common-harness/persisted-ui-state-controller.ts +309 -0
- package/browser/src/common-harness/text-session-bridge.ts +452 -0
- package/browser/src/common-harness/types.ts +205 -0
- package/browser/src/common-harness/ui-chrome.ts +191 -0
- package/browser/src/common-harness/ui-imports.ts +529 -0
- package/browser/src/common-harness/wasm-module-cache.ts +47 -0
- package/browser/src/common-harness.ts +27 -0
- package/browser/src/file-processing-worker.ts +89 -0
- package/browser/src/host-events.ts +97 -0
- package/browser/src/host-services.ts +203 -0
- package/browser/src/index.ts +62 -0
- package/browser/src/persisted-ui-state.ts +206 -0
- package/browser/src/routed-harness.ts +198 -0
- package/browser/src/worker-bootstrap.ts +483 -0
- package/browser/src/worker-manager.ts +230 -0
- package/browser/src/worker-types.ts +50 -0
- package/package.json +89 -0
- package/scripts/build-demo-as.sh +91 -0
- package/scripts/build.sh +325 -0
- package/scripts/generate-host-events.ts +175 -0
- package/scripts/generate-host-services.ts +157 -0
- package/src/Fui.ts +205 -0
- package/src/FuiExports.ts +55 -0
- package/src/FuiPrimitives.ts +15 -0
- package/src/FuiWorker.ts +3 -0
- package/src/FuiWorkerExports.ts +6 -0
- package/src/bindings/ui.ts +531 -0
- package/src/color.ts +86 -0
- package/src/controls/AntiSelectionArea.ts +23 -0
- package/src/controls/Button.ts +750 -0
- package/src/controls/Checkbox.ts +181 -0
- package/src/controls/ContextMenu.ts +885 -0
- package/src/controls/ControlTemplateSet.ts +37 -0
- package/src/controls/Dialog.ts +355 -0
- package/src/controls/Dropdown.ts +856 -0
- package/src/controls/Form.ts +110 -0
- package/src/controls/NavLink.ts +211 -0
- package/src/controls/Popup.ts +129 -0
- package/src/controls/ProgressBar.ts +180 -0
- package/src/controls/RadioButton.ts +135 -0
- package/src/controls/RadioGroup.ts +244 -0
- package/src/controls/SelectionArea.ts +75 -0
- package/src/controls/Slider.ts +471 -0
- package/src/controls/Switch.ts +132 -0
- package/src/controls/TextArea.ts +20 -0
- package/src/controls/TextInput.ts +7 -0
- package/src/controls/index.ts +18 -0
- package/src/controls/internal/ButtonPresenter.ts +95 -0
- package/src/controls/internal/CheckboxIndicatorPresenter.ts +93 -0
- package/src/controls/internal/DropdownChevronPresenter.ts +67 -0
- package/src/controls/internal/DropdownFieldPresenter.ts +110 -0
- package/src/controls/internal/DropdownOptionRowPresenter.ts +82 -0
- package/src/controls/internal/PopupPresenter.ts +198 -0
- package/src/controls/internal/PressableIndicatorPresenter.ts +32 -0
- package/src/controls/internal/PressableLabeledControl.ts +221 -0
- package/src/controls/internal/RadioIndicatorPresenter.ts +73 -0
- package/src/controls/internal/SliderPresenter.ts +157 -0
- package/src/controls/internal/SwitchIndicatorPresenter.ts +72 -0
- package/src/controls/internal/TextInputCore.ts +695 -0
- package/src/controls/internal/TextInputPresenter.ts +72 -0
- package/src/controls/templating.ts +54 -0
- package/src/core/Action.ts +94 -0
- package/src/core/Actions.ts +37 -0
- package/src/core/Animation.ts +412 -0
- package/src/core/Application.ts +328 -0
- package/src/core/Assets.ts +264 -0
- package/src/core/AttachedProperties.ts +32 -0
- package/src/core/Bitmap.ts +70 -0
- package/src/core/BoundCallback.ts +104 -0
- package/src/core/Callbacks.ts +17 -0
- package/src/core/ContextMenuManager.ts +466 -0
- package/src/core/DebugApi.ts +30 -0
- package/src/core/Disposable.ts +10 -0
- package/src/core/DragDropManager.ts +179 -0
- package/src/core/DragGesture.ts +184 -0
- package/src/core/DynamicAssetIds.ts +24 -0
- package/src/core/Errors.ts +48 -0
- package/src/core/EventRouter.ts +408 -0
- package/src/core/ExternalDropManager.ts +122 -0
- package/src/core/Fetch.ts +264 -0
- package/src/core/FetchFfi.ts +15 -0
- package/src/core/File.ts +1002 -0
- package/src/core/FocusAdornerManager.ts +263 -0
- package/src/core/FocusVisibility.ts +36 -0
- package/src/core/FrameScheduler.ts +28 -0
- package/src/core/KeyboardScroll.ts +161 -0
- package/src/core/KeyboardScrollTracker.ts +386 -0
- package/src/core/Logger.ts +80 -0
- package/src/core/Navigation.ts +13 -0
- package/src/core/Node.ts +1708 -0
- package/src/core/PersistedState.ts +102 -0
- package/src/core/PersistedUiState.ts +142 -0
- package/src/core/Platform.ts +219 -0
- package/src/core/Signal.ts +89 -0
- package/src/core/Theme.ts +365 -0
- package/src/core/Timers.ts +129 -0
- package/src/core/ToolTip.ts +122 -0
- package/src/core/ToolTipManager.ts +459 -0
- package/src/core/Transitions.ts +34 -0
- package/src/core/Typography.ts +204 -0
- package/src/core/Worker.ts +196 -0
- package/src/core/bind.ts +37 -0
- package/src/core/event_exports.ts +596 -0
- package/src/core/ffi.ts +728 -0
- package/src/host-services/runtime.ts +25 -0
- package/src/nodes/FlexBox.ts +789 -0
- package/src/nodes/GradientStop.ts +9 -0
- package/src/nodes/Grid.ts +183 -0
- package/src/nodes/Image.ts +189 -0
- package/src/nodes/Portal.ts +14 -0
- package/src/nodes/RichText.ts +312 -0
- package/src/nodes/ScrollBar.ts +570 -0
- package/src/nodes/ScrollBox.ts +415 -0
- package/src/nodes/ScrollState.ts +10 -0
- package/src/nodes/ScrollView.ts +511 -0
- package/src/nodes/Svg.ts +142 -0
- package/src/nodes/Text.ts +145 -0
- package/src/nodes/TextCore.ts +558 -0
- package/src/nodes/VirtualList.ts +431 -0
- package/src/nodes/helpers.ts +25 -0
- package/src/nodes/index.ts +14 -0
- package/src/tsconfig.json +7 -0
- package/src/worker/Worker.ts +169 -0
- package/src/worker/WorkerJob.ts +65 -0
- package/src/worker/ffi.ts +23 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
const DEFAULT_ACCENT_COLOR = 0x2563ebff;
|
|
2
|
+
const URL_PREVIEW_BAR_ID = 'fui-url-bar';
|
|
3
|
+
const PLATFORM_FAMILY_UNKNOWN = 0;
|
|
4
|
+
const PLATFORM_FAMILY_APPLE = 1;
|
|
5
|
+
const PLATFORM_FAMILY_WINDOWS = 2;
|
|
6
|
+
const PLATFORM_FAMILY_LINUX = 3;
|
|
7
|
+
const LOADING_OVERLAY_ID = 'effindom-loading-overlay';
|
|
8
|
+
const LOADING_TITLE_ID = 'effindom-loading-title';
|
|
9
|
+
const LOADING_DETAIL_ID = 'effindom-loading-detail';
|
|
10
|
+
|
|
11
|
+
function packColor(red: number, green: number, blue: number, alpha = 255): number {
|
|
12
|
+
return ((((red & 0xff) << 24) | ((green & 0xff) << 16) | ((blue & 0xff) << 8) | (alpha & 0xff)) >>> 0);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function parseCssColorToRgba(colorValue: string): number | null {
|
|
16
|
+
const probeParent = document.body ?? document.documentElement;
|
|
17
|
+
const probe = document.createElement('span');
|
|
18
|
+
probe.style.color = colorValue;
|
|
19
|
+
if (probe.style.color.length === 0) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
probe.style.position = 'absolute';
|
|
23
|
+
probe.style.pointerEvents = 'none';
|
|
24
|
+
probe.style.opacity = '0';
|
|
25
|
+
probeParent.appendChild(probe);
|
|
26
|
+
const computed = getComputedStyle(probe).color.trim();
|
|
27
|
+
probe.remove();
|
|
28
|
+
|
|
29
|
+
const match = /^rgba?\(([^)]+)\)$/.exec(computed);
|
|
30
|
+
if (match === null) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const parts = match[1].split(',').map((part) => part.trim());
|
|
34
|
+
if (parts.length < 3) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const red = Number.parseInt(parts[0] ?? '', 10);
|
|
38
|
+
const green = Number.parseInt(parts[1] ?? '', 10);
|
|
39
|
+
const blue = Number.parseInt(parts[2] ?? '', 10);
|
|
40
|
+
if ([red, green, blue].some((channel) => Number.isNaN(channel))) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const alphaPart = parts[3];
|
|
45
|
+
const alpha = alphaPart === undefined
|
|
46
|
+
? 255
|
|
47
|
+
: Math.max(0, Math.min(255, Math.round(Number.parseFloat(alphaPart) * 255)));
|
|
48
|
+
return packColor(red, green, blue, alpha);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function ensureUrlPreviewBar(): HTMLDivElement {
|
|
52
|
+
const existing = document.getElementById(URL_PREVIEW_BAR_ID);
|
|
53
|
+
if (existing instanceof HTMLDivElement) {
|
|
54
|
+
return existing;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const bar = document.createElement('div');
|
|
58
|
+
bar.id = URL_PREVIEW_BAR_ID;
|
|
59
|
+
bar.hidden = true;
|
|
60
|
+
bar.dataset.visible = 'false';
|
|
61
|
+
bar.setAttribute('aria-hidden', 'true');
|
|
62
|
+
bar.style.position = 'fixed';
|
|
63
|
+
bar.style.left = '12px';
|
|
64
|
+
bar.style.bottom = '12px';
|
|
65
|
+
bar.style.maxWidth = 'min(60vw, 720px)';
|
|
66
|
+
bar.style.padding = '6px 10px';
|
|
67
|
+
bar.style.borderRadius = '10px';
|
|
68
|
+
bar.style.background = 'rgba(15, 23, 42, 0.84)';
|
|
69
|
+
bar.style.color = '#f8fafc';
|
|
70
|
+
bar.style.font = '12px/1.4 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
71
|
+
bar.style.letterSpacing = '0.01em';
|
|
72
|
+
bar.style.whiteSpace = 'nowrap';
|
|
73
|
+
bar.style.overflow = 'hidden';
|
|
74
|
+
bar.style.textOverflow = 'ellipsis';
|
|
75
|
+
bar.style.pointerEvents = 'none';
|
|
76
|
+
bar.style.opacity = '0';
|
|
77
|
+
bar.style.transform = 'translateY(6px)';
|
|
78
|
+
bar.style.transition = 'opacity 120ms ease, transform 120ms ease';
|
|
79
|
+
bar.style.backdropFilter = 'blur(12px)';
|
|
80
|
+
bar.style.boxShadow = '0 10px 28px rgba(2, 6, 23, 0.24)';
|
|
81
|
+
bar.style.zIndex = '2147483647';
|
|
82
|
+
(document.body ?? document.documentElement).appendChild(bar);
|
|
83
|
+
return bar;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function waitForFrame(): Promise<void> {
|
|
87
|
+
return new Promise<void>((resolve) => {
|
|
88
|
+
requestAnimationFrame(() => {
|
|
89
|
+
requestAnimationFrame(() => {
|
|
90
|
+
resolve();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export class HarnessUiChrome {
|
|
97
|
+
setLoadingOverlay(state: 'loading' | 'error', title: string, detail: string): void {
|
|
98
|
+
const overlay = document.getElementById(LOADING_OVERLAY_ID);
|
|
99
|
+
const titleNode = document.getElementById(LOADING_TITLE_ID);
|
|
100
|
+
const detailNode = document.getElementById(LOADING_DETAIL_ID);
|
|
101
|
+
if (!(overlay instanceof HTMLElement) || !(titleNode instanceof HTMLElement) || !(detailNode instanceof HTMLElement)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
overlay.dataset.state = state;
|
|
105
|
+
overlay.hidden = false;
|
|
106
|
+
overlay.setAttribute('aria-hidden', 'false');
|
|
107
|
+
titleNode.textContent = title;
|
|
108
|
+
detailNode.textContent = detail;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
hideLoadingOverlay(): void {
|
|
112
|
+
const overlay = document.getElementById(LOADING_OVERLAY_ID);
|
|
113
|
+
if (!(overlay instanceof HTMLElement)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
overlay.hidden = true;
|
|
117
|
+
overlay.dataset.state = 'ready';
|
|
118
|
+
overlay.setAttribute('aria-hidden', 'true');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
setUrlPreviewText(text: string): void {
|
|
122
|
+
const bar = ensureUrlPreviewBar();
|
|
123
|
+
if (text.length === 0) {
|
|
124
|
+
bar.textContent = '';
|
|
125
|
+
bar.hidden = true;
|
|
126
|
+
bar.dataset.visible = 'false';
|
|
127
|
+
bar.style.opacity = '0';
|
|
128
|
+
bar.style.transform = 'translateY(6px)';
|
|
129
|
+
window.__fuiUrlPreviewText = '';
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
bar.textContent = text;
|
|
134
|
+
bar.hidden = false;
|
|
135
|
+
bar.dataset.visible = 'true';
|
|
136
|
+
bar.style.opacity = '1';
|
|
137
|
+
bar.style.transform = 'translateY(0)';
|
|
138
|
+
window.__fuiUrlPreviewText = text;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
readHostAccentColor(): number {
|
|
142
|
+
const accent = getComputedStyle(document.documentElement).getPropertyValue('accent-color').trim();
|
|
143
|
+
if (accent.length === 0 || accent === 'auto') {
|
|
144
|
+
return DEFAULT_ACCENT_COLOR;
|
|
145
|
+
}
|
|
146
|
+
return parseCssColorToRgba(accent) ?? DEFAULT_ACCENT_COLOR;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
detectPlatformFamily(): number {
|
|
150
|
+
const navigatorWithUserAgentData = navigator as Navigator & {
|
|
151
|
+
userAgentData?: {
|
|
152
|
+
platform?: string;
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
const platform = (
|
|
156
|
+
navigatorWithUserAgentData.userAgentData?.platform ??
|
|
157
|
+
navigator.platform ??
|
|
158
|
+
navigator.userAgent
|
|
159
|
+
).toLowerCase();
|
|
160
|
+
if (
|
|
161
|
+
platform.includes('mac') ||
|
|
162
|
+
platform.includes('iphone') ||
|
|
163
|
+
platform.includes('ipad') ||
|
|
164
|
+
platform.includes('ipod') ||
|
|
165
|
+
platform.includes('ios')
|
|
166
|
+
) {
|
|
167
|
+
return PLATFORM_FAMILY_APPLE;
|
|
168
|
+
}
|
|
169
|
+
if (platform.includes('win')) {
|
|
170
|
+
return PLATFORM_FAMILY_WINDOWS;
|
|
171
|
+
}
|
|
172
|
+
if (
|
|
173
|
+
platform.includes('linux') ||
|
|
174
|
+
platform.includes('android') ||
|
|
175
|
+
platform.includes('x11') ||
|
|
176
|
+
platform.includes('cros')
|
|
177
|
+
) {
|
|
178
|
+
return PLATFORM_FAMILY_LINUX;
|
|
179
|
+
}
|
|
180
|
+
return PLATFORM_FAMILY_UNKNOWN;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
detectCoarsePointer(): boolean {
|
|
184
|
+
return window.matchMedia('(pointer: coarse)').matches || navigator.maxTouchPoints > 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
getCanvasSizeSource(canvas: HTMLCanvasElement): HTMLElement | HTMLCanvasElement {
|
|
188
|
+
const source = canvas.closest('[data-effindom-canvas-size-source]');
|
|
189
|
+
return source instanceof HTMLElement ? source : canvas;
|
|
190
|
+
}
|
|
191
|
+
}
|