@joewinke/jatui 0.21.0 → 0.23.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/CLAUDE.md +47 -1
- package/dist/actions/reveal.d.ts +37 -0
- package/dist/actions/reveal.js +42 -0
- package/dist/components/AudioRecorder.svelte +749 -0
- package/dist/components/AudioRecorder.svelte.d.ts +36 -0
- package/dist/components/IconSelector.svelte +417 -0
- package/dist/components/IconSelector.svelte.d.ts +55 -0
- package/dist/components/InfiniteGrid.svelte +305 -0
- package/dist/components/InfiniteGrid.svelte.d.ts +71 -0
- package/dist/components/InfiniteSearchGrid.svelte +131 -0
- package/dist/components/InfiniteSearchGrid.svelte.d.ts +67 -0
- package/dist/components/KeyboardShortcutsOverlay.svelte +40 -3
- package/dist/components/KeyboardShortcutsOverlay.svelte.d.ts +31 -16
- package/dist/components/MediaCaptureIcon.svelte +23 -0
- package/dist/components/MediaCaptureIcon.svelte.d.ts +1 -1
- package/dist/components/ThumbnailGrid.svelte +137 -0
- package/dist/components/ThumbnailGrid.svelte.d.ts +42 -0
- package/dist/components/batch/BatchJobTable.svelte +549 -0
- package/dist/components/batch/BatchJobTable.svelte.d.ts +114 -0
- package/dist/components/batch/QuotaMeter.svelte +78 -0
- package/dist/components/batch/QuotaMeter.svelte.d.ts +16 -0
- package/dist/components/batch/batchQueue.d.ts +56 -0
- package/dist/components/batch/batchQueue.js +81 -0
- package/dist/components/batch/elapsedEstimate.d.ts +24 -0
- package/dist/components/batch/elapsedEstimate.js +25 -0
- package/dist/components/batch/pollOperation.d.ts +45 -0
- package/dist/components/batch/pollOperation.js +80 -0
- package/dist/components/batch/useElapsedEstimate.d.ts +10 -0
- package/dist/components/batch/useElapsedEstimate.js +38 -0
- package/dist/components/infiniteGridLoader.d.ts +70 -0
- package/dist/components/infiniteGridLoader.js +141 -0
- package/dist/components/table/columnResize.d.ts +38 -0
- package/dist/components/table/columnResize.js +117 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/variant/VariantMatrixPicker.svelte +181 -0
- package/dist/components/variant/VariantMatrixPicker.svelte.d.ts +37 -0
- package/dist/components/variant/variantCombinations.d.ts +75 -0
- package/dist/components/variant/variantCombinations.js +100 -0
- package/dist/history.d.ts +44 -0
- package/dist/history.js +87 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +27 -0
- package/dist/styles/motion.css +100 -0
- package/dist/utils/keyboardShortcutRegistry.d.ts +152 -0
- package/dist/utils/keyboardShortcutRegistry.js +365 -0
- package/package.json +5 -1
package/dist/history.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot undo/redo history. Forked from @wayflow/core's history.ts (see
|
|
3
|
+
* README.md) and generalized to any graph type `G` — this module only
|
|
4
|
+
* deep-clones snapshots, it never inspects node/edge shape.
|
|
5
|
+
*
|
|
6
|
+
* Adds two things upstream keeps outside `core` (in its DOM editor package):
|
|
7
|
+
* push-on-first-move (`beginChange`/`endChange`) so a drag/resize gesture
|
|
8
|
+
* pushes exactly one pre-change snapshot no matter how many move events it
|
|
9
|
+
* fires, and `untracked()` to run a compound multi-step mutation (e.g.
|
|
10
|
+
* paste = add nodes + add edges) without each step pushing its own entry.
|
|
11
|
+
*
|
|
12
|
+
* CANONICAL HOME: this is the shared copy (jatui-00jfh, rebuilding the lost
|
|
13
|
+
* jat-gjw72 upstream half). The JAT IDE (ide/src/lib/utils/history.ts) and
|
|
14
|
+
* JST (src/lib/workflows/core/history.ts) carry vendored copies that
|
|
15
|
+
* repoint their imports at 'jatui' and are deleted at the swap.
|
|
16
|
+
*/
|
|
17
|
+
export const MAX_UNDO_DEPTH = 50;
|
|
18
|
+
/**
|
|
19
|
+
* Deep-clones plain JSON-shaped state. Not `structuredClone` — callers pass
|
|
20
|
+
* Svelte 5 `$state` proxies (e.g. the canvas's reactive nodes/edges arrays),
|
|
21
|
+
* and `structuredClone` throws `DataCloneError` on those in real browsers
|
|
22
|
+
* (verified in-browser). A JSON round-trip reads through the proxy's
|
|
23
|
+
* property getters like any other consumer and is safe for graph data (no
|
|
24
|
+
* Date/Map/Set/functions).
|
|
25
|
+
*/
|
|
26
|
+
function deepClone(value) {
|
|
27
|
+
return JSON.parse(JSON.stringify(value));
|
|
28
|
+
}
|
|
29
|
+
export function createHistory() {
|
|
30
|
+
return { undoStack: [], redoStack: [], changing: false, suppressed: 0 };
|
|
31
|
+
}
|
|
32
|
+
/** Deep-clones `graph` onto the undo stack (capped at maxDepth) and clears redo. No-ops while suppressed. */
|
|
33
|
+
export function pushState(history, graph, maxDepth = MAX_UNDO_DEPTH) {
|
|
34
|
+
if (history.suppressed > 0)
|
|
35
|
+
return;
|
|
36
|
+
if (history.undoStack.length >= maxDepth) {
|
|
37
|
+
history.undoStack.shift();
|
|
38
|
+
}
|
|
39
|
+
history.undoStack.push(deepClone(graph));
|
|
40
|
+
history.redoStack = [];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Push-on-first-move: call on every move event of a drag/resize gesture.
|
|
44
|
+
* Pushes the pre-gesture snapshot only the first time it's called since the
|
|
45
|
+
* last endChange() — a click that never drags won't add a history entry.
|
|
46
|
+
*/
|
|
47
|
+
export function beginChange(history, graph, maxDepth = MAX_UNDO_DEPTH) {
|
|
48
|
+
if (history.changing)
|
|
49
|
+
return;
|
|
50
|
+
history.changing = true;
|
|
51
|
+
pushState(history, graph, maxDepth);
|
|
52
|
+
}
|
|
53
|
+
/** Ends the current push-on-first-move gesture so the next beginChange() can push again. */
|
|
54
|
+
export function endChange(history) {
|
|
55
|
+
history.changing = false;
|
|
56
|
+
}
|
|
57
|
+
/** Runs `fn` with history pushes suppressed — for compound ops that should land as zero or one entries (pair with a manual pushState before calling). */
|
|
58
|
+
export function untracked(history, fn) {
|
|
59
|
+
history.suppressed++;
|
|
60
|
+
try {
|
|
61
|
+
fn();
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
history.suppressed--;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Pops the most recent undo entry, pushing `currentGraph` onto redo. Returns null if nothing to undo. */
|
|
68
|
+
export function undo(history, currentGraph) {
|
|
69
|
+
if (history.undoStack.length === 0)
|
|
70
|
+
return null;
|
|
71
|
+
history.redoStack.push(deepClone(currentGraph));
|
|
72
|
+
return history.undoStack.pop();
|
|
73
|
+
}
|
|
74
|
+
/** Pops the most recent redo entry, pushing `currentGraph` onto undo. Returns null if nothing to redo. */
|
|
75
|
+
export function redo(history, currentGraph) {
|
|
76
|
+
if (history.redoStack.length === 0)
|
|
77
|
+
return null;
|
|
78
|
+
history.undoStack.push(deepClone(currentGraph));
|
|
79
|
+
return history.redoStack.pop();
|
|
80
|
+
}
|
|
81
|
+
/** Clears both stacks and any in-progress gesture/suppression state. */
|
|
82
|
+
export function clearHistory(history) {
|
|
83
|
+
history.undoStack = [];
|
|
84
|
+
history.redoStack = [];
|
|
85
|
+
history.changing = false;
|
|
86
|
+
history.suppressed = 0;
|
|
87
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,10 @@ export { createDirtyGuard } from './utils/dirtyGuard';
|
|
|
56
56
|
export type { DirtyGuard, DirtyGuardOptions, BeforeNavigateFn } from './utils/dirtyGuard';
|
|
57
57
|
export { default as MediaLightbox } from './components/MediaLightbox.svelte';
|
|
58
58
|
export type { MediaItem } from './components/MediaLightbox.svelte';
|
|
59
|
+
export { default as InfiniteGrid } from './components/InfiniteGrid.svelte';
|
|
60
|
+
export { default as InfiniteSearchGrid } from './components/InfiniteSearchGrid.svelte';
|
|
61
|
+
export { createInfiniteLoader } from './components/infiniteGridLoader';
|
|
62
|
+
export type { InfinitePage, InfiniteLoadContext, InfiniteLoadFn, InfiniteLoader, InfiniteLoaderState, InfiniteStatus } from './components/infiniteGridLoader';
|
|
59
63
|
export { default as Button } from './components/Button.svelte';
|
|
60
64
|
export { default as Badge } from './components/Badge.svelte';
|
|
61
65
|
export { default as Card } from './components/Card.svelte';
|
|
@@ -78,6 +82,8 @@ export { default as LazyImage } from './components/LazyImage.svelte';
|
|
|
78
82
|
export { default as ResizablePanel } from './components/ResizablePanel.svelte';
|
|
79
83
|
export { default as VoicePlayer } from './components/VoicePlayer.svelte';
|
|
80
84
|
export { default as SpeechForm } from './components/SpeechForm.svelte';
|
|
85
|
+
export { default as AudioRecorder } from './components/AudioRecorder.svelte';
|
|
86
|
+
export type { AudioRecordingResult } from './components/AudioRecorder.svelte';
|
|
81
87
|
export { default as ThemeSelector } from './components/ThemeSelector.svelte';
|
|
82
88
|
export { default as Sparkline } from './components/Sparkline.svelte';
|
|
83
89
|
export { default as BurndownChart } from './components/BurndownChart.svelte';
|
|
@@ -93,6 +99,8 @@ export type { FileDropzoneFile } from './components/FileDropzone.svelte';
|
|
|
93
99
|
export { default as VariablePicker } from './components/VariablePicker.svelte';
|
|
94
100
|
export type { TemplateVar, TemplateVarGroup } from './types/templateVars';
|
|
95
101
|
export { default as EmojiPicker } from './components/EmojiPicker.svelte';
|
|
102
|
+
export { default as IconSelector } from './components/IconSelector.svelte';
|
|
103
|
+
export type { IconSelectorOption, IconComponentProps } from './components/IconSelector.svelte';
|
|
96
104
|
export { EMOJI_DATA, ALL_EMOJIS, searchEmojis } from './data/emojis';
|
|
97
105
|
export type { EmojiEntry, EmojiGroup } from './data/emojis';
|
|
98
106
|
export { default as LinkShortener } from './components/LinkShortener.svelte';
|
|
@@ -166,6 +174,8 @@ export type { MarkupTool, Point, MarkupShape, ArrowShape, RectangleShape, Ellips
|
|
|
166
174
|
export type { Annotation, AnnotationProfile, AnnotationThread, AnnotationCallbacks, } from './types/annotation';
|
|
167
175
|
export { default as KeyboardShortcutsOverlay } from './components/KeyboardShortcutsOverlay.svelte';
|
|
168
176
|
export type { KeyboardShortcut, SectionEntry as KeyboardShortcutSectionEntry, ShortcutSection as KeyboardShortcutSection, } from './components/KeyboardShortcutsOverlay.svelte';
|
|
177
|
+
export { createShortcutRegistry, getShortcutRegistry, formatShortcut, parseCombo as parseShortcutCombo, isTypingTarget, detectPlatform as detectShortcutPlatform, SIDEBAR_TOGGLE_KEY, } from './utils/keyboardShortcutRegistry';
|
|
178
|
+
export type { ShortcutRegistry, ShortcutDefinition, ShortcutModifier, ShortcutPlatform, PushContextOptions as ShortcutContextOptions, RegistrySection as ShortcutRegistrySection, ToSectionsOptions as ShortcutSectionsOptions, ShortcutRegistryOptions, ShortcutEventTarget, } from './utils/keyboardShortcutRegistry';
|
|
169
179
|
export { default as MapView } from './components/MapView.svelte';
|
|
170
180
|
export { default as LocationMap } from './components/LocationMap.svelte';
|
|
171
181
|
export { default as GPSTracker } from './components/GPSTracker.svelte';
|
|
@@ -177,6 +187,10 @@ export { staggerEntrance } from './actions/staggerEntrance';
|
|
|
177
187
|
export type { StaggerEntranceOptions } from './actions/staggerEntrance';
|
|
178
188
|
export { attention } from './actions/attention';
|
|
179
189
|
export type { AttentionEffect, AttentionOptions } from './actions/attention';
|
|
190
|
+
export { reveal, REVEAL_HIDDEN_CLASS, REVEAL_BASE_CLASS } from './actions/reveal';
|
|
191
|
+
export type { RevealOptions, RevealVariant } from './actions/reveal';
|
|
192
|
+
export { default as ThumbnailGrid } from './components/ThumbnailGrid.svelte';
|
|
193
|
+
export type { ThumbnailItem } from './components/ThumbnailGrid.svelte';
|
|
180
194
|
export { floating, makeVirtualAnchor } from './actions/floating';
|
|
181
195
|
export type { FloatingOptions, Placement } from './actions/floating';
|
|
182
196
|
export { glide } from './transitions/glide';
|
|
@@ -225,3 +239,19 @@ export { computeActiveSection, DEFAULT_ACTIVATION_RATIO } from './components/bas
|
|
|
225
239
|
export type { SectionRect, SpyViewport, SpyScrollState } from './components/basic/sectionNavSpy';
|
|
226
240
|
export { default as Slider } from './components/basic/Slider.svelte';
|
|
227
241
|
export { default as Pagination } from './components/basic/Pagination.svelte';
|
|
242
|
+
export { MAX_UNDO_DEPTH, createHistory, pushState, beginChange, endChange, untracked, undo, redo, clearHistory } from './history';
|
|
243
|
+
export type { History } from './history';
|
|
244
|
+
export { default as BatchJobTable } from './components/batch/BatchJobTable.svelte';
|
|
245
|
+
export type { JobContext, RowControls, BatchControls, BatchPhase } from './components/batch/BatchJobTable.svelte';
|
|
246
|
+
export { default as QuotaMeter } from './components/batch/QuotaMeter.svelte';
|
|
247
|
+
export { toJobRows, nextJobsToStart, isProcessLimitReached, moveJob, summarizeJobs, formatElapsed } from './components/batch/batchQueue';
|
|
248
|
+
export type { JobRow, JobStatus, BatchSummary, DispatchLimits } from './components/batch/batchQueue';
|
|
249
|
+
export { rollingAverage, estimateRemainingMs } from './components/batch/elapsedEstimate';
|
|
250
|
+
export type { EtaInput } from './components/batch/elapsedEstimate';
|
|
251
|
+
export { useElapsedEstimate } from './components/batch/useElapsedEstimate';
|
|
252
|
+
export type { ElapsedEstimate } from './components/batch/useElapsedEstimate';
|
|
253
|
+
export { pollOperation, PollTimeoutError } from './components/batch/pollOperation';
|
|
254
|
+
export type { PollStep, PollContext, PollOptions } from './components/batch/pollOperation';
|
|
255
|
+
export { default as VariantMatrixPicker } from './components/variant/VariantMatrixPicker.svelte';
|
|
256
|
+
export { countCombinations, generateCombinations, generateVariantFilename, findVariantOption, variantCategoryMode } from './components/variant/variantCombinations';
|
|
257
|
+
export type { VariantCategory, VariantOption, VariantSelection, VariantSelectionMode, VariantCombination } from './components/variant/variantCombinations';
|
package/dist/index.js
CHANGED
|
@@ -73,6 +73,10 @@ export { default as PresenceStack } from './components/PresenceStack.svelte';
|
|
|
73
73
|
export { default as DirtyFormHost } from './components/DirtyFormHost.svelte';
|
|
74
74
|
export { createDirtyGuard } from './utils/dirtyGuard';
|
|
75
75
|
export { default as MediaLightbox } from './components/MediaLightbox.svelte';
|
|
76
|
+
// Cursor-paged infinite-scroll grids, harvested from chimaro (jatui-m4uz3.4).
|
|
77
|
+
export { default as InfiniteGrid } from './components/InfiniteGrid.svelte';
|
|
78
|
+
export { default as InfiniteSearchGrid } from './components/InfiniteSearchGrid.svelte';
|
|
79
|
+
export { createInfiniteLoader } from './components/infiniteGridLoader';
|
|
76
80
|
// Components — from Flush
|
|
77
81
|
export { default as Button } from './components/Button.svelte';
|
|
78
82
|
export { default as Badge } from './components/Badge.svelte';
|
|
@@ -97,6 +101,7 @@ export { default as LazyImage } from './components/LazyImage.svelte';
|
|
|
97
101
|
export { default as ResizablePanel } from './components/ResizablePanel.svelte';
|
|
98
102
|
export { default as VoicePlayer } from './components/VoicePlayer.svelte';
|
|
99
103
|
export { default as SpeechForm } from './components/SpeechForm.svelte';
|
|
104
|
+
export { default as AudioRecorder } from './components/AudioRecorder.svelte';
|
|
100
105
|
// Components — from Headcount
|
|
101
106
|
export { default as ThemeSelector } from './components/ThemeSelector.svelte';
|
|
102
107
|
export { default as Sparkline } from './components/Sparkline.svelte';
|
|
@@ -112,6 +117,8 @@ export { default as EntityPreviewCard } from './components/EntityPreviewCard.sve
|
|
|
112
117
|
export { default as VariablePicker } from './components/VariablePicker.svelte';
|
|
113
118
|
// Components — Emoji
|
|
114
119
|
export { default as EmojiPicker } from './components/EmojiPicker.svelte';
|
|
120
|
+
// Components — Icon selection
|
|
121
|
+
export { default as IconSelector } from './components/IconSelector.svelte';
|
|
115
122
|
// Emoji data
|
|
116
123
|
export { EMOJI_DATA, ALL_EMOJIS, searchEmojis } from './data/emojis';
|
|
117
124
|
// Components — from Meadow
|
|
@@ -183,6 +190,7 @@ export { default as AnnotationPanel } from './components/AnnotationPanel.svelte'
|
|
|
183
190
|
export { MARKUP_COLORS, DEFAULT_STROKE_WIDTH, renderShape, renderAllShapes, nextShapeId, } from './components/markup';
|
|
184
191
|
// Components — Keyboard Navigation
|
|
185
192
|
export { default as KeyboardShortcutsOverlay } from './components/KeyboardShortcutsOverlay.svelte';
|
|
193
|
+
export { createShortcutRegistry, getShortcutRegistry, formatShortcut, parseCombo as parseShortcutCombo, isTypingTarget, detectPlatform as detectShortcutPlatform, SIDEBAR_TOGGLE_KEY, } from './utils/keyboardShortcutRegistry';
|
|
186
194
|
// Components — Google Maps (DispatchMap fork + location primitives)
|
|
187
195
|
export { default as MapView } from './components/MapView.svelte';
|
|
188
196
|
export { default as LocationMap } from './components/LocationMap.svelte';
|
|
@@ -202,6 +210,13 @@ export { loadGoogleMapsAPI, isGoogleMapsLoaded, isPlacesLoaded, isGeometryLoaded
|
|
|
202
210
|
export { tooltip } from './actions/tooltip';
|
|
203
211
|
export { staggerEntrance } from './actions/staggerEntrance';
|
|
204
212
|
export { attention } from './actions/attention';
|
|
213
|
+
// Scroll-reveal (jatui-m4uz3.3, chimaro port): IntersectionObserver
|
|
214
|
+
// scroll-reveal whose variants live in styles/motion.css as jatui-reveal-*
|
|
215
|
+
// classes on the --motion-* tokens — no shipped animista.css.
|
|
216
|
+
export { reveal, REVEAL_HIDDEN_CLASS, REVEAL_BASE_CLASS } from './actions/reveal';
|
|
217
|
+
// Thumbnail grid (jatui-m4uz3.3, chimaro port): generic {id,url,alt} strip
|
|
218
|
+
// with overflow counter, remove/add affordances and a cell snippet override.
|
|
219
|
+
export { default as ThumbnailGrid } from './components/ThumbnailGrid.svelte';
|
|
205
220
|
export { floating, makeVirtualAnchor } from './actions/floating';
|
|
206
221
|
export { glide } from './transitions/glide';
|
|
207
222
|
// View Transitions kit
|
|
@@ -260,3 +275,15 @@ export { default as SectionNav } from './components/basic/SectionNav.svelte';
|
|
|
260
275
|
export { computeActiveSection, DEFAULT_ACTIVATION_RATIO } from './components/basic/sectionNavSpy';
|
|
261
276
|
export { default as Slider } from './components/basic/Slider.svelte';
|
|
262
277
|
export { default as Pagination } from './components/basic/Pagination.svelte';
|
|
278
|
+
// Snapshot undo/redo history (wayflow-core) — also importable as 'jatui/history' (jatui-00jfh).
|
|
279
|
+
export { MAX_UNDO_DEPTH, createHistory, pushState, beginChange, endChange, untracked, undo, redo, clearHistory } from './history';
|
|
280
|
+
// Batch queue runner (harvested from vid-gen BatchGenerator — jatui-m4uz3.7).
|
|
281
|
+
export { default as BatchJobTable } from './components/batch/BatchJobTable.svelte';
|
|
282
|
+
export { default as QuotaMeter } from './components/batch/QuotaMeter.svelte';
|
|
283
|
+
export { toJobRows, nextJobsToStart, isProcessLimitReached, moveJob, summarizeJobs, formatElapsed } from './components/batch/batchQueue';
|
|
284
|
+
export { rollingAverage, estimateRemainingMs } from './components/batch/elapsedEstimate';
|
|
285
|
+
export { useElapsedEstimate } from './components/batch/useElapsedEstimate';
|
|
286
|
+
export { pollOperation, PollTimeoutError } from './components/batch/pollOperation';
|
|
287
|
+
// Variant matrix picker + combination algebra (harvested from vid-gen FrameVariantGenerator — jatui-m4uz3.8).
|
|
288
|
+
export { default as VariantMatrixPicker } from './components/variant/VariantMatrixPicker.svelte';
|
|
289
|
+
export { countCombinations, generateCombinations, generateVariantFilename, findVariantOption, variantCategoryMode } from './components/variant/variantCombinations';
|
package/dist/styles/motion.css
CHANGED
|
@@ -44,3 +44,103 @@
|
|
|
44
44
|
scroll-behavior: auto !important;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* Scroll-reveal (use:reveal) — ported from chimaro's animista-powered reveal
|
|
50
|
+
* action (jatui-m4uz3.3). The action toggles `.jatui-reveal-hidden` off and
|
|
51
|
+
* `.jatui-reveal jatui-reveal-<variant>` on when the element first intersects
|
|
52
|
+
* the viewport. Every class here reads ONLY the tokens above — animista.css
|
|
53
|
+
* is deliberately NOT shipped; the variants below are the remap.
|
|
54
|
+
*/
|
|
55
|
+
.jatui-reveal-hidden {
|
|
56
|
+
opacity: 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.jatui-reveal {
|
|
60
|
+
animation-duration: var(--motion-move);
|
|
61
|
+
animation-timing-function: var(--motion-glide);
|
|
62
|
+
animation-fill-mode: both; /* holds the from-state through any animation-delay */
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.jatui-reveal-fade-in {
|
|
66
|
+
animation-name: jatui-reveal-fade-in;
|
|
67
|
+
}
|
|
68
|
+
.jatui-reveal-fade-in-bottom {
|
|
69
|
+
animation-name: jatui-reveal-fade-in-bottom;
|
|
70
|
+
}
|
|
71
|
+
.jatui-reveal-fade-in-top {
|
|
72
|
+
animation-name: jatui-reveal-fade-in-top;
|
|
73
|
+
}
|
|
74
|
+
.jatui-reveal-fade-in-left {
|
|
75
|
+
animation-name: jatui-reveal-fade-in-left;
|
|
76
|
+
}
|
|
77
|
+
.jatui-reveal-fade-in-right {
|
|
78
|
+
animation-name: jatui-reveal-fade-in-right;
|
|
79
|
+
}
|
|
80
|
+
.jatui-reveal-scale-in-center {
|
|
81
|
+
animation-name: jatui-reveal-scale-in-center;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@keyframes jatui-reveal-fade-in {
|
|
85
|
+
from {
|
|
86
|
+
opacity: 0;
|
|
87
|
+
}
|
|
88
|
+
to {
|
|
89
|
+
opacity: 1;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@keyframes jatui-reveal-fade-in-bottom {
|
|
94
|
+
from {
|
|
95
|
+
transform: translateY(24px);
|
|
96
|
+
opacity: 0;
|
|
97
|
+
}
|
|
98
|
+
to {
|
|
99
|
+
transform: translateY(0);
|
|
100
|
+
opacity: 1;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@keyframes jatui-reveal-fade-in-top {
|
|
105
|
+
from {
|
|
106
|
+
transform: translateY(-24px);
|
|
107
|
+
opacity: 0;
|
|
108
|
+
}
|
|
109
|
+
to {
|
|
110
|
+
transform: translateY(0);
|
|
111
|
+
opacity: 1;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@keyframes jatui-reveal-fade-in-left {
|
|
116
|
+
from {
|
|
117
|
+
transform: translateX(-24px);
|
|
118
|
+
opacity: 0;
|
|
119
|
+
}
|
|
120
|
+
to {
|
|
121
|
+
transform: translateX(0);
|
|
122
|
+
opacity: 1;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@keyframes jatui-reveal-fade-in-right {
|
|
127
|
+
from {
|
|
128
|
+
transform: translateX(24px);
|
|
129
|
+
opacity: 0;
|
|
130
|
+
}
|
|
131
|
+
to {
|
|
132
|
+
transform: translateX(0);
|
|
133
|
+
opacity: 1;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@keyframes jatui-reveal-scale-in-center {
|
|
138
|
+
from {
|
|
139
|
+
transform: scale(0.6);
|
|
140
|
+
opacity: 0;
|
|
141
|
+
}
|
|
142
|
+
to {
|
|
143
|
+
transform: scale(1);
|
|
144
|
+
opacity: 1;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyboard shortcut registry — the data source `KeyboardShortcutsOverlay`
|
|
3
|
+
* was always missing (jatui-m4uz3.6, harvested from chimaro's
|
|
4
|
+
* keyboardShortcutManager with its app-specific default registrations
|
|
5
|
+
* stripped).
|
|
6
|
+
*
|
|
7
|
+
* One registry per app (or use the lazy `getShortcutRegistry()` singleton).
|
|
8
|
+
* Components register shortcuts against a CONTEXT and get back an
|
|
9
|
+
* unregister function, which is exactly what a Svelte `$effect` wants to
|
|
10
|
+
* return:
|
|
11
|
+
*
|
|
12
|
+
* $effect(() => registry.register([
|
|
13
|
+
* { key: 'j', description: 'Next item', context: 'list', action: next },
|
|
14
|
+
* { key: 'mod+k', description: 'Search', action: openPalette, allowInInput: true },
|
|
15
|
+
* ]));
|
|
16
|
+
*
|
|
17
|
+
* Contexts form a STACK. `global` is always the bottom. `pushContext()`
|
|
18
|
+
* returns a pop function. When a key is pressed the stack is walked from
|
|
19
|
+
* the top down and the first matching, enabled shortcut wins — so a
|
|
20
|
+
* context higher up shadows the same combo lower down. A context pushed
|
|
21
|
+
* with `{ modal: true }` stops the walk: everything beneath it (including
|
|
22
|
+
* `global`) is suppressed while it is on the stack — that is how a dialog
|
|
23
|
+
* keeps page shortcuts from firing behind it.
|
|
24
|
+
*
|
|
25
|
+
* Sharp edges handled here so every app doesn't re-learn them:
|
|
26
|
+
* - Input focus: shortcuts don't fire while typing in a text input,
|
|
27
|
+
* textarea, select or contenteditable (checkboxes/buttons/ranges don't
|
|
28
|
+
* count as typing). Opt back in per shortcut with `allowInInput`.
|
|
29
|
+
* - IME composition and already-handled (`defaultPrevented`) events are
|
|
30
|
+
* ignored.
|
|
31
|
+
* - Modifiers: `mod` is ⌘ on macOS and Ctrl elsewhere. Matching is exact —
|
|
32
|
+
* `mod+k` does not fire on `mod+shift+k`. Shift is implied by printable
|
|
33
|
+
* symbols (`?` is Shift+/ on most layouts), so `key: '?'` matches without
|
|
34
|
+
* listing `shift`. macOS Option rewrites `event.key` (Alt+K → "˚"), so
|
|
35
|
+
* alt combos fall back to `event.code`.
|
|
36
|
+
* - Browser-reserved combos: Ctrl+B / Ctrl+T / Ctrl+W / Ctrl+N belong to the
|
|
37
|
+
* browser (Chrome won't hand some of them to the page at all). The sidebar
|
|
38
|
+
* convention across JAT apps is `mod+\` — see `SIDEBAR_TOGGLE_KEY`.
|
|
39
|
+
*
|
|
40
|
+
* Pure TypeScript, no Svelte runes and no DOM globals at import time, so it
|
|
41
|
+
* is SSR-safe and unit-testable under plain node.
|
|
42
|
+
*/
|
|
43
|
+
export type ShortcutModifier = 'mod' | 'meta' | 'ctrl' | 'shift' | 'alt' | 'cmd';
|
|
44
|
+
export type ShortcutPlatform = 'mac' | 'other';
|
|
45
|
+
export interface ShortcutDefinition {
|
|
46
|
+
/**
|
|
47
|
+
* `KeyboardEvent.key` value (case-insensitive for letters), optionally
|
|
48
|
+
* prefixed with modifiers: `'k'`, `'mod+k'`, `'shift+ArrowDown'`, `'?'`,
|
|
49
|
+
* `'mod+\\'`. Use `'+'` / `'mod++'` for the plus key itself.
|
|
50
|
+
*/
|
|
51
|
+
key: string;
|
|
52
|
+
/** Extra modifiers, merged with any parsed from `key`. `cmd` is an alias of `mod`. */
|
|
53
|
+
modifiers?: ShortcutModifier | ShortcutModifier[];
|
|
54
|
+
/** Shown in the overlay. */
|
|
55
|
+
description: string;
|
|
56
|
+
action: (event: KeyboardEvent) => void | Promise<void>;
|
|
57
|
+
/** Context this shortcut belongs to. Default `'global'`. */
|
|
58
|
+
context?: string;
|
|
59
|
+
/** Live predicate — a disabled shortcut is skipped and the walk continues. */
|
|
60
|
+
enabled?: () => boolean;
|
|
61
|
+
/** Fire even while focus is in a text field. Default false. */
|
|
62
|
+
allowInInput?: boolean;
|
|
63
|
+
/** Fire on auto-repeat keydowns (held key). Default true. */
|
|
64
|
+
allowRepeat?: boolean;
|
|
65
|
+
/** Call `preventDefault()` when this shortcut fires. Default true. */
|
|
66
|
+
preventDefault?: boolean;
|
|
67
|
+
/** Overlay section title. Defaults to the context's label. */
|
|
68
|
+
group?: string;
|
|
69
|
+
/** Register but leave out of the overlay. */
|
|
70
|
+
hidden?: boolean;
|
|
71
|
+
/** Overrides the computed keycap label in the overlay (e.g. `'j / ↓'`). */
|
|
72
|
+
label?: string;
|
|
73
|
+
}
|
|
74
|
+
export interface PushContextOptions {
|
|
75
|
+
/** Suppress every context beneath this one (including `global`) while pushed. */
|
|
76
|
+
modal?: boolean;
|
|
77
|
+
/** Overlay section title for this context. Default: the context name. */
|
|
78
|
+
label?: string;
|
|
79
|
+
}
|
|
80
|
+
/** Same shape as `KeyboardShortcutsOverlay`'s `ShortcutSection`. */
|
|
81
|
+
export interface RegistrySection {
|
|
82
|
+
title: string;
|
|
83
|
+
shortcuts: {
|
|
84
|
+
key: string;
|
|
85
|
+
description: string;
|
|
86
|
+
}[];
|
|
87
|
+
}
|
|
88
|
+
export interface ToSectionsOptions {
|
|
89
|
+
/**
|
|
90
|
+
* `'active'` (default) lists only contexts that can fire right now —
|
|
91
|
+
* the live part of the stack, top first. `'all'` lists every context
|
|
92
|
+
* with registrations.
|
|
93
|
+
*/
|
|
94
|
+
scope?: 'active' | 'all';
|
|
95
|
+
/** Drop shortcuts whose `enabled()` currently returns false. Default false. */
|
|
96
|
+
onlyEnabled?: boolean;
|
|
97
|
+
}
|
|
98
|
+
export interface ShortcutRegistryOptions {
|
|
99
|
+
/** Force the platform (tests, SSR). Default: sniffed from `navigator`. */
|
|
100
|
+
platform?: ShortcutPlatform;
|
|
101
|
+
/** Overlay labels for contexts. `global` defaults to `'General'`. */
|
|
102
|
+
contextLabels?: Record<string, string>;
|
|
103
|
+
/** Called when an action throws or rejects. Default: `console.error`. */
|
|
104
|
+
onError?: (error: unknown, shortcut: ShortcutDefinition) => void;
|
|
105
|
+
}
|
|
106
|
+
/** Minimal event-target shape `attach()` needs (window, document, an element). */
|
|
107
|
+
export interface ShortcutEventTarget {
|
|
108
|
+
addEventListener(type: 'keydown', listener: (e: KeyboardEvent) => void): void;
|
|
109
|
+
removeEventListener(type: 'keydown', listener: (e: KeyboardEvent) => void): void;
|
|
110
|
+
}
|
|
111
|
+
export interface ShortcutRegistry {
|
|
112
|
+
/** Register one or many shortcuts. Returns an unregister function. */
|
|
113
|
+
register(shortcuts: ShortcutDefinition | ShortcutDefinition[]): () => void;
|
|
114
|
+
/** Push a context onto the stack. Returns a pop function (idempotent). */
|
|
115
|
+
pushContext(name: string, options?: PushContextOptions): () => void;
|
|
116
|
+
/** Context names that can currently fire, top of stack first. */
|
|
117
|
+
activeContexts(): string[];
|
|
118
|
+
/** Listen for keydown on `target` (default `window`). Returns a detach function. */
|
|
119
|
+
attach(target?: ShortcutEventTarget): () => void;
|
|
120
|
+
/** Dispatch an event by hand. Returns true when a shortcut fired. */
|
|
121
|
+
handleKeydown(event: KeyboardEvent): boolean;
|
|
122
|
+
/** Shortcuts grouped for `KeyboardShortcutsOverlay`'s `sections` prop. */
|
|
123
|
+
toSections(options?: ToSectionsOptions): RegistrySection[];
|
|
124
|
+
/** Every registration, in registration order. */
|
|
125
|
+
list(): ShortcutDefinition[];
|
|
126
|
+
/** Keycap label for a shortcut on this registry's platform (`⌘K`, `Ctrl+K`). */
|
|
127
|
+
format(shortcut: ShortcutDefinition | string): string;
|
|
128
|
+
/** Notified after every register/unregister/push/pop. Returns unsubscribe. */
|
|
129
|
+
subscribe(listener: () => void): () => void;
|
|
130
|
+
readonly platform: ShortcutPlatform;
|
|
131
|
+
}
|
|
132
|
+
/** The sidebar-toggle convention. Ctrl+B is reserved by Chrome (bookmarks bar). */
|
|
133
|
+
export declare const SIDEBAR_TOGGLE_KEY = "mod+\\";
|
|
134
|
+
interface ParsedCombo {
|
|
135
|
+
key: string;
|
|
136
|
+
mod: boolean;
|
|
137
|
+
meta: boolean;
|
|
138
|
+
ctrl: boolean;
|
|
139
|
+
shift: boolean;
|
|
140
|
+
alt: boolean;
|
|
141
|
+
}
|
|
142
|
+
export declare function detectPlatform(): ShortcutPlatform;
|
|
143
|
+
/** Parse `'mod+shift+k'` (plus any extra modifiers) into a normalized combo. */
|
|
144
|
+
export declare function parseCombo(key: string, extra?: ShortcutModifier | ShortcutModifier[]): ParsedCombo;
|
|
145
|
+
/** True when keystrokes on `target` are text entry (so bare-key shortcuts must not fire). */
|
|
146
|
+
export declare function isTypingTarget(target: EventTarget | null | undefined): boolean;
|
|
147
|
+
/** Keycap label: `⌘⇧K` on macOS, `Ctrl+Shift+K` elsewhere. */
|
|
148
|
+
export declare function formatShortcut(shortcut: ShortcutDefinition | string, platform?: ShortcutPlatform): string;
|
|
149
|
+
export declare function createShortcutRegistry(options?: ShortcutRegistryOptions): ShortcutRegistry;
|
|
150
|
+
/** Lazily-created app-wide registry, for apps that want one without threading it through props. */
|
|
151
|
+
export declare function getShortcutRegistry(): ShortcutRegistry;
|
|
152
|
+
export {};
|