@dreamtree-org/twreact-ui 1.3.9 → 1.3.11

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 (128) hide show
  1. package/README.md +32 -0
  2. package/ai-skills/dreamtree-ui.md +12 -7
  3. package/dist/ai-schema.json +156 -29
  4. package/dist/charts/index.js +195 -66
  5. package/dist/components/blocks/AppShell.d.ts.map +1 -1
  6. package/dist/components/charts/CartesianChart.d.ts.map +1 -1
  7. package/dist/components/charts/ChartFrame.d.ts.map +1 -1
  8. package/dist/components/charts/useChartLayout.d.ts +25 -0
  9. package/dist/components/charts/useChartLayout.d.ts.map +1 -0
  10. package/dist/components/core/Accordion.d.ts.map +1 -1
  11. package/dist/components/core/Button.d.ts.map +1 -1
  12. package/dist/components/core/Checkbox.d.ts.map +1 -1
  13. package/dist/components/core/ColorPicker.d.ts.map +1 -1
  14. package/dist/components/core/DatePicker.d.ts.map +1 -1
  15. package/dist/components/core/Form.d.ts.map +1 -1
  16. package/dist/components/core/Input.d.ts.map +1 -1
  17. package/dist/components/core/Loader.d.ts.map +1 -1
  18. package/dist/components/core/LocationPicker.d.ts.map +1 -1
  19. package/dist/components/core/PriceRangePicker.d.ts +0 -29
  20. package/dist/components/core/PriceRangePicker.d.ts.map +1 -1
  21. package/dist/components/core/ProgressBar.d.ts.map +1 -1
  22. package/dist/components/core/Radio.d.ts.map +1 -1
  23. package/dist/components/core/Rate.d.ts.map +1 -1
  24. package/dist/components/core/RoundedTag.d.ts.map +1 -1
  25. package/dist/components/core/Skeleton.d.ts.map +1 -1
  26. package/dist/components/core/Slider.d.ts.map +1 -1
  27. package/dist/components/core/SpeechToText.d.ts.map +1 -1
  28. package/dist/components/core/Switch.d.ts.map +1 -1
  29. package/dist/components/core/Table/ColumnMenu.d.ts.map +1 -1
  30. package/dist/components/core/Table/Pagination.d.ts.map +1 -1
  31. package/dist/components/core/Table/TableRow.d.ts.map +1 -1
  32. package/dist/components/core/Table/helpers.d.ts +2 -0
  33. package/dist/components/core/Table/helpers.d.ts.map +1 -1
  34. package/dist/components/core/Tabs.d.ts +2 -5
  35. package/dist/components/core/Tabs.d.ts.map +1 -1
  36. package/dist/components/core/TextToSpeech.d.ts +2 -7
  37. package/dist/components/core/TextToSpeech.d.ts.map +1 -1
  38. package/dist/components/core/Textarea.d.ts.map +1 -1
  39. package/dist/components/core/Tooltip.d.ts.map +1 -1
  40. package/dist/components/feedback/Alert.d.ts.map +1 -1
  41. package/dist/components/feedback/Dialog.d.ts.map +1 -1
  42. package/dist/components/feedback/Toast.d.ts.map +1 -1
  43. package/dist/components/navigation/Breadcrumbs.d.ts.map +1 -1
  44. package/dist/components/navigation/FootNav.d.ts.map +1 -1
  45. package/dist/components/navigation/Sidebar.d.ts.map +1 -1
  46. package/dist/components/utility/Avatar.d.ts +8 -0
  47. package/dist/components/utility/Avatar.d.ts.map +1 -1
  48. package/dist/components/utility/AvatarGroup.d.ts +4 -0
  49. package/dist/components/utility/AvatarGroup.d.ts.map +1 -0
  50. package/dist/components/utility/Badge.d.ts.map +1 -1
  51. package/dist/components/utility/Card.d.ts.map +1 -1
  52. package/dist/components/utility/Carousel.d.ts.map +1 -1
  53. package/dist/components/utility/FileUpload.d.ts.map +1 -1
  54. package/dist/components/utility/Pagination.d.ts.map +1 -1
  55. package/dist/components/utility/Sortable.d.ts.map +1 -1
  56. package/dist/components/utility/Stepper.d.ts.map +1 -1
  57. package/dist/esm/components/blocks/AppShell.js +24 -18
  58. package/dist/esm/components/blocks/EmptyState.js +1 -1
  59. package/dist/esm/components/blocks/ErrorState.js +1 -1
  60. package/dist/esm/components/blocks/LoadingState.js +4 -4
  61. package/dist/esm/components/blocks/StatCard.js +6 -6
  62. package/dist/esm/components/blocks/StatusPill.js +5 -8
  63. package/dist/esm/components/charts/CartesianChart.js +85 -62
  64. package/dist/esm/components/charts/ChartFrame.js +12 -5
  65. package/dist/esm/components/charts/useChartLayout.js +105 -0
  66. package/dist/esm/components/core/Accordion.js +40 -9
  67. package/dist/esm/components/core/Button.js +49 -25
  68. package/dist/esm/components/core/Checkbox.js +71 -45
  69. package/dist/esm/components/core/ColorPicker.js +49 -48
  70. package/dist/esm/components/core/DatePicker.js +97 -58
  71. package/dist/esm/components/core/Form.js +35 -8
  72. package/dist/esm/components/core/Input.js +89 -20
  73. package/dist/esm/components/core/Loader.js +30 -44
  74. package/dist/esm/components/core/LocationPicker.js +82 -16
  75. package/dist/esm/components/core/PriceRangePicker.js +205 -218
  76. package/dist/esm/components/core/ProgressBar.js +8 -12
  77. package/dist/esm/components/core/Radio.js +43 -15
  78. package/dist/esm/components/core/Rate.js +109 -50
  79. package/dist/esm/components/core/RoundedTag.js +27 -10
  80. package/dist/esm/components/core/Skeleton.js +13 -14
  81. package/dist/esm/components/core/Slider.js +24 -6
  82. package/dist/esm/components/core/SpeechToText.js +68 -16
  83. package/dist/esm/components/core/Switch.js +88 -16
  84. package/dist/esm/components/core/Table/ColumnMenu.js +2 -4
  85. package/dist/esm/components/core/Table/Pagination.js +15 -18
  86. package/dist/esm/components/core/Table/TableRow.js +2 -2
  87. package/dist/esm/components/core/Table/helpers.js +33 -1
  88. package/dist/esm/components/core/Tabs.js +185 -37
  89. package/dist/esm/components/core/TextToSpeech.js +121 -28
  90. package/dist/esm/components/core/Textarea.js +10 -2
  91. package/dist/esm/components/core/Tooltip.js +100 -28
  92. package/dist/esm/components/feedback/Alert.js +21 -11
  93. package/dist/esm/components/feedback/Dialog.js +44 -100
  94. package/dist/esm/components/feedback/Toast.js +24 -5
  95. package/dist/esm/components/navigation/Breadcrumbs.js +97 -35
  96. package/dist/esm/components/navigation/FootNav.js +102 -13
  97. package/dist/esm/components/navigation/Sidebar.js +13 -61
  98. package/dist/esm/components/utility/Avatar.js +37 -22
  99. package/dist/esm/components/utility/AvatarGroup.js +56 -0
  100. package/dist/esm/components/utility/Badge.js +43 -23
  101. package/dist/esm/components/utility/Card.js +32 -8
  102. package/dist/esm/components/utility/Carousel.js +165 -38
  103. package/dist/esm/components/utility/FileUpload.js +106 -31
  104. package/dist/esm/components/utility/Pagination.js +33 -15
  105. package/dist/esm/components/utility/Sortable.js +6 -2
  106. package/dist/esm/components/utility/Stepper.js +110 -47
  107. package/dist/esm/hooks/useFocusTrap.js +10 -2
  108. package/dist/esm/hooks/useSliderValues.js +8 -2
  109. package/dist/esm/hooks/useSortable.js +107 -5
  110. package/dist/esm/index.js +1 -0
  111. package/dist/esm/utils/touchTarget.js +4 -1
  112. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  113. package/dist/hooks/useSliderValues.d.ts +6 -2
  114. package/dist/hooks/useSliderValues.d.ts.map +1 -1
  115. package/dist/hooks/useSortable.d.ts +11 -1
  116. package/dist/hooks/useSortable.d.ts.map +1 -1
  117. package/dist/index.css +1 -1
  118. package/dist/index.d.ts +3 -2
  119. package/dist/index.esm.css +1 -1
  120. package/dist/index.esm.js +3734 -2174
  121. package/dist/index.js +3732 -2171
  122. package/dist/types/charts.d.ts +3 -1
  123. package/dist/types/charts.d.ts.map +1 -1
  124. package/dist/types/index.d.ts +64 -9
  125. package/dist/types/index.d.ts.map +1 -1
  126. package/doc/README.md +1 -0
  127. package/mcp/catalog.snapshot.json +350 -121
  128. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumbs.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/Breadcrumbs.jsx"],"names":[],"mappings":";AAQA,qFAoDG;kBA5De,OAAO"}
