@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.
Files changed (267) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +316 -2
  3. package/THIRD_PARTY_NOTICES.md +39 -0
  4. package/Yozai-OFL.txt +94 -0
  5. package/dist/Button.d.ts +36 -0
  6. package/dist/Button.js +89 -0
  7. package/dist/PencilIcon.d.ts +22 -0
  8. package/dist/PencilIcon.js +210 -0
  9. package/dist/PencilLine.d.ts +10 -0
  10. package/dist/PencilLine.js +91 -0
  11. package/dist/PencilSurface.d.ts +19 -0
  12. package/dist/PencilSurface.js +19 -0
  13. package/dist/PencilText.d.ts +16 -0
  14. package/dist/PencilText.js +338 -0
  15. package/dist/accordion/Accordion.d.ts +27 -0
  16. package/dist/accordion/Accordion.js +40 -0
  17. package/dist/accordion/index.d.ts +2 -0
  18. package/dist/accordion/index.js +1 -0
  19. package/dist/alert-dialog/index.d.ts +64 -0
  20. package/dist/alert-dialog/index.js +109 -0
  21. package/dist/assets/ui-hand-yozai.woff2 +0 -0
  22. package/dist/audio-player/index.d.ts +60 -0
  23. package/dist/audio-player/index.js +101 -0
  24. package/dist/breadcrumb/index.d.ts +16 -0
  25. package/dist/breadcrumb/index.js +25 -0
  26. package/dist/calendar/index.d.ts +21 -0
  27. package/dist/calendar/index.js +41 -0
  28. package/dist/carousel/index.d.ts +51 -0
  29. package/dist/carousel/index.js +290 -0
  30. package/dist/choice-grid/index.d.ts +38 -0
  31. package/dist/choice-grid/index.js +85 -0
  32. package/dist/color-picker/color.d.ts +15 -0
  33. package/dist/color-picker/color.js +55 -0
  34. package/dist/color-picker/index.d.ts +31 -0
  35. package/dist/color-picker/index.js +69 -0
  36. package/dist/command/index.d.ts +23 -0
  37. package/dist/command/index.js +39 -0
  38. package/dist/content/index.d.ts +106 -0
  39. package/dist/content/index.js +80 -0
  40. package/dist/context-menu/index.d.ts +76 -0
  41. package/dist/context-menu/index.js +240 -0
  42. package/dist/data-table/index.d.ts +47 -0
  43. package/dist/data-table/index.js +91 -0
  44. package/dist/date-picker/index.d.ts +50 -0
  45. package/dist/date-picker/index.js +180 -0
  46. package/dist/day-agenda/index.d.ts +43 -0
  47. package/dist/day-agenda/index.js +47 -0
  48. package/dist/day-agenda/layout.d.ts +20 -0
  49. package/dist/day-agenda/layout.js +60 -0
  50. package/dist/display/ProgressRing.d.ts +6 -0
  51. package/dist/display/ProgressRing.js +146 -0
  52. package/dist/display/index.d.ts +59 -0
  53. package/dist/display/index.js +75 -0
  54. package/dist/dockable-panel/index.d.ts +41 -0
  55. package/dist/dockable-panel/index.js +253 -0
  56. package/dist/dockable-panel/model.d.ts +21 -0
  57. package/dist/dockable-panel/model.js +61 -0
  58. package/dist/drawer/index.d.ts +63 -0
  59. package/dist/drawer/index.js +86 -0
  60. package/dist/dropdown-menu/index.d.ts +34 -0
  61. package/dist/dropdown-menu/index.js +40 -0
  62. package/dist/editable/index.d.ts +53 -0
  63. package/dist/editable/index.js +162 -0
  64. package/dist/empty/index.d.ts +21 -0
  65. package/dist/empty/index.js +23 -0
  66. package/dist/flip/index.d.ts +49 -0
  67. package/dist/flip/index.js +138 -0
  68. package/dist/form/EditablePencilText.d.ts +13 -0
  69. package/dist/form/EditablePencilText.js +323 -0
  70. package/dist/form/Field.d.ts +13 -0
  71. package/dist/form/Field.js +26 -0
  72. package/dist/form/Input.d.ts +27 -0
  73. package/dist/form/Input.js +97 -0
  74. package/dist/form/InputAction.d.ts +7 -0
  75. package/dist/form/InputAction.js +24 -0
  76. package/dist/form/Textarea.d.ts +17 -0
  77. package/dist/form/Textarea.js +102 -0
  78. package/dist/form/context.d.ts +12 -0
  79. package/dist/form/context.js +10 -0
  80. package/dist/form/controlProps.d.ts +23 -0
  81. package/dist/form/controlProps.js +20 -0
  82. package/dist/form/index.d.ts +7 -0
  83. package/dist/form/index.js +3 -0
  84. package/dist/form/types.d.ts +6 -0
  85. package/dist/form/types.js +1 -0
  86. package/dist/heatmap/index.d.ts +59 -0
  87. package/dist/heatmap/index.js +248 -0
  88. package/dist/hotkey/index.d.ts +37 -0
  89. package/dist/hotkey/index.js +130 -0
  90. package/dist/hotkey/model.d.ts +27 -0
  91. package/dist/hotkey/model.js +97 -0
  92. package/dist/hover-card/index.d.ts +33 -0
  93. package/dist/hover-card/index.js +141 -0
  94. package/dist/image-cropper/index.d.ts +82 -0
  95. package/dist/image-cropper/index.js +261 -0
  96. package/dist/image-cropper/model.d.ts +42 -0
  97. package/dist/image-cropper/model.js +94 -0
  98. package/dist/image-viewer/index.d.ts +79 -0
  99. package/dist/image-viewer/index.js +220 -0
  100. package/dist/image-viewer/model.d.ts +9 -0
  101. package/dist/image-viewer/model.js +18 -0
  102. package/dist/images/layers-2x.png +0 -0
  103. package/dist/images/layers.png +0 -0
  104. package/dist/images/marker-icon.png +0 -0
  105. package/dist/index.d.ts +75 -0
  106. package/dist/index.js +69 -0
  107. package/dist/input-number/index.d.ts +16 -0
  108. package/dist/input-number/index.js +77 -0
  109. package/dist/internal/InputActionContext.d.ts +1 -0
  110. package/dist/internal/InputActionContext.js +3 -0
  111. package/dist/internal/cache.d.ts +14 -0
  112. package/dist/internal/cache.js +54 -0
  113. package/dist/internal/line.d.ts +4 -0
  114. package/dist/internal/line.js +21 -0
  115. package/dist/internal/paper.d.ts +1 -0
  116. package/dist/internal/paper.js +65 -0
  117. package/dist/internal/random.d.ts +3 -0
  118. package/dist/internal/random.js +30 -0
  119. package/dist/internal/recovery.d.ts +1 -0
  120. package/dist/internal/recovery.js +52 -0
  121. package/dist/internal/renderTokens.d.ts +10 -0
  122. package/dist/internal/renderTokens.js +13 -0
  123. package/dist/internal/stroke.d.ts +24 -0
  124. package/dist/internal/stroke.js +144 -0
  125. package/dist/internal/surfaceRenderer.d.ts +41 -0
  126. package/dist/internal/surfaceRenderer.js +178 -0
  127. package/dist/internal/textQueue.d.ts +1 -0
  128. package/dist/internal/textQueue.js +37 -0
  129. package/dist/internal/textRenderer.d.ts +28 -0
  130. package/dist/internal/textRenderer.js +239 -0
  131. package/dist/internal/travelIcons.d.ts +24 -0
  132. package/dist/internal/travelIcons.js +14 -0
  133. package/dist/internal/useBrowserLayoutEffect.d.ts +2 -0
  134. package/dist/internal/useBrowserLayoutEffect.js +3 -0
  135. package/dist/internal/usePencilSurface.d.ts +3 -0
  136. package/dist/internal/usePencilSurface.js +116 -0
  137. package/dist/internal/useSelectionDrawing.d.ts +2 -0
  138. package/dist/internal/useSelectionDrawing.js +90 -0
  139. package/dist/internal/wash.d.ts +16 -0
  140. package/dist/internal/wash.js +149 -0
  141. package/dist/journey-map/MapScale.d.ts +4 -0
  142. package/dist/journey-map/MapScale.js +54 -0
  143. package/dist/journey-map/index.d.ts +39 -0
  144. package/dist/journey-map/index.js +197 -0
  145. package/dist/journey-map/terrain.d.ts +8 -0
  146. package/dist/journey-map/terrain.js +127 -0
  147. package/dist/keypad/index.d.ts +23 -0
  148. package/dist/keypad/index.js +63 -0
  149. package/dist/keypad/model.d.ts +20 -0
  150. package/dist/keypad/model.js +33 -0
  151. package/dist/layout/index.d.ts +63 -0
  152. package/dist/layout/index.js +62 -0
  153. package/dist/log/index.d.ts +45 -0
  154. package/dist/log/index.js +159 -0
  155. package/dist/log/model.d.ts +16 -0
  156. package/dist/log/model.js +13 -0
  157. package/dist/node-graph/index.d.ts +123 -0
  158. package/dist/node-graph/index.js +304 -0
  159. package/dist/number-ticker/index.d.ts +29 -0
  160. package/dist/number-ticker/index.js +132 -0
  161. package/dist/number-ticker/model.d.ts +8 -0
  162. package/dist/number-ticker/model.js +34 -0
  163. package/dist/overflow-list/index.d.ts +39 -0
  164. package/dist/overflow-list/index.js +230 -0
  165. package/dist/overflow-list/layout.d.ts +19 -0
  166. package/dist/overflow-list/layout.js +44 -0
  167. package/dist/overlay/Overlay.d.ts +65 -0
  168. package/dist/overlay/Overlay.js +77 -0
  169. package/dist/overlay/Popover.d.ts +43 -0
  170. package/dist/overlay/Popover.js +45 -0
  171. package/dist/overlay/index.d.ts +4 -0
  172. package/dist/overlay/index.js +2 -0
  173. package/dist/overlay/themeBridge.d.ts +8 -0
  174. package/dist/overlay/themeBridge.js +98 -0
  175. package/dist/pagination/index.d.ts +23 -0
  176. package/dist/pagination/index.js +41 -0
  177. package/dist/pagination/model.d.ts +4 -0
  178. package/dist/pagination/model.js +42 -0
  179. package/dist/pan-zoom/index.d.ts +71 -0
  180. package/dist/pan-zoom/index.js +175 -0
  181. package/dist/pencil.d.ts +10 -0
  182. package/dist/pencil.js +39 -0
  183. package/dist/radar/index.d.ts +54 -0
  184. package/dist/radar/index.js +220 -0
  185. package/dist/range-slider/index.d.ts +16 -0
  186. package/dist/range-slider/index.js +22 -0
  187. package/dist/rating/index.d.ts +28 -0
  188. package/dist/rating/index.js +127 -0
  189. package/dist/resizable/index.d.ts +32 -0
  190. package/dist/resizable/index.js +50 -0
  191. package/dist/scroll-area/index.d.ts +36 -0
  192. package/dist/scroll-area/index.js +44 -0
  193. package/dist/segmented-progress/SegmentedProgress.d.ts +17 -0
  194. package/dist/segmented-progress/SegmentedProgress.js +42 -0
  195. package/dist/select/MultipleSelect.d.ts +44 -0
  196. package/dist/select/MultipleSelect.js +124 -0
  197. package/dist/select/SearchableSelect.d.ts +45 -0
  198. package/dist/select/SearchableSelect.js +50 -0
  199. package/dist/select/Select.d.ts +109 -0
  200. package/dist/select/Select.js +205 -0
  201. package/dist/select/index.d.ts +4 -0
  202. package/dist/select/index.js +2 -0
  203. package/dist/selection/Checkbox.d.ts +9 -0
  204. package/dist/selection/Checkbox.js +37 -0
  205. package/dist/selection/RadioGroup.d.ts +23 -0
  206. package/dist/selection/RadioGroup.js +82 -0
  207. package/dist/selection/Switch.d.ts +8 -0
  208. package/dist/selection/Switch.js +36 -0
  209. package/dist/selection/index.d.ts +6 -0
  210. package/dist/selection/index.js +3 -0
  211. package/dist/selection/useNativeChecked.d.ts +13 -0
  212. package/dist/selection/useNativeChecked.js +27 -0
  213. package/dist/slider/index.d.ts +11 -0
  214. package/dist/slider/index.js +45 -0
  215. package/dist/slot/index.d.ts +24 -0
  216. package/dist/slot/index.js +29 -0
  217. package/dist/sortable/index.d.ts +50 -0
  218. package/dist/sortable/index.js +278 -0
  219. package/dist/sortable/model.d.ts +30 -0
  220. package/dist/sortable/model.js +64 -0
  221. package/dist/sparkline/index.d.ts +19 -0
  222. package/dist/sparkline/index.js +240 -0
  223. package/dist/sparkline/model.d.ts +16 -0
  224. package/dist/sparkline/model.js +28 -0
  225. package/dist/steps/index.d.ts +16 -0
  226. package/dist/steps/index.js +37 -0
  227. package/dist/styles.css +8226 -0
  228. package/dist/tabs/index.d.ts +22 -0
  229. package/dist/tabs/index.js +42 -0
  230. package/dist/tag-input/index.d.ts +69 -0
  231. package/dist/tag-input/index.js +325 -0
  232. package/dist/tag-input/model.d.ts +14 -0
  233. package/dist/tag-input/model.js +38 -0
  234. package/dist/time-picker/index.d.ts +15 -0
  235. package/dist/time-picker/index.js +168 -0
  236. package/dist/timeline/index.d.ts +14 -0
  237. package/dist/timeline/index.js +16 -0
  238. package/dist/toast/index.d.ts +27 -0
  239. package/dist/toast/index.js +36 -0
  240. package/dist/toggle-group/index.d.ts +17 -0
  241. package/dist/toggle-group/index.js +26 -0
  242. package/dist/tokens.css +356 -0
  243. package/dist/tooltip/Tooltip.d.ts +24 -0
  244. package/dist/tooltip/Tooltip.js +32 -0
  245. package/dist/tooltip/index.d.ts +2 -0
  246. package/dist/tooltip/index.js +1 -0
  247. package/dist/transfer/index.d.ts +64 -0
  248. package/dist/transfer/index.js +174 -0
  249. package/dist/transfer/model.d.ts +12 -0
  250. package/dist/transfer/model.js +33 -0
  251. package/dist/tree/index.d.ts +39 -0
  252. package/dist/tree/index.js +36 -0
  253. package/dist/tree-select/index.d.ts +59 -0
  254. package/dist/tree-select/index.js +142 -0
  255. package/dist/tree-select/model.d.ts +31 -0
  256. package/dist/tree-select/model.js +135 -0
  257. package/dist/typewriter/index.d.ts +21 -0
  258. package/dist/typewriter/index.js +101 -0
  259. package/dist/typewriter/model.d.ts +7 -0
  260. package/dist/typewriter/model.js +45 -0
  261. package/dist/upload/index.d.ts +59 -0
  262. package/dist/upload/index.js +230 -0
  263. package/dist/virtual-list/index.d.ts +44 -0
  264. package/dist/virtual-list/index.js +128 -0
  265. package/dist/virtual-list/model.d.ts +7 -0
  266. package/dist/virtual-list/model.js +27 -0
  267. package/package.json +119 -4
@@ -0,0 +1,220 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { scaleLinear } from 'd3-scale';
3
+ import { curveLinearClosed, lineRadial } from 'd3-shape';
4
+ import { forwardRef, useEffect, useId, useMemo, useRef, useState } from 'react';
5
+ import { PencilSurface } from '../PencilSurface.js';
6
+ import { PencilText } from '../PencilText.js';
7
+ import { Button } from '../Button.js';
8
+ import { Table } from '../content/index.js';
9
+ import { observeCanvasRecovery } from '../internal/recovery.js';
10
+ import { seedToNumber } from '../internal/random.js';
11
+ import { pencilStroke } from '../internal/stroke.js';
12
+ import { drawPencilWash } from '../internal/wash.js';
13
+ import { effectiveDpr } from '../internal/cache.js';
14
+ import { maxStrokeRoughness, pencilRenderDefaults, readRenderToken } from '../internal/renderTokens.js';
15
+ function RadarInk({ axisAngles, axes, levels, radius, center, seriesPoints, }) {
16
+ const canvasRef = useRef(null);
17
+ const [ready, setReady] = useState(false);
18
+ useEffect(() => {
19
+ const canvas = canvasRef.current;
20
+ if (!canvas)
21
+ return undefined;
22
+ let disposed = false;
23
+ let lastPaint = '';
24
+ const paint = () => {
25
+ const width = canvas.clientWidth;
26
+ const height = canvas.clientHeight;
27
+ if (!width || !height) {
28
+ lastPaint = '';
29
+ delete canvas.dataset.ready;
30
+ setReady(false);
31
+ return;
32
+ }
33
+ try {
34
+ const dpr = effectiveDpr(2);
35
+ const context = canvas.getContext('2d');
36
+ if (!context || context.isContextLost?.()) {
37
+ setReady(current => current ? false : current);
38
+ return;
39
+ }
40
+ const style = getComputedStyle(canvas);
41
+ const strokeWidth = readRenderToken(style, '--inkra-stroke-width', pencilRenderDefaults.strokeWidth, 0.3, 3);
42
+ const roughness = readRenderToken(style, '--inkra-stroke-amplitude', pencilRenderDefaults.strokeRoughness, 0, maxStrokeRoughness);
43
+ const washStrength = readRenderToken(style, '--inkra-wash-strength', pencilRenderDefaults.washStrength, 0, 1)
44
+ * (0.18 / pencilRenderDefaults.washStrength);
45
+ const washSpacing = readRenderToken(style, '--inkra-wash-spacing', pencilRenderDefaults.washSpacing, 1, 6);
46
+ const washRoughness = readRenderToken(style, '--inkra-wash-roughness', pencilRenderDefaults.washRoughness, 0, 6);
47
+ const washAngle = readRenderToken(style, '--inkra-wash-angle', pencilRenderDefaults.washAngle, -85, 85);
48
+ const washInset = readRenderToken(style, '--inkra-wash-inset', 2, 0, 24);
49
+ const resolveColor = (token, fallback) => style.getPropertyValue(token).trim() || fallback;
50
+ const resolvePaint = (value, fallback) => {
51
+ const probe = document.createElement('span');
52
+ probe.style.color = value;
53
+ probe.style.position = 'absolute';
54
+ probe.style.inlineSize = '0';
55
+ probe.style.blockSize = '0';
56
+ canvas.parentElement?.appendChild(probe);
57
+ const resolved = getComputedStyle(probe).color;
58
+ probe.remove();
59
+ return resolved && resolved !== 'rgba(0, 0, 0, 0)' ? resolved : fallback;
60
+ };
61
+ const borderColor = resolveColor('--inkra-border', '#99aa9b');
62
+ const paperColor = resolveColor('--inkra-paper', '#f4f0e3');
63
+ const resolvedSeriesColors = seriesPoints.map(entry => resolvePaint(entry.color, borderColor));
64
+ const key = JSON.stringify([width, height, dpr, borderColor, paperColor, strokeWidth, roughness, washStrength, washSpacing, washRoughness, washAngle, washInset, levels, radius, axisAngles, resolvedSeriesColors, seriesPoints.map(entry => [entry.item.id, entry.points.map(point => point.value)])]);
65
+ if (key === lastPaint && canvas.dataset.ready === 'true')
66
+ return;
67
+ canvas.width = Math.ceil(width * dpr);
68
+ canvas.height = Math.ceil(height * dpr);
69
+ context.setTransform(dpr, 0, 0, dpr, 0, 0);
70
+ context.clearRect(0, 0, width, height);
71
+ const scaleX = width / 1000;
72
+ const scaleY = height / 1000;
73
+ const line = (points, color, weight, seed, closed = false) => {
74
+ if (points.length < 2)
75
+ return;
76
+ const path = closed ? [...points, points[0]] : points;
77
+ pencilStroke(context, path, color, weight, seedToNumber(seed), roughness, 2, closed, { variation: 0.82, breaks: 0.2, grain: 0.72, gain: 2.1, step: 0.7 });
78
+ };
79
+ const coordinate = (angle, r) => [(center + Math.sin(angle) * r) * scaleX, (center - Math.cos(angle) * r) * scaleY];
80
+ const gridColor = borderColor;
81
+ for (let level = 1; level <= levels; level += 1) {
82
+ line(axisAngles.map(angle => coordinate(angle, radius * level / levels)), gridColor, strokeWidth * 0.55, `radar-grid-${level}`, true);
83
+ }
84
+ axes.forEach((_, index) => line([coordinate(0, 0), coordinate(axisAngles[index], radius)], gridColor, strokeWidth * 0.5, `radar-axis-${index}`));
85
+ seriesPoints.forEach(({ item, points, index }, seriesIndex) => {
86
+ const resolvedColor = resolvedSeriesColors[seriesIndex];
87
+ const valid = points.filter(point => point.value != null).map(point => coordinate(point.angle, point.radius));
88
+ if (valid.length < 2)
89
+ return;
90
+ const minX = Math.min(...valid.map(point => point[0]));
91
+ const maxX = Math.max(...valid.map(point => point[0]));
92
+ const minY = Math.min(...valid.map(point => point[1]));
93
+ const maxY = Math.max(...valid.map(point => point[1]));
94
+ context.save();
95
+ context.beginPath();
96
+ valid.forEach(([x, y], pointIndex) => pointIndex ? context.lineTo(x, y) : context.moveTo(x, y));
97
+ context.closePath();
98
+ context.clip();
99
+ drawPencilWash(context, { x: minX, y: minY, width: Math.max(1, maxX - minX), height: Math.max(1, maxY - minY) }, resolvedColor, seedToNumber(`radar-wash-${String(item.id)}`), { strength: washStrength, spacing: washSpacing, roughness: washRoughness, inset: washInset, radius: 8, edgeReach: 4, angle: washAngle, dpr });
100
+ context.restore();
101
+ line(valid, resolvedColor, strokeWidth * (0.68 + (index === 0 ? 0.12 : 0)), `radar-series-${String(item.id)}`, true);
102
+ points.forEach((point, pointIndex) => {
103
+ if (point.value == null)
104
+ return;
105
+ const [x, y] = coordinate(point.angle, point.radius);
106
+ const marker = index % 3 === 1
107
+ ? [[x - 5, y - 5], [x + 5, y - 5], [x + 5, y + 5], [x - 5, y + 5], [x - 5, y - 5]]
108
+ : index % 3 === 2
109
+ ? [[x, y - 6], [x + 6, y + 5], [x - 6, y + 5], [x, y - 6]]
110
+ : Array.from({ length: 25 }, (_, markerIndex) => { const angle = markerIndex / 24 * Math.PI * 2; return [x + Math.cos(angle) * 5, y + Math.sin(angle) * 5]; });
111
+ pencilStroke(context, marker, resolvedColor, strokeWidth * 0.9, seedToNumber(`radar-marker-${String(item.id)}-${pointIndex}`), roughness, 2, true, { variation: 0.78, breaks: 0.24, grain: 0.7, gain: 2.1, step: 0.55 });
112
+ void pointIndex;
113
+ });
114
+ });
115
+ lastPaint = key;
116
+ canvas.dataset.ready = 'true';
117
+ if (!disposed)
118
+ setReady(current => current ? current : true);
119
+ }
120
+ catch {
121
+ lastPaint = '';
122
+ delete canvas.dataset.ready;
123
+ setReady(false);
124
+ canvas.width = 1;
125
+ canvas.height = 1;
126
+ canvas.getContext('2d')?.clearRect(0, 0, 1, 1);
127
+ }
128
+ };
129
+ const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(paint);
130
+ const inheritedStyle = new MutationObserver(paint);
131
+ for (let node = canvas; node; node = node.parentElement)
132
+ inheritedStyle.observe(node, { attributes: true, attributeFilter: ['style', 'class', 'dir', 'data-theme', 'data-inkra-theme'] });
133
+ const scheme = window.matchMedia('(prefers-color-scheme: dark)');
134
+ scheme.addEventListener('change', paint);
135
+ const stopRecovery = observeCanvasRecovery(() => { lastPaint = ''; delete canvas.dataset.ready; paint(); });
136
+ observer?.observe(canvas);
137
+ paint();
138
+ return () => { disposed = true; observer?.disconnect(); inheritedStyle.disconnect(); scheme.removeEventListener('change', paint); stopRecovery(); };
139
+ }, [axes, axisAngles, center, levels, radius, seriesPoints]);
140
+ return _jsx("canvas", { "aria-hidden": "true", className: "inkra-radar__ink", "data-ready": ready || undefined, ref: canvasRef });
141
+ }
142
+ const palette = ['#4b96aa', '#994f3f', '#629568', '#8d6b9c', '#c58b47'];
143
+ function keyPart(value) { return JSON.stringify([typeof value, value]); }
144
+ function sameKey(a, b) { return a != null && b != null && a === b; }
145
+ function axisText(axis) { return axis.ariaLabel ?? (typeof axis.label === 'string' || typeof axis.label === 'number' ? String(axis.label) : String(axis.id)); }
146
+ function cssSize(value, fallback) {
147
+ if (typeof value === 'number')
148
+ return Number.isFinite(value) ? `${Math.max(220, value)}px` : fallback;
149
+ return value || fallback;
150
+ }
151
+ function finite(value) { return typeof value === 'number' && Number.isFinite(value); }
152
+ function formatNumber(value, axis, getValueLabel) {
153
+ return axis.formatValue?.(value) ?? getValueLabel?.(value, axis) ?? String(value);
154
+ }
155
+ function textNode(value, seed) {
156
+ return typeof value === 'string' || typeof value === 'number' ? _jsx(PencilText, { seed: seed, children: String(value) }) : value;
157
+ }
158
+ function domainForAxis(axis, values) {
159
+ let min = finite(axis.min) ? axis.min : values.length ? Math.min(...values) : 0;
160
+ let max = finite(axis.max) ? axis.max : values.length ? Math.max(...values) : 1;
161
+ if (min > max)
162
+ [min, max] = [max, min];
163
+ if (min === max) {
164
+ const pad = Math.abs(min) * 0.5 || 1;
165
+ return [min - pad, max + pad];
166
+ }
167
+ return [min, max];
168
+ }
169
+ function paintStyle(color) {
170
+ return { '--inkra-accent': color, '--inkra-accent-soft': color, '--inkra-accent-strong': color };
171
+ }
172
+ export const Radar = forwardRef(function Radar({ axes, series, label, description, size = 'min(100%, 34rem)', maxRadius, levels = 4, showAxes = true, showLabels = true, showLegend = true, showValues = true, showTable = true, legendLabel = 'Series', missingLabel = 'Missing', emptyMessage = 'No radar data', selectedSeries, defaultSelectedSeries = null, onSelectedSeriesChange, renderAxisLabel, renderValueLabel, getValueLabel, className, style, ...props }, forwardedRef) {
173
+ const id = useId();
174
+ const labelId = `inkra-radar-${id}-label`;
175
+ const descriptionId = description == null ? undefined : `inkra-radar-${id}-description`;
176
+ const [internalSelected, setInternalSelected] = useState(defaultSelectedSeries);
177
+ const selected = selectedSeries === undefined ? internalSelected : selectedSeries ?? null;
178
+ const visibleSeries = series.filter(item => !item.hidden);
179
+ const domains = useMemo(() => new Map(axes.map(axis => {
180
+ const values = visibleSeries.flatMap(item => item.data.filter(point => point.axisId === axis.id && finite(point.value)).map(point => point.value));
181
+ return [keyPart(axis.id), domainForAxis(axis, values)];
182
+ })), [axes, visibleSeries]);
183
+ const side = 1000;
184
+ const radius = Math.max(120, Math.min(maxRadius ?? 390, 470));
185
+ const axisCount = axes.length;
186
+ const angles = axes.map((_, index) => (index * Math.PI * 2) / Math.max(1, axisCount));
187
+ const center = side / 2;
188
+ const valuePoints = (item) => axes.map((axis, index) => {
189
+ const point = item.data.find(candidate => candidate.axisId === axis.id) ?? { axisId: axis.id, value: null };
190
+ const domain = domains.get(keyPart(axis.id)) ?? [0, 1];
191
+ const value = finite(point.value) ? point.value : null;
192
+ const scale = scaleLinear().domain(domain).range([0, radius]).clamp(true);
193
+ return { angle: angles[index], radius: value == null ? 0 : scale(value), value, point, axis };
194
+ });
195
+ const line = useMemo(() => lineRadial().angle(point => point.angle).radius(point => point.radius).curve(curveLinearClosed), []);
196
+ const rootStyle = { ...style, '--inkra-radar-size': cssSize(size, 'min(100%, 34rem)'), '--inkra-radar-levels': Math.max(2, Math.min(8, Math.round(levels))) };
197
+ const selectSeries = (item) => {
198
+ const next = sameKey(selected, item.id) ? null : item.id;
199
+ if (selectedSeries === undefined)
200
+ setInternalSelected(next);
201
+ onSelectedSeriesChange?.(next, next == null ? null : item);
202
+ };
203
+ const renderValue = (context) => {
204
+ if (renderValueLabel)
205
+ return renderValueLabel(context);
206
+ return context.missing ? missingLabel : showValues ? formatNumber(context.value, context.axis, getValueLabel) : '•';
207
+ };
208
+ return _jsxs("div", { ...props, ref: forwardedRef, className: ['inkra-radar', className].filter(Boolean).join(' '), style: rootStyle, children: [_jsxs("div", { className: "inkra-radar__heading", children: [_jsx("div", { className: "inkra-radar__label", id: labelId, children: typeof label === 'string' ? _jsx(PencilText, { seed: `${id}-label`, children: label }) : label }), description == null ? null : _jsx("div", { className: "inkra-radar__description", id: descriptionId, children: textNode(description, `${id}-description`) })] }), axes.length < 3 || visibleSeries.length === 0 ? _jsx("div", { className: "inkra-radar__empty", children: textNode(emptyMessage, `${id}-empty`) }) : _jsxs(_Fragment, { children: [_jsxs("div", { className: "inkra-radar__viewport", children: [_jsx(RadarInk, { axisAngles: angles, axes: showAxes ? axes : [], center: center, levels: Math.max(2, Math.min(8, Math.round(levels))), radius: radius, seriesPoints: visibleSeries.map((item, index) => ({ item, points: valuePoints(item), color: item.color ?? palette[index % palette.length], index })) }), _jsxs("svg", { "aria-hidden": "true", className: "inkra-radar__svg-fallback", viewBox: `0 0 ${side} ${side}`, focusable: "false", role: "presentation", children: [_jsx("circle", { cx: center, cy: center, r: radius, fill: "none", stroke: "currentColor", strokeWidth: "1" }), visibleSeries.map(item => _jsx("path", { d: line(valuePoints(item)) ?? undefined, transform: `translate(${center} ${center})` }, keyPart(item.id)))] }), showLabels ? _jsx("div", { "aria-hidden": "true", className: "inkra-radar__labels", children: axes.map((axis, index) => {
209
+ const x = 50 + Math.sin(angles[index]) * 48;
210
+ const y = 50 - Math.cos(angles[index]) * 48;
211
+ return _jsx("span", { className: "inkra-radar__axis-label", style: { left: `${x}%`, top: `${y}%` }, children: renderAxisLabel ? renderAxisLabel(axis) : textNode(axis.label, `${id}-axis-${String(axis.id)}`) }, keyPart(axis.id));
212
+ }) }) : null] }), _jsx("div", { "aria-describedby": descriptionId, "aria-labelledby": labelId, className: "inkra-radar__summary", role: "group", children: visibleSeries.map((item, index) => {
213
+ const points = valuePoints(item);
214
+ const color = item.color ?? palette[index % palette.length];
215
+ return _jsxs("div", { className: "inkra-radar__series-summary", "data-series-id": item.id, children: [_jsxs(Button, { "aria-pressed": sameKey(selected, item.id), className: "inkra-radar__legend-button", onClick: () => selectSeries(item), size: "sm", variant: "ghost", children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-radar__legend-mark", radius: 4, seed: `radar-${keyPart(item.id)}`, style: paintStyle(color), variant: sameKey(selected, item.id) ? 'selection' : 'quiet' }), textNode(item.label, `${id}-summary-${String(item.id)}`)] }), _jsx("div", { className: "inkra-radar__values", children: points.map((point, pointIndex) => {
216
+ const context = { axis: point.axis, series: item, point: point.point, value: point.value, missing: point.value == null };
217
+ return _jsxs("span", { className: "inkra-radar__value", "data-missing": context.missing || undefined, children: [_jsx("strong", { children: textNode(point.axis.label, `${id}-value-axis-${String(point.axis.id)}`) }), " ", textNode(renderValue(context), `${id}-value-${String(item.id)}-${String(point.axis.id)}`)] }, pointIndex);
218
+ }) })] }, keyPart(item.id));
219
+ }) }), showLegend ? _jsxs("div", { "aria-label": typeof legendLabel === 'string' ? legendLabel : undefined, className: "inkra-radar__legend", role: "group", children: [_jsx("span", { className: "inkra-radar__legend-title", children: textNode(legendLabel, `${id}-legend-title`) }), visibleSeries.map((item, index) => _jsxs(Button, { "aria-pressed": sameKey(selected, item.id), className: "inkra-radar__legend-button", onClick: () => selectSeries(item), size: "sm", variant: "ghost", children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-radar__legend-mark", radius: 4, seed: `radar-legend-${keyPart(item.id)}`, style: paintStyle(item.color ?? palette[index % palette.length]), variant: sameKey(selected, item.id) ? 'selection' : 'quiet' }), textNode(item.label, `${id}-legend-${String(item.id)}`)] }, keyPart(item.id)))] }) : null, showTable ? _jsx(Table.Container, { "aria-label": typeof label === 'string' ? label : undefined, "aria-describedby": descriptionId, children: _jsxs(Table.Root, { className: "inkra-radar__table", children: [_jsx(Table.Caption, { children: textNode('Radar data', `${id}-table-caption`) }), _jsx(Table.Header, { children: _jsxs(Table.Row, { children: [_jsx(Table.Head, { children: textNode('Series', `${id}-table-series`) }), axes.map(axis => _jsx(Table.Head, { children: textNode(axis.label, `${id}-table-axis-${String(axis.id)}`) }, keyPart(axis.id)))] }) }), _jsx(Table.Body, { children: visibleSeries.map(item => _jsxs(Table.Row, { children: [_jsx(Table.Head, { scope: "row", children: textNode(item.label, `${id}-table-series-${String(item.id)}`) }), axes.map(axis => { const point = item.data.find(candidate => candidate.axisId === axis.id); const missing = !finite(point?.value); return _jsx(Table.Cell, { "data-missing": missing || undefined, children: textNode(missing ? missingLabel : formatNumber(point?.value, axis, getValueLabel), `${id}-table-value-${String(item.id)}-${String(axis.id)}`) }, keyPart(axis.id)); })] }, keyPart(item.id))) })] }) }) : null] })] });
220
+ });
@@ -0,0 +1,16 @@
1
+ import type { SliderProps } from '../slider/index.js';
2
+ /** A numeric range ordered as [minimum, maximum]. */
3
+ export type RangeSliderValue = [number, number];
4
+ export interface RangeSliderProps extends Omit<SliderProps, 'defaultValue' | 'minStepsBetweenThumbs' | 'onValueChange' | 'onValueCommit' | 'preserveThumbOrder' | 'thumbLabels' | 'value'> {
5
+ value?: RangeSliderValue;
6
+ defaultValue?: RangeSliderValue;
7
+ onValueChange?: (value: RangeSliderValue) => void;
8
+ onValueCommit?: (value: RangeSliderValue) => void;
9
+ /** Minimum numeric distance between endpoints. Rounded up to the next step and ignored when allowCross is true. */
10
+ minDistance?: number;
11
+ /** Allow a thumb to pass the other and exchange its low/high endpoint role. */
12
+ allowCross?: boolean;
13
+ /** Accessible names for the current low and high endpoints. */
14
+ thumbLabels?: readonly [string, string];
15
+ }
16
+ export declare const RangeSlider: import("react").ForwardRefExoticComponent<RangeSliderProps & import("react").RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from 'react';
3
+ import { Slider } from '../slider/index.js';
4
+ const DEFAULT_LABELS = ['Minimum value', 'Maximum value'];
5
+ function asRangeValue(value) {
6
+ return [value[0], value[1]];
7
+ }
8
+ function normalizeRangeValue(value) {
9
+ return value[0] <= value[1] ? value : [value[1], value[0]];
10
+ }
11
+ function getMinimumSteps(minDistance, step) {
12
+ if (!Number.isFinite(minDistance) || minDistance <= 0)
13
+ return 0;
14
+ if (!Number.isFinite(step) || step <= 0)
15
+ return 0;
16
+ return Math.ceil(minDistance / step);
17
+ }
18
+ export const RangeSlider = forwardRef(function RangeSlider({ allowCross = false, defaultValue, max = 100, min = 0, minDistance = 0, onValueChange, onValueCommit, step = 1, thumbLabels = DEFAULT_LABELS, value, ...props }, forwardedRef) {
19
+ const controlledValue = value === undefined ? undefined : normalizeRangeValue(value);
20
+ const uncontrolledDefault = value === undefined ? normalizeRangeValue(defaultValue ?? [min, max]) : undefined;
21
+ return _jsx(Slider, { ...props, defaultValue: uncontrolledDefault, max: max, min: min, minStepsBetweenThumbs: allowCross ? 0 : getMinimumSteps(minDistance, step), onValueChange: next => onValueChange?.(asRangeValue(next)), onValueCommit: next => onValueCommit?.(asRangeValue(next)), preserveThumbOrder: !allowCross, ref: forwardedRef, step: step, thumbLabels: thumbLabels, value: controlledValue });
22
+ });
@@ -0,0 +1,28 @@
1
+ import { type HTMLAttributes, type ReactNode } from 'react';
2
+ export type RatingSize = 'sm' | 'md' | 'lg';
3
+ export type RatingClearStrategy = boolean | 'reselect' | 'keyboard';
4
+ export interface RatingSymbolState {
5
+ /** One-based symbol position. */
6
+ index: number;
7
+ /** Fraction displayed for this symbol, from 0 to 1. */
8
+ fraction: number;
9
+ filled: boolean;
10
+ previewing: boolean;
11
+ }
12
+ export interface RatingProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'defaultValue' | 'onChange'> {
13
+ value?: number;
14
+ defaultValue?: number;
15
+ onValueChange?: (value: number) => void;
16
+ count?: number;
17
+ step?: number;
18
+ clearable?: RatingClearStrategy;
19
+ disabled?: boolean;
20
+ readOnly?: boolean;
21
+ size?: RatingSize;
22
+ dir?: 'ltr' | 'rtl';
23
+ symbol?: ReactNode;
24
+ renderSymbol?: (state: RatingSymbolState) => ReactNode;
25
+ getValueLabel?: (value: number, count: number) => string;
26
+ }
27
+ export declare function normalizeRatingValue(value: number | undefined, count: number, step: number): number;
28
+ export declare const Rating: import("react").ForwardRefExoticComponent<RatingProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,127 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useId, useMemo, useState, } from 'react';
3
+ import { PencilIcon } from '../PencilIcon.js';
4
+ const defaultSymbolPaths = [
5
+ { d: 'M12 2.5 L21.5 12 L12 21.5 L2.5 12 Z' },
6
+ { d: 'M7.5 12 L12 7.5 L16.5 12 L12 16.5 Z', mode: 'scuff' },
7
+ ];
8
+ function finitePositive(value, fallback) {
9
+ return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : fallback;
10
+ }
11
+ function decimalPlaces(value) {
12
+ const [coefficient, exponentText] = String(value).toLowerCase().split('e');
13
+ const [, fraction = ''] = coefficient.split('.');
14
+ const exponent = Number(exponentText ?? 0);
15
+ return Math.max(0, fraction.length - exponent);
16
+ }
17
+ export function normalizeRatingValue(value, count, step) {
18
+ const numeric = typeof value === 'number' && Number.isFinite(value) ? value : 0;
19
+ const precision = Math.min(8, Math.max(decimalPlaces(step), decimalPlaces(count)));
20
+ const snapped = Math.round(numeric / step) * step;
21
+ return Number(Math.min(count, Math.max(0, snapped)).toFixed(precision));
22
+ }
23
+ function allowsReselectClear(clearable) {
24
+ return clearable === true || clearable === 'reselect';
25
+ }
26
+ function allowsKeyboardClear(clearable) {
27
+ return clearable === true || clearable === 'keyboard';
28
+ }
29
+ export const Rating = forwardRef(function Rating({ value, defaultValue = 0, onValueChange, count: countProp = 5, step: stepProp = 1, clearable = false, disabled = false, readOnly = false, size = 'md', dir, symbol, renderSymbol, getValueLabel = (nextValue, maximum) => `${nextValue} of ${maximum}`, className = '', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, onBlur, onKeyDown, onPointerLeave, ...props }, forwardedRef) {
30
+ const count = Math.max(1, Math.floor(finitePositive(countProp, 5)));
31
+ const step = Math.min(count, finitePositive(stepProp, 1));
32
+ const controlled = value !== undefined;
33
+ const [uncontrolledValue, setUncontrolledValue] = useState(() => normalizeRatingValue(defaultValue, count, step));
34
+ const committedValue = normalizeRatingValue(controlled ? value : uncontrolledValue, count, step);
35
+ const [previewValue, setPreviewValue] = useState(null);
36
+ const displayValue = previewValue ?? committedValue;
37
+ const symbolId = useId();
38
+ const symbolIndexes = useMemo(() => Array.from({ length: count }, (_, index) => index), [count]);
39
+ const defaultIconSize = size === 'sm' ? 26 : size === 'lg' ? 38 : 32;
40
+ useEffect(() => {
41
+ if (disabled || readOnly)
42
+ setPreviewValue(null);
43
+ }, [disabled, readOnly]);
44
+ const commit = (nextValue) => {
45
+ if (disabled || readOnly)
46
+ return;
47
+ const normalized = normalizeRatingValue(nextValue, count, step);
48
+ const cleared = normalized === committedValue && normalized !== 0 && allowsReselectClear(clearable);
49
+ const resolved = cleared ? 0 : normalized;
50
+ setPreviewValue(null);
51
+ if (resolved === committedValue)
52
+ return;
53
+ if (!controlled)
54
+ setUncontrolledValue(resolved);
55
+ onValueChange?.(resolved);
56
+ };
57
+ const valueFromPointer = (event, index) => {
58
+ const rect = event.currentTarget.getBoundingClientRect();
59
+ const physicalFraction = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 1;
60
+ const logicalFraction = (dir ?? getComputedStyle(event.currentTarget).direction) === 'rtl'
61
+ ? 1 - physicalFraction
62
+ : physicalFraction;
63
+ const rawValue = index + Math.min(1, Math.max(0, logicalFraction));
64
+ return normalizeRatingValue(Math.max(step, Math.ceil((rawValue - Number.EPSILON) / step) * step), count, step);
65
+ };
66
+ const handleKeyDown = (event) => {
67
+ onKeyDown?.(event);
68
+ if (event.defaultPrevented || disabled || readOnly)
69
+ return;
70
+ const rtl = (dir ?? getComputedStyle(event.currentTarget).direction) === 'rtl';
71
+ let nextValue = null;
72
+ if (event.key === 'ArrowUp')
73
+ nextValue = committedValue + step;
74
+ if (event.key === 'ArrowDown')
75
+ nextValue = committedValue - step;
76
+ if (event.key === 'ArrowRight')
77
+ nextValue = committedValue + (rtl ? -step : step);
78
+ if (event.key === 'ArrowLeft')
79
+ nextValue = committedValue + (rtl ? step : -step);
80
+ if (event.key === 'Home')
81
+ nextValue = allowsKeyboardClear(clearable) ? 0 : Math.min(step, count);
82
+ if (event.key === 'End')
83
+ nextValue = count;
84
+ if (['Backspace', 'Delete', 'Escape'].includes(event.key) && allowsKeyboardClear(clearable))
85
+ nextValue = 0;
86
+ if (nextValue === null)
87
+ return;
88
+ event.preventDefault();
89
+ setPreviewValue(null);
90
+ let normalized = normalizeRatingValue(nextValue, count, step);
91
+ if (normalized === 0 && committedValue > 0 && !allowsKeyboardClear(clearable)) {
92
+ normalized = Math.min(step, count);
93
+ }
94
+ if (normalized === committedValue)
95
+ return;
96
+ if (!controlled)
97
+ setUncontrolledValue(normalized);
98
+ onValueChange?.(normalized);
99
+ };
100
+ const renderLayerSymbol = (index, fraction, filled) => {
101
+ const state = {
102
+ index: index + 1,
103
+ fraction,
104
+ filled,
105
+ previewing: previewValue !== null,
106
+ };
107
+ if (renderSymbol)
108
+ return renderSymbol(state);
109
+ if (symbol !== undefined)
110
+ return symbol;
111
+ return _jsx(PencilIcon, { paths: defaultSymbolPaths, sourceSize: 24, size: defaultIconSize, active: filled, seed: `${symbolId}-${index}` });
112
+ };
113
+ return (_jsx("div", { ...props, "aria-disabled": disabled || undefined, "aria-label": ariaLabel ?? (ariaLabelledBy ? undefined : 'Rating'), "aria-labelledby": ariaLabelledBy, "aria-readonly": readOnly || undefined, "aria-valuemax": count, "aria-valuemin": 0, "aria-valuenow": committedValue, "aria-valuetext": getValueLabel(committedValue, count), className: ['inkra-rating', className].filter(Boolean).join(' '), "data-disabled": disabled || undefined, "data-previewing": previewValue !== null || undefined, "data-readonly": readOnly || undefined, "data-size": size, dir: dir, onBlur: (event) => {
114
+ setPreviewValue(null);
115
+ onBlur?.(event);
116
+ }, onKeyDown: handleKeyDown, onPointerLeave: (event) => {
117
+ setPreviewValue(null);
118
+ onPointerLeave?.(event);
119
+ }, ref: forwardedRef, role: "slider", tabIndex: disabled ? undefined : (props.tabIndex ?? 0), children: _jsx("span", { className: "inkra-rating__symbols", "aria-hidden": "true", children: symbolIndexes.map((index) => {
120
+ const fraction = Math.min(1, Math.max(0, displayValue - index));
121
+ return (_jsxs("span", { className: "inkra-rating__symbol-target", "data-index": index + 1, onClick: (event) => commit(valueFromPointer(event, index)), onPointerMove: (event) => {
122
+ if (event.pointerType === 'mouse' && !disabled && !readOnly) {
123
+ setPreviewValue(valueFromPointer(event, index));
124
+ }
125
+ }, children: [_jsx("span", { className: "inkra-rating__symbol inkra-rating__symbol--empty", children: renderLayerSymbol(index, 0, false) }), _jsx("span", { className: "inkra-rating__fill", style: { inlineSize: `${fraction * 100}%` }, children: _jsx("span", { className: "inkra-rating__symbol inkra-rating__symbol--filled", children: renderLayerSymbol(index, fraction, true) }) })] }, index));
126
+ }) }) }));
127
+ });
@@ -0,0 +1,32 @@
1
+ import { useGroupCallbackRef, useGroupRef, usePanelCallbackRef, usePanelRef } from 'react-resizable-panels';
2
+ import type { Ref } from 'react';
3
+ import type { GroupImperativeHandle, GroupProps, Layout, LayoutChangedMeta, PanelImperativeHandle, PanelProps, SeparatorProps } from 'react-resizable-panels';
4
+ export type ResizableOrientation = 'horizontal' | 'vertical';
5
+ export type ResizableLayout = Layout;
6
+ export type ResizableLayoutChangeMeta = LayoutChangedMeta;
7
+ export type ResizableRootRef = GroupImperativeHandle;
8
+ export type ResizablePanelRef = PanelImperativeHandle;
9
+ export interface ResizableRootProps extends Omit<GroupProps, 'defaultLayout' | 'elementRef' | 'groupRef' | 'onLayoutChange' | 'onLayoutChanged' | 'orientation' | 'resizeTargetMinimumSize'> {
10
+ orientation?: ResizableOrientation;
11
+ layout?: ResizableLayout;
12
+ defaultLayout?: ResizableLayout;
13
+ onLayoutChange?: (layout: ResizableLayout) => void;
14
+ onLayoutCommit?: (layout: ResizableLayout, meta: ResizableLayoutChangeMeta) => void;
15
+ rootRef?: Ref<HTMLDivElement>;
16
+ apiRef?: Ref<ResizableRootRef>;
17
+ resizeTargetMinimumSize?: GroupProps['resizeTargetMinimumSize'];
18
+ }
19
+ declare function ResizableRoot({ apiRef, className, defaultLayout, layout, onLayoutChange, onLayoutCommit, orientation, resizeTargetMinimumSize, rootRef, ...props }: ResizableRootProps): import("react").JSX.Element;
20
+ export type ResizablePanelProps = PanelProps;
21
+ declare function ResizablePanel({ className, ...props }: ResizablePanelProps): import("react").JSX.Element;
22
+ export interface ResizableHandleProps extends SeparatorProps {
23
+ label?: string;
24
+ lineSeed?: string | number;
25
+ }
26
+ declare function ResizableHandle({ 'aria-label': ariaLabel, children, className, label, lineSeed, ...props }: ResizableHandleProps): import("react").JSX.Element;
27
+ export declare const Resizable: Readonly<{
28
+ Root: typeof ResizableRoot;
29
+ Panel: typeof ResizablePanel;
30
+ Handle: typeof ResizableHandle;
31
+ }>;
32
+ export { useGroupCallbackRef as useResizableRootCallbackRef, useGroupRef as useResizableRootRef, usePanelCallbackRef as useResizablePanelCallbackRef, usePanelRef as useResizablePanelRef, };
@@ -0,0 +1,50 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Group as ResizableGroupPrimitive, Panel as ResizablePanelPrimitive, Separator as ResizableSeparatorPrimitive, useGroupCallbackRef, useGroupRef, usePanelCallbackRef, usePanelRef, } from 'react-resizable-panels';
3
+ import { useCallback, useReducer } from 'react';
4
+ import { PencilLine } from '../PencilLine.js';
5
+ import { PencilSurface } from '../PencilSurface.js';
6
+ import { useBrowserLayoutEffect } from '../internal/useBrowserLayoutEffect.js';
7
+ const classes = (...values) => values.filter(Boolean).join(' ');
8
+ function assignRef(ref, value) {
9
+ if (typeof ref === 'function')
10
+ ref(value);
11
+ else if (ref)
12
+ ref.current = value;
13
+ }
14
+ function layoutsEqual(current, requested) {
15
+ const currentIds = Object.keys(current);
16
+ const requestedIds = Object.keys(requested);
17
+ return currentIds.length === requestedIds.length
18
+ && requestedIds.every((id) => Math.abs((current[id] ?? -1) - requested[id]) < 0.001);
19
+ }
20
+ function ResizableRoot({ apiRef, className, defaultLayout, layout, onLayoutChange, onLayoutCommit, orientation = 'horizontal', resizeTargetMinimumSize = { coarse: 44, fine: 12 }, rootRef, ...props }) {
21
+ const [group, setGroup] = useGroupCallbackRef();
22
+ const [layoutRevision, refreshControlledLayout] = useReducer((value) => value + 1, 0);
23
+ const setApiRef = useCallback((value) => {
24
+ setGroup(value);
25
+ assignRef(apiRef, value);
26
+ }, [apiRef, setGroup]);
27
+ const handleLayoutChange = useCallback((nextLayout) => {
28
+ onLayoutChange?.(nextLayout);
29
+ if (layout !== undefined)
30
+ refreshControlledLayout();
31
+ }, [layout, onLayoutChange]);
32
+ useBrowserLayoutEffect(() => {
33
+ if (!group || layout === undefined || layoutsEqual(group.getLayout(), layout))
34
+ return;
35
+ group.setLayout(layout);
36
+ }, [group, layout, layoutRevision]);
37
+ return _jsx(ResizableGroupPrimitive, { ...props, className: classes('inkra-resizable', className), "data-orientation": orientation, defaultLayout: layout ?? defaultLayout, elementRef: rootRef, groupRef: setApiRef, onLayoutChange: handleLayoutChange, onLayoutChanged: onLayoutCommit, orientation: orientation, resizeTargetMinimumSize: resizeTargetMinimumSize });
38
+ }
39
+ function ResizablePanel({ className, ...props }) {
40
+ return _jsx(ResizablePanelPrimitive, { ...props, className: classes('inkra-resizable__panel', className) });
41
+ }
42
+ function ResizableHandle({ 'aria-label': ariaLabel, children, className, label = 'Resize panels', lineSeed = 'inkra-resizable-handle', ...props }) {
43
+ return _jsxs(ResizableSeparatorPrimitive, { ...props, "aria-label": ariaLabel ?? label, className: classes('inkra-resizable__handle', className), children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-resizable__handle-focus", seed: `${lineSeed}-focus`, variant: "outline" }), _jsxs("span", { "aria-hidden": "true", className: "inkra-resizable__handle-mark", children: [_jsx(PencilLine, { className: "inkra-resizable__handle-line inkra-resizable__handle-line--horizontal", seed: `${lineSeed}-horizontal` }), _jsx(PencilLine, { className: "inkra-resizable__handle-line inkra-resizable__handle-line--vertical", orientation: "vertical", seed: `${lineSeed}-vertical` }), children] })] });
44
+ }
45
+ export const Resizable = Object.freeze({
46
+ Root: ResizableRoot,
47
+ Panel: ResizablePanel,
48
+ Handle: ResizableHandle,
49
+ });
50
+ export { useGroupCallbackRef as useResizableRootCallbackRef, useGroupRef as useResizableRootRef, usePanelCallbackRef as useResizablePanelCallbackRef, usePanelRef as useResizablePanelRef, };
@@ -0,0 +1,36 @@
1
+ import type { ScrollAreaContentProps as PrimitiveContentProps, ScrollAreaCornerProps as PrimitiveCornerProps, ScrollAreaRootProps as PrimitiveRootProps, ScrollAreaScrollbarProps as PrimitiveScrollbarProps, ScrollAreaThumbProps as PrimitiveThumbProps, ScrollAreaViewportProps as PrimitiveViewportProps } from '@base-ui/react/scroll-area';
2
+ import { type HTMLAttributes, type ReactNode } from 'react';
3
+ export type ScrollAreaVisibility = 'auto' | 'always';
4
+ export interface ScrollAreaProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
5
+ children?: ReactNode;
6
+ /** Keep custom scrollbars visible, or reveal them while scrolling/hovering. */
7
+ type?: ScrollAreaVisibility;
8
+ /** The distance in pixels before overflow edge attributes become active. */
9
+ overflowEdgeThreshold?: PrimitiveRootProps['overflowEdgeThreshold'];
10
+ /** Stable seed used by the pencil scrollbar surfaces. */
11
+ seed?: string | number;
12
+ /** Localized accessible name for the scrollable viewport. */
13
+ viewportLabel?: string;
14
+ viewportProps?: Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'role'>;
15
+ }
16
+ export type ScrollAreaRootProps = PrimitiveRootProps;
17
+ export type ScrollAreaViewportProps = PrimitiveViewportProps;
18
+ export type ScrollAreaScrollbarProps = PrimitiveScrollbarProps;
19
+ export type ScrollAreaThumbProps = PrimitiveThumbProps;
20
+ export type ScrollAreaContentProps = PrimitiveContentProps;
21
+ export type ScrollAreaCornerProps = PrimitiveCornerProps;
22
+ declare const ScrollAreaRoot: import("react").ForwardRefExoticComponent<ScrollAreaProps & import("react").RefAttributes<HTMLDivElement>>;
23
+ declare const Viewport: import("react").ForwardRefExoticComponent<Omit<PrimitiveViewportProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
24
+ declare const Content: import("react").ForwardRefExoticComponent<Omit<PrimitiveContentProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
25
+ declare const Scrollbar: import("react").ForwardRefExoticComponent<Omit<PrimitiveScrollbarProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
26
+ declare const Thumb: import("react").ForwardRefExoticComponent<Omit<PrimitiveThumbProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
27
+ declare const Corner: import("react").ForwardRefExoticComponent<Omit<PrimitiveCornerProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
28
+ export declare const ScrollArea: import("react").ForwardRefExoticComponent<ScrollAreaProps & import("react").RefAttributes<HTMLDivElement>> & {
29
+ Root: import("react").ForwardRefExoticComponent<ScrollAreaProps & import("react").RefAttributes<HTMLDivElement>>;
30
+ Viewport: import("react").ForwardRefExoticComponent<Omit<PrimitiveViewportProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
31
+ Content: import("react").ForwardRefExoticComponent<Omit<PrimitiveContentProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
32
+ Scrollbar: import("react").ForwardRefExoticComponent<Omit<PrimitiveScrollbarProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
33
+ Thumb: import("react").ForwardRefExoticComponent<Omit<PrimitiveThumbProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
34
+ Corner: import("react").ForwardRefExoticComponent<Omit<PrimitiveCornerProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
35
+ };
36
+ export { ScrollAreaRoot, Viewport as ScrollAreaViewport, Content as ScrollAreaContent, Scrollbar as ScrollAreaScrollbar, Thumb as ScrollAreaThumb, Corner as ScrollAreaCorner };
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ScrollArea as ScrollAreaPrimitive } from '@base-ui/react/scroll-area';
3
+ import { forwardRef, useId } from 'react';
4
+ import { PencilSurface } from '../PencilSurface.js';
5
+ function classes(...values) {
6
+ return values.filter(Boolean).join(' ');
7
+ }
8
+ function withClassName(base, value) {
9
+ return typeof value === 'function'
10
+ ? (state) => classes(base, value(state))
11
+ : classes(base, value);
12
+ }
13
+ const ScrollAreaRoot = forwardRef(function ScrollAreaRoot({ 'aria-label': ariaLabel, children, className, overflowEdgeThreshold, seed, style, type = 'auto', viewportLabel, viewportProps, ...props }, ref) {
14
+ const generatedId = useId();
15
+ const resolvedSeed = seed ?? `inkra-scroll-area-${generatedId}`;
16
+ const viewportClassName = classes('inkra-scroll-area__viewport', viewportProps?.className);
17
+ const viewportStyle = viewportProps?.style;
18
+ const viewportLabelValue = viewportProps?.['aria-label'] ?? viewportLabel ?? ariaLabel;
19
+ return _jsxs(ScrollAreaPrimitive.Root, { ...props, ...(ariaLabel ? { 'aria-label': ariaLabel } : {}), className: classes('inkra-scroll-area', className), "data-type": type, overflowEdgeThreshold: overflowEdgeThreshold, ref: ref, style: style, children: [_jsx(ScrollAreaPrimitive.Viewport, { ...viewportProps, "aria-label": viewportLabelValue, className: viewportClassName, style: viewportStyle, children: children }), _jsxs(ScrollAreaPrimitive.Scrollbar, { className: "inkra-scroll-area__scrollbar", orientation: "vertical", children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-scroll-area__track", radius: 3, seed: `${resolvedSeed}-vertical-track`, variant: "quiet" }), _jsx(ScrollAreaPrimitive.Thumb, { className: "inkra-scroll-area__thumb", children: _jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-scroll-area__thumb-surface", radius: 3, seed: `${resolvedSeed}-vertical-thumb`, variant: "outline" }) })] }), _jsxs(ScrollAreaPrimitive.Scrollbar, { className: "inkra-scroll-area__scrollbar", orientation: "horizontal", children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-scroll-area__track", radius: 3, seed: `${resolvedSeed}-horizontal-track`, variant: "quiet" }), _jsx(ScrollAreaPrimitive.Thumb, { className: "inkra-scroll-area__thumb", children: _jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-scroll-area__thumb-surface", radius: 3, seed: `${resolvedSeed}-horizontal-thumb`, variant: "outline" }) })] }), _jsx(ScrollAreaPrimitive.Corner, { className: "inkra-scroll-area__corner" })] });
20
+ });
21
+ const Viewport = forwardRef(function Viewport({ className, ...props }, ref) {
22
+ return _jsx(ScrollAreaPrimitive.Viewport, { ...props, className: withClassName('inkra-scroll-area__viewport', className), ref: ref });
23
+ });
24
+ const Content = forwardRef(function Content({ className, ...props }, ref) {
25
+ return _jsx(ScrollAreaPrimitive.Content, { ...props, className: withClassName('inkra-scroll-area__content', className), ref: ref });
26
+ });
27
+ const Scrollbar = forwardRef(function Scrollbar({ className, ...props }, ref) {
28
+ return _jsx(ScrollAreaPrimitive.Scrollbar, { ...props, className: withClassName('inkra-scroll-area__scrollbar', className), ref: ref });
29
+ });
30
+ const Thumb = forwardRef(function Thumb({ className, ...props }, ref) {
31
+ return _jsx(ScrollAreaPrimitive.Thumb, { ...props, className: withClassName('inkra-scroll-area__thumb', className), ref: ref });
32
+ });
33
+ const Corner = forwardRef(function Corner({ className, ...props }, ref) {
34
+ return _jsx(ScrollAreaPrimitive.Corner, { ...props, className: withClassName('inkra-scroll-area__corner', className), ref: ref });
35
+ });
36
+ export const ScrollArea = Object.assign(ScrollAreaRoot, {
37
+ Root: ScrollAreaRoot,
38
+ Viewport,
39
+ Content,
40
+ Scrollbar,
41
+ Thumb,
42
+ Corner,
43
+ });
44
+ export { ScrollAreaRoot, Viewport as ScrollAreaViewport, Content as ScrollAreaContent, Scrollbar as ScrollAreaScrollbar, Thumb as ScrollAreaThumb, Corner as ScrollAreaCorner };
@@ -0,0 +1,17 @@
1
+ export type ProgressPartialSegment = 'fractional' | 'complete' | 'next';
2
+ export interface ProgressThreshold {
3
+ value: number;
4
+ color: string;
5
+ }
6
+ interface SegmentedProgressProps {
7
+ count: number;
8
+ gap: number;
9
+ max: number;
10
+ partialSegment: ProgressPartialSegment;
11
+ percent: number | null;
12
+ seed: string | number;
13
+ segmentColors?: readonly string[];
14
+ thresholds?: readonly ProgressThreshold[];
15
+ }
16
+ export declare function SegmentedProgress({ count, gap, max, partialSegment, percent, seed, segmentColors, thresholds, }: SegmentedProgressProps): import("react").JSX.Element;
17
+ export {};