@joewinke/jatui 0.54.0 → 0.55.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 +5 -1
- package/README.md +3 -1
- package/dist/ambience/default.d.ts +3 -17
- package/dist/ambience/default.js +3 -2
- package/dist/ambience/engine.js +14 -3
- package/dist/ambience/groups.d.ts +45 -0
- package/dist/ambience/groups.js +98 -0
- package/dist/ambience/index.d.ts +4 -2
- package/dist/ambience/index.js +3 -1
- package/dist/ambience/registry.d.ts +6 -6
- package/dist/ambience/registry.js +31 -8
- package/dist/ambience/scapes/playlist.d.ts +16 -3
- package/dist/ambience/scapes/playlist.js +22 -1
- package/dist/ambience/types.d.ts +47 -3
- package/dist/components/AmbienceToggle.svelte +398 -106
- package/dist/components/AmbienceToggle.svelte.d.ts +56 -25
- package/dist/components/DatePicker.svelte +1 -0
- package/dist/components/DateRangePicker.svelte +1 -0
- package/dist/components/EventCalendar.svelte +1 -0
- package/dist/components/calendar/MonthGrid.svelte +14 -0
- package/dist/components/calendar/MonthGrid.svelte.d.ts +8 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/package.json +1 -1
|
@@ -5,16 +5,25 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Interaction contract:
|
|
7
7
|
* - Click (or Space/Enter) = play / stop the last scape. A gesture-gated
|
|
8
|
-
* engine call, made synchronously inside the click handler.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* engine call, made synchronously inside the click handler. With no
|
|
9
|
+
* playable scape registered (links only) the click opens the menu.
|
|
10
|
+
* - The menu (menu button pattern) opens with ArrowDown/ArrowUp, a
|
|
11
|
+
* press-and-hold (~450 ms) or a right-click (Android/Chrome fire
|
|
11
12
|
* contextmenu on touch holds; iOS may cancel the pointer instead —
|
|
12
|
-
* the keyboard path always works).
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* the keyboard path always works). Top level: a volume slider wired to
|
|
14
|
+
* `engine.setVolume`, then one row per section — Radio / Focus /
|
|
15
|
+
* Noise / Meditation … in the host's order (`AmbienceOptions.groups`,
|
|
16
|
+
* jatui-mdq2p) — each opening a submenu of its items. Right / Enter /
|
|
17
|
+
* Space open a submenu and move focus into it; Left / Escape close it
|
|
18
|
+
* and return focus to its row (the ContextMenu submenu pattern); a
|
|
19
|
+
* mouse hover opens a row's submenu without moving focus.
|
|
20
|
+
* - Scapes are `menuitemradio` (current one checked; its section row
|
|
21
|
+
* carries a dot and the scape's name). Link items (radio stations) are
|
|
22
|
+
* real `<a target="_blank">` menu items with an external-link glyph:
|
|
23
|
+
* the station's own site or player opens in a new tab. Nothing is
|
|
24
|
+
* relayed — we never proxy a third-party stream.
|
|
25
|
+
* - A playing playlist shows its current track's attribution (title,
|
|
26
|
+
* composer, license) under the playlist item and its section row.
|
|
18
27
|
*
|
|
19
28
|
* A11y: the trigger is `aria-pressed` while playing and carries the full
|
|
20
29
|
* menu-button wiring (`aria-expanded` / `aria-haspopup` / `aria-controls`).
|
|
@@ -27,24 +36,24 @@
|
|
|
27
36
|
* Token-only theming (DaisyUI + `--jatui-*` + `--motion-*`). SSR-safe: the
|
|
28
37
|
* engine is lazy and nothing here touches `window` at import.
|
|
29
38
|
*/
|
|
30
|
-
import type {
|
|
31
|
-
|
|
39
|
+
import type { AmbienceGroupDef, AmbienceItem, ScapeGroup } from '../ambience/types';
|
|
40
|
+
import { type AmbienceSection } from '../ambience/groups';
|
|
41
|
+
import { type PlaylistTrack } from '../ambience/scapes/playlist';
|
|
42
|
+
/** Default menu section order (when the host configures no `groups`). */
|
|
32
43
|
export declare const AMBIENCE_GROUP_ORDER: readonly ScapeGroup[];
|
|
33
|
-
/** Human labels for the
|
|
34
|
-
export declare const GROUP_LABELS: Readonly<Record<
|
|
35
|
-
/** One
|
|
36
|
-
export
|
|
37
|
-
group: ScapeGroup;
|
|
38
|
-
label: string;
|
|
39
|
-
scapes: Scape[];
|
|
40
|
-
}
|
|
44
|
+
/** Human labels for the library's own groups. */
|
|
45
|
+
export declare const GROUP_LABELS: Readonly<Record<string, string>>;
|
|
46
|
+
/** One section of the menu: a top-level row and its submenu. */
|
|
47
|
+
export type AmbienceScapeGroup = AmbienceSection;
|
|
41
48
|
/**
|
|
42
|
-
* Group
|
|
43
|
-
* within a
|
|
44
|
-
*
|
|
45
|
-
* first-seen order — a menu never silently drops a registered
|
|
49
|
+
* Group items for the menu: the host's section order (or the default),
|
|
50
|
+
* registration order within a section, empty sections omitted. A group
|
|
51
|
+
* missing from the order still renders, after the ordered ones, in
|
|
52
|
+
* first-seen order — a menu never silently drops a registered item.
|
|
46
53
|
*/
|
|
47
|
-
export declare function groupScapes(
|
|
54
|
+
export declare function groupScapes(items: AmbienceItem[], groups?: ReadonlyArray<ScapeGroup | AmbienceGroupDef>): AmbienceScapeGroup[];
|
|
55
|
+
/** "Gymnopédie No. 1 — Erik Satie · Public domain": a playing track's line. */
|
|
56
|
+
export declare function nowPlayingLine(track: PlaylistTrack | null | undefined): string;
|
|
48
57
|
/**
|
|
49
58
|
* The live label — "Ambience: Hibiscus, playing" while sounding,
|
|
50
59
|
* "Ambience: Hibiscus, stopped" once a scape has been selected but is not
|
|
@@ -61,8 +70,30 @@ export declare const PLAY_ERROR_LABEL = "Ambience: couldn't start \u2014 tap aga
|
|
|
61
70
|
* and settles on the exhale — 6% total, clamped against out-of-range input.
|
|
62
71
|
*/
|
|
63
72
|
export declare function breathScale(value: number): number;
|
|
73
|
+
/** Submenu width (px) — matches the `w-64` class on the submenu panel. */
|
|
74
|
+
export declare const SUBMENU_WIDTH = 256;
|
|
75
|
+
/**
|
|
76
|
+
* Where a submenu goes, in viewport px. Beside the menu panel on the
|
|
77
|
+
* preferred side (the side the menu already extends to), else the other
|
|
78
|
+
* side, else — a phone, no room either side — overlapping the panel just
|
|
79
|
+
* below its row, clamped inside the viewport.
|
|
80
|
+
*/
|
|
81
|
+
export declare function placeSubmenu(row: {
|
|
82
|
+
top: number;
|
|
83
|
+
bottom: number;
|
|
84
|
+
}, panel: {
|
|
85
|
+
left: number;
|
|
86
|
+
right: number;
|
|
87
|
+
}, viewport: {
|
|
88
|
+
width: number;
|
|
89
|
+
}, prefer: 'left' | 'right', width?: number, gap?: number, margin?: number): {
|
|
90
|
+
x: number;
|
|
91
|
+
y: number;
|
|
92
|
+
side: 'left' | 'right' | 'over';
|
|
93
|
+
};
|
|
94
|
+
import type { Ambience } from '../ambience/types';
|
|
64
95
|
type $$ComponentProps = {
|
|
65
|
-
/** The engine instance (from `createAmbience()`). The component never creates one, and never kills it — the host owns the engine's lifecycle. */
|
|
96
|
+
/** The engine instance (from `createAmbience()`). The component never creates one, and never kills it — the host owns the engine's lifecycle. Section order/labels come from the engine's `groups` option. */
|
|
66
97
|
engine: Ambience;
|
|
67
98
|
/** Smaller app-shell footprint: 40px trigger with an 18px glyph (default 44px / 20px). Never below the 40px touch floor. */
|
|
68
99
|
compact?: boolean;
|
|
@@ -38,6 +38,14 @@
|
|
|
38
38
|
/** Tint every enabled in-month day (booking calendars: "these days are open"). */
|
|
39
39
|
highlightEnabled?: boolean;
|
|
40
40
|
size?: 'sm' | 'md' | 'lg';
|
|
41
|
+
/**
|
|
42
|
+
* Stretch to the container's width (default). Pass `false` inside a
|
|
43
|
+
* shrink-to-fit host — a popover with `width: max-content`, a flex item
|
|
44
|
+
* sized by its content: a `width: 100%` table's max-content is unbounded
|
|
45
|
+
* in Chrome, so the host grows to ~670,000px and the days land off-screen
|
|
46
|
+
* (jatui-ewfh3). `false` sizes the grid to seven cells and centres it.
|
|
47
|
+
*/
|
|
48
|
+
fill?: boolean;
|
|
41
49
|
/** Accessible name; defaults to "March 2026". */
|
|
42
50
|
ariaLabel?: string;
|
|
43
51
|
rtl?: boolean;
|
|
@@ -83,6 +91,7 @@
|
|
|
83
91
|
hideWeekdays = false,
|
|
84
92
|
highlightEnabled = false,
|
|
85
93
|
size = 'md',
|
|
94
|
+
fill = true,
|
|
86
95
|
ariaLabel,
|
|
87
96
|
rtl = false,
|
|
88
97
|
onSelect,
|
|
@@ -143,6 +152,7 @@
|
|
|
143
152
|
<table
|
|
144
153
|
bind:this={gridEl}
|
|
145
154
|
class="jatui-month-grid jatui-month-grid--{size} {className}"
|
|
155
|
+
class:jatui-month-grid--intrinsic={!fill}
|
|
146
156
|
role="grid"
|
|
147
157
|
aria-label={label}
|
|
148
158
|
dir={rtl ? 'rtl' : undefined}
|
|
@@ -230,6 +240,10 @@
|
|
|
230
240
|
width: 100%;
|
|
231
241
|
min-width: calc(var(--_cell) * 7);
|
|
232
242
|
}
|
|
243
|
+
.jatui-month-grid--intrinsic {
|
|
244
|
+
width: calc(var(--_cell) * 7);
|
|
245
|
+
margin-inline: auto;
|
|
246
|
+
}
|
|
233
247
|
.jatui-month-grid--sm {
|
|
234
248
|
--_cell: 2rem;
|
|
235
249
|
}
|
|
@@ -35,6 +35,14 @@ export interface MonthGridProps {
|
|
|
35
35
|
/** Tint every enabled in-month day (booking calendars: "these days are open"). */
|
|
36
36
|
highlightEnabled?: boolean;
|
|
37
37
|
size?: 'sm' | 'md' | 'lg';
|
|
38
|
+
/**
|
|
39
|
+
* Stretch to the container's width (default). Pass `false` inside a
|
|
40
|
+
* shrink-to-fit host — a popover with `width: max-content`, a flex item
|
|
41
|
+
* sized by its content: a `width: 100%` table's max-content is unbounded
|
|
42
|
+
* in Chrome, so the host grows to ~670,000px and the days land off-screen
|
|
43
|
+
* (jatui-ewfh3). `false` sizes the grid to seven cells and centres it.
|
|
44
|
+
*/
|
|
45
|
+
fill?: boolean;
|
|
38
46
|
/** Accessible name; defaults to "March 2026". */
|
|
39
47
|
ariaLabel?: string;
|
|
40
48
|
rtl?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -408,8 +408,9 @@ export { default as ImageReveal } from './components/ImageReveal.svelte';
|
|
|
408
408
|
export { imageRevealPhase, imageRevealBusy, imageRevealInitials, imageRevealSize, imageRevealTone, IMAGE_REVEAL_SIZES, IMAGE_REVEAL_RADIUS } from './components/imageReveal';
|
|
409
409
|
export type { ImageRevealPhase, ImageRevealShape, ImageRevealSizeName, ImageRevealToneName, ImageRevealState } from './components/imageReveal';
|
|
410
410
|
export { default as AmbienceToggle, AMBIENCE_GROUP_ORDER } from './components/AmbienceToggle.svelte';
|
|
411
|
-
export { createAmbience, createDefaultAmbience, DEFAULT_SCAPES, BreathClock, BREATHS_PER_MINUTE, MASTER, ScapeRegistry, hibiscusScape, focusScape, noiseScapes, brownNoiseScape, pinkNoiseScape, whiteNoiseScape, rain, waves } from './ambience';
|
|
412
|
-
export type { DefaultAmbienceOptions } from './ambience';
|
|
413
|
-
export type { Ambience, AmbienceOptions, AmbienceState, BreathState, Scape, ScapeContext, ScapeGroup, ScapeInstance } from './ambience';
|
|
411
|
+
export { createAmbience, createDefaultAmbience, DEFAULT_SCAPES, BreathClock, BREATHS_PER_MINUTE, MASTER, ScapeRegistry, hibiscusScape, focusScape, noiseScapes, brownNoiseScape, pinkNoiseScape, whiteNoiseScape, rain, waves, AMBIENCE_DEFAULT_GROUP_ORDER, AMBIENCE_DEFAULT_GROUP_LABELS, groupAmbienceItems, ambienceGroupLabel, isAmbienceLink, normalizeAmbienceGroups, radioStation, safeAmbienceHref } from './ambience';
|
|
412
|
+
export type { DefaultAmbienceOptions, AmbienceSection } from './ambience';
|
|
413
|
+
export type { Ambience, AmbienceGroupDef, AmbienceItem, AmbienceLink, AmbienceOptions, AmbienceState, BreathState, Scape, ScapeContext, ScapeGroup, ScapeInstance } from './ambience';
|
|
414
414
|
export { createPlaylistScape } from './ambience';
|
|
415
|
+
export { isPlaylistScape, trackAttribution } from './ambience';
|
|
415
416
|
export type { PlaylistScape, PlaylistScapeOptions, PlaylistManifest, PlaylistState, PlaylistStatus, PlaylistTrack } from './ambience';
|
package/dist/index.js
CHANGED
|
@@ -457,7 +457,8 @@ export { imageRevealPhase, imageRevealBusy, imageRevealInitials, imageRevealSize
|
|
|
457
457
|
// navigation; createDefaultAmbience() pre-registers every shipped scape
|
|
458
458
|
// (hibiscus, focus, brown/pink/white noise, rain, waves).
|
|
459
459
|
export { default as AmbienceToggle, AMBIENCE_GROUP_ORDER } from './components/AmbienceToggle.svelte';
|
|
460
|
-
export { createAmbience, createDefaultAmbience, DEFAULT_SCAPES, BreathClock, BREATHS_PER_MINUTE, MASTER, ScapeRegistry, hibiscusScape, focusScape, noiseScapes, brownNoiseScape, pinkNoiseScape, whiteNoiseScape, rain, waves } from './ambience';
|
|
460
|
+
export { createAmbience, createDefaultAmbience, DEFAULT_SCAPES, BreathClock, BREATHS_PER_MINUTE, MASTER, ScapeRegistry, hibiscusScape, focusScape, noiseScapes, brownNoiseScape, pinkNoiseScape, whiteNoiseScape, rain, waves, AMBIENCE_DEFAULT_GROUP_ORDER, AMBIENCE_DEFAULT_GROUP_LABELS, groupAmbienceItems, ambienceGroupLabel, isAmbienceLink, normalizeAmbienceGroups, radioStation, safeAmbienceHref } from './ambience';
|
|
461
461
|
// Playlist scape (phase 2) — per-host, never in DEFAULT_SCAPES: build with
|
|
462
462
|
// createPlaylistScape() and register on the engine yourself.
|
|
463
463
|
export { createPlaylistScape } from './ambience';
|
|
464
|
+
export { isPlaylistScape, trackAttribution } from './ambience';
|