1
+ {"version":3,"file":"Breadcrumbs.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/Breadcrumbs.jsx"],"names":[],"mappings":";AA4BA,qFA4GG;kBAxIgD,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"FootNav.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/FootNav.jsx"],"names":[],"mappings":";AAmBA,iFA0DG;kBA7Ee,OAAO"}
1
+ {"version":3,"file":"FootNav.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/FootNav.jsx"],"names":[],"mappings":";AAoDA,iFAuFG;kBA3Ie,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/Sidebar.jsx"],"names":[],"mappings":";AAiGA;;;;;;;;;;;;;;;;;GAiBG;AACH,iFA2kBG;kBAtrBI,OAAO"}
1
+ {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/Sidebar.jsx"],"names":[],"mappings":";AAkFA;;;;;;;;;;;;;;;;;GAiBG;AACH,iFAohBG;kBAhnBI,OAAO"}
@@ -1,3 +1,11 @@
1
+ export const AVATAR_SIZES: {
2
+ xs: string;
3
+ sm: string;
4
+ md: string;
5
+ lg: string;
6
+ xl: string;
7
+ '2xl': string;
8
+ };
1
9
  export default Avatar;
2
10
  declare const Avatar: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
3
11
  import React from 'react';
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Avatar.jsx"],"names":[],"mappings":";AAIA,gFA6GG;kBAjHe,OAAO"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Avatar.jsx"],"names":[],"mappings":"AAKA;;;;;;;EAOE;;AAEF,gFA6GG;kBA3He,OAAO"}
@@ -0,0 +1,4 @@
1
+ export default AvatarGroup;
2
+ declare const AvatarGroup: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
3
+ import React from 'react';
4
+ //# sourceMappingURL=AvatarGroup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AvatarGroup.d.ts","sourceRoot":"","sources":["../../../src/components/utility/AvatarGroup.jsx"],"names":[],"mappings":";AAkBA,qFA2CG;kBA7De,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Badge.jsx"],"names":[],"mappings":";AAGA,+EA8CG;kBAjDe,OAAO"}
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Badge.jsx"],"names":[],"mappings":";AA8BA,+EAuCG;kBArEe,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Card.jsx"],"names":[],"mappings":";AAGA,8EAqBG;kBAxBe,OAAO"}
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Card.jsx"],"names":[],"mappings":";AAYA,8EAyCG;kBArDe,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Carousel.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Carousel.jsx"],"names":[],"mappings":"AAIA,iFAsFE;;kBA1FgB,OAAO"}
1
+ {"version":3,"file":"Carousel.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Carousel.jsx"],"names":[],"mappings":"AA2BA,iFAkME;;kBA7NgB,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../../src/components/utility/FileUpload.jsx"],"names":[],"mappings":";AAYA,oFAyKG;kBArLkD,OAAO"}
1
+ {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../../src/components/utility/FileUpload.jsx"],"names":[],"mappings":";AAqBA,oFA4OG;kBAjQkD,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Pagination.jsx"],"names":[],"mappings":";AAIA,oFA8HG;kBAlIe,OAAO"}
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Pagination.jsx"],"names":[],"mappings":";AAkBA,oFA4IG;kBA9Je,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sortable.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Sortable.jsx"],"names":[],"mappings":";AAqBA,kFAoHG;kBAzI0G,OAAO"}
1
+ {"version":3,"file":"Sortable.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Sortable.jsx"],"names":[],"mappings":";AAqBA,kFAsHG;kBA3I0G,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Stepper.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Stepper.jsx"],"names":[],"mappings":";AAIA,iFAuIG;kBA3Ie,OAAO"}
1
+ {"version":3,"file":"Stepper.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Stepper.jsx"],"names":[],"mappings":";AAgEA,iFAqIG;kBArMe,OAAO"}
@@ -1,9 +1,11 @@
1
1
  'use client';
