@inkra/react 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +316 -2
- package/THIRD_PARTY_NOTICES.md +39 -0
- package/Yozai-OFL.txt +94 -0
- package/dist/Button.d.ts +36 -0
- package/dist/Button.js +89 -0
- package/dist/PencilIcon.d.ts +22 -0
- package/dist/PencilIcon.js +210 -0
- package/dist/PencilLine.d.ts +10 -0
- package/dist/PencilLine.js +91 -0
- package/dist/PencilSurface.d.ts +19 -0
- package/dist/PencilSurface.js +19 -0
- package/dist/PencilText.d.ts +16 -0
- package/dist/PencilText.js +338 -0
- package/dist/accordion/Accordion.d.ts +27 -0
- package/dist/accordion/Accordion.js +40 -0
- package/dist/accordion/index.d.ts +2 -0
- package/dist/accordion/index.js +1 -0
- package/dist/alert-dialog/index.d.ts +64 -0
- package/dist/alert-dialog/index.js +109 -0
- package/dist/assets/ui-hand-yozai.woff2 +0 -0
- package/dist/audio-player/index.d.ts +60 -0
- package/dist/audio-player/index.js +101 -0
- package/dist/breadcrumb/index.d.ts +16 -0
- package/dist/breadcrumb/index.js +25 -0
- package/dist/calendar/index.d.ts +21 -0
- package/dist/calendar/index.js +41 -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 +23 -0
- package/dist/command/index.js +39 -0
- package/dist/content/index.d.ts +106 -0
- package/dist/content/index.js +80 -0
- package/dist/context-menu/index.d.ts +76 -0
- package/dist/context-menu/index.js +240 -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/day-agenda/index.d.ts +43 -0
- package/dist/day-agenda/index.js +47 -0
- package/dist/day-agenda/layout.d.ts +20 -0
- package/dist/day-agenda/layout.js +60 -0
- package/dist/display/ProgressRing.d.ts +6 -0
- package/dist/display/ProgressRing.js +146 -0
- package/dist/display/index.d.ts +59 -0
- package/dist/display/index.js +75 -0
- 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 +86 -0
- package/dist/dropdown-menu/index.d.ts +34 -0
- package/dist/dropdown-menu/index.js +40 -0
- 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.d.ts +13 -0
- package/dist/form/EditablePencilText.js +323 -0
- package/dist/form/Field.d.ts +13 -0
- package/dist/form/Field.js +26 -0
- package/dist/form/Input.d.ts +27 -0
- package/dist/form/Input.js +97 -0
- package/dist/form/InputAction.d.ts +7 -0
- package/dist/form/InputAction.js +24 -0
- package/dist/form/Textarea.d.ts +17 -0
- package/dist/form/Textarea.js +102 -0
- package/dist/form/context.d.ts +12 -0
- package/dist/form/context.js +10 -0
- package/dist/form/controlProps.d.ts +23 -0
- package/dist/form/controlProps.js +20 -0
- package/dist/form/index.d.ts +7 -0
- package/dist/form/index.js +3 -0
- package/dist/form/types.d.ts +6 -0
- package/dist/form/types.js +1 -0
- 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/images/layers-2x.png +0 -0
- package/dist/images/layers.png +0 -0
- package/dist/images/marker-icon.png +0 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +69 -0
- package/dist/input-number/index.d.ts +16 -0
- package/dist/input-number/index.js +77 -0
- package/dist/internal/InputActionContext.d.ts +1 -0
- package/dist/internal/InputActionContext.js +3 -0
- package/dist/internal/cache.d.ts +14 -0
- package/dist/internal/cache.js +54 -0
- package/dist/internal/line.d.ts +4 -0
- package/dist/internal/line.js +21 -0
- package/dist/internal/paper.d.ts +1 -0
- package/dist/internal/paper.js +65 -0
- package/dist/internal/random.d.ts +3 -0
- package/dist/internal/random.js +30 -0
- package/dist/internal/recovery.d.ts +1 -0
- package/dist/internal/recovery.js +52 -0
- package/dist/internal/renderTokens.d.ts +10 -0
- package/dist/internal/renderTokens.js +13 -0
- package/dist/internal/stroke.d.ts +24 -0
- package/dist/internal/stroke.js +144 -0
- package/dist/internal/surfaceRenderer.d.ts +41 -0
- package/dist/internal/surfaceRenderer.js +178 -0
- package/dist/internal/textQueue.d.ts +1 -0
- package/dist/internal/textQueue.js +37 -0
- package/dist/internal/textRenderer.d.ts +28 -0
- package/dist/internal/textRenderer.js +239 -0
- package/dist/internal/travelIcons.d.ts +24 -0
- package/dist/internal/travelIcons.js +14 -0
- package/dist/internal/useBrowserLayoutEffect.d.ts +2 -0
- package/dist/internal/useBrowserLayoutEffect.js +3 -0
- package/dist/internal/usePencilSurface.d.ts +3 -0
- package/dist/internal/usePencilSurface.js +116 -0
- package/dist/internal/useSelectionDrawing.d.ts +2 -0
- package/dist/internal/useSelectionDrawing.js +90 -0
- package/dist/internal/wash.d.ts +16 -0
- package/dist/internal/wash.js +149 -0
- package/dist/journey-map/MapScale.d.ts +4 -0
- package/dist/journey-map/MapScale.js +54 -0
- package/dist/journey-map/index.d.ts +39 -0
- package/dist/journey-map/index.js +197 -0
- package/dist/journey-map/terrain.d.ts +8 -0
- package/dist/journey-map/terrain.js +127 -0
- 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 +29 -0
- package/dist/number-ticker/index.js +132 -0
- package/dist/number-ticker/model.d.ts +8 -0
- package/dist/number-ticker/model.js +34 -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 +65 -0
- package/dist/overlay/Overlay.js +77 -0
- package/dist/overlay/Popover.d.ts +43 -0
- package/dist/overlay/Popover.js +45 -0
- package/dist/overlay/index.d.ts +4 -0
- package/dist/overlay/index.js +2 -0
- package/dist/overlay/themeBridge.d.ts +8 -0
- package/dist/overlay/themeBridge.js +98 -0
- 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/pencil.d.ts +10 -0
- package/dist/pencil.js +39 -0
- package/dist/radar/index.d.ts +54 -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/select/MultipleSelect.d.ts +44 -0
- package/dist/select/MultipleSelect.js +124 -0
- package/dist/select/SearchableSelect.d.ts +45 -0
- package/dist/select/SearchableSelect.js +50 -0
- package/dist/select/Select.d.ts +109 -0
- package/dist/select/Select.js +205 -0
- package/dist/select/index.d.ts +4 -0
- package/dist/select/index.js +2 -0
- package/dist/selection/Checkbox.d.ts +9 -0
- package/dist/selection/Checkbox.js +37 -0
- package/dist/selection/RadioGroup.d.ts +23 -0
- package/dist/selection/RadioGroup.js +82 -0
- package/dist/selection/Switch.d.ts +8 -0
- package/dist/selection/Switch.js +36 -0
- package/dist/selection/index.d.ts +6 -0
- package/dist/selection/index.js +3 -0
- package/dist/selection/useNativeChecked.d.ts +13 -0
- package/dist/selection/useNativeChecked.js +27 -0
- package/dist/slider/index.d.ts +11 -0
- package/dist/slider/index.js +45 -0
- 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 +278 -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 +8226 -0
- package/dist/tabs/index.d.ts +22 -0
- package/dist/tabs/index.js +42 -0
- 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 +356 -0
- package/dist/tooltip/Tooltip.d.ts +24 -0
- package/dist/tooltip/Tooltip.js +32 -0
- package/dist/tooltip/index.d.ts +2 -0
- package/dist/tooltip/index.js +1 -0
- 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 +128 -0
- package/dist/virtual-list/model.d.ts +7 -0
- package/dist/virtual-list/model.js +27 -0
- package/package.json +119 -4
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
|
|
3
|
+
import { useBrowserLayoutEffect } from './internal/useBrowserLayoutEffect.js';
|
|
4
|
+
import { effectiveDpr } from './internal/cache.js';
|
|
5
|
+
import { observeCanvasRecovery } from './internal/recovery.js';
|
|
6
|
+
import { seedToNumber } from './internal/random.js';
|
|
7
|
+
import { pencilLettering, renderPencilText } from './internal/textRenderer.js';
|
|
8
|
+
import { readRenderToken } from './internal/renderTokens.js';
|
|
9
|
+
import { queueTextPaint } from './internal/textQueue.js';
|
|
10
|
+
function textSeed(text) {
|
|
11
|
+
return Array.from(text).reduce((seed, character) => Math.imul(seed ^ character.codePointAt(0), 16777619), 71) >>> 0;
|
|
12
|
+
}
|
|
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) {
|
|
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;
|
|
103
|
+
const size = Number.parseFloat(style.fontSize);
|
|
104
|
+
const context = canvas.getContext('2d');
|
|
105
|
+
const padding = 5;
|
|
106
|
+
const width = localWidth + padding * 2;
|
|
107
|
+
const height = localHeight + padding * 2;
|
|
108
|
+
const dpr = effectiveDpr(2);
|
|
109
|
+
if (width * height * dpr ** 2 > 2 * 1024 * 1024 || !context || context.isContextLost?.())
|
|
110
|
+
return false;
|
|
111
|
+
canvas.width = Math.ceil(width * dpr);
|
|
112
|
+
canvas.height = Math.ceil(height * dpr);
|
|
113
|
+
Object.assign(canvas.style, {
|
|
114
|
+
left: `-${padding}px`,
|
|
115
|
+
top: `-${padding}px`,
|
|
116
|
+
right: 'auto',
|
|
117
|
+
bottom: 'auto',
|
|
118
|
+
width: `${width}px`,
|
|
119
|
+
height: `${height}px`,
|
|
120
|
+
});
|
|
121
|
+
context.scale(dpr, dpr);
|
|
122
|
+
context.font = `400 ${size}px ${style.fontFamily}`;
|
|
123
|
+
context.fontKerning = 'none';
|
|
124
|
+
const ascent = context.measureText(text).fontBoundingBoxAscent ?? size;
|
|
125
|
+
const lines = measureLocalTextLines(element, source, text, localWidth, localHeight);
|
|
126
|
+
for (const line of lines) {
|
|
127
|
+
const lineText = line.text.trimEnd();
|
|
128
|
+
if (!lineText)
|
|
129
|
+
continue;
|
|
130
|
+
const sprite = renderPencilText(lineText, {
|
|
131
|
+
size,
|
|
132
|
+
seed: seedToNumber(seed) ^ textSeed(line.text),
|
|
133
|
+
glyphSeed,
|
|
134
|
+
color: style.color,
|
|
135
|
+
family: style.fontFamily,
|
|
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
|
+
},
|
|
144
|
+
});
|
|
145
|
+
if (sprite.ink.getContext('2d')?.isContextLost?.())
|
|
146
|
+
return false;
|
|
147
|
+
context.drawImage(sprite.ink, padding + line.left - sprite.padding, padding + line.top + ascent - sprite.ascent - sprite.padding, sprite.width, sprite.height);
|
|
148
|
+
}
|
|
149
|
+
canvas.dataset.lines = String(lines.length);
|
|
150
|
+
element.dataset.pencilReady = 'true';
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
const PencilTextImplementation = forwardRef(function PencilText({ as: Element = 'span', children, seed, ellipsis = false, className = '', ...props }, forwardedRef) {
|
|
154
|
+
const [fittedText, setText] = useState(children);
|
|
155
|
+
const text = ellipsis ? fittedText : children;
|
|
156
|
+
const elementRef = useRef(null);
|
|
157
|
+
const sourceRef = useRef(null);
|
|
158
|
+
const canvasRef = useRef(null);
|
|
159
|
+
const resolvedSeed = seed ?? children;
|
|
160
|
+
const glyphSeed = seedToNumber(seed ?? 'inkra-latin-lettering-v1');
|
|
161
|
+
useImperativeHandle(forwardedRef, () => elementRef.current);
|
|
162
|
+
useBrowserLayoutEffect(() => {
|
|
163
|
+
if (!ellipsis) {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
const node = elementRef.current;
|
|
167
|
+
const canvas = canvasRef.current;
|
|
168
|
+
if (!node || !canvas)
|
|
169
|
+
return undefined;
|
|
170
|
+
let disposed = false;
|
|
171
|
+
const fit = () => {
|
|
172
|
+
const width = node.clientWidth - 8;
|
|
173
|
+
if (width <= 0)
|
|
174
|
+
return;
|
|
175
|
+
const style = getComputedStyle(node);
|
|
176
|
+
const context = canvas.getContext('2d');
|
|
177
|
+
if (!context || context.isContextLost?.())
|
|
178
|
+
return;
|
|
179
|
+
context.font = `400 ${style.fontSize} ${style.fontFamily}`;
|
|
180
|
+
context.fontKerning = 'none';
|
|
181
|
+
const measure = (value) => context.measureText(value).width;
|
|
182
|
+
if (measure(children) <= width) {
|
|
183
|
+
setText(previous => previous === children ? previous : children);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const characters = Array.from(children);
|
|
187
|
+
let low = 0;
|
|
188
|
+
let high = characters.length;
|
|
189
|
+
while (low < high) {
|
|
190
|
+
const middle = Math.ceil((low + high) / 2);
|
|
191
|
+
if (measure(`${characters.slice(0, middle).join('')}…`) <= width)
|
|
192
|
+
low = middle;
|
|
193
|
+
else
|
|
194
|
+
high = middle - 1;
|
|
195
|
+
}
|
|
196
|
+
const clipped = `${characters.slice(0, low).join('').trimEnd()}…`;
|
|
197
|
+
setText(previous => previous === clipped ? previous : clipped);
|
|
198
|
+
};
|
|
199
|
+
const resize = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(fit);
|
|
200
|
+
resize?.observe(node);
|
|
201
|
+
document.fonts?.ready.then(() => { if (!disposed)
|
|
202
|
+
fit(); });
|
|
203
|
+
fit();
|
|
204
|
+
return () => {
|
|
205
|
+
disposed = true;
|
|
206
|
+
resize?.disconnect();
|
|
207
|
+
};
|
|
208
|
+
}, [children, ellipsis]);
|
|
209
|
+
useBrowserLayoutEffect(() => {
|
|
210
|
+
const node = elementRef.current;
|
|
211
|
+
const source = sourceRef.current;
|
|
212
|
+
const canvas = canvasRef.current;
|
|
213
|
+
if (!node || !source || !canvas)
|
|
214
|
+
return undefined;
|
|
215
|
+
delete node.dataset.pencilReady;
|
|
216
|
+
let disposed = false;
|
|
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';
|
|
242
|
+
let pending = null;
|
|
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
|
+
};
|
|
272
|
+
const schedule = () => {
|
|
273
|
+
if (!visible || !dirty || disposed)
|
|
274
|
+
return;
|
|
275
|
+
// Visible text is enhanced before paint; only nearby text waits for idle time.
|
|
276
|
+
if (inViewport()) {
|
|
277
|
+
pending?.();
|
|
278
|
+
pending = null;
|
|
279
|
+
paint();
|
|
280
|
+
}
|
|
281
|
+
else if (!pending) {
|
|
282
|
+
pending = queueTextPaint(paint);
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
const markDirty = () => {
|
|
286
|
+
dirty = true;
|
|
287
|
+
delete node.dataset.pencilReady;
|
|
288
|
+
schedule();
|
|
289
|
+
};
|
|
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);
|
|
298
|
+
resize?.observe(node);
|
|
299
|
+
const colorScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
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);
|
|
305
|
+
const intersection = typeof IntersectionObserver === 'undefined' ? null : new IntersectionObserver(entries => {
|
|
306
|
+
visible = entries[entries.length - 1]?.isIntersecting ?? false;
|
|
307
|
+
schedule();
|
|
308
|
+
}, { rootMargin: '240px' });
|
|
309
|
+
intersection?.observe(node);
|
|
310
|
+
const fonts = document.fonts;
|
|
311
|
+
fonts?.addEventListener('loadingdone', refreshAppearance);
|
|
312
|
+
fonts?.addEventListener('loadingerror', refreshAppearance);
|
|
313
|
+
fonts?.ready.then(() => { if (!disposed)
|
|
314
|
+
refreshAppearance(); });
|
|
315
|
+
const stopRecovery = observeCanvasRecovery(() => {
|
|
316
|
+
pending?.();
|
|
317
|
+
pending = null;
|
|
318
|
+
markDirty();
|
|
319
|
+
});
|
|
320
|
+
schedule();
|
|
321
|
+
return () => {
|
|
322
|
+
disposed = true;
|
|
323
|
+
stopRecovery();
|
|
324
|
+
pending?.();
|
|
325
|
+
resize?.disconnect();
|
|
326
|
+
intersection?.disconnect();
|
|
327
|
+
inheritedStyle.disconnect();
|
|
328
|
+
colorScheme.removeEventListener('change', refreshAppearance);
|
|
329
|
+
fonts?.removeEventListener('loadingdone', refreshAppearance);
|
|
330
|
+
fonts?.removeEventListener('loadingerror', refreshAppearance);
|
|
331
|
+
};
|
|
332
|
+
}, [text, resolvedSeed, glyphSeed]);
|
|
333
|
+
const classes = ['inkra-pencil-text', ellipsis && 'inkra-pencil-text--ellipsis', className]
|
|
334
|
+
.filter(Boolean).join(' ');
|
|
335
|
+
const title = props.title ?? (ellipsis ? children : undefined);
|
|
336
|
+
return (_jsxs(Element, { ...props, className: classes, ref: elementRef, title: title, children: [_jsx("span", { className: "inkra-pencil-text__source", ref: sourceRef, children: children }), _jsx("canvas", { "aria-hidden": "true", "data-renderer": "inkra-pencil-lettering-c", ref: canvasRef })] }));
|
|
337
|
+
});
|
|
338
|
+
export const PencilText = PencilTextImplementation;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
export type AccordionRootProps = AccordionPrimitive.AccordionSingleProps | AccordionPrimitive.AccordionMultipleProps;
|
|
4
|
+
export declare const AccordionRoot: import("react").ForwardRefExoticComponent<AccordionRootProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
5
|
+
export interface AccordionItemProps extends AccordionPrimitive.AccordionItemProps {
|
|
6
|
+
dividerSeed?: string | number;
|
|
7
|
+
showDivider?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const AccordionItem: import("react").ForwardRefExoticComponent<AccordionItemProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
10
|
+
export type AccordionHeaderProps = AccordionPrimitive.AccordionHeaderProps;
|
|
11
|
+
export declare const AccordionHeader: import("react").ForwardRefExoticComponent<AccordionPrimitive.AccordionHeaderProps & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
12
|
+
export interface AccordionTriggerProps extends AccordionPrimitive.AccordionTriggerProps {
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
seed?: string | number;
|
|
15
|
+
}
|
|
16
|
+
export declare const AccordionTrigger: import("react").ForwardRefExoticComponent<AccordionTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
17
|
+
export interface AccordionContentProps extends AccordionPrimitive.AccordionContentProps {
|
|
18
|
+
contentClassName?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const AccordionContent: import("react").ForwardRefExoticComponent<AccordionContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
21
|
+
export declare const Accordion: Readonly<{
|
|
22
|
+
Root: import("react").ForwardRefExoticComponent<AccordionRootProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
23
|
+
Item: import("react").ForwardRefExoticComponent<AccordionItemProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
24
|
+
Header: import("react").ForwardRefExoticComponent<AccordionPrimitive.AccordionHeaderProps & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
25
|
+
Trigger: import("react").ForwardRefExoticComponent<AccordionTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
26
|
+
Content: import("react").ForwardRefExoticComponent<AccordionContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
27
|
+
}>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
3
|
+
import { createContext, forwardRef, useContext, useId } from 'react';
|
|
4
|
+
import { PencilIcon } from '../PencilIcon.js';
|
|
5
|
+
import { PencilLine } from '../PencilLine.js';
|
|
6
|
+
import { PencilSurface } from '../PencilSurface.js';
|
|
7
|
+
import { PencilText } from '../PencilText.js';
|
|
8
|
+
const chevronDownPaths = [
|
|
9
|
+
{ d: 'M6 9L12 15L18 9' },
|
|
10
|
+
];
|
|
11
|
+
const AccordionOrientationContext = createContext('vertical');
|
|
12
|
+
function classes(...values) {
|
|
13
|
+
return values.filter(Boolean).join(' ');
|
|
14
|
+
}
|
|
15
|
+
export const AccordionRoot = forwardRef(function AccordionRoot({ className, orientation = 'vertical', ...props }, ref) {
|
|
16
|
+
return (_jsx(AccordionOrientationContext.Provider, { value: orientation, children: _jsx(AccordionPrimitive.Root, { ...props, className: classes('inkra-accordion', className), orientation: orientation, ref: ref }) }));
|
|
17
|
+
});
|
|
18
|
+
export const AccordionItem = forwardRef(function AccordionItem({ children, className, dividerSeed, showDivider = true, value, ...props }, ref) {
|
|
19
|
+
const orientation = useContext(AccordionOrientationContext);
|
|
20
|
+
return (_jsxs(AccordionPrimitive.Item, { ...props, className: classes('inkra-accordion__item', className), ref: ref, value: value, children: [children, showDivider ? (_jsx(PencilLine, { className: "inkra-accordion__divider", orientation: orientation === 'horizontal' ? 'vertical' : 'horizontal', seed: dividerSeed ?? `inkra-accordion-divider-${value}`, weight: 0.8 })) : null] }));
|
|
21
|
+
});
|
|
22
|
+
export const AccordionHeader = forwardRef(function AccordionHeader({ className, ...props }, ref) {
|
|
23
|
+
return (_jsx(AccordionPrimitive.Header, { ...props, className: classes('inkra-accordion__header', className), ref: ref }));
|
|
24
|
+
});
|
|
25
|
+
export const AccordionTrigger = forwardRef(function AccordionTrigger({ children, className, icon, seed, ...props }, ref) {
|
|
26
|
+
const generatedId = useId();
|
|
27
|
+
const resolvedSeed = seed ?? `inkra-accordion-trigger-${generatedId}`;
|
|
28
|
+
const triggerIcon = icon === undefined ? (_jsx(PencilIcon, { className: "inkra-accordion__trigger-glyph", paths: chevronDownPaths, seed: `${resolvedSeed}-chevron`, size: 16, sourceSize: 24 })) : icon;
|
|
29
|
+
return (_jsxs(AccordionPrimitive.Trigger, { ...props, className: classes('inkra-accordion__trigger', className), ref: ref, children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-accordion__focus-ring", radius: 6, seed: `${resolvedSeed}-focus`, variant: "outline" }), _jsx("span", { className: "inkra-accordion__trigger-label", children: typeof children === 'string' ? (_jsx(PencilText, { seed: `${resolvedSeed}-text`, children: children })) : children }), triggerIcon == null ? null : (_jsx("span", { "aria-hidden": "true", className: "inkra-accordion__trigger-icon", children: triggerIcon }))] }));
|
|
30
|
+
});
|
|
31
|
+
export const AccordionContent = forwardRef(function AccordionContent({ children, className, contentClassName, ...props }, ref) {
|
|
32
|
+
return (_jsx(AccordionPrimitive.Content, { ...props, className: classes('inkra-accordion__content', className), ref: ref, children: _jsx("div", { className: classes('inkra-accordion__content-body', contentClassName), children: children }) }));
|
|
33
|
+
});
|
|
34
|
+
export const Accordion = Object.freeze({
|
|
35
|
+
Root: AccordionRoot,
|
|
36
|
+
Item: AccordionItem,
|
|
37
|
+
Header: AccordionHeader,
|
|
38
|
+
Trigger: AccordionTrigger,
|
|
39
|
+
Content: AccordionContent,
|
|
40
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Accordion, AccordionContent, AccordionHeader, AccordionItem, AccordionRoot, AccordionTrigger, } from './Accordion.js';
|
|
@@ -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): import("react").JSX.Element;
|
|
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,109 @@
|
|
|
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 { PortalThemeBridge, PortalThemeProvider, 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 (_jsx(DialogPrimitive.Portal, { ...props, children: _jsx(PortalThemeBridge, { children: children }) }));
|
|
36
|
+
}
|
|
37
|
+
export const AlertDialogBackdrop = forwardRef(function AlertDialogBackdrop({ className, ...props }, ref) {
|
|
38
|
+
return (_jsx(DialogPrimitive.Overlay, { ...props, className: classes('inkra-alert-dialog__backdrop', className), ref: ref }));
|
|
39
|
+
});
|
|
40
|
+
export const AlertDialogContent = forwardRef(function AlertDialogContent({ children, className, onEscapeKeyDown, onInteractOutside, onOpenAutoFocus, onPointerDownOutside, seed, ...props }, forwardedRef) {
|
|
41
|
+
const context = useContext(AlertDialogContext);
|
|
42
|
+
const contentRef = useRef(null);
|
|
43
|
+
const id = useId();
|
|
44
|
+
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 => {
|
|
45
|
+
contentRef.current = node;
|
|
46
|
+
assignRef(forwardedRef, node);
|
|
47
|
+
}, onEscapeKeyDown: event => {
|
|
48
|
+
onEscapeKeyDown?.(event);
|
|
49
|
+
if (context?.pending)
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
}, onInteractOutside: event => {
|
|
52
|
+
onInteractOutside?.(event);
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
}, onPointerDownOutside: event => {
|
|
55
|
+
onPointerDownOutside?.(event);
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
}, onOpenAutoFocus: event => {
|
|
58
|
+
onOpenAutoFocus?.(event);
|
|
59
|
+
if (event.defaultPrevented)
|
|
60
|
+
return;
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
queueMicrotask(() => (context?.cancelRef.current ?? contentRef.current)?.focus());
|
|
63
|
+
}, 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 }) }) }));
|
|
64
|
+
});
|
|
65
|
+
export const AlertDialogTitle = forwardRef(function AlertDialogTitle({ children, className, seed, ...props }, ref) {
|
|
66
|
+
const id = useId();
|
|
67
|
+
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 }) }));
|
|
68
|
+
});
|
|
69
|
+
export const AlertDialogDescription = forwardRef(function AlertDialogDescription({ children, className, seed, ...props }, ref) {
|
|
70
|
+
const id = useId();
|
|
71
|
+
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 }) }));
|
|
72
|
+
});
|
|
73
|
+
export const AlertDialogHeader = forwardRef(function AlertDialogHeader({ children, className, divided = true, ...props }, ref) {
|
|
74
|
+
const id = useId();
|
|
75
|
+
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] }));
|
|
76
|
+
});
|
|
77
|
+
export const AlertDialogBody = forwardRef(function AlertDialogBody({ className, ...props }, ref) {
|
|
78
|
+
return _jsx("div", { ...props, className: classes('inkra-alert-dialog__body', className), ref: ref });
|
|
79
|
+
});
|
|
80
|
+
export const AlertDialogFooter = forwardRef(function AlertDialogFooter({ align = 'end', children, className, divided = true, ...props }, ref) {
|
|
81
|
+
const id = useId();
|
|
82
|
+
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] }));
|
|
83
|
+
});
|
|
84
|
+
export const AlertDialogCancel = forwardRef(function AlertDialogCancel({ disabled, variant = 'secondary', ...props }, forwardedRef) {
|
|
85
|
+
const context = useContext(AlertDialogContext);
|
|
86
|
+
return (_jsx(DialogPrimitive.Close, { asChild: true, children: _jsx(Button, { ...props, disabled: disabled || context?.pending, ref: node => {
|
|
87
|
+
assignRef(forwardedRef, node);
|
|
88
|
+
assignRef(context?.cancelRef, node);
|
|
89
|
+
}, type: "button", variant: variant }) }));
|
|
90
|
+
});
|
|
91
|
+
export const AlertDialogAction = forwardRef(function AlertDialogAction({ closeOnAction = true, disabled, loading, variant = 'destructive', ...props }, ref) {
|
|
92
|
+
const pending = useContext(AlertDialogContext)?.pending ?? false;
|
|
93
|
+
const button = (_jsx(Button, { ...props, "aria-busy": pending || undefined, disabled: disabled || pending, loading: loading || pending, ref: ref, type: "button", variant: variant }));
|
|
94
|
+
return closeOnAction ? _jsx(DialogPrimitive.Close, { asChild: true, children: button }) : button;
|
|
95
|
+
});
|
|
96
|
+
export const AlertDialog = Object.freeze({
|
|
97
|
+
Root: AlertDialogRoot,
|
|
98
|
+
Trigger: AlertDialogTrigger,
|
|
99
|
+
Portal: AlertDialogPortal,
|
|
100
|
+
Backdrop: AlertDialogBackdrop,
|
|
101
|
+
Content: AlertDialogContent,
|
|
102
|
+
Header: AlertDialogHeader,
|
|
103
|
+
Body: AlertDialogBody,
|
|
104
|
+
Footer: AlertDialogFooter,
|
|
105
|
+
Title: AlertDialogTitle,
|
|
106
|
+
Description: AlertDialogDescription,
|
|
107
|
+
Cancel: AlertDialogCancel,
|
|
108
|
+
Action: AlertDialogAction,
|
|
109
|
+
});
|
|
Binary file
|
|
@@ -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>>;
|