cursedbelt 5.93.0 → 5.95.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/dist/react/components/AppShell.d.ts +12 -1
- package/dist/react/components/AppShell.d.ts.map +1 -1
- package/dist/react/components/AppShell.js +24 -5
- package/dist/react/components/AppShell.js.map +1 -1
- package/dist/react/components/ComboboxField.js +2 -2
- package/dist/react/components/ComboboxField.js.map +1 -1
- package/dist/react/components/CommentThread.d.ts +9 -3
- package/dist/react/components/CommentThread.d.ts.map +1 -1
- package/dist/react/components/CommentThread.js +25 -11
- package/dist/react/components/CommentThread.js.map +1 -1
- package/dist/react/components/DatePicker.d.ts +9 -5
- package/dist/react/components/DatePicker.d.ts.map +1 -1
- package/dist/react/components/DatePicker.js +192 -27
- package/dist/react/components/DatePicker.js.map +1 -1
- package/dist/react/components/InlineEditableText.d.ts +12 -2
- package/dist/react/components/InlineEditableText.d.ts.map +1 -1
- package/dist/react/components/InlineEditableText.js +11 -8
- package/dist/react/components/InlineEditableText.js.map +1 -1
- package/dist/react/components/VoiceNote.d.ts +20 -0
- package/dist/react/components/VoiceNote.d.ts.map +1 -0
- package/dist/react/components/VoiceNote.js +54 -0
- package/dist/react/components/VoiceNote.js.map +1 -0
- package/dist/react/components/VoiceRecorder.d.ts +35 -0
- package/dist/react/components/VoiceRecorder.d.ts.map +1 -0
- package/dist/react/components/VoiceRecorder.js +155 -0
- package/dist/react/components/VoiceRecorder.js.map +1 -0
- package/dist/react/components/suggestionList.js +2 -2
- package/dist/react/components/suggestionList.js.map +1 -1
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/lib/dateText.d.ts +21 -0
- package/dist/react/lib/dateText.d.ts.map +1 -0
- package/dist/react/lib/dateText.js +94 -0
- package/dist/react/lib/dateText.js.map +1 -0
- package/dist/react/lib/floatingStyles.d.ts +12 -0
- package/dist/react/lib/floatingStyles.d.ts.map +1 -1
- package/dist/react/lib/floatingStyles.js +12 -0
- package/dist/react/lib/floatingStyles.js.map +1 -1
- package/dist/react/map-frame/MapFrame.d.ts +219 -0
- package/dist/react/map-frame/MapFrame.d.ts.map +1 -0
- package/dist/react/map-frame/MapFrame.js +726 -0
- package/dist/react/map-frame/MapFrame.js.map +1 -0
- package/dist/react/map-frame/geo.d.ts +210 -0
- package/dist/react/map-frame/geo.d.ts.map +1 -0
- package/dist/react/map-frame/geo.js +345 -0
- package/dist/react/map-frame/geo.js.map +1 -0
- package/dist/react/map-frame/index.d.ts +5 -0
- package/dist/react/map-frame/index.d.ts.map +1 -0
- package/dist/react/map-frame/index.js +3 -0
- package/dist/react/map-frame/index.js.map +1 -0
- package/dist/styles-areas/analytics.css +11 -10
- package/dist/styles-areas/canvas-hud.css +5 -5
- package/dist/styles-areas/data-table.css +13 -12
- package/dist/styles-areas/fields.css +12 -10
- package/dist/styles-areas/stats.css +12 -11
- package/dist/styles-areas/wizard.css +6 -6
- package/dist/styles-areas/workbench.css +17 -17
- package/dist/styles-utilities.css +15 -0
- package/package.json +13 -1
- package/scripts/guardrails-baseline.json +1 -1
- package/scripts/styleAreas.ts +1 -1
- package/src/react/components/AppShell.spec.tsx +53 -0
- package/src/react/components/AppShell.tsx +79 -23
- package/src/react/components/ComboboxField.tsx +2 -2
- package/src/react/components/CommentThread.spec.tsx +25 -0
- package/src/react/components/CommentThread.tsx +60 -10
- package/src/react/components/ControlHeightScale.spec.tsx +2 -2
- package/src/react/components/DatePicker.spec.tsx +186 -5
- package/src/react/components/DatePicker.tsx +416 -63
- package/src/react/components/InlineEditableText.spec.tsx +29 -0
- package/src/react/components/InlineEditableText.tsx +26 -10
- package/src/react/components/VoiceNote.tsx +92 -0
- package/src/react/components/VoiceRecorder.spec.tsx +116 -0
- package/src/react/components/VoiceRecorder.tsx +224 -0
- package/src/react/components/suggestionList.tsx +2 -2
- package/src/react/index.ts +9 -0
- package/src/react/lib/dateText.ts +94 -0
- package/src/react/lib/floatingStyles.spec.ts +36 -1
- package/src/react/lib/floatingStyles.ts +13 -0
- package/src/react/map-frame/MapFrame.spec.ts +168 -0
- package/src/react/map-frame/MapFrame.tsx +954 -0
- package/src/react/map-frame/geo.spec.ts +393 -0
- package/src/react/map-frame/geo.ts +421 -0
- package/src/react/map-frame/index.ts +34 -0
- package/src/react/media/HoverScrubVideoThumb.spec.tsx +4 -0
- package/src/styles-areas/analytics.css +11 -10
- package/src/styles-areas/canvas-hud.css +5 -5
- package/src/styles-areas/data-table.css +13 -12
- package/src/styles-areas/fields.css +12 -10
- package/src/styles-areas/stats.css +12 -11
- package/src/styles-areas/wizard.css +6 -6
- package/src/styles-areas/workbench.css +17 -17
- package/src/styles-utilities.css +15 -0
|
@@ -1,33 +1,160 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { DayPicker } from '@daypicker/react';
|
|
3
|
-
import { Calendar } from 'lucide-react';
|
|
4
|
-
import { useState } from 'react';
|
|
3
|
+
import { Calendar, ChevronDown, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, } from 'lucide-react';
|
|
4
|
+
import { useEffect, useId, useState } from 'react';
|
|
5
5
|
import { useMediaQuery } from '../hooks/useMediaQuery.js';
|
|
6
6
|
import { cn } from '../lib/cn.js';
|
|
7
|
+
import { RAW_BUTTON } from '../lib/cn.js';
|
|
8
|
+
import { TAP_TARGET_HEIGHT } from '../lib/tapTarget.js';
|
|
9
|
+
import { parseDateText } from '../lib/dateText.js';
|
|
7
10
|
import { DAY_PICKER_CLASS_NAMES, DayPickerChevron, formatDateDisplay, isoToLocalDate, localDateToIso, ThemedDayButton, } from '../lib/daypicker.js';
|
|
8
|
-
import { declareFieldWidth
|
|
11
|
+
import { declareFieldWidth } from '../lib/field.js';
|
|
9
12
|
import { Drawer } from './Drawer.js';
|
|
13
|
+
import { Button } from './Button.js';
|
|
14
|
+
import { IconButton } from './IconButton.js';
|
|
15
|
+
import { Input } from './Input.js';
|
|
10
16
|
import { Popover } from './Popover.js';
|
|
11
|
-
import {
|
|
17
|
+
import { ScrollArea } from './ScrollArea.js';
|
|
18
|
+
const monthStart = (d) => new Date(d.getFullYear(), d.getMonth(), 1);
|
|
19
|
+
const addMonths = (d, n) => new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
20
|
+
/** Keep a month inside the [min, max] months, if given. */
|
|
21
|
+
function clampMonth(d, min, max) {
|
|
22
|
+
const first = monthStart(d);
|
|
23
|
+
if (min && first < monthStart(min))
|
|
24
|
+
return monthStart(min);
|
|
25
|
+
if (max && first > monthStart(max))
|
|
26
|
+
return monthStart(max);
|
|
27
|
+
return first;
|
|
28
|
+
}
|
|
29
|
+
const sameMonth = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
30
|
+
const CHOOSER_BUTTON = `flex h-[var(--control-h-sm)] ${TAP_TARGET_HEIGHT} w-full items-center justify-center rounded-md text-sm transition-colors hover:bg-accent/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent disabled:pointer-events-none disabled:opacity-30`;
|
|
31
|
+
const CHOOSER_SELECTED = 'bg-accent-solid text-white hover:bg-accent-solid-hover';
|
|
32
|
+
/** One cell of the year / month chooser grids. */
|
|
33
|
+
function ChooserCell({ current, disabled, tall, label, onPick, children, }) {
|
|
34
|
+
return (_jsx("button", {
|
|
35
|
+
// guardrails-ignore no-raw-action-button: task 3764 — a cell in the year/month chooser grid, a
|
|
36
|
+
// presentational selection like ThemedDayButton (STANDARDS.md §4a carve-out).
|
|
37
|
+
type: 'button', disabled: disabled, "aria-current": current ? 'date' : undefined, "aria-label": label, ref: (el) => {
|
|
38
|
+
// Bring the viewed year into view in the scrolling year grid.
|
|
39
|
+
if (el && current)
|
|
40
|
+
el.scrollIntoView?.({ block: 'center' });
|
|
41
|
+
}, className: cn(RAW_BUTTON, CHOOSER_BUTTON, tall && 'h-[var(--control-h-lg)]', current && CHOOSER_SELECTED), onClick: onPick, children: children }));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The calendar body: month + year steppers, a caption that opens a year/month chooser, and
|
|
45
|
+
* the day grid. PageUp/PageDown (month) and Shift+PageUp/PageDown (year) are DayPicker's own,
|
|
46
|
+
* per the WAI-ARIA date-picker dialog pattern; the month is controlled here so the steppers,
|
|
47
|
+
* the chooser and the keys all move the same view.
|
|
48
|
+
*/
|
|
49
|
+
function DatePickerCalendar({ selected, month, onMonthChange, onSelect, minDate, maxDate, }) {
|
|
50
|
+
const [view, setView] = useState('days');
|
|
51
|
+
const [chosenYear, setChosenYear] = useState(month.getFullYear());
|
|
52
|
+
const disabledMatchers = [];
|
|
53
|
+
if (minDate)
|
|
54
|
+
disabledMatchers.push({ before: minDate });
|
|
55
|
+
if (maxDate)
|
|
56
|
+
disabledMatchers.push({ after: maxDate });
|
|
57
|
+
const step = (months) => onMonthChange(clampMonth(addMonths(month, months), minDate, maxDate));
|
|
58
|
+
const stepDisabled = (months) => sameMonth(clampMonth(addMonths(month, months), minDate, maxDate), month);
|
|
59
|
+
if (view === 'years') {
|
|
60
|
+
const thisYear = new Date().getFullYear();
|
|
61
|
+
const first = minDate ? minDate.getFullYear() : Math.min(1900, month.getFullYear());
|
|
62
|
+
const last = maxDate ? maxDate.getFullYear() : Math.max(thisYear + 30, month.getFullYear());
|
|
63
|
+
const years = Array.from({ length: last - first + 1 }, (_, i) => first + i);
|
|
64
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: `flex h-[var(--control-h-lg)] ${TAP_TARGET_HEIGHT} items-center gap-1 pb-1`, children: [_jsx(IconButton, { label: 'Back to calendar', size: 'sm', onClick: () => setView('days'), children: _jsx(ChevronLeft, {}) }), _jsx("span", { className: 'flex-1 text-center text-sm font-semibold', children: "Choose a year" }), _jsx("span", { className: 'w-[var(--control-h-sm)]', "aria-hidden": true })] }), _jsx(ScrollArea, { className: 'max-h-60', space: 'none', safeArea: false, children: _jsx("fieldset", { "aria-label": 'Year', className: 'm-0 grid min-w-0 grid-cols-4 gap-1 border-0 p-0', children: years.map((year) => {
|
|
65
|
+
const isCurrent = year === month.getFullYear();
|
|
66
|
+
return (_jsx(ChooserCell, { current: isCurrent, onPick: () => {
|
|
67
|
+
setChosenYear(year);
|
|
68
|
+
setView('months');
|
|
69
|
+
}, children: year }, year));
|
|
70
|
+
}) }) })] }));
|
|
71
|
+
}
|
|
72
|
+
if (view === 'months') {
|
|
73
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: `flex h-[var(--control-h-lg)] ${TAP_TARGET_HEIGHT} items-center gap-1 pb-1`, children: [_jsx(IconButton, { label: 'Choose another year', size: 'sm', onClick: () => setView('years'), children: _jsx(ChevronLeft, {}) }), _jsx("span", { className: 'flex-1 text-center text-sm font-semibold', children: chosenYear }), _jsx("span", { className: 'w-[var(--control-h-sm)]', "aria-hidden": true })] }), _jsx("fieldset", { "aria-label": 'Month', className: 'm-0 grid min-w-0 grid-cols-3 gap-1 border-0 p-0', children: Array.from({ length: 12 }, (_, i) => {
|
|
74
|
+
const start = new Date(chosenYear, i, 1);
|
|
75
|
+
const outOfRange = (minDate !== undefined && start < monthStart(minDate)) ||
|
|
76
|
+
(maxDate !== undefined && start > monthStart(maxDate));
|
|
77
|
+
const isCurrent = sameMonth(start, month);
|
|
78
|
+
return (_jsx(ChooserCell, { current: isCurrent, disabled: outOfRange, tall: true, label: start.toLocaleDateString(undefined, { month: 'long', year: 'numeric' }), onPick: () => {
|
|
79
|
+
onMonthChange(start);
|
|
80
|
+
setView('days');
|
|
81
|
+
}, children: start.toLocaleDateString(undefined, { month: 'short' }) }, start.getTime()));
|
|
82
|
+
}) })] }));
|
|
83
|
+
}
|
|
84
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: 'flex items-center gap-0.5 pb-1', children: [_jsx(IconButton, { label: 'Previous year', size: 'sm', disabled: stepDisabled(-12), onClick: () => step(-12), children: _jsx(ChevronsLeft, {}) }), _jsx(IconButton, { label: 'Previous month', size: 'sm', disabled: stepDisabled(-1), onClick: () => step(-1), children: _jsx(ChevronLeft, {}) }), _jsxs(Button, { variant: 'ghost', size: 'sm', tooltip: 'Choose month and year', "aria-haspopup": 'dialog', "aria-label": `${month.toLocaleDateString(undefined, { month: 'long', year: 'numeric' })}, choose month and year`, className: `min-w-0 flex-1 gap-1 font-semibold ${TAP_TARGET_HEIGHT}`, onClick: () => {
|
|
85
|
+
setChosenYear(month.getFullYear());
|
|
86
|
+
setView('years');
|
|
87
|
+
}, children: [_jsx("span", { className: 'truncate', children: month.toLocaleDateString(undefined, { month: 'long', year: 'numeric' }) }), _jsx(ChevronDown, { className: 'h-3.5 w-3.5 shrink-0 opacity-60' })] }), _jsx(IconButton, { label: 'Next month', size: 'sm', disabled: stepDisabled(1), onClick: () => step(1), children: _jsx(ChevronRight, {}) }), _jsx(IconButton, { label: 'Next year', size: 'sm', disabled: stepDisabled(12), onClick: () => step(12), children: _jsx(ChevronsRight, {}) })] }), _jsx(DayPicker, { mode: 'single', selected: selected, onSelect: onSelect, month: month, onMonthChange: (next) => onMonthChange(clampMonth(next, minDate, maxDate)), hideNavigation: true, classNames: { ...DAY_PICKER_CLASS_NAMES, month_caption: 'hidden' }, components: { DayButton: ThemedDayButton, Chevron: DayPickerChevron }, disabled: disabledMatchers.length > 0 ? disabledMatchers : undefined, startMonth: minDate, endMonth: maxDate })] }));
|
|
88
|
+
}
|
|
12
89
|
/**
|
|
13
|
-
* Token-themed date picker on `@daypicker/react`.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
90
|
+
* Token-themed date picker on `@daypicker/react`. The field is a text input a person can
|
|
91
|
+
* TYPE a date into (`2015-12-05`, `12/5/2015`, `Dec 5 2015`, `December 5, 2015`, `5 Dec
|
|
92
|
+
* 2015`; a two-digit year reads as the nearest sensible century), normalized to ISO on
|
|
93
|
+
* blur or Enter — and a calendar button beside it opens a popover on desktop or a bottom
|
|
94
|
+
* sheet on mobile (<640 px). In the calendar the month AND year step with buttons, the
|
|
95
|
+
* caption opens a year/month chooser, and PageUp/PageDown (Shift for a year) move the view.
|
|
17
96
|
*
|
|
18
97
|
* Value is an ISO date string (`'YYYY-MM-DD'`), matching what a native date
|
|
19
|
-
* input produces, so it's drop-in compatible with existing RHF form schemas.
|
|
98
|
+
* input produces, so it's drop-in compatible with existing RHF form schemas. Typed text that
|
|
99
|
+
* does not parse, or falls outside `min`/`max`, never reaches `onChange`: the field turns
|
|
100
|
+
* invalid with a short reason, and Escape restores the last good value.
|
|
20
101
|
*/
|
|
21
102
|
export function DatePicker({ value, onChange, onBlur, placeholder = 'Pick a date', disabled, id, name, min, max, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, size = 'md', ...rest }) {
|
|
22
103
|
const [open, setOpen] = useState(false);
|
|
23
104
|
const isMobile = useMediaQuery('(max-width: 639px)');
|
|
105
|
+
const [anchor, setAnchor] = useState(null);
|
|
106
|
+
const errorId = useId();
|
|
24
107
|
const selectedDate = value ? isoToLocalDate(value) : undefined;
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
108
|
+
const minDate = min ? isoToLocalDate(min) : undefined;
|
|
109
|
+
const maxDate = max ? isoToLocalDate(max) : undefined;
|
|
110
|
+
// The text being typed, or null while the field just shows the value.
|
|
111
|
+
const [draft, setDraft] = useState(null);
|
|
112
|
+
const [error, setError] = useState(null);
|
|
113
|
+
const [month, setMonth] = useState(() => clampMonth(selectedDate ?? new Date(), minDate, maxDate));
|
|
114
|
+
// A new value from outside (or a pick in the calendar) replaces whatever was being typed
|
|
115
|
+
// and moves the calendar's view to it. min/max only bound the clamp: the view moves when the
|
|
116
|
+
// value does, so they stay out of the dependency list.
|
|
117
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: see above
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
setDraft(null);
|
|
120
|
+
setError(null);
|
|
121
|
+
if (value)
|
|
122
|
+
setMonth(clampMonth(isoToLocalDate(value), minDate, maxDate));
|
|
123
|
+
}, [value]);
|
|
124
|
+
const display = selectedDate ? formatDateDisplay(selectedDate) : '';
|
|
125
|
+
const inputText = draft ?? display;
|
|
126
|
+
const refuse = (reason) => {
|
|
127
|
+
setError(reason);
|
|
128
|
+
return false;
|
|
129
|
+
};
|
|
130
|
+
/** Parse the draft; on success call onChange once and return to the display form. */
|
|
131
|
+
const commitDraft = () => {
|
|
132
|
+
if (draft === null)
|
|
133
|
+
return true;
|
|
134
|
+
if (draft.trim() === '') {
|
|
135
|
+
setDraft(null);
|
|
136
|
+
setError(null);
|
|
137
|
+
if (value)
|
|
138
|
+
onChange?.(undefined);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
const parsed = parseDateText(draft);
|
|
142
|
+
if (!parsed.ok)
|
|
143
|
+
return refuse(parsed.reason);
|
|
144
|
+
const date = isoToLocalDate(parsed.iso);
|
|
145
|
+
if (minDate && date < minDate) {
|
|
146
|
+
return refuse(`Pick a date on or after ${formatDateDisplay(minDate)}`);
|
|
147
|
+
}
|
|
148
|
+
if (maxDate && date > maxDate) {
|
|
149
|
+
return refuse(`Pick a date on or before ${formatDateDisplay(maxDate)}`);
|
|
150
|
+
}
|
|
151
|
+
setDraft(null);
|
|
152
|
+
setError(null);
|
|
153
|
+
setMonth(clampMonth(date, minDate, maxDate));
|
|
154
|
+
if (parsed.iso !== value)
|
|
155
|
+
onChange?.(parsed.iso);
|
|
156
|
+
return true;
|
|
157
|
+
};
|
|
31
158
|
const handleSelect = (date) => {
|
|
32
159
|
onChange?.(date ? localDateToIso(date) : undefined);
|
|
33
160
|
setOpen(false);
|
|
@@ -35,21 +162,59 @@ export function DatePicker({ value, onChange, onBlur, placeholder = 'Pick a date
|
|
|
35
162
|
};
|
|
36
163
|
const handleOpenChange = (next) => {
|
|
37
164
|
setOpen(next);
|
|
38
|
-
if (
|
|
165
|
+
if (next) {
|
|
166
|
+
// Open on the typed date when the text is valid, else on the value.
|
|
167
|
+
setMonth(clampMonth(selectedDate ?? new Date(), minDate, maxDate));
|
|
168
|
+
}
|
|
169
|
+
else
|
|
39
170
|
onBlur?.();
|
|
40
171
|
};
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
172
|
+
const openCalendar = () => {
|
|
173
|
+
if (disabled)
|
|
174
|
+
return;
|
|
175
|
+
if (draft !== null) {
|
|
176
|
+
const parsed = parseDateText(draft);
|
|
177
|
+
if (parsed.ok)
|
|
178
|
+
setMonth(clampMonth(isoToLocalDate(parsed.iso), minDate, maxDate));
|
|
179
|
+
}
|
|
180
|
+
setOpen(true);
|
|
181
|
+
};
|
|
182
|
+
const invalid = ariaInvalid || error !== null ? true : undefined;
|
|
183
|
+
const describedBy = [ariaDescribedBy, error ? errorId : undefined].filter(Boolean).join(' ');
|
|
184
|
+
const field = (_jsxs("div", { ref: setAnchor, className: 'relative w-full', children: [_jsx(Input, { ...rest, type: 'text', maxLength: 64, size: size, id: id, name: name, disabled: disabled, autoComplete: 'off', spellCheck: false, value: inputText, placeholder: placeholder, "aria-invalid": invalid, "aria-describedby": describedBy || undefined, onFocus: (e) => e.currentTarget.select(), onChange: (e) => {
|
|
185
|
+
setDraft(e.target.value);
|
|
186
|
+
setError(null);
|
|
187
|
+
}, onKeyDown: (e) => {
|
|
188
|
+
if (e.key === 'Enter') {
|
|
189
|
+
e.preventDefault();
|
|
190
|
+
commitDraft();
|
|
191
|
+
}
|
|
192
|
+
else if (e.key === 'Escape' && (draft !== null || error !== null)) {
|
|
193
|
+
e.preventDefault();
|
|
194
|
+
e.stopPropagation();
|
|
195
|
+
setDraft(null);
|
|
196
|
+
setError(null);
|
|
197
|
+
}
|
|
198
|
+
else if (e.key === 'ArrowDown' && e.altKey) {
|
|
199
|
+
e.preventDefault();
|
|
200
|
+
openCalendar();
|
|
201
|
+
}
|
|
202
|
+
}, onBlur: (e) => {
|
|
203
|
+
commitDraft();
|
|
204
|
+
// Focus moving to the calendar button (or into its panel) is not the field being left.
|
|
205
|
+
const next = e.relatedTarget;
|
|
206
|
+
if (!open && !(next && anchor?.contains(next)))
|
|
207
|
+
onBlur?.();
|
|
208
|
+
}, className: 'pr-11 pointer-coarse:pr-12' }), _jsx(IconButton, { size: size, label: selectedDate ? `Change date, ${display}` : placeholder, disabled: disabled, "aria-haspopup": 'dialog', "aria-expanded": open, onClick: () => (open ? handleOpenChange(false) : openCalendar()), className: 'absolute right-0 top-0 text-muted-foreground hover:text-foreground', children: _jsx(Calendar, { className: 'opacity-70' }) })] }));
|
|
209
|
+
const message = error ? (_jsx("p", { id: errorId, role: 'alert', className: 'mt-1 text-xs text-field-error', children: error })) : null;
|
|
210
|
+
const calendar = (_jsx(DatePickerCalendar, { selected: selectedDate, month: month, onMonthChange: setMonth, onSelect: handleSelect, minDate: minDate, maxDate: maxDate }));
|
|
49
211
|
if (isMobile) {
|
|
50
|
-
return (_jsxs(
|
|
212
|
+
return (_jsxs("div", { className: 'w-full', children: [field, message, _jsx(Drawer, { open: open, onClose: () => handleOpenChange(false), side: 'bottom', size: 'md', children: _jsx("div", { className: 'flex justify-center py-2', children: calendar }) })] }));
|
|
51
213
|
}
|
|
52
|
-
return (_jsx(Popover, {
|
|
214
|
+
return (_jsxs("div", { className: 'w-full', children: [field, message, _jsx(Popover, { anchor: anchor, open: open, onOpenChange: handleOpenChange, align: 'start', arrow: false,
|
|
215
|
+
// 🔴 Wide enough for the longest caption beside its four steppers: at 296 "September 2026"
|
|
216
|
+
// truncated to "September 20…" (photos' lightbox, forge task 3764). 320 still fits a 390px phone.
|
|
217
|
+
width: 320, children: calendar })] }));
|
|
53
218
|
}
|
|
54
219
|
declareFieldWidth(DatePicker, 'sm');
|
|
55
220
|
//# sourceMappingURL=DatePicker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.js","sourceRoot":"","sources":["../../../src/react/components/DatePicker.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DatePicker.js","sourceRoot":"","sources":["../../../src/react/components/DatePicker.tsx"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,16 @@ export interface InlineEditableTextProps {
|
|
|
27
27
|
* edit needs a separate, explicit affordance.
|
|
28
28
|
*/
|
|
29
29
|
trigger?: 'text' | 'icon';
|
|
30
|
+
/**
|
|
31
|
+
* Where the caret lands when editing starts (default `'select-all'`):
|
|
32
|
+
* - `'select-all'` — the whole value is selected, so typing replaces it (a title, a name).
|
|
33
|
+
* - `'end'` — the caret goes after the last character and nothing is selected; for
|
|
34
|
+
* paragraphs someone ADDS to (notes, a description), where one stray keystroke
|
|
35
|
+
* would otherwise replace everything they wrote.
|
|
36
|
+
*/
|
|
37
|
+
caret?: 'select-all' | 'end';
|
|
38
|
+
/** The editor's character ceiling (default 10,000) — the server's limit, so the editor stops where a save would be refused. */
|
|
39
|
+
maxLength?: number;
|
|
30
40
|
ariaLabel?: string;
|
|
31
41
|
}
|
|
32
42
|
/**
|
|
@@ -35,7 +45,7 @@ export interface InlineEditableTextProps {
|
|
|
35
45
|
* primitive, used anywhere a title/heading should be edited in place. Fully
|
|
36
46
|
* token-driven (accent border + ring on the editor); the editor focuses and
|
|
37
47
|
* selects its text on mount so typing replaces (and the cursor is never stranded
|
|
38
|
-
* at position 0).
|
|
48
|
+
* at position 0) — or, with `caret='end'`, puts the caret after the text.
|
|
39
49
|
*/
|
|
40
|
-
export declare function InlineEditableText({ value, onChange, canEdit, multiline, placeholder, className, inputClassName, trigger, wrap, ariaLabel, ...rest }: InlineEditableTextProps): import("react").JSX.Element | null;
|
|
50
|
+
export declare function InlineEditableText({ value, onChange, canEdit, multiline, placeholder, className, inputClassName, trigger, wrap, caret, maxLength, ariaLabel, ...rest }: InlineEditableTextProps): import("react").JSX.Element | null;
|
|
41
51
|
//# sourceMappingURL=InlineEditableText.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InlineEditableText.d.ts","sourceRoot":"","sources":["../../../src/react/components/InlineEditableText.tsx"],"names":[],"mappings":"AAUA,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;gEAC4D;IAC5D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;gEAC4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;sDAGkD;IAClD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,OAAc,EACd,SAAiB,EACjB,WAAyB,EACzB,SAAS,EACT,cAAc,EACd,OAAgB,EAChB,IAAW,EACX,SAAS,EACT,GAAG,IAAI,EACR,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"InlineEditableText.d.ts","sourceRoot":"","sources":["../../../src/react/components/InlineEditableText.tsx"],"names":[],"mappings":"AAUA,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;gEAC4D;IAC5D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;gEAC4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;sDAGkD;IAClD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7B,+HAA+H;IAC/H,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,OAAc,EACd,SAAiB,EACjB,WAAyB,EACzB,SAAS,EACT,cAAc,EACd,OAAgB,EAChB,IAAW,EACX,KAAoB,EACpB,SAAkB,EAClB,SAAS,EACT,GAAG,IAAI,EACR,EAAE,uBAAuB,sCAgJzB"}
|
|
@@ -14,9 +14,9 @@ import { RAW_BUTTON } from '../lib/cn.js';
|
|
|
14
14
|
* primitive, used anywhere a title/heading should be edited in place. Fully
|
|
15
15
|
* token-driven (accent border + ring on the editor); the editor focuses and
|
|
16
16
|
* selects its text on mount so typing replaces (and the cursor is never stranded
|
|
17
|
-
* at position 0).
|
|
17
|
+
* at position 0) — or, with `caret='end'`, puts the caret after the text.
|
|
18
18
|
*/
|
|
19
|
-
export function InlineEditableText({ value, onChange, canEdit = true, multiline = false, placeholder = 'Add text…', className, inputClassName, trigger = 'text', wrap = true, ariaLabel, ...rest }) {
|
|
19
|
+
export function InlineEditableText({ value, onChange, canEdit = true, multiline = false, placeholder = 'Add text…', className, inputClassName, trigger = 'text', wrap = true, caret = 'select-all', maxLength = 10_000, ariaLabel, ...rest }) {
|
|
20
20
|
const [editing, setEditing] = useState(false);
|
|
21
21
|
const [draft, setDraft] = useState(value);
|
|
22
22
|
const begin = () => {
|
|
@@ -35,20 +35,23 @@ export function InlineEditableText({ value, onChange, canEdit = true, multiline
|
|
|
35
35
|
setDraft(value);
|
|
36
36
|
setEditing(false);
|
|
37
37
|
};
|
|
38
|
-
// Focus + select-all as soon as the editor mounts (it only renders while
|
|
39
|
-
// MUST be identity-stable: an inline ref callback gets detached/re-attached on every
|
|
38
|
+
// Focus + select-all (or caret-at-end) as soon as the editor mounts (it only renders while
|
|
39
|
+
// editing). MUST be identity-stable: an inline ref callback gets detached/re-attached on every
|
|
40
40
|
// render, so each keystroke's setDraft re-render would re-run el.select() and the next
|
|
41
41
|
// character would replace everything typed so far (one-character-survives bug).
|
|
42
42
|
const focusOnMount = useCallback((el) => {
|
|
43
43
|
if (!el)
|
|
44
44
|
return;
|
|
45
45
|
el.focus();
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
if (caret === 'end')
|
|
47
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
48
|
+
else
|
|
49
|
+
el.select();
|
|
50
|
+
}, [caret]);
|
|
48
51
|
if (editing) {
|
|
49
52
|
const editorClass = cn('block w-full rounded-sm border border-accent bg-surface px-1 -mx-1 text-foreground outline-none ring-2 ring-accent/30', className, inputClassName);
|
|
50
53
|
if (multiline) {
|
|
51
|
-
return (_jsx(AutoGrowTextarea, { ...rest, ref: focusOnMount, "aria-label": ariaLabel, className: cn(editorClass, 'resize-none'), maxLength:
|
|
54
|
+
return (_jsx(AutoGrowTextarea, { ...rest, ref: focusOnMount, "aria-label": ariaLabel, className: cn(editorClass, 'resize-none'), maxLength: maxLength, value: draft, onChange: (e) => setDraft(e.target.value), onBlur: commit, onKeyDown: (e) => {
|
|
52
55
|
if (e.key === 'Escape') {
|
|
53
56
|
// Escape cancels THIS edit only — never bubbles on to close a
|
|
54
57
|
// surrounding Modal/Drawer in the same keystroke.
|
|
@@ -59,7 +62,7 @@ export function InlineEditableText({ value, onChange, canEdit = true, multiline
|
|
|
59
62
|
commit();
|
|
60
63
|
} }));
|
|
61
64
|
}
|
|
62
|
-
return (_jsx(Input, { ...rest, ref: focusOnMount, "aria-label": ariaLabel, className: editorClass, maxLength:
|
|
65
|
+
return (_jsx(Input, { ...rest, ref: focusOnMount, "aria-label": ariaLabel, className: editorClass, maxLength: maxLength, value: draft, onChange: (e) => setDraft(e.target.value), onBlur: commit, onKeyDown: (e) => {
|
|
63
66
|
if (e.key === 'Escape') {
|
|
64
67
|
// Escape cancels THIS edit only — never bubbles on to close a
|
|
65
68
|
// surrounding Modal/Drawer in the same keystroke.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InlineEditableText.js","sourceRoot":"","sources":["../../../src/react/components/InlineEditableText.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"InlineEditableText.js","sourceRoot":"","sources":["../../../src/react/components/InlineEditableText.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** `m:ss` — a voice note is minutes long at most. */
|
|
2
|
+
export declare function formatVoiceTime(ms: number): string;
|
|
3
|
+
export interface VoiceNoteProps {
|
|
4
|
+
/** The audio's URL — a signed media URL, or an object URL for a recording not yet sent. */
|
|
5
|
+
src: string;
|
|
6
|
+
/** The length when the caller already knows it; otherwise the element's own metadata says. */
|
|
7
|
+
durationMs?: number;
|
|
8
|
+
/** What the play button names: "Play voice comment by Alice". */
|
|
9
|
+
label?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A voice note: play/pause, a seek track and the time — the compact pill a message thread draws
|
|
14
|
+
* (iMessage, WhatsApp, Slack huddles), not the browser's own `<audio controls>`, whose look and
|
|
15
|
+
* height differ in every engine and which ignores the theme.
|
|
16
|
+
*
|
|
17
|
+
* `preload='metadata'`: a thread of ten notes fetches ten headers, not ten files.
|
|
18
|
+
*/
|
|
19
|
+
export declare function VoiceNote({ src, durationMs, label, className, ...rest }: VoiceNoteProps): import("react").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=VoiceNote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceNote.d.ts","sourceRoot":"","sources":["../../../src/react/components/VoiceNote.tsx"],"names":[],"mappings":"AAKA,qDAAqD;AACrD,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED,MAAM,WAAW,cAAc;IAC7B,2FAA2F;IAC3F,GAAG,EAAE,MAAM,CAAC;IACZ,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAyB,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,cAAc,+BA+D3G"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Pause, Play } from 'lucide-react';
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { cn } from '../lib/cn.js';
|
|
5
|
+
import { IconButton } from './IconButton.js';
|
|
6
|
+
/** `m:ss` — a voice note is minutes long at most. */
|
|
7
|
+
export function formatVoiceTime(ms) {
|
|
8
|
+
const s = Math.max(0, Math.floor(ms / 1000));
|
|
9
|
+
return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A voice note: play/pause, a seek track and the time — the compact pill a message thread draws
|
|
13
|
+
* (iMessage, WhatsApp, Slack huddles), not the browser's own `<audio controls>`, whose look and
|
|
14
|
+
* height differ in every engine and which ignores the theme.
|
|
15
|
+
*
|
|
16
|
+
* `preload='metadata'`: a thread of ten notes fetches ten headers, not ten files.
|
|
17
|
+
*/
|
|
18
|
+
export function VoiceNote({ src, durationMs, label = 'Play voice note', className, ...rest }) {
|
|
19
|
+
const audio = useRef(null);
|
|
20
|
+
const [playing, setPlaying] = useState(false);
|
|
21
|
+
const [at, setAt] = useState(0);
|
|
22
|
+
const [length, setLength] = useState(durationMs ?? 0);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (durationMs)
|
|
25
|
+
setLength(durationMs);
|
|
26
|
+
}, [durationMs]);
|
|
27
|
+
const toggle = () => {
|
|
28
|
+
const el = audio.current;
|
|
29
|
+
if (!el)
|
|
30
|
+
return;
|
|
31
|
+
if (el.paused)
|
|
32
|
+
void el.play().catch(() => setPlaying(false));
|
|
33
|
+
else
|
|
34
|
+
el.pause();
|
|
35
|
+
};
|
|
36
|
+
return (_jsxs("div", { ...rest, "data-cb-voice-note": '', className: cn('flex min-w-0 items-center gap-2', className), children: [_jsx("audio", { ref: audio, src: src, preload: 'metadata', onPlay: () => setPlaying(true), onPause: () => setPlaying(false), onEnded: () => {
|
|
37
|
+
setPlaying(false);
|
|
38
|
+
setAt(0);
|
|
39
|
+
}, onTimeUpdate: (e) => setAt(e.currentTarget.currentTime * 1000), onLoadedMetadata: (e) => {
|
|
40
|
+
// A MediaRecorder WebM says `Infinity` until it has been read through; keep the caller's.
|
|
41
|
+
const d = e.currentTarget.duration;
|
|
42
|
+
if (Number.isFinite(d) && d > 0)
|
|
43
|
+
setLength(d * 1000);
|
|
44
|
+
} }), _jsx(IconButton, { label: playing ? 'Pause' : label, size: 'sm', variant: 'secondary', className: 'shrink-0 rounded-full', onClick: toggle, children: playing ? _jsx(Pause, {}) : _jsx(Play, {}) }), _jsx("input", {
|
|
45
|
+
// guardrails-ignore no-raw-inputs: perf — a voice note's own seek track (type=range), not a form
|
|
46
|
+
// field — the native range keeps Radix's slider (~6 kB gzip) out of every comment thread.
|
|
47
|
+
type: 'range', "aria-label": 'Position', "aria-valuetext": formatVoiceTime(at), min: 0, max: Math.max(1, length), step: 100, value: Math.min(at, Math.max(1, length)), disabled: !length, onChange: (e) => {
|
|
48
|
+
const v = Number(e.target.value);
|
|
49
|
+
setAt(v);
|
|
50
|
+
if (audio.current)
|
|
51
|
+
audio.current.currentTime = v / 1000;
|
|
52
|
+
}, className: 'h-1 min-w-16 flex-1 cursor-pointer accent-[var(--accent-solid)] disabled:cursor-not-allowed' }), _jsx("span", { className: 'shrink-0 text-xs tabular-nums text-muted-foreground', children: formatVoiceTime(playing || at > 0 ? at : length) })] }));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=VoiceNote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceNote.js","sourceRoot":"","sources":["../../../src/react/components/VoiceNote.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,qDAAqD;AACrD,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IAC7C,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACpE,CAAC;AAYD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,GAAG,iBAAiB,EAAE,SAAS,EAAE,GAAG,IAAI,EAAkB;IAC1G,MAAM,KAAK,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;IAEtD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU;YAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;QACzB,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,IAAI,EAAE,CAAC,MAAM;YAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;;YACxD,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CACL,kBAAS,IAAI,wBAAqB,EAAE,EAAC,SAAS,EAAE,EAAE,CAAC,iCAAiC,EAAE,SAAS,CAAC,aAE9F,gBACE,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,GAAG,EACR,OAAO,EAAC,UAAU,EAClB,MAAM,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAChC,OAAO,EAAE,GAAG,EAAE;oBACZ,UAAU,CAAC,KAAK,CAAC,CAAC;oBAClB,KAAK,CAAC,CAAC,CAAC,CAAC;gBACX,CAAC,EACD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,EAC9D,gBAAgB,EAAE,CAAC,CAAC,EAAE,EAAE;oBACtB,0FAA0F;oBAC1F,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC;oBACnC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;wBAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;gBACvD,CAAC,GACD,EACF,KAAC,UAAU,IAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,SAAS,EAAC,uBAAuB,EAAC,OAAO,EAAE,MAAM,YAC1H,OAAO,CAAC,CAAC,CAAC,KAAC,KAAK,KAAG,CAAC,CAAC,CAAC,KAAC,IAAI,KAAG,GACpB,EACb;gBACE,iGAAiG;gBACjG,0FAA0F;gBAC1F,IAAI,EAAC,OAAO,gBACD,UAAU,oBACL,eAAe,CAAC,EAAE,CAAC,EACnC,GAAG,EAAE,CAAC,EACN,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,EACxB,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EACxC,QAAQ,EAAE,CAAC,MAAM,EACjB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;oBACd,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACjC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACT,IAAI,KAAK,CAAC,OAAO;wBAAE,KAAK,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC;gBAC1D,CAAC,EACD,SAAS,EAAC,6FAA6F,GACvG,EACF,eAAM,SAAS,EAAC,qDAAqD,YAClE,eAAe,CAAC,OAAO,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAC5C,IACH,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Two minutes: a spoken memory, not a podcast. Opus at speech rates is ~0.5 MB, AAC ~2 MB. */
|
|
2
|
+
export declare const VOICE_MAX_MS = 120000;
|
|
3
|
+
/**
|
|
4
|
+
* The container a recording is written in, best first: Opus in WebM where Chromium and Firefox
|
|
5
|
+
* take it, AAC in MP4 for WebKit (Safari records no WebM). `null` when the browser records none.
|
|
6
|
+
*/
|
|
7
|
+
export declare const VOICE_MIME_CANDIDATES: readonly ["audio/webm;codecs=opus", "audio/mp4", "audio/webm", "audio/ogg;codecs=opus"];
|
|
8
|
+
export declare function pickVoiceMime(isSupported?: (type: string) => boolean): string | null;
|
|
9
|
+
export interface VoiceRecording {
|
|
10
|
+
blob: Blob;
|
|
11
|
+
/** The container without its codec parameter — `audio/webm`, `audio/mp4` — what a server keys on. */
|
|
12
|
+
mime: string;
|
|
13
|
+
durationMs: number;
|
|
14
|
+
}
|
|
15
|
+
export interface VoiceRecorderProps {
|
|
16
|
+
/** The recording, when the person sends it. */
|
|
17
|
+
onDone: (recording: VoiceRecording) => void;
|
|
18
|
+
/** Canceled, discarded, or the microphone could not be had. */
|
|
19
|
+
onCancel: () => void;
|
|
20
|
+
/** Recording stops itself here and waits to be sent or discarded. Default {@link VOICE_MAX_MS}. */
|
|
21
|
+
maxMs?: number;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Records one voice note from the microphone. It starts on mount — the person already tapped
|
|
26
|
+
* "record" to show it — and shows a running time and a level meter so they can see it hears them.
|
|
27
|
+
* **Send** stops and hands the recording over in one tap (WhatsApp's flow, not stop → review →
|
|
28
|
+
* send); **Cancel** throws it away. At `maxMs` it stops by itself and offers the take back to
|
|
29
|
+
* listen to, send or discard, rather than sending something nobody chose to send.
|
|
30
|
+
*
|
|
31
|
+
* The level meter reads an `AnalyserNode` when the browser has Web Audio; without one the
|
|
32
|
+
* meter stays dark and the recording still works.
|
|
33
|
+
*/
|
|
34
|
+
export declare function VoiceRecorder({ onDone, onCancel, maxMs, className, ...rest }: VoiceRecorderProps): import("react").JSX.Element;
|
|
35
|
+
//# sourceMappingURL=VoiceRecorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceRecorder.d.ts","sourceRoot":"","sources":["../../../src/react/components/VoiceRecorder.tsx"],"names":[],"mappings":"AAMA,+FAA+F;AAC/F,eAAO,MAAM,YAAY,SAAU,CAAC;AAEpC;;;GAGG;AACH,eAAO,MAAM,qBAAqB,yFAA0F,CAAC;AAE7H,wBAAgB,aAAa,CAC3B,WAAW,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAyF,GACvH,MAAM,GAAG,IAAI,CAEf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,IAAI,CAAC;IACX,qGAAqG;IACrG,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,MAAM,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;IAC5C,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,mGAAmG;IACnG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAoB,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,kBAAkB,+BA+J/G"}
|