2
2
  import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2, createForOfIteratorHelper as _createForOfIteratorHelper } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
3
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
4
- import React, { useState, useRef, useCallback, useEffect } from 'react';
4
+ import React, { useState, useRef, useCallback } from 'react';
5
5
  import { X, Menu } from 'lucide-react';
6
6
  import { cn } from '../../utils/cn.js';
7
+ import { useFocusTrap } from '../../hooks/useFocusTrap.js';
8
+ import { useScrollLock } from '../../hooks/useScrollLock.js';
7
9
 
8
10
  var _excluded = ["brand", "nav", "sidebarFooter", "topbar", "pageTitle", "linkAs", "children", "className"];
9
11
  // Extracted from procurementpro/components/app-shell.tsx (12 of 13 products hand-roll a shell).
@@ -105,23 +107,22 @@ var AppShell = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
105
107
  open = _useState2[0],
106
108
  setOpen = _useState2[1];
107
109
  var menuButton = useRef(null);
110
+ var drawer = useRef(null);
108
111
  var close = useCallback(function () {
109
112
  return setOpen(false);
110
113
  }, []);
111
- useEffect(function () {
112
- if (!open) return undefined;
113
- var onKey = function onKey(e) {
114
- if (e.key === 'Escape') {
115
- var _menuButton$current;
116
- setOpen(false);
117
- (_menuButton$current = menuButton.current) === null || _menuButton$current === void 0 || _menuButton$current.focus();
118
- }
119
- };
120
- document.addEventListener('keydown', onKey);
121
- return function () {
122
- return document.removeEventListener('keydown', onKey);
123
- };
124
- }, [open]);
114
+ // Mobile drawer is a modal dialog: focus moves in, Tab is trapped, Escape
115
+ // closes, focus returns to the menu button, and the page behind is locked.
116
+ useScrollLock(open);
117
+ useFocusTrap(drawer, {
118
+ active: open,
119
+ onEscape: function onEscape() {
120
+ var _menuButton$current;
121
+ close();
122
+ // Some browsers (Safari) don't focus a clicked button, so the opener may be <body>.
123
+ (_menuButton$current = menuButton.current) === null || _menuButton$current === void 0 || _menuButton$current.focus();
124
+ }
125
+ });
125
126
  var sidebar = jsxs(Fragment, {
126
127
  children: [jsxs("div", {
127
128
  className: "flex items-center justify-between px-5 pb-4 pt-5 text-white",
@@ -134,7 +135,8 @@ var AppShell = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
134
135
  onClick: close,
135
136
  "aria-label": "Close navigation",
136
137
  children: jsx(X, {
137
- className: "h-5 w-5"
138
+ className: "h-5 w-5",
139
+ "aria-hidden": "true"
138
140
  })
139
141
  })]
140
142
  }), jsx(NavList, {
@@ -165,8 +167,12 @@ var AppShell = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
165
167
  onClick: close,
166
168
  "aria-hidden": "true"
167
169
  }), jsx("aside", {
168
- className: "absolute inset-y-0 left-0 flex w-72 max-w-[85%] flex-col bg-shell",
169
- "aria-label": "Sidebar",
170
+ ref: drawer,
171
+ role: "dialog",
172
+ "aria-modal": "true",
173
+ "aria-label": "Navigation",
174
+ tabIndex: -1,
175
+ className: "absolute inset-y-0 left-0 flex w-72 max-w-[85%] flex-col bg-shell focus:outline-none",
170
176
  children: sidebar
171
177
  })]
172
178
  }), jsxs("div", {
@@ -22,7 +22,7 @@ var EmptyState = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
22
22
  className: cn('flex flex-col items-center justify-center gap-2 text-center', compact ? 'px-4 py-8' : 'px-6 py-12', className)
23
23
  }, props), {}, {
24
24
  children: [jsx("span", {
25
- className: "mb-1 grid h-12 w-12 place-items-center rounded-full bg-secondary-100 text-muted",
25
+ className: "mb-1 grid h-12 w-12 place-items-center rounded-full bg-secondary-100 text-muted dark:bg-gray-800",
26
26
  "aria-hidden": "true",
27
27
  children: icon || jsx(Inbox, {
28
28
  className: "h-6 w-6"
@@ -25,7 +25,7 @@ var ErrorState = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
25
25
  className: cn('flex flex-col items-center justify-center gap-2 px-6 py-12 text-center', className)
26
26
  }, props), {}, {
27
27
  children: [jsx("span", {
28
- className: "mb-1 grid h-12 w-12 place-items-center rounded-full bg-error-50 text-error-600",
28
+ className: "mb-1 grid h-12 w-12 place-items-center rounded-full bg-error-50 text-error-600 dark:bg-error-900/30 dark:text-error-400",
29
29
  "aria-hidden": "true",
30
30
  children: jsx(AlertCircle, {
31
31
  className: "h-6 w-6"
@@ -17,7 +17,7 @@ var Bone = function Bone(_ref) {
17
17
  className = _ref.className;
18
18
  return jsx("span", {
19
19
  "aria-hidden": "true",
20
- className: cn('block animate-pulse rounded-control bg-gray-200 motion-reduce:animate-none', className),
20
+ className: cn('block animate-pulse rounded-control bg-line motion-reduce:animate-none', className),
21
21
  style: {
22
22
  width: width,
23
23
  height: height
@@ -28,7 +28,7 @@ var Line = Bone;
28
28
  var shapes = {
29
29
  table: function table(rows) {
30
30
  return jsx("div", {
31
- className: "divide-y divide-gray-200",
31
+ className: "divide-y divide-line",
32
32
  children: Array.from({
33
33
  length: rows
34
34
  }, function (_, i) {
@@ -54,7 +54,7 @@ var shapes = {
54
54
  length: rows
55
55
  }, function (_, i) {
56
56
  return jsxs("div", {
57
- className: "flex flex-col gap-3 rounded-card border border-gray-200 p-4",
57
+ className: "flex flex-col gap-3 rounded-card border border-line p-4",
58
58
  children: [jsx(Line, {
59
59
  width: "60%",
60
60
  height: 16
@@ -72,7 +72,7 @@ var shapes = {
72
72
  length: rows
73
73
  }, function (_, i) {
74
74
  return jsxs("div", {
75
- className: "flex items-center gap-4 rounded-card border border-gray-200 bg-surface p-5",
75
+ className: "flex items-center gap-4 rounded-card border border-line bg-surface p-5",
76
76
  children: [jsx(Bone, {
77
77
  width: 48,
78
78
  height: 48
@@ -11,12 +11,12 @@ var _excluded = ["label", "value", "icon", "tone", "change", "loading", "classNa
11
11
  // Extracted from PracticePro/components/ui/StatCard.tsx (28 imports), with tones mapped to the
12
12
  // semantic scales instead of product colours. Class names are written out in full so Tailwind keeps them.
13
13
  var TONES = {
14
- primary: 'bg-primary-50 text-primary-600',
15
- secondary: 'bg-secondary-100 text-secondary-600',
16
- success: 'bg-success-50 text-success-600',
17
- warning: 'bg-warning-50 text-warning-600',
18
- error: 'bg-error-50 text-error-600',
19
- info: 'bg-info-50 text-info-600'
14
+ primary: 'bg-primary-50 text-primary-600 dark:bg-primary-900/40 dark:text-primary-300',
15
+ secondary: 'bg-secondary-100 text-secondary-600 dark:bg-secondary-800/60 dark:text-secondary-300',
16
+ success: 'bg-success-50 text-success-600 dark:bg-success-900/40 dark:text-success-300',
17
+ warning: 'bg-warning-50 text-warning-600 dark:bg-warning-900/40 dark:text-warning-300',
18
+ error: 'bg-error-50 text-error-600 dark:bg-error-900/40 dark:text-error-300',
19
+ info: 'bg-info-50 text-info-600 dark:bg-info-900/40 dark:text-info-300'
20
20
  };
21
21
  var StatCard = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
22
22
  var _change$goodWhenUp, _change$unit;
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
- import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { jsx } from 'react/jsx-runtime';
4
4
  import React from 'react';
5
5
  import { cn } from '../../utils/cn.js';
6
6
  import Badge from '../utility/Badge.js';
@@ -37,17 +37,14 @@ var StatusPill = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
37
37
  var resolvedTone = (entry === null || entry === void 0 ? void 0 : entry.tone) || tone || 'neutral';
38
38
  var label = (_ref2 = children !== null && children !== void 0 ? children : entry === null || entry === void 0 ? void 0 : entry.label) !== null && _ref2 !== void 0 ? _ref2 : status != null ? humanizeStatus(status) : null;
39
39
  var resolvedIcon = icon !== null && icon !== void 0 ? icon : entry === null || entry === void 0 ? void 0 : entry.icon;
40
- return jsxs(Badge, _objectSpread2(_objectSpread2({
40
+ return jsx(Badge, _objectSpread2(_objectSpread2({
41
41
  ref: ref,
42
42
  variant: TONE_TO_VARIANT[resolvedTone] || 'secondary',
43
43
  size: "sm",
44
- className: cn('gap-1.5 whitespace-nowrap', className)
44
+ className: cn('gap-1.5 whitespace-nowrap', className),
45
+ icon: resolvedIcon
45
46
  }, props), {}, {
46
- children: [resolvedIcon && jsx("span", {
47
- className: "inline-flex h-3.5 w-3.5 items-center",
48
- "aria-hidden": "true",
49
- children: resolvedIcon
50
- }), label]
47
+ children: label
51
48
  }));
52
49
  });
53
50
  StatusPill.displayName = 'StatusPill';
@@ -1,13 +1,15 @@
1
1
  'use client';
2
- import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2, toConsumableArray as _toConsumableArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
2
+ import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2, toConsumableArray as _toConsumableArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
4
  import React from 'react';
5
5
  import { ResponsiveContainer, AreaChart, BarChart, LineChart, CartesianGrid, XAxis, YAxis, Tooltip, Bar, Area, Line } from 'recharts';
6
6
  import { ChartFrame, ChartTooltipContent } from './ChartFrame.js';
7
7
  import { useChartTheme, useChartId, defaultValueFormatter } from './chartTheme.js';
8
+ import { useElementWidth, usePinnedTooltip, yAxisWidthFor, tickGapFor } from './useChartLayout.js';
8
9
  import { useReducedMotion } from '../../hooks/useReducedMotion.js';
9
10
 
10
- var _excluded = ["kind", "data", "index", "categories", "colors", "valueFormatter", "xAxisFormatter", "height", "showLegend", "showTooltip", "showXAxis", "showYAxis", "showGrid", "yAxisWidth", "curveType", "stacked", "horizontal", "showDots", "connectNulls", "animate", "title", "description", "emptyState", "accessibleTable", "className"];
11
+ var _excluded = ["kind", "data", "index", "categories", "colors", "valueFormatter", "xAxisFormatter", "height", "aspectRatio", "showLegend", "showTooltip", "showXAxis", "showYAxis", "showGrid", "yAxisWidth", "curveType", "stacked", "horizontal", "showDots", "connectNulls", "animate", "title", "description", "emptyState", "accessibleTable", "className"],
12
+ _excluded2 = ["ref"];
11
13
  var ROOTS = {
12
14
  line: LineChart,
13
15
  bar: BarChart,
@@ -101,6 +103,7 @@ var CartesianChart = /*#__PURE__*/React.forwardRef(function CartesianChart(_ref2
101
103
  xAxisFormatter = _ref2.xAxisFormatter,
102
104
  _ref2$height = _ref2.height,
103
105
  height = _ref2$height === void 0 ? 300 : _ref2$height,
106
+ aspectRatio = _ref2.aspectRatio,
104
107
  _ref2$showLegend = _ref2.showLegend,
105
108
  showLegend = _ref2$showLegend === void 0 ? true : _ref2$showLegend,
106
109
  _ref2$showTooltip = _ref2.showTooltip,
@@ -111,8 +114,7 @@ var CartesianChart = /*#__PURE__*/React.forwardRef(function CartesianChart(_ref2
111
114
  showYAxis = _ref2$showYAxis === void 0 ? true : _ref2$showYAxis,
112
115
  _ref2$showGrid = _ref2.showGrid,
113
116
  showGrid = _ref2$showGrid === void 0 ? true : _ref2$showGrid,
114
- _ref2$yAxisWidth = _ref2.yAxisWidth,
115
- yAxisWidth = _ref2$yAxisWidth === void 0 ? 48 : _ref2$yAxisWidth,
117
+ yAxisWidth = _ref2.yAxisWidth,
116
118
  _ref2$curveType = _ref2.curveType,
117
119
  curveType = _ref2$curveType === void 0 ? "monotone" : _ref2$curveType,
118
120
  _ref2$stacked = _ref2.stacked,
@@ -147,6 +149,20 @@ var CartesianChart = /*#__PURE__*/React.forwardRef(function CartesianChart(_ref2
147
149
  var formatIndex = xAxisFormatter || function (v) {
148
150
  return v == null ? "" : String(v);
149
151
  };
152
+ var _useElementWidth = useElementWidth(),
153
+ _useElementWidth2 = _slicedToArray(_useElementWidth, 2),
154
+ measureRef = _useElementWidth2[0],
155
+ width = _useElementWidth2[1];
156
+ var pin = usePinnedTooltip(showTooltip);
157
+ var _pin$wrapperProps = pin.wrapperProps,
158
+ pinRef = _pin$wrapperProps.ref,
159
+ pinWrapperProps = _objectWithoutProperties(_pin$wrapperProps, _excluded2);
160
+ // An explicit yAxisWidth always wins; otherwise narrow charts give the plot more room.
161
+ var valueAxisWidth = yAxisWidth !== null && yAxisWidth !== void 0 ? yAxisWidth : yAxisWidthFor(width);
162
+ var setWrapperNode = React.useCallback(function (node) {
163
+ measureRef.current = node;
164
+ pinRef.current = node;
165
+ }, [measureRef, pinRef]);
150
166
  var categoryAxis = {
151
167
  dataKey: index,
152
168
  tick: tick,
@@ -154,7 +170,7 @@ var CartesianChart = /*#__PURE__*/React.forwardRef(function CartesianChart(_ref2
154
170
  axisLine: false,
155
171
  tickFormatter: xAxisFormatter,
156
172
  hide: !showXAxis,
157
- minTickGap: 8
173
+ minTickGap: tickGapFor(width)
158
174
  };
159
175
  var valueAxis = {
160
176
  tick: tick,
@@ -162,7 +178,7 @@ var CartesianChart = /*#__PURE__*/React.forwardRef(function CartesianChart(_ref2
162
178
  axisLine: false,
163
179
  tickFormatter: valueFormatter,
164
180
  hide: !showYAxis,
165
- width: yAxisWidth
181
+ width: valueAxisWidth
166
182
  };
167
183
  return jsx(ChartFrame, _objectSpread2(_objectSpread2({
168
184
  ref: ref,
@@ -172,6 +188,7 @@ var CartesianChart = /*#__PURE__*/React.forwardRef(function CartesianChart(_ref2
172
188
  defaultTitle: TITLES[kind],
173
189
  data: data,
174
190
  height: height,
191
+ aspectRatio: aspectRatio,
175
192
  emptyState: emptyState,
176
193
  accessibleTable: accessibleTable,
177
194
  legend: showLegend ? categories.map(function (c, i) {
@@ -192,64 +209,70 @@ var CartesianChart = /*#__PURE__*/React.forwardRef(function CartesianChart(_ref2
192
209
  };
193
210
  })))
194
211
  }, rest), {}, {
195
- children: jsx(ResponsiveContainer, {
196
- width: "100%",
197
- height: "100%",
198
- minWidth: 0,
199
- children: jsxs(Root, {
200
- id: chartId,
201
- data: data,
202
- layout: isHorizontalBars ? "vertical" : "horizontal",
203
- margin: {
204
- top: 8,
205
- right: 8,
206
- bottom: 0,
207
- left: 0
208
- },
209
- accessibilityLayer: false,
210
- children: [showGrid && jsx(CartesianGrid, {
211
- stroke: chrome.grid,
212
- strokeDasharray: "3 3",
213
- vertical: isHorizontalBars,
214
- horizontal: !isHorizontalBars
215
- }), isHorizontalBars ? jsx(XAxis, _objectSpread2(_objectSpread2({
216
- type: "number"
217
- }, valueAxis), {}, {
218
- hide: !showXAxis,
219
- width: undefined
220
- })) : jsx(XAxis, _objectSpread2({}, categoryAxis)), isHorizontalBars ? jsx(YAxis, _objectSpread2(_objectSpread2({
221
- type: "category"
222
- }, categoryAxis), {}, {
223
- hide: !showYAxis,
224
- width: yAxisWidth,
225
- interval: 0
226
- })) : jsx(YAxis, _objectSpread2({}, valueAxis)), showTooltip && jsx(Tooltip, {
227
- cursor: kind === "bar" ? {
228
- fill: chrome.grid,
229
- fillOpacity: 0.4
230
- } : {
231
- stroke: chrome.grid
212
+ children: jsx("div", _objectSpread2(_objectSpread2({
213
+ className: "h-full w-full",
214
+ ref: setWrapperNode
215
+ }, pinWrapperProps), {}, {
216
+ children: jsx(ResponsiveContainer, {
217
+ width: "100%",
218
+ height: "100%",
219
+ minWidth: 0,
220
+ children: jsxs(Root, {
221
+ id: chartId,
222
+ onClick: pin.onChartClick,
223
+ data: data,
224
+ layout: isHorizontalBars ? "vertical" : "horizontal",
225
+ margin: {
226
+ top: 8,
227
+ right: 8,
228
+ bottom: 0,
229
+ left: 0
232
230
  },
233
- isAnimationActive: false,
234
- content: jsx(ChartTooltipContent, {
235
- valueFormatter: valueFormatter
236
- })
237
- }), categories.map(function (category, i) {
238
- return renderSeries(kind, {
239
- id: "".concat(chartId, "-").concat(i),
240
- category: category,
241
- color: series[i],
242
- curve: curve,
243
- stacked: stacked,
244
- showDots: showDots,
245
- connectNulls: connectNulls,
246
- animate: animate && !reducedMotion,
247
- horizontal: isHorizontalBars,
248
- barRadius: 4
249
- });
250
- })]
231
+ accessibilityLayer: false,
232
+ children: [showGrid && jsx(CartesianGrid, {
233
+ stroke: chrome.grid,
234
+ strokeDasharray: "3 3",
235
+ vertical: isHorizontalBars,
236
+ horizontal: !isHorizontalBars
237
+ }), isHorizontalBars ? jsx(XAxis, _objectSpread2(_objectSpread2({
238
+ type: "number"
239
+ }, valueAxis), {}, {
240
+ hide: !showXAxis,
241
+ width: undefined
242
+ })) : jsx(XAxis, _objectSpread2({}, categoryAxis)), isHorizontalBars ? jsx(YAxis, _objectSpread2(_objectSpread2({
243
+ type: "category"
244
+ }, categoryAxis), {}, {
245
+ hide: !showYAxis,
246
+ width: valueAxisWidth,
247
+ interval: 0
248
+ })) : jsx(YAxis, _objectSpread2({}, valueAxis)), showTooltip && jsx(Tooltip, _objectSpread2({
249
+ cursor: kind === "bar" ? {
250
+ fill: chrome.grid,
251
+ fillOpacity: 0.4
252
+ } : {
253
+ stroke: chrome.grid
254
+ },
255
+ isAnimationActive: false,
256
+ content: jsx(ChartTooltipContent, {
257
+ valueFormatter: valueFormatter
258
+ })
259
+ }, pin.tooltipProps)), categories.map(function (category, i) {
260
+ return renderSeries(kind, {
261
+ id: "".concat(chartId, "-").concat(i),
262
+ category: category,
263
+ color: series[i],
264
+ curve: curve,
265
+ stacked: stacked,
266
+ showDots: showDots,
267
+ connectNulls: connectNulls,
268
+ animate: animate && !reducedMotion,
269
+ horizontal: isHorizontalBars,
270
+ barRadius: 4
271
+ });
272
+ })]
273
+ })
251
274
  })
252
- })
275
+ }))
253
276
  }));
254
277
  });
255
278
 
@@ -4,14 +4,19 @@ import { jsx, jsxs } from 'react/jsx-runtime';
4
4
  import React, { useId } from 'react';
5
5
  import { cn } from '../../utils/cn.js';
6
6
 
7
- var _excluded = ["className", "title", "description", "defaultTitle", "data", "height", "emptyState", "legend", "accessibleTable", "tableColumns", "children", "aria-label"];
7
+ var _excluded = ["className", "title", "description", "defaultTitle", "data", "height", "aspectRatio", "emptyState", "legend", "accessibleTable", "tableColumns", "children", "aria-label"];
8
8
  // The swatch colour arrives as a custom property so a token (`rgb(var(--dt-*))`)
9
9
  // and a resolved rgb() string both work.
10
10
  var swatch = function swatch(size) {
11
11
  return cn("inline-block shrink-0 rounded-full bg-[color:var(--dt-chart-color)]", size);
12
12
  };
13
- var sizeStyle = function sizeStyle(height) {
14
- return {
13
+ // `aspectRatio` (e.g. 16 / 9), when given, replaces the fixed height so the chart
14
+ // scales with its container width.
15
+ var sizeStyle = function sizeStyle(height, aspectRatio) {
16
+ return aspectRatio ? {
17
+ aspectRatio: String(aspectRatio),
18
+ width: "100%"
19
+ } : {
15
20
  height: typeof height === "number" ? "".concat(height, "px") : height
16
21
  };
17
22
  };
@@ -46,6 +51,7 @@ function ChartTooltipContent(_ref2) {
46
51
  if (!active || !payload || !payload.length) return null;
47
52
  return jsxs("div", {
48
53
  className: "rounded-md border border-gray-200 bg-white px-3 py-2 text-xs text-gray-900 shadow-md dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100",
54
+ "data-chart-tooltip": "",
49
55
  children: [!hideLabel && label != null && label !== "" && jsx("p", {
50
56
  className: "mb-1 font-medium",
51
57
  children: label
@@ -119,6 +125,7 @@ var ChartFrame = /*#__PURE__*/React.forwardRef(function ChartFrame(_ref4, ref) {
119
125
  defaultTitle = _ref4.defaultTitle,
120
126
  data = _ref4.data,
121
127
  height = _ref4.height,
128
+ aspectRatio = _ref4.aspectRatio,
122
129
  _ref4$emptyState = _ref4.emptyState,
123
130
  emptyState = _ref4$emptyState === void 0 ? "No data to display" : _ref4$emptyState,
124
131
  legend = _ref4.legend,
@@ -134,7 +141,7 @@ var ChartFrame = /*#__PURE__*/React.forwardRef(function ChartFrame(_ref4, ref) {
134
141
  return jsx("div", _objectSpread2(_objectSpread2({
135
142
  ref: ref,
136
143
  className: cn("flex w-full items-center justify-center rounded-md border border-dashed border-gray-300 text-sm text-gray-500 dark:border-gray-700 dark:text-gray-400", className),
137
- style: sizeStyle(height),
144
+ style: sizeStyle(height, aspectRatio),
138
145
  role: "status",
139
146
  "aria-label": name,
140
147
  "data-empty": "true"
@@ -151,7 +158,7 @@ var ChartFrame = /*#__PURE__*/React.forwardRef(function ChartFrame(_ref4, ref) {
151
158
  "aria-label": name,
152
159
  "aria-describedby": description ? descriptionId : undefined,
153
160
  className: "w-full text-gray-500 dark:text-gray-400",
154
- style: sizeStyle(height),
161
+ style: sizeStyle(height, aspectRatio),
155
162
  children: children
156
163
  }), description && jsx("p", {
157
164
  id: descriptionId,
@@ -0,0 +1,105 @@
1
+ 'use client';
2
+ import { slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { useRef, useState, useEffect, useCallback } from 'react';
4
+
5
+ // Internal to the charts entry point. Small-screen helpers for the cartesian
6
+ // charts: measured width (for adaptive ticks / axis width) and a tooltip that a
7
+ // tap can pin open on touch screens.
8
+ /** Gap (px) recharts keeps between x-axis ticks: wider on narrow charts so labels don't collide. */
9
+ function tickGapFor(width) {
10
+ if (!width) return 8;
11
+ if (width < 360) return 32;
12
+ if (width < 640) return 16;
13
+ return 8;
14
+ }
15
+ /** Default value-axis width (px) when the consumer didn't set `yAxisWidth`. */
16
+ function yAxisWidthFor(width) {
17
+ if (!width) return 48;
18
+ return width < 400 ? 36 : 48;
19
+ }
20
+ /** Tracks the rendered width of `ref`'s element. `0` until measured. */
21
+ function useElementWidth() {
22
+ var ref = useRef(null);
23
+ var _useState = useState(0),
24
+ _useState2 = _slicedToArray(_useState, 2),
25
+ width = _useState2[0],
26
+ setWidth = _useState2[1];
27
+ useEffect(function () {
28
+ var node = ref.current;
29
+ if (!node) return undefined;
30
+ var measure = function measure() {
31
+ return setWidth(Math.round(node.getBoundingClientRect().width || 0));
32
+ };
33
+ measure();
34
+ if (typeof ResizeObserver === "undefined") return undefined;
35
+ var observer = new ResizeObserver(measure);
36
+ observer.observe(node);
37
+ return function () {
38
+ return observer.disconnect();
39
+ };
40
+ }, []);
41
+ return [ref, width];
42
+ }
43
+ var readIndex = function readIndex(state) {
44
+ var _state$activeTooltipI;
45
+ var raw = (_state$activeTooltipI = state === null || state === void 0 ? void 0 : state.activeTooltipIndex) !== null && _state$activeTooltipI !== void 0 ? _state$activeTooltipI : state === null || state === void 0 ? void 0 : state.activeIndex;
46
+ if (raw === undefined || raw === null || raw === "") return undefined;
47
+ var n = Number(raw);
48
+ return Number.isNaN(n) ? raw : n;
49
+ };
50
+ /**
51
+ * Tap-to-pin tooltip for touch. A tap on the chart pins the tooltip at the
52
+ * tapped point; a second tap on the chart, or a tap outside it, unpins it.
53
+ * Mouse and pen keep the normal hover tooltip.
54
+ *
55
+ * Returns props for a wrapper element, an `onChartClick` for the recharts root
56
+ * and `tooltipProps` to spread on `<Tooltip>`.
57
+ */
58
+ function usePinnedTooltip() {
59
+ var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
60
+ var wrapperRef = useRef(null);
61
+ var pointerType = useRef("mouse");
62
+ var _useState3 = useState(null),
63
+ _useState4 = _slicedToArray(_useState3, 2),
64
+ pinned = _useState4[0],
65
+ setPinned = _useState4[1]; // null | { index }
66
+ var onPointerDownCapture = useCallback(function (e) {
67
+ pointerType.current = e.pointerType || "mouse";
68
+ }, []);
69
+ var toggle = useCallback(function (state) {
70
+ if (!enabled || pointerType.current !== "touch") return;
71
+ setPinned(function (current) {
72
+ return current ? null : {
73
+ index: readIndex(state)
74
+ };
75
+ });
76
+ }, [enabled]);
77
+ // A tap outside the chart unpins.
78
+ useEffect(function () {
79
+ if (!pinned) return undefined;
80
+ var onDown = function onDown(e) {
81
+ if (wrapperRef.current && !wrapperRef.current.contains(e.target)) setPinned(null);
82
+ };
83
+ document.addEventListener("pointerdown", onDown);
84
+ return function () {
85
+ return document.removeEventListener("pointerdown", onDown);
86
+ };
87
+ }, [pinned]);
88
+ var tooltipProps = pinned ? _objectSpread2({
89
+ active: true
90
+ }, pinned.index !== undefined ? {
91
+ defaultIndex: pinned.index
92
+ } : {}) : {};
93
+ return {
94
+ pinned: Boolean(pinned),
95
+ wrapperProps: {
96
+ ref: wrapperRef,
97
+ onPointerDownCapture: onPointerDownCapture,
98
+ "data-tooltip-pinned": pinned ? "true" : undefined
99
+ },
100
+ onChartClick: toggle,
101
+ tooltipProps: tooltipProps
102
+ };
103
+ }
104
+
105
+ export { tickGapFor, useElementWidth, usePinnedTooltip, yAxisWidthFor };