@inkra/react 0.1.0 → 0.3.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/README.md +186 -1
- package/dist/PencilIcon.js +14 -16
- package/dist/PencilLine.js +18 -12
- package/dist/PencilText.js +192 -59
- package/dist/alert-dialog/index.d.ts +64 -0
- package/dist/alert-dialog/index.js +111 -0
- package/dist/audio-player/index.d.ts +60 -0
- package/dist/audio-player/index.js +101 -0
- package/dist/carousel/index.d.ts +51 -0
- package/dist/carousel/index.js +290 -0
- package/dist/choice-grid/index.d.ts +38 -0
- package/dist/choice-grid/index.js +85 -0
- package/dist/color-picker/color.d.ts +15 -0
- package/dist/color-picker/color.js +55 -0
- package/dist/color-picker/index.d.ts +31 -0
- package/dist/color-picker/index.js +69 -0
- package/dist/command/index.d.ts +45 -0
- package/dist/command/index.js +39 -0
- package/dist/context-menu/index.d.ts +76 -0
- package/dist/context-menu/index.js +241 -0
- package/dist/data-table/index.d.ts +47 -0
- package/dist/data-table/index.js +91 -0
- package/dist/date-picker/index.d.ts +50 -0
- package/dist/date-picker/index.js +180 -0
- package/dist/display/ProgressRing.d.ts +6 -0
- package/dist/display/ProgressRing.js +146 -0
- package/dist/display/index.d.ts +27 -0
- package/dist/display/index.js +18 -2
- package/dist/dockable-panel/index.d.ts +41 -0
- package/dist/dockable-panel/index.js +253 -0
- package/dist/dockable-panel/model.d.ts +21 -0
- package/dist/dockable-panel/model.js +61 -0
- package/dist/drawer/index.d.ts +63 -0
- package/dist/drawer/index.js +88 -0
- package/dist/dropdown-menu/index.d.ts +1 -1
- package/dist/dropdown-menu/index.js +3 -2
- package/dist/editable/index.d.ts +53 -0
- package/dist/editable/index.js +162 -0
- package/dist/empty/index.d.ts +21 -0
- package/dist/empty/index.js +23 -0
- package/dist/flip/index.d.ts +49 -0
- package/dist/flip/index.js +138 -0
- package/dist/form/EditablePencilText.js +188 -143
- package/dist/form/Input.js +1 -1
- package/dist/form/Textarea.d.ts +12 -0
- package/dist/form/Textarea.js +83 -4
- package/dist/form/index.d.ts +1 -1
- package/dist/heatmap/index.d.ts +59 -0
- package/dist/heatmap/index.js +248 -0
- package/dist/hotkey/index.d.ts +37 -0
- package/dist/hotkey/index.js +130 -0
- package/dist/hotkey/model.d.ts +27 -0
- package/dist/hotkey/model.js +97 -0
- package/dist/hover-card/index.d.ts +33 -0
- package/dist/hover-card/index.js +141 -0
- package/dist/image-cropper/index.d.ts +82 -0
- package/dist/image-cropper/index.js +261 -0
- package/dist/image-cropper/model.d.ts +42 -0
- package/dist/image-cropper/model.js +94 -0
- package/dist/image-viewer/index.d.ts +79 -0
- package/dist/image-viewer/index.js +220 -0
- package/dist/image-viewer/model.d.ts +9 -0
- package/dist/image-viewer/model.js +18 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +47 -0
- package/dist/input-number/index.d.ts +6 -0
- package/dist/input-number/index.js +126 -15
- package/dist/input-number/model.d.ts +13 -0
- package/dist/input-number/model.js +50 -0
- package/dist/internal/cache.d.ts +1 -1
- package/dist/internal/cache.js +1 -1
- package/dist/internal/renderTokens.d.ts +10 -0
- package/dist/internal/renderTokens.js +13 -0
- package/dist/internal/surfaceRenderer.d.ts +14 -6
- package/dist/internal/surfaceRenderer.js +15 -12
- package/dist/internal/textRenderer.d.ts +1 -0
- package/dist/internal/textRenderer.js +33 -7
- package/dist/internal/usePencilSurface.js +16 -8
- package/dist/internal/useSelectionDrawing.js +15 -11
- package/dist/journey-map/MapScale.js +3 -1
- package/dist/journey-map/index.js +3 -1
- package/dist/keypad/index.d.ts +23 -0
- package/dist/keypad/index.js +63 -0
- package/dist/keypad/model.d.ts +20 -0
- package/dist/keypad/model.js +33 -0
- package/dist/layout/index.d.ts +63 -0
- package/dist/layout/index.js +62 -0
- package/dist/log/index.d.ts +45 -0
- package/dist/log/index.js +159 -0
- package/dist/log/model.d.ts +16 -0
- package/dist/log/model.js +13 -0
- package/dist/node-graph/index.d.ts +123 -0
- package/dist/node-graph/index.js +304 -0
- package/dist/number-ticker/index.d.ts +31 -0
- package/dist/number-ticker/index.js +135 -0
- package/dist/number-ticker/model.d.ts +41 -0
- package/dist/number-ticker/model.js +163 -0
- package/dist/number-ticker/precision.d.ts +7 -0
- package/dist/number-ticker/precision.js +134 -0
- package/dist/overflow-list/index.d.ts +39 -0
- package/dist/overflow-list/index.js +230 -0
- package/dist/overflow-list/layout.d.ts +19 -0
- package/dist/overflow-list/layout.js +44 -0
- package/dist/overlay/Overlay.d.ts +1 -1
- package/dist/overlay/Overlay.js +4 -2
- package/dist/overlay/Popover.d.ts +1 -1
- package/dist/overlay/Popover.js +3 -2
- package/dist/overlay/themeBridge.d.ts +12 -1
- package/dist/overlay/themeBridge.js +27 -1
- package/dist/pagination/index.d.ts +23 -0
- package/dist/pagination/index.js +41 -0
- package/dist/pagination/model.d.ts +4 -0
- package/dist/pagination/model.js +42 -0
- package/dist/pan-zoom/index.d.ts +71 -0
- package/dist/pan-zoom/index.js +175 -0
- package/dist/radar/index.d.ts +56 -0
- package/dist/radar/index.js +220 -0
- package/dist/range-slider/index.d.ts +16 -0
- package/dist/range-slider/index.js +22 -0
- package/dist/rating/index.d.ts +28 -0
- package/dist/rating/index.js +127 -0
- package/dist/resizable/index.d.ts +32 -0
- package/dist/resizable/index.js +50 -0
- package/dist/scroll-area/index.d.ts +36 -0
- package/dist/scroll-area/index.js +44 -0
- package/dist/segmented-progress/SegmentedProgress.d.ts +17 -0
- package/dist/segmented-progress/SegmentedProgress.js +42 -0
- package/dist/slider/index.js +1 -1
- package/dist/slot/index.d.ts +24 -0
- package/dist/slot/index.js +29 -0
- package/dist/sortable/index.d.ts +50 -0
- package/dist/sortable/index.js +283 -0
- package/dist/sortable/model.d.ts +30 -0
- package/dist/sortable/model.js +64 -0
- package/dist/sparkline/index.d.ts +19 -0
- package/dist/sparkline/index.js +240 -0
- package/dist/sparkline/model.d.ts +16 -0
- package/dist/sparkline/model.js +28 -0
- package/dist/steps/index.d.ts +16 -0
- package/dist/steps/index.js +37 -0
- package/dist/styles.css +4957 -269
- package/dist/tag-input/index.d.ts +69 -0
- package/dist/tag-input/index.js +325 -0
- package/dist/tag-input/model.d.ts +14 -0
- package/dist/tag-input/model.js +38 -0
- package/dist/time-picker/index.d.ts +15 -0
- package/dist/time-picker/index.js +168 -0
- package/dist/timeline/index.d.ts +14 -0
- package/dist/timeline/index.js +16 -0
- package/dist/toast/index.d.ts +27 -0
- package/dist/toast/index.js +36 -0
- package/dist/toggle-group/index.d.ts +17 -0
- package/dist/toggle-group/index.js +26 -0
- package/dist/tokens.css +10 -9
- package/dist/tooltip/Tooltip.d.ts +1 -1
- package/dist/tooltip/Tooltip.js +3 -2
- package/dist/transfer/index.d.ts +64 -0
- package/dist/transfer/index.js +174 -0
- package/dist/transfer/model.d.ts +12 -0
- package/dist/transfer/model.js +33 -0
- package/dist/tree/index.d.ts +39 -0
- package/dist/tree/index.js +36 -0
- package/dist/tree-select/index.d.ts +59 -0
- package/dist/tree-select/index.js +142 -0
- package/dist/tree-select/model.d.ts +31 -0
- package/dist/tree-select/model.js +135 -0
- package/dist/typewriter/index.d.ts +21 -0
- package/dist/typewriter/index.js +101 -0
- package/dist/typewriter/model.d.ts +7 -0
- package/dist/typewriter/model.js +45 -0
- package/dist/upload/index.d.ts +59 -0
- package/dist/upload/index.js +230 -0
- package/dist/virtual-list/index.d.ts +44 -0
- package/dist/virtual-list/index.js +129 -0
- package/dist/virtual-list/model.d.ts +7 -0
- package/dist/virtual-list/model.js +27 -0
- package/package.json +23 -3
package/dist/PencilText.js
CHANGED
|
@@ -1,24 +1,110 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef,
|
|
2
|
+
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
|
|
3
3
|
import { useBrowserLayoutEffect } from './internal/useBrowserLayoutEffect.js';
|
|
4
4
|
import { effectiveDpr } from './internal/cache.js';
|
|
5
5
|
import { observeCanvasRecovery } from './internal/recovery.js';
|
|
6
6
|
import { seedToNumber } from './internal/random.js';
|
|
7
|
-
import { renderPencilText } from './internal/textRenderer.js';
|
|
7
|
+
import { pencilLettering, renderPencilText } from './internal/textRenderer.js';
|
|
8
|
+
import { readRenderToken } from './internal/renderTokens.js';
|
|
8
9
|
import { queueTextPaint } from './internal/textQueue.js';
|
|
9
10
|
function textSeed(text) {
|
|
10
11
|
return Array.from(text).reduce((seed, character) => Math.imul(seed ^ character.codePointAt(0), 16777619), 71) >>> 0;
|
|
11
12
|
}
|
|
12
|
-
function
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
function pixelValue(value) {
|
|
14
|
+
const parsed = Number.parseFloat(value);
|
|
15
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
16
|
+
}
|
|
17
|
+
function localBorderBox(element, style = getComputedStyle(element)) {
|
|
18
|
+
const horizontalExtras = pixelValue(style.paddingLeft) + pixelValue(style.paddingRight)
|
|
19
|
+
+ pixelValue(style.borderLeftWidth) + pixelValue(style.borderRightWidth);
|
|
20
|
+
const verticalExtras = pixelValue(style.paddingTop) + pixelValue(style.paddingBottom)
|
|
21
|
+
+ pixelValue(style.borderTopWidth) + pixelValue(style.borderBottomWidth);
|
|
22
|
+
const computedWidth = pixelValue(style.width);
|
|
23
|
+
const computedHeight = pixelValue(style.height);
|
|
24
|
+
return {
|
|
25
|
+
width: computedWidth > 0
|
|
26
|
+
? computedWidth + (style.boxSizing === 'border-box' ? 0 : horizontalExtras)
|
|
27
|
+
: element.offsetWidth,
|
|
28
|
+
height: computedHeight > 0
|
|
29
|
+
? computedHeight + (style.boxSizing === 'border-box' ? 0 : verticalExtras)
|
|
30
|
+
: element.offsetHeight,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function copyComputedStyle(source, target) {
|
|
34
|
+
for (const property of source) {
|
|
35
|
+
target.setProperty(property, source.getPropertyValue(property), source.getPropertyPriority(property));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function measureLocalTextLines(element, liveSource, text, width, height) {
|
|
39
|
+
if (!width || !height || !text)
|
|
40
|
+
return [];
|
|
41
|
+
const computed = getComputedStyle(element);
|
|
42
|
+
const sourceComputed = getComputedStyle(liveSource);
|
|
43
|
+
const probe = document.createElement(element.tagName.toLowerCase());
|
|
44
|
+
const source = document.createElement('span');
|
|
45
|
+
copyComputedStyle(computed, probe.style);
|
|
46
|
+
copyComputedStyle(sourceComputed, source.style);
|
|
47
|
+
probe.setAttribute('aria-hidden', 'true');
|
|
48
|
+
probe.inert = true;
|
|
49
|
+
Object.assign(probe.style, {
|
|
50
|
+
boxSizing: 'border-box',
|
|
51
|
+
contain: 'layout style paint',
|
|
52
|
+
height: `${height}px`,
|
|
53
|
+
left: '-100000px',
|
|
54
|
+
margin: '0',
|
|
55
|
+
maxHeight: `${height}px`,
|
|
56
|
+
maxWidth: `${width}px`,
|
|
57
|
+
minHeight: `${height}px`,
|
|
58
|
+
minWidth: `${width}px`,
|
|
59
|
+
overflow: 'visible',
|
|
60
|
+
pointerEvents: 'none',
|
|
61
|
+
position: 'fixed',
|
|
62
|
+
rotate: 'none',
|
|
63
|
+
scale: 'none',
|
|
64
|
+
top: '0',
|
|
65
|
+
transform: 'none',
|
|
66
|
+
translate: 'none',
|
|
67
|
+
visibility: 'hidden',
|
|
68
|
+
width: `${width}px`,
|
|
69
|
+
});
|
|
70
|
+
source.textContent = text;
|
|
71
|
+
probe.append(source);
|
|
72
|
+
document.body.append(probe);
|
|
73
|
+
try {
|
|
74
|
+
const box = probe.getBoundingClientRect();
|
|
75
|
+
const range = document.createRange();
|
|
76
|
+
const lines = [];
|
|
77
|
+
let offset = 0;
|
|
78
|
+
for (const character of text) {
|
|
79
|
+
range.setStart(source.firstChild, offset);
|
|
80
|
+
offset += character.length;
|
|
81
|
+
range.setEnd(source.firstChild, offset);
|
|
82
|
+
const rectangle = range.getBoundingClientRect();
|
|
83
|
+
const left = rectangle.left - box.left;
|
|
84
|
+
const top = rectangle.top - box.top;
|
|
85
|
+
let line = lines[lines.length - 1];
|
|
86
|
+
if (!line || Math.abs(line.top - top) > 1) {
|
|
87
|
+
line = { text: '', left, top };
|
|
88
|
+
lines.push(line);
|
|
89
|
+
}
|
|
90
|
+
line.text += character;
|
|
91
|
+
}
|
|
92
|
+
return lines;
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
probe.remove();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function paintText(element, source, canvas, text, seed, glyphSeed) {
|
|
16
99
|
const style = getComputedStyle(element);
|
|
100
|
+
const { width: localWidth, height: localHeight } = localBorderBox(element, style);
|
|
101
|
+
if (!localWidth || !localHeight || text.length > 4096 || !source.firstChild)
|
|
102
|
+
return false;
|
|
17
103
|
const size = Number.parseFloat(style.fontSize);
|
|
18
104
|
const context = canvas.getContext('2d');
|
|
19
105
|
const padding = 5;
|
|
20
|
-
const width =
|
|
21
|
-
const height =
|
|
106
|
+
const width = localWidth + padding * 2;
|
|
107
|
+
const height = localHeight + padding * 2;
|
|
22
108
|
const dpr = effectiveDpr(2);
|
|
23
109
|
if (width * height * dpr ** 2 > 2 * 1024 * 1024 || !context || context.isContextLost?.())
|
|
24
110
|
return false;
|
|
@@ -36,21 +122,7 @@ function paintText(element, source, canvas, text, seed) {
|
|
|
36
122
|
context.font = `400 ${size}px ${style.fontFamily}`;
|
|
37
123
|
context.fontKerning = 'none';
|
|
38
124
|
const ascent = context.measureText(text).fontBoundingBoxAscent ?? size;
|
|
39
|
-
const
|
|
40
|
-
const lines = [];
|
|
41
|
-
let offset = 0;
|
|
42
|
-
for (const character of text) {
|
|
43
|
-
range.setStart(source.firstChild, offset);
|
|
44
|
-
offset += character.length;
|
|
45
|
-
range.setEnd(source.firstChild, offset);
|
|
46
|
-
const rectangle = range.getBoundingClientRect();
|
|
47
|
-
let line = lines[lines.length - 1];
|
|
48
|
-
if (!line || Math.abs(line.top - rectangle.top) > 1) {
|
|
49
|
-
line = { text: '', left: rectangle.left, top: rectangle.top };
|
|
50
|
-
lines.push(line);
|
|
51
|
-
}
|
|
52
|
-
line.text += character;
|
|
53
|
-
}
|
|
125
|
+
const lines = measureLocalTextLines(element, source, text, localWidth, localHeight);
|
|
54
126
|
for (const line of lines) {
|
|
55
127
|
const lineText = line.text.trimEnd();
|
|
56
128
|
if (!lineText)
|
|
@@ -58,28 +130,37 @@ function paintText(element, source, canvas, text, seed) {
|
|
|
58
130
|
const sprite = renderPencilText(lineText, {
|
|
59
131
|
size,
|
|
60
132
|
seed: seedToNumber(seed) ^ textSeed(line.text),
|
|
133
|
+
glyphSeed,
|
|
61
134
|
color: style.color,
|
|
62
135
|
family: style.fontFamily,
|
|
63
136
|
dpr,
|
|
137
|
+
settings: {
|
|
138
|
+
variation: readRenderToken(style, '--inkra-letter-variation', pencilLettering.variation, 0, 1),
|
|
139
|
+
breaks: readRenderToken(style, '--inkra-letter-breaks', pencilLettering.breaks, 0, 1),
|
|
140
|
+
outline: readRenderToken(style, '--inkra-letter-outline', pencilLettering.outline, 0, 1),
|
|
141
|
+
fill: readRenderToken(style, '--inkra-letter-fill', pencilLettering.fill, 0, 1),
|
|
142
|
+
grain: readRenderToken(style, '--inkra-letter-grain', pencilLettering.grain, 0, 1),
|
|
143
|
+
},
|
|
64
144
|
});
|
|
65
145
|
if (sprite.ink.getContext('2d')?.isContextLost?.())
|
|
66
146
|
return false;
|
|
67
|
-
context.drawImage(sprite.ink, padding + line.left -
|
|
147
|
+
context.drawImage(sprite.ink, padding + line.left - sprite.padding, padding + line.top + ascent - sprite.ascent - sprite.padding, sprite.width, sprite.height);
|
|
68
148
|
}
|
|
69
149
|
canvas.dataset.lines = String(lines.length);
|
|
70
150
|
element.dataset.pencilReady = 'true';
|
|
71
151
|
return true;
|
|
72
152
|
}
|
|
73
153
|
const PencilTextImplementation = forwardRef(function PencilText({ as: Element = 'span', children, seed, ellipsis = false, className = '', ...props }, forwardedRef) {
|
|
74
|
-
const [
|
|
154
|
+
const [fittedText, setText] = useState(children);
|
|
155
|
+
const text = ellipsis ? fittedText : children;
|
|
75
156
|
const elementRef = useRef(null);
|
|
76
157
|
const sourceRef = useRef(null);
|
|
77
158
|
const canvasRef = useRef(null);
|
|
78
159
|
const resolvedSeed = seed ?? children;
|
|
160
|
+
const glyphSeed = seedToNumber(seed ?? 'inkra-latin-lettering-v1');
|
|
79
161
|
useImperativeHandle(forwardedRef, () => elementRef.current);
|
|
80
162
|
useBrowserLayoutEffect(() => {
|
|
81
163
|
if (!ellipsis) {
|
|
82
|
-
setText(children);
|
|
83
164
|
return undefined;
|
|
84
165
|
}
|
|
85
166
|
const node = elementRef.current;
|
|
@@ -125,7 +206,7 @@ const PencilTextImplementation = forwardRef(function PencilText({ as: Element =
|
|
|
125
206
|
resize?.disconnect();
|
|
126
207
|
};
|
|
127
208
|
}, [children, ellipsis]);
|
|
128
|
-
|
|
209
|
+
useBrowserLayoutEffect(() => {
|
|
129
210
|
const node = elementRef.current;
|
|
130
211
|
const source = sourceRef.current;
|
|
131
212
|
const canvas = canvasRef.current;
|
|
@@ -133,51 +214,104 @@ const PencilTextImplementation = forwardRef(function PencilText({ as: Element =
|
|
|
133
214
|
return undefined;
|
|
134
215
|
delete node.dataset.pencilReady;
|
|
135
216
|
let disposed = false;
|
|
136
|
-
|
|
217
|
+
const inViewport = () => {
|
|
218
|
+
const box = node.getBoundingClientRect();
|
|
219
|
+
if (!box.width || !box.height || !node.isConnected)
|
|
220
|
+
return false;
|
|
221
|
+
let left = Math.max(0, box.left);
|
|
222
|
+
let top = Math.max(0, box.top);
|
|
223
|
+
let right = Math.min(window.innerWidth, box.right);
|
|
224
|
+
let bottom = Math.min(window.innerHeight, box.bottom);
|
|
225
|
+
for (let parent = node.parentElement; parent && left < right && top < bottom; parent = parent.parentElement) {
|
|
226
|
+
const style = getComputedStyle(parent);
|
|
227
|
+
if (style.overflowX === 'visible' && style.overflowY === 'visible')
|
|
228
|
+
continue;
|
|
229
|
+
const clip = parent.getBoundingClientRect();
|
|
230
|
+
if (style.overflowX !== 'visible') {
|
|
231
|
+
left = Math.max(left, clip.left);
|
|
232
|
+
right = Math.min(right, clip.right);
|
|
233
|
+
}
|
|
234
|
+
if (style.overflowY !== 'visible') {
|
|
235
|
+
top = Math.max(top, clip.top);
|
|
236
|
+
bottom = Math.min(bottom, clip.bottom);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return left < right && top < bottom;
|
|
240
|
+
};
|
|
241
|
+
let visible = inViewport() || typeof IntersectionObserver === 'undefined';
|
|
137
242
|
let pending = null;
|
|
138
243
|
let dirty = true;
|
|
244
|
+
let lastAppearance = '';
|
|
245
|
+
const appearanceKey = () => {
|
|
246
|
+
const style = getComputedStyle(node);
|
|
247
|
+
const localBox = localBorderBox(node, style);
|
|
248
|
+
return JSON.stringify([
|
|
249
|
+
localBox.width, localBox.height, effectiveDpr(2),
|
|
250
|
+
style.fontSize && style.fontFamily
|
|
251
|
+
? document.fonts?.check(`400 ${style.fontSize} ${style.fontFamily}`, text) : false,
|
|
252
|
+
...['color', 'font-family', 'font-size', 'line-height', 'text-align', 'text-indent',
|
|
253
|
+
'letter-spacing', 'white-space', 'word-break', 'overflow-wrap', 'direction',
|
|
254
|
+
'padding-top', 'padding-left', 'padding-right', 'padding-bottom',
|
|
255
|
+
'--inkra-letter-variation', '--inkra-letter-breaks', '--inkra-letter-outline',
|
|
256
|
+
'--inkra-letter-fill', '--inkra-letter-grain'].map(name => style.getPropertyValue(name)),
|
|
257
|
+
]);
|
|
258
|
+
};
|
|
259
|
+
const paint = () => {
|
|
260
|
+
pending = null;
|
|
261
|
+
if (!disposed && visible && dirty) {
|
|
262
|
+
try {
|
|
263
|
+
if (paintText(node, source, canvas, text, resolvedSeed, glyphSeed))
|
|
264
|
+
lastAppearance = appearanceKey();
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
delete node.dataset.pencilReady;
|
|
268
|
+
}
|
|
269
|
+
dirty = false;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
139
272
|
const schedule = () => {
|
|
140
|
-
if (!visible || !dirty ||
|
|
273
|
+
if (!visible || !dirty || disposed)
|
|
141
274
|
return;
|
|
142
|
-
|
|
275
|
+
// Visible text is enhanced before paint; only nearby text waits for idle time.
|
|
276
|
+
if (inViewport()) {
|
|
277
|
+
pending?.();
|
|
143
278
|
pending = null;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
delete node.dataset.pencilReady;
|
|
150
|
-
}
|
|
151
|
-
dirty = false;
|
|
152
|
-
}
|
|
153
|
-
});
|
|
279
|
+
paint();
|
|
280
|
+
}
|
|
281
|
+
else if (!pending) {
|
|
282
|
+
pending = queueTextPaint(paint);
|
|
283
|
+
}
|
|
154
284
|
};
|
|
155
285
|
const markDirty = () => {
|
|
156
286
|
dirty = true;
|
|
157
287
|
delete node.dataset.pencilReady;
|
|
158
288
|
schedule();
|
|
159
289
|
};
|
|
160
|
-
|
|
290
|
+
// Scroll locks and pointer-event changes must not hide already-painted text.
|
|
291
|
+
const refreshAppearance = () => {
|
|
292
|
+
if (disposed || !node.isConnected)
|
|
293
|
+
return;
|
|
294
|
+
if (appearanceKey() !== lastAppearance)
|
|
295
|
+
markDirty();
|
|
296
|
+
};
|
|
297
|
+
const resize = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(refreshAppearance);
|
|
161
298
|
resize?.observe(node);
|
|
162
|
-
const appearance = new MutationObserver(markDirty);
|
|
163
|
-
appearance.observe(document.documentElement, {
|
|
164
|
-
attributes: true,
|
|
165
|
-
subtree: true,
|
|
166
|
-
attributeFilter: ['data-theme', 'data-inkra-theme'],
|
|
167
|
-
});
|
|
168
299
|
const colorScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
169
|
-
|
|
300
|
+
const inheritedStyle = new MutationObserver(refreshAppearance);
|
|
301
|
+
for (let element = node; element; element = element.parentElement) {
|
|
302
|
+
inheritedStyle.observe(element, { attributes: true, attributeFilter: ['style', 'class', 'dir', 'data-theme', 'data-inkra-theme'] });
|
|
303
|
+
}
|
|
304
|
+
colorScheme.addEventListener('change', refreshAppearance);
|
|
170
305
|
const intersection = typeof IntersectionObserver === 'undefined' ? null : new IntersectionObserver(entries => {
|
|
171
306
|
visible = entries[entries.length - 1]?.isIntersecting ?? false;
|
|
172
307
|
schedule();
|
|
173
|
-
}, { rootMargin: '
|
|
308
|
+
}, { rootMargin: '240px' });
|
|
174
309
|
intersection?.observe(node);
|
|
175
310
|
const fonts = document.fonts;
|
|
176
|
-
fonts?.addEventListener('
|
|
177
|
-
fonts?.addEventListener('
|
|
178
|
-
fonts?.addEventListener('loadingerror', markDirty);
|
|
311
|
+
fonts?.addEventListener('loadingdone', refreshAppearance);
|
|
312
|
+
fonts?.addEventListener('loadingerror', refreshAppearance);
|
|
179
313
|
fonts?.ready.then(() => { if (!disposed)
|
|
180
|
-
|
|
314
|
+
refreshAppearance(); });
|
|
181
315
|
const stopRecovery = observeCanvasRecovery(() => {
|
|
182
316
|
pending?.();
|
|
183
317
|
pending = null;
|
|
@@ -190,13 +324,12 @@ const PencilTextImplementation = forwardRef(function PencilText({ as: Element =
|
|
|
190
324
|
pending?.();
|
|
191
325
|
resize?.disconnect();
|
|
192
326
|
intersection?.disconnect();
|
|
193
|
-
|
|
194
|
-
colorScheme.removeEventListener('change',
|
|
195
|
-
fonts?.removeEventListener('
|
|
196
|
-
fonts?.removeEventListener('
|
|
197
|
-
fonts?.removeEventListener('loadingerror', markDirty);
|
|
327
|
+
inheritedStyle.disconnect();
|
|
328
|
+
colorScheme.removeEventListener('change', refreshAppearance);
|
|
329
|
+
fonts?.removeEventListener('loadingdone', refreshAppearance);
|
|
330
|
+
fonts?.removeEventListener('loadingerror', refreshAppearance);
|
|
198
331
|
};
|
|
199
|
-
}, [text, resolvedSeed]);
|
|
332
|
+
}, [text, resolvedSeed, glyphSeed]);
|
|
200
333
|
const classes = ['inkra-pencil-text', ellipsis && 'inkra-pencil-text--ellipsis', className]
|
|
201
334
|
.filter(Boolean).join(' ');
|
|
202
335
|
const title = props.title ?? (ellipsis ? children : undefined);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
2
|
+
import type { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
3
|
+
import type { ButtonProps } from '../Button.js';
|
|
4
|
+
export interface AlertDialogRootProps extends Omit<DialogPrimitive.DialogProps, 'open' | 'defaultOpen' | 'onOpenChange' | 'modal'> {
|
|
5
|
+
defaultOpen?: boolean;
|
|
6
|
+
onOpenChange?: (open: boolean) => void;
|
|
7
|
+
open?: boolean;
|
|
8
|
+
pending?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function AlertDialogRoot({ defaultOpen, onOpenChange, open, pending, ...props }: AlertDialogRootProps): import("react").JSX.Element;
|
|
11
|
+
export type AlertDialogTriggerProps = DialogPrimitive.DialogTriggerProps;
|
|
12
|
+
export declare const AlertDialogTrigger: import("react").ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
13
|
+
export type AlertDialogPortalProps = DialogPrimitive.DialogPortalProps;
|
|
14
|
+
export declare function AlertDialogPortal({ children, ...props }: AlertDialogPortalProps): ReactNode;
|
|
15
|
+
export type AlertDialogBackdropProps = DialogPrimitive.DialogOverlayProps;
|
|
16
|
+
export declare const AlertDialogBackdrop: import("react").ForwardRefExoticComponent<DialogPrimitive.DialogOverlayProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
17
|
+
export interface AlertDialogContentProps extends DialogPrimitive.DialogContentProps {
|
|
18
|
+
seed?: string | number;
|
|
19
|
+
}
|
|
20
|
+
export declare const AlertDialogContent: import("react").ForwardRefExoticComponent<AlertDialogContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
21
|
+
export interface AlertDialogTitleProps extends Omit<ComponentPropsWithoutRef<typeof DialogPrimitive.Title>, 'children'> {
|
|
22
|
+
children: string;
|
|
23
|
+
seed?: string | number;
|
|
24
|
+
}
|
|
25
|
+
export declare const AlertDialogTitle: import("react").ForwardRefExoticComponent<AlertDialogTitleProps & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
26
|
+
export interface AlertDialogDescriptionProps extends Omit<ComponentPropsWithoutRef<typeof DialogPrimitive.Description>, 'children'> {
|
|
27
|
+
children: string;
|
|
28
|
+
seed?: string | number;
|
|
29
|
+
}
|
|
30
|
+
export declare const AlertDialogDescription: import("react").ForwardRefExoticComponent<AlertDialogDescriptionProps & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
31
|
+
export interface AlertDialogHeaderProps extends ComponentPropsWithoutRef<'div'> {
|
|
32
|
+
divided?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare const AlertDialogHeader: import("react").ForwardRefExoticComponent<AlertDialogHeaderProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
35
|
+
export type AlertDialogBodyProps = ComponentPropsWithoutRef<'div'>;
|
|
36
|
+
export declare const AlertDialogBody: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
37
|
+
export interface AlertDialogFooterProps extends ComponentPropsWithoutRef<'div'> {
|
|
38
|
+
align?: 'start' | 'center' | 'end';
|
|
39
|
+
divided?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare const AlertDialogFooter: import("react").ForwardRefExoticComponent<AlertDialogFooterProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
42
|
+
export interface AlertDialogCancelProps extends Omit<ButtonProps, 'type'> {
|
|
43
|
+
children?: ReactNode;
|
|
44
|
+
}
|
|
45
|
+
export declare const AlertDialogCancel: import("react").ForwardRefExoticComponent<AlertDialogCancelProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
46
|
+
export interface AlertDialogActionProps extends Omit<ButtonProps, 'type'> {
|
|
47
|
+
children?: ReactNode;
|
|
48
|
+
closeOnAction?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export declare const AlertDialogAction: import("react").ForwardRefExoticComponent<AlertDialogActionProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
51
|
+
export declare const AlertDialog: Readonly<{
|
|
52
|
+
Root: typeof AlertDialogRoot;
|
|
53
|
+
Trigger: import("react").ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
54
|
+
Portal: typeof AlertDialogPortal;
|
|
55
|
+
Backdrop: import("react").ForwardRefExoticComponent<DialogPrimitive.DialogOverlayProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
56
|
+
Content: import("react").ForwardRefExoticComponent<AlertDialogContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
57
|
+
Header: import("react").ForwardRefExoticComponent<AlertDialogHeaderProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
58
|
+
Body: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
59
|
+
Footer: import("react").ForwardRefExoticComponent<AlertDialogFooterProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
60
|
+
Title: import("react").ForwardRefExoticComponent<AlertDialogTitleProps & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
61
|
+
Description: import("react").ForwardRefExoticComponent<AlertDialogDescriptionProps & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
62
|
+
Cancel: import("react").ForwardRefExoticComponent<AlertDialogCancelProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
63
|
+
Action: import("react").ForwardRefExoticComponent<AlertDialogActionProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
64
|
+
}>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
3
|
+
import { createContext, forwardRef, useContext, useId, useRef, useState, } from 'react';
|
|
4
|
+
import { Button } from '../Button.js';
|
|
5
|
+
import { PencilLine } from '../PencilLine.js';
|
|
6
|
+
import { PencilSurface } from '../PencilSurface.js';
|
|
7
|
+
import { PencilText } from '../PencilText.js';
|
|
8
|
+
import { mapPortalChildren, PortalThemeProvider, usePortalThemeProps, usePortalTriggerRef, } from '../overlay/themeBridge.js';
|
|
9
|
+
const classes = (...values) => values.filter(Boolean).join(' ');
|
|
10
|
+
function assignRef(ref, value) {
|
|
11
|
+
if (typeof ref === 'function')
|
|
12
|
+
ref(value);
|
|
13
|
+
else if (ref)
|
|
14
|
+
ref.current = value;
|
|
15
|
+
}
|
|
16
|
+
const AlertDialogContext = createContext(null);
|
|
17
|
+
export function AlertDialogRoot({ defaultOpen = false, onOpenChange, open, pending = false, ...props }) {
|
|
18
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
|
|
19
|
+
const cancelRef = useRef(null);
|
|
20
|
+
const controlled = open !== undefined;
|
|
21
|
+
const currentOpen = controlled ? open : uncontrolledOpen;
|
|
22
|
+
function handleOpenChange(nextOpen) {
|
|
23
|
+
if (!nextOpen && pending)
|
|
24
|
+
return;
|
|
25
|
+
if (!controlled)
|
|
26
|
+
setUncontrolledOpen(nextOpen);
|
|
27
|
+
onOpenChange?.(nextOpen);
|
|
28
|
+
}
|
|
29
|
+
return (_jsx(PortalThemeProvider, { children: _jsx(AlertDialogContext.Provider, { value: { cancelRef, pending }, children: _jsx(DialogPrimitive.Root, { ...props, modal: true, open: currentOpen, onOpenChange: handleOpenChange }) }) }));
|
|
30
|
+
}
|
|
31
|
+
export const AlertDialogTrigger = forwardRef(function AlertDialogTrigger(props, forwardedRef) {
|
|
32
|
+
return _jsx(DialogPrimitive.Trigger, { ...props, ref: usePortalTriggerRef(forwardedRef) });
|
|
33
|
+
});
|
|
34
|
+
export function AlertDialogPortal({ children, ...props }) {
|
|
35
|
+
return mapPortalChildren(children, child => _jsx(DialogPrimitive.Portal, { ...props, children: child }));
|
|
36
|
+
}
|
|
37
|
+
export const AlertDialogBackdrop = forwardRef(function AlertDialogBackdrop({ className, ...props }, ref) {
|
|
38
|
+
props = usePortalThemeProps(props);
|
|
39
|
+
return (_jsx(DialogPrimitive.Overlay, { ...props, className: classes('inkra-alert-dialog__backdrop', className), ref: ref }));
|
|
40
|
+
});
|
|
41
|
+
export const AlertDialogContent = forwardRef(function AlertDialogContent({ children, className, onEscapeKeyDown, onInteractOutside, onOpenAutoFocus, onPointerDownOutside, seed, ...props }, forwardedRef) {
|
|
42
|
+
const context = useContext(AlertDialogContext);
|
|
43
|
+
const contentRef = useRef(null);
|
|
44
|
+
const id = useId();
|
|
45
|
+
props = usePortalThemeProps(props);
|
|
46
|
+
return (_jsx(DialogPrimitive.Content, { ...props, role: "alertdialog", "aria-busy": context?.pending || undefined, className: classes('inkra-alert-dialog__content', className), "data-pending": context?.pending || undefined, ref: node => {
|
|
47
|
+
contentRef.current = node;
|
|
48
|
+
assignRef(forwardedRef, node);
|
|
49
|
+
}, onEscapeKeyDown: event => {
|
|
50
|
+
onEscapeKeyDown?.(event);
|
|
51
|
+
if (context?.pending)
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
}, onInteractOutside: event => {
|
|
54
|
+
onInteractOutside?.(event);
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
}, onPointerDownOutside: event => {
|
|
57
|
+
onPointerDownOutside?.(event);
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
}, onOpenAutoFocus: event => {
|
|
60
|
+
onOpenAutoFocus?.(event);
|
|
61
|
+
if (event.defaultPrevented)
|
|
62
|
+
return;
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
queueMicrotask(() => (context?.cancelRef.current ?? contentRef.current)?.focus());
|
|
65
|
+
}, children: _jsx(PencilSurface, { className: "inkra-alert-dialog__surface", radius: 8, seed: seed ?? `inkra-alert-dialog-${id}`, variant: "paper", children: _jsx("div", { className: "inkra-alert-dialog__layout", children: children }) }) }));
|
|
66
|
+
});
|
|
67
|
+
export const AlertDialogTitle = forwardRef(function AlertDialogTitle({ children, className, seed, ...props }, ref) {
|
|
68
|
+
const id = useId();
|
|
69
|
+
return (_jsx(DialogPrimitive.Title, { ...props, className: classes('inkra-alert-dialog__title', className), ref: ref, children: _jsx(PencilText, { seed: seed ?? `inkra-alert-dialog-title-${id}`, children: children }) }));
|
|
70
|
+
});
|
|
71
|
+
export const AlertDialogDescription = forwardRef(function AlertDialogDescription({ children, className, seed, ...props }, ref) {
|
|
72
|
+
const id = useId();
|
|
73
|
+
return (_jsx(DialogPrimitive.Description, { ...props, className: classes('inkra-alert-dialog__description', className), ref: ref, children: _jsx(PencilText, { seed: seed ?? `inkra-alert-dialog-description-${id}`, children: children }) }));
|
|
74
|
+
});
|
|
75
|
+
export const AlertDialogHeader = forwardRef(function AlertDialogHeader({ children, className, divided = true, ...props }, ref) {
|
|
76
|
+
const id = useId();
|
|
77
|
+
return (_jsxs("div", { ...props, className: classes('inkra-alert-dialog__header', className), "data-divided": divided || undefined, ref: ref, children: [_jsx("div", { className: "inkra-alert-dialog__heading", children: children }), divided ? _jsx(PencilLine, { className: "inkra-alert-dialog__divider", seed: `alert-header-${id}` }) : null] }));
|
|
78
|
+
});
|
|
79
|
+
export const AlertDialogBody = forwardRef(function AlertDialogBody({ className, ...props }, ref) {
|
|
80
|
+
return _jsx("div", { ...props, className: classes('inkra-alert-dialog__body', className), ref: ref });
|
|
81
|
+
});
|
|
82
|
+
export const AlertDialogFooter = forwardRef(function AlertDialogFooter({ align = 'end', children, className, divided = true, ...props }, ref) {
|
|
83
|
+
const id = useId();
|
|
84
|
+
return (_jsxs("div", { ...props, className: classes('inkra-alert-dialog__footer', className), "data-align": align, "data-divided": divided || undefined, ref: ref, children: [divided ? _jsx(PencilLine, { className: "inkra-alert-dialog__divider", seed: `alert-footer-${id}` }) : null, children] }));
|
|
85
|
+
});
|
|
86
|
+
export const AlertDialogCancel = forwardRef(function AlertDialogCancel({ disabled, variant = 'secondary', ...props }, forwardedRef) {
|
|
87
|
+
const context = useContext(AlertDialogContext);
|
|
88
|
+
return (_jsx(DialogPrimitive.Close, { asChild: true, children: _jsx(Button, { ...props, disabled: disabled || context?.pending, ref: node => {
|
|
89
|
+
assignRef(forwardedRef, node);
|
|
90
|
+
assignRef(context?.cancelRef, node);
|
|
91
|
+
}, type: "button", variant: variant }) }));
|
|
92
|
+
});
|
|
93
|
+
export const AlertDialogAction = forwardRef(function AlertDialogAction({ closeOnAction = true, disabled, loading, variant = 'destructive', ...props }, ref) {
|
|
94
|
+
const pending = useContext(AlertDialogContext)?.pending ?? false;
|
|
95
|
+
const button = (_jsx(Button, { ...props, "aria-busy": pending || undefined, disabled: disabled || pending, loading: loading || pending, ref: ref, type: "button", variant: variant }));
|
|
96
|
+
return closeOnAction ? _jsx(DialogPrimitive.Close, { asChild: true, children: button }) : button;
|
|
97
|
+
});
|
|
98
|
+
export const AlertDialog = Object.freeze({
|
|
99
|
+
Root: AlertDialogRoot,
|
|
100
|
+
Trigger: AlertDialogTrigger,
|
|
101
|
+
Portal: AlertDialogPortal,
|
|
102
|
+
Backdrop: AlertDialogBackdrop,
|
|
103
|
+
Content: AlertDialogContent,
|
|
104
|
+
Header: AlertDialogHeader,
|
|
105
|
+
Body: AlertDialogBody,
|
|
106
|
+
Footer: AlertDialogFooter,
|
|
107
|
+
Title: AlertDialogTitle,
|
|
108
|
+
Description: AlertDialogDescription,
|
|
109
|
+
Cancel: AlertDialogCancel,
|
|
110
|
+
Action: AlertDialogAction,
|
|
111
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AudioHTMLAttributes, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export type AudioPlayerStatus = 'idle' | 'loading' | 'ready' | 'playing' | 'paused' | 'buffering' | 'ended' | 'blocked' | 'error';
|
|
3
|
+
export interface AudioPlayerState {
|
|
4
|
+
status: AudioPlayerStatus;
|
|
5
|
+
currentTime: number;
|
|
6
|
+
duration: number;
|
|
7
|
+
buffered: number;
|
|
8
|
+
volume: number;
|
|
9
|
+
muted: boolean;
|
|
10
|
+
playbackRate: number;
|
|
11
|
+
canPlay: boolean;
|
|
12
|
+
error: MediaError | null;
|
|
13
|
+
}
|
|
14
|
+
export interface AudioPlayerControls {
|
|
15
|
+
audio: HTMLAudioElement | null;
|
|
16
|
+
state: AudioPlayerState;
|
|
17
|
+
play: () => Promise<void>;
|
|
18
|
+
pause: () => void;
|
|
19
|
+
togglePlay: () => Promise<void>;
|
|
20
|
+
seek: (time: number) => void;
|
|
21
|
+
setVolume: (volume: number) => void;
|
|
22
|
+
setMuted: (muted: boolean) => void;
|
|
23
|
+
setPlaybackRate: (rate: number) => void;
|
|
24
|
+
focus: () => void;
|
|
25
|
+
}
|
|
26
|
+
export interface AudioPlayerLabels {
|
|
27
|
+
play?: string;
|
|
28
|
+
pause?: string;
|
|
29
|
+
mute?: string;
|
|
30
|
+
unmute?: string;
|
|
31
|
+
seek?: string;
|
|
32
|
+
volume?: string;
|
|
33
|
+
rate?: string;
|
|
34
|
+
loading?: string;
|
|
35
|
+
blocked?: string;
|
|
36
|
+
error?: string;
|
|
37
|
+
time?: (current: number, duration: number) => string;
|
|
38
|
+
}
|
|
39
|
+
export interface AudioPlayerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onError' | 'onChange' | 'onVolumeChange'> {
|
|
40
|
+
src?: string;
|
|
41
|
+
preload?: AudioHTMLAttributes<HTMLAudioElement>['preload'];
|
|
42
|
+
autoPlay?: boolean;
|
|
43
|
+
crossOrigin?: AudioHTMLAttributes<HTMLAudioElement>['crossOrigin'];
|
|
44
|
+
defaultVolume?: number;
|
|
45
|
+
volume?: number;
|
|
46
|
+
defaultMuted?: boolean;
|
|
47
|
+
muted?: boolean;
|
|
48
|
+
defaultPlaybackRate?: number;
|
|
49
|
+
playbackRate?: number;
|
|
50
|
+
onVolumeChange?: (volume: number) => void;
|
|
51
|
+
onMutedChange?: (muted: boolean) => void;
|
|
52
|
+
onPlaybackRateChange?: (rate: number) => void;
|
|
53
|
+
onTimeChange?: (currentTime: number) => void;
|
|
54
|
+
onStateChange?: (state: AudioPlayerState) => void;
|
|
55
|
+
onError?: (error: MediaError | DOMException | null) => void;
|
|
56
|
+
labels?: AudioPlayerLabels;
|
|
57
|
+
renderControls?: (controls: AudioPlayerControls) => ReactNode;
|
|
58
|
+
audioProps?: Omit<AudioHTMLAttributes<HTMLAudioElement>, 'src' | 'controls' | 'autoPlay' | 'preload' | 'volume' | 'muted' | 'playbackRate' | 'onError'>;
|
|
59
|
+
}
|
|
60
|
+
export declare const AudioPlayer: import("react").ForwardRefExoticComponent<AudioPlayerProps & import("react").RefAttributes<AudioPlayerControls>>;
|