@lerianstudio/sindarian-ui 1.4.0-beta.8 → 2.0.0-beta.10

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 (196) hide show
  1. package/dist/components/breadcrumb/index.d.ts.map +1 -1
  2. package/dist/components/breadcrumb/index.js +25 -1
  3. package/dist/components/card/account-card/index.d.ts.map +1 -1
  4. package/dist/components/card/account-card/index.js +5 -5
  5. package/dist/components/card/basic-card/index.d.ts.map +1 -1
  6. package/dist/components/card/basic-card/index.js +2 -2
  7. package/dist/components/card/entity-card/index.js +4 -4
  8. package/dist/components/dialog/confirmation-dialog/index.d.ts +36 -5
  9. package/dist/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
  10. package/dist/components/dialog/confirmation-dialog/index.js +5 -2
  11. package/dist/components/entity-box/index.d.ts +18 -2
  12. package/dist/components/entity-box/index.d.ts.map +1 -1
  13. package/dist/components/entity-box/index.js +33 -5
  14. package/dist/components/entity-data-table/index.d.ts.map +1 -1
  15. package/dist/components/entity-data-table/index.js +1 -1
  16. package/dist/components/form/file-upload-field/index.d.ts +11 -2
  17. package/dist/components/form/file-upload-field/index.d.ts.map +1 -1
  18. package/dist/components/form/file-upload-field/index.js +8 -3
  19. package/dist/components/form/input-field/index.d.ts +41 -2
  20. package/dist/components/form/input-field/index.d.ts.map +1 -1
  21. package/dist/components/form/input-field/index.js +73 -15
  22. package/dist/components/form/password-field/index.d.ts +5 -1
  23. package/dist/components/form/password-field/index.d.ts.map +1 -1
  24. package/dist/components/form/password-field/index.js +2 -2
  25. package/dist/components/form/select-field/index.d.ts +9 -1
  26. package/dist/components/form/select-field/index.d.ts.map +1 -1
  27. package/dist/components/form/select-field/index.js +2 -2
  28. package/dist/components/page-header/index.d.ts.map +1 -1
  29. package/dist/components/page-header/index.js +2 -2
  30. package/dist/components/table/id-table-cell.d.ts +5 -1
  31. package/dist/components/table/id-table-cell.d.ts.map +1 -1
  32. package/dist/components/table/id-table-cell.js +48 -6
  33. package/dist/components/ui/autocomplete/index.d.ts +58 -6
  34. package/dist/components/ui/autocomplete/index.d.ts.map +1 -1
  35. package/dist/components/ui/autocomplete/index.js +96 -16
  36. package/dist/components/ui/badge/index.d.ts +11 -7
  37. package/dist/components/ui/badge/index.d.ts.map +1 -1
  38. package/dist/components/ui/badge/index.js +31 -9
  39. package/dist/components/ui/button/styles.css +31 -1
  40. package/dist/components/ui/calendar/index.d.ts.map +1 -1
  41. package/dist/components/ui/calendar/index.js +7 -1
  42. package/dist/components/ui/card/index.d.ts.map +1 -1
  43. package/dist/components/ui/card/index.js +1 -1
  44. package/dist/components/ui/copy-field/index.d.ts.map +1 -1
  45. package/dist/components/ui/copy-field/index.js +1 -1
  46. package/dist/components/ui/dropdown-menu/index.d.ts.map +1 -1
  47. package/dist/components/ui/dropdown-menu/index.js +4 -1
  48. package/dist/components/ui/field/index.d.ts.map +1 -1
  49. package/dist/components/ui/field/index.js +5 -2
  50. package/dist/components/ui/file-upload/index.d.ts +235 -9
  51. package/dist/components/ui/file-upload/index.d.ts.map +1 -1
  52. package/dist/components/ui/file-upload/index.js +354 -17
  53. package/dist/components/ui/form.d.ts +4 -0
  54. package/dist/components/ui/form.d.ts.map +1 -1
  55. package/dist/components/ui/form.js +53 -8
  56. package/dist/components/ui/input/styles.css +30 -2
  57. package/dist/components/ui/multiple-select/index.js +2 -2
  58. package/dist/components/ui/progress/index.d.ts +15 -1
  59. package/dist/components/ui/progress/index.d.ts.map +1 -1
  60. package/dist/components/ui/progress/index.js +25 -2
  61. package/dist/components/ui/sheet/index.d.ts.map +1 -1
  62. package/dist/components/ui/sheet/index.js +2 -2
  63. package/dist/components/ui/sidebar/index.d.ts +1 -0
  64. package/dist/components/ui/sidebar/index.d.ts.map +1 -1
  65. package/dist/components/ui/sidebar/index.js +1 -0
  66. package/dist/components/ui/sidebar/sidebar-expand-button.d.ts +1 -1
  67. package/dist/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
  68. package/dist/components/ui/sidebar/sidebar-expand-button.js +32 -2
  69. package/dist/components/ui/sidebar/sidebar-item.d.ts +1 -1
  70. package/dist/components/ui/sidebar/sidebar-item.d.ts.map +1 -1
  71. package/dist/components/ui/sidebar/sidebar-item.js +28 -4
  72. package/dist/components/ui/sidebar/sidebar-provider.d.ts +37 -0
  73. package/dist/components/ui/sidebar/sidebar-provider.d.ts.map +1 -1
  74. package/dist/components/ui/sidebar/sidebar-provider.js +125 -4
  75. package/dist/components/ui/sidebar/sidebar-root.d.ts +38 -1
  76. package/dist/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
  77. package/dist/components/ui/sidebar/sidebar-root.js +100 -5
  78. package/dist/components/ui/sidebar/sidebar-trigger.d.ts +18 -0
  79. package/dist/components/ui/sidebar/sidebar-trigger.d.ts.map +1 -0
  80. package/dist/components/ui/sidebar/sidebar-trigger.js +30 -0
  81. package/dist/components/ui/toggle-group/index.d.ts +1 -1
  82. package/dist/components/ui/toggle-group/index.d.ts.map +1 -1
  83. package/dist/components/ui/toggle-group/index.js +73 -4
  84. package/dist/components/ui/tooltip/index.d.ts +15 -0
  85. package/dist/components/ui/tooltip/index.d.ts.map +1 -1
  86. package/dist/components/ui/tooltip/index.js +16 -1
  87. package/dist/domain/blotter/index.d.ts +4 -2
  88. package/dist/domain/blotter/index.d.ts.map +1 -1
  89. package/dist/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
  90. package/dist/domain/delinquency-aging/aging-buckets.js +8 -3
  91. package/dist/domain/delinquency-aging/index.d.ts.map +1 -1
  92. package/dist/domain/delinquency-aging/index.js +8 -3
  93. package/dist/domain/key-id/index.js +1 -1
  94. package/dist/domain/status-rail/index.js +1 -1
  95. package/dist/domain/threshold-gauge/index.d.ts.map +1 -1
  96. package/dist/domain/threshold-gauge/index.js +9 -5
  97. package/dist/enterprise/stat-card/index.d.ts.map +1 -1
  98. package/dist/enterprise/stat-card/index.js +12 -4
  99. package/dist/esm/components/breadcrumb/index.d.ts.map +1 -1
  100. package/dist/esm/components/breadcrumb/index.js +25 -1
  101. package/dist/esm/components/card/account-card/index.d.ts.map +1 -1
  102. package/dist/esm/components/card/account-card/index.js +5 -5
  103. package/dist/esm/components/card/basic-card/index.d.ts.map +1 -1
  104. package/dist/esm/components/card/basic-card/index.js +2 -2
  105. package/dist/esm/components/card/entity-card/index.js +4 -4
  106. package/dist/esm/components/dialog/confirmation-dialog/index.d.ts +36 -5
  107. package/dist/esm/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
  108. package/dist/esm/components/dialog/confirmation-dialog/index.js +5 -2
  109. package/dist/esm/components/entity-box/index.d.ts +18 -2
  110. package/dist/esm/components/entity-box/index.d.ts.map +1 -1
  111. package/dist/esm/components/entity-box/index.js +30 -5
  112. package/dist/esm/components/entity-data-table/index.d.ts.map +1 -1
  113. package/dist/esm/components/entity-data-table/index.js +1 -1
  114. package/dist/esm/components/form/file-upload-field/index.d.ts +11 -2
  115. package/dist/esm/components/form/file-upload-field/index.d.ts.map +1 -1
  116. package/dist/esm/components/form/file-upload-field/index.js +8 -3
  117. package/dist/esm/components/form/input-field/index.d.ts +41 -2
  118. package/dist/esm/components/form/input-field/index.d.ts.map +1 -1
  119. package/dist/esm/components/form/input-field/index.js +73 -15
  120. package/dist/esm/components/form/password-field/index.d.ts +5 -1
  121. package/dist/esm/components/form/password-field/index.d.ts.map +1 -1
  122. package/dist/esm/components/form/password-field/index.js +2 -2
  123. package/dist/esm/components/form/select-field/index.d.ts +9 -1
  124. package/dist/esm/components/form/select-field/index.d.ts.map +1 -1
  125. package/dist/esm/components/form/select-field/index.js +2 -2
  126. package/dist/esm/components/page-header/index.d.ts.map +1 -1
  127. package/dist/esm/components/page-header/index.js +2 -2
  128. package/dist/esm/components/table/id-table-cell.d.ts +5 -1
  129. package/dist/esm/components/table/id-table-cell.d.ts.map +1 -1
  130. package/dist/esm/components/table/id-table-cell.js +48 -3
  131. package/dist/esm/components/ui/autocomplete/index.d.ts +58 -6
  132. package/dist/esm/components/ui/autocomplete/index.d.ts.map +1 -1
  133. package/dist/esm/components/ui/autocomplete/index.js +96 -16
  134. package/dist/esm/components/ui/badge/index.d.ts +11 -7
  135. package/dist/esm/components/ui/badge/index.d.ts.map +1 -1
  136. package/dist/esm/components/ui/badge/index.js +31 -9
  137. package/dist/esm/components/ui/calendar/index.d.ts.map +1 -1
  138. package/dist/esm/components/ui/calendar/index.js +8 -2
  139. package/dist/esm/components/ui/card/index.d.ts.map +1 -1
  140. package/dist/esm/components/ui/card/index.js +1 -1
  141. package/dist/esm/components/ui/copy-field/index.d.ts.map +1 -1
  142. package/dist/esm/components/ui/copy-field/index.js +1 -1
  143. package/dist/esm/components/ui/dropdown-menu/index.d.ts.map +1 -1
  144. package/dist/esm/components/ui/dropdown-menu/index.js +4 -1
  145. package/dist/esm/components/ui/field/index.d.ts.map +1 -1
  146. package/dist/esm/components/ui/field/index.js +5 -2
  147. package/dist/esm/components/ui/file-upload/index.d.ts +235 -9
  148. package/dist/esm/components/ui/file-upload/index.d.ts.map +1 -1
  149. package/dist/esm/components/ui/file-upload/index.js +353 -17
  150. package/dist/esm/components/ui/form.d.ts +4 -0
  151. package/dist/esm/components/ui/form.d.ts.map +1 -1
  152. package/dist/esm/components/ui/form.js +53 -8
  153. package/dist/esm/components/ui/multiple-select/index.js +2 -2
  154. package/dist/esm/components/ui/progress/index.d.ts +15 -1
  155. package/dist/esm/components/ui/progress/index.d.ts.map +1 -1
  156. package/dist/esm/components/ui/progress/index.js +25 -2
  157. package/dist/esm/components/ui/sheet/index.d.ts.map +1 -1
  158. package/dist/esm/components/ui/sheet/index.js +2 -2
  159. package/dist/esm/components/ui/sidebar/index.d.ts +1 -0
  160. package/dist/esm/components/ui/sidebar/index.d.ts.map +1 -1
  161. package/dist/esm/components/ui/sidebar/index.js +1 -0
  162. package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts +1 -1
  163. package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
  164. package/dist/esm/components/ui/sidebar/sidebar-expand-button.js +32 -2
  165. package/dist/esm/components/ui/sidebar/sidebar-item.d.ts +1 -1
  166. package/dist/esm/components/ui/sidebar/sidebar-item.d.ts.map +1 -1
  167. package/dist/esm/components/ui/sidebar/sidebar-item.js +28 -4
  168. package/dist/esm/components/ui/sidebar/sidebar-provider.d.ts +37 -0
  169. package/dist/esm/components/ui/sidebar/sidebar-provider.d.ts.map +1 -1
  170. package/dist/esm/components/ui/sidebar/sidebar-provider.js +122 -1
  171. package/dist/esm/components/ui/sidebar/sidebar-root.d.ts +38 -1
  172. package/dist/esm/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
  173. package/dist/esm/components/ui/sidebar/sidebar-root.js +102 -7
  174. package/dist/esm/components/ui/sidebar/sidebar-trigger.d.ts +18 -0
  175. package/dist/esm/components/ui/sidebar/sidebar-trigger.d.ts.map +1 -0
  176. package/dist/esm/components/ui/sidebar/sidebar-trigger.js +26 -0
  177. package/dist/esm/components/ui/toggle-group/index.d.ts +1 -1
  178. package/dist/esm/components/ui/toggle-group/index.d.ts.map +1 -1
  179. package/dist/esm/components/ui/toggle-group/index.js +73 -4
  180. package/dist/esm/components/ui/tooltip/index.d.ts +15 -0
  181. package/dist/esm/components/ui/tooltip/index.d.ts.map +1 -1
  182. package/dist/esm/components/ui/tooltip/index.js +16 -1
  183. package/dist/esm/domain/blotter/index.d.ts +4 -2
  184. package/dist/esm/domain/blotter/index.d.ts.map +1 -1
  185. package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
  186. package/dist/esm/domain/delinquency-aging/aging-buckets.js +8 -3
  187. package/dist/esm/domain/delinquency-aging/index.d.ts.map +1 -1
  188. package/dist/esm/domain/delinquency-aging/index.js +8 -3
  189. package/dist/esm/domain/key-id/index.js +1 -1
  190. package/dist/esm/domain/status-rail/index.js +1 -1
  191. package/dist/esm/domain/threshold-gauge/index.d.ts.map +1 -1
  192. package/dist/esm/domain/threshold-gauge/index.js +9 -5
  193. package/dist/esm/enterprise/stat-card/index.d.ts.map +1 -1
  194. package/dist/esm/enterprise/stat-card/index.js +12 -4
  195. package/dist/globals.css +101 -32
  196. package/package.json +5 -3
@@ -77,7 +77,7 @@ exports.MultipleSelectTrigger = react_1.default.forwardRef(({ className, childre
77
77
  setOpen(false);
78
78
  inputRef.current?.blur();
79
79
  });
80
- return ((0, jsx_runtime_1.jsxs)("div", { ref: _ref, className: (0, utils_1.cn)('bg-background ring-offset-background placeholder:text-shadcn-400 focus:ring-ring border-shadcn-400 flex flex-row rounded-md border text-sm focus:ring-2 focus:ring-offset-0 focus:outline-hidden focus-visible:outline-hidden md:text-sm [&>span]:line-clamp-1', {
80
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: _ref, className: (0, utils_1.cn)('bg-background ring-offset-background placeholder:text-input-placeholder focus:ring-ring border-input-border flex flex-row rounded-md border text-sm focus:ring-2 focus:ring-offset-0 focus:outline-hidden focus-visible:outline-hidden md:text-sm [&>span]:line-clamp-1', {
81
81
  'h-10': value.length === 0,
82
82
  'min-h-10': value.length > 0,
83
83
  'cursor-text': !disabled && !readOnly && value.length !== 0,
@@ -116,7 +116,7 @@ exports.MultipleSelectValue = react_1.default.forwardRef(({ className, ...props
116
116
  value?.map((value) => ((0, jsx_runtime_1.jsxs)(badge_1.Badge, { variant: "secondary", className: (0, utils_1.cn)('data-disabled:bg-muted-foreground data-fixed:bg-muted-foreground data-disabled:text-muted data-fixed:text-muted data-disabled:hover:bg-muted-foreground data-fixed:hover:bg-muted-foreground'), children: [showValue ? value : options[value], (0, jsx_runtime_1.jsx)("button", { type: "button", className: (0, utils_1.cn)('ring-offset-background focus:ring-ring ml-1 rounded-full outline-hidden focus:ring-2 focus:ring-offset-2', disabled && 'hidden'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "text-muted-foreground hover:text-foreground h-3 w-3", onClick: (event) => {
117
117
  event.stopPropagation();
118
118
  handleChange(value);
119
- } }) })] }, value))), (0, jsx_runtime_1.jsx)(cmdk_1.Command.Input, { ...props, ref: inputRef, disabled: disabled, className: (0, utils_1.cn)('placeholder:text-muted-foreground bg-transparent outline-hidden focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50 disabled:placeholder:opacity-0', className) })] }));
119
+ } }) })] }, value))), (0, jsx_runtime_1.jsx)(cmdk_1.Command.Input, { ...props, ref: inputRef, disabled: disabled, className: (0, utils_1.cn)('placeholder:text-input-placeholder bg-transparent outline-hidden focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50 disabled:placeholder:opacity-0', className) })] }));
120
120
  });
121
121
  exports.MultipleSelectValue.displayName = 'MultipleSelectValue';
122
122
  exports.MultipleSelectEmpty = react_1.default.forwardRef(({ className, ...props }, forwardedRef) => {
@@ -3,6 +3,20 @@ import * as ProgressPrimitive from '@radix-ui/react-progress';
3
3
  type ProgressProps = React.ComponentProps<typeof ProgressPrimitive.Root> & {
4
4
  indicatorColor?: string;
5
5
  };
6
- declare function Progress({ className, value, indicatorColor, ...props }: ProgressProps): React.JSX.Element;
6
+ /**
7
+ * `value` and `max` are Radix's own props, so the bar reports `aria-valuenow` /
8
+ * `aria-valuemax` and flips `data-state` between `loading` and `complete`.
9
+ * Omitting `value`, or passing `null`, is Radix's indeterminate state and draws
10
+ * an empty track.
11
+ *
12
+ * Both numbers are BOUNDED BEFORE THE ROOT SEES THEM, so the drawn width and
13
+ * the announced value can never disagree. Radix accepts a value only inside
14
+ * `[0, max]`: hand it one outside and the root drops `aria-valuenow`, sticks
15
+ * `data-state` on `indeterminate` and logs an error, while the indicator here
16
+ * goes on drawing the clamped bar. Substituting 100 for a non-positive max is
17
+ * Radix's own fallback, and is also what keeps a `max` of 0 from dividing by
18
+ * zero.
19
+ */
20
+ declare function Progress({ className, value, max, indicatorColor, ...props }: ProgressProps): React.JSX.Element;
7
21
  export { Progress };
8
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/progress/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAA;AAI7D,KAAK,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,GAAG;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,KAAK,EACL,cAA6B,EAC7B,GAAG,KAAK,EACT,EAAE,aAAa,qBAiBf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/progress/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAA;AAI7D,KAAK,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,GAAG;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,KAAK,EACL,GAAG,EACH,cAA6B,EAC7B,GAAG,KAAK,EACT,EAAE,aAAa,qBA6Bf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -38,6 +38,29 @@ exports.Progress = Progress;
38
38
  const jsx_runtime_1 = require("react/jsx-runtime");
39
39
  const ProgressPrimitive = __importStar(require("@radix-ui/react-progress"));
40
40
  const utils_1 = require("../../../lib/utils");
41
- function Progress({ className, value, indicatorColor = 'bg-primary', ...props }) {
42
- return ((0, jsx_runtime_1.jsx)(ProgressPrimitive.Root, { "data-slot": "progress", className: (0, utils_1.cn)('bg-primary/20 relative h-4 w-full overflow-hidden rounded-full', className), ...props, children: (0, jsx_runtime_1.jsx)(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: (0, utils_1.cn)('h-full w-full flex-1 transition-all', indicatorColor), style: { transform: `translateX(-${100 - (value || 0)}%)` } }) }));
41
+ /**
42
+ * `value` and `max` are Radix's own props, so the bar reports `aria-valuenow` /
43
+ * `aria-valuemax` and flips `data-state` between `loading` and `complete`.
44
+ * Omitting `value`, or passing `null`, is Radix's indeterminate state and draws
45
+ * an empty track.
46
+ *
47
+ * Both numbers are BOUNDED BEFORE THE ROOT SEES THEM, so the drawn width and
48
+ * the announced value can never disagree. Radix accepts a value only inside
49
+ * `[0, max]`: hand it one outside and the root drops `aria-valuenow`, sticks
50
+ * `data-state` on `indeterminate` and logs an error, while the indicator here
51
+ * goes on drawing the clamped bar. Substituting 100 for a non-positive max is
52
+ * Radix's own fallback, and is also what keeps a `max` of 0 from dividing by
53
+ * zero.
54
+ */
55
+ function Progress({ className, value, max, indicatorColor = 'bg-primary', ...props }) {
56
+ const scale = Number.isFinite(max) && max > 0 ? max : 100;
57
+ // Bound against `scale`, not against the rejected `max`: with `max={0}` the
58
+ // scale is already 100, and clamping to 0 would report a finished bar empty.
59
+ // Non-finite values are indeterminate, matching Radix without producing an
60
+ // invalid CSS transform.
61
+ const bounded = Number.isFinite(value)
62
+ ? Math.min(scale, Math.max(0, value))
63
+ : null;
64
+ const percent = ((bounded ?? 0) / scale) * 100;
65
+ return ((0, jsx_runtime_1.jsx)(ProgressPrimitive.Root, { "data-slot": "progress", value: bounded, max: scale, className: (0, utils_1.cn)('bg-primary/20 relative h-4 w-full overflow-hidden rounded-full', className), ...props, children: (0, jsx_runtime_1.jsx)(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: (0, utils_1.cn)('h-full w-full flex-1 transition-all', indicatorColor), style: { transform: `translateX(-${100 - percent}%)` } }) }));
43
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sheet/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,cAAc,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE,iBAAS,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,IAAI,CAAC,qBAE5E;AAED,iBAAS,YAAY,CAAC,EACpB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,OAAO,CAAC,qBAErD;AAED,iBAAS,UAAU,CAAC,EAClB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,KAAK,CAAC,qBAEnD;AAED,iBAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,MAAM,CAAC,qBAEpD;AAED,iBAAS,YAAY,CAAC,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,OAAO,CAAC,qBAWrD;AAED,QAAA,MAAM,aAAa;;8EAiBlB,CAAA;AAED,KAAK,iBAAiB,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,OAAO,CAAC,GAC1E,YAAY,CAAC,OAAO,aAAa,CAAC,CAAA;AAEpC,iBAAS,YAAY,CAAC,EACpB,IAAc,EACd,SAAS,EACT,QAAQ,EACR,iBAAiB,EACjB,GAAG,KAAK,EACT,EAAE,iBAAiB,qBAsCnB;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWxE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWxE;AAED,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,KAAK,CAAC,qBAWnD;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,WAAW,CAAC,qBAQzD;AAED,OAAO,EACL,KAAK,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,UAAU,EACV,gBAAgB,EACjB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sheet/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,cAAc,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE,iBAAS,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,IAAI,CAAC,qBAE5E;AAED,iBAAS,YAAY,CAAC,EACpB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,OAAO,CAAC,qBAErD;AAED,iBAAS,UAAU,CAAC,EAClB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,KAAK,CAAC,qBAEnD;AAED,iBAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,MAAM,CAAC,qBAEpD;AAED,iBAAS,YAAY,CAAC,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,OAAO,CAAC,qBAWrD;AAED,QAAA,MAAM,aAAa;;8EAiBlB,CAAA;AAED,KAAK,iBAAiB,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,OAAO,CAAC,GAC1E,YAAY,CAAC,OAAO,aAAa,CAAC,CAAA;AAEpC,iBAAS,YAAY,CAAC,EACpB,IAAc,EACd,SAAS,EACT,QAAQ,EACR,iBAAiB,EACjB,GAAG,KAAK,EACT,EAAE,iBAAiB,qBA6CnB;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWxE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWxE;AAED,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,KAAK,CAAC,qBAWnD;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,WAAW,CAAC,qBAQzD;AAED,OAAO,EACL,KAAK,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,UAAU,EACV,gBAAgB,EACjB,CAAA"}
@@ -87,7 +87,7 @@ function SheetContent({ side = 'right', className, children, onInteractOutside,
87
87
  }
88
88
  onInteractOutside?.(event);
89
89
  }, [onInteractOutside]);
90
- return ((0, jsx_runtime_1.jsxs)(SheetPortal, { children: [(0, jsx_runtime_1.jsx)(SheetOverlay, {}), (0, jsx_runtime_1.jsxs)(SheetPrimitive.Content, { "data-slot": "sheet-content", className: (0, utils_1.cn)('flex max-h-screen flex-col overflow-x-auto px-8 pb-0', sheetVariants({ side }), className), onInteractOutside: handleInteractOutside, ...props, children: [children, (0, jsx_runtime_1.jsxs)(SheetPrimitive.Close, { className: "data-[state=open]:bg-secondary absolute top-7 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-hidden disabled:pointer-events-none", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "h-6 w-6" }), (0, jsx_runtime_1.jsx)("span", { className: "sr-only", children: "Close" })] })] })] }));
90
+ return ((0, jsx_runtime_1.jsxs)(SheetPortal, { children: [(0, jsx_runtime_1.jsx)(SheetOverlay, {}), (0, jsx_runtime_1.jsxs)(SheetPrimitive.Content, { "data-slot": "sheet-content", className: (0, utils_1.cn)('flex max-h-screen flex-col overflow-x-auto px-8 pb-0', sheetVariants({ side }), className), onInteractOutside: handleInteractOutside, ...props, children: [children, (0, jsx_runtime_1.jsxs)(SheetPrimitive.Close, { className: "data-[state=open]:bg-secondary ring-offset-background focus-visible:ring-ring absolute top-7 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:pointer-events-none", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "h-6 w-6" }), (0, jsx_runtime_1.jsx)("span", { className: "sr-only", children: "Close" })] })] })] }));
91
91
  }
92
92
  function SheetHeader({ className, ...props }) {
93
93
  return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "sheet-header", className: (0, utils_1.cn)('mb-4 flex flex-col space-y-2 text-center sm:text-left', className), ...props }));
@@ -99,5 +99,5 @@ function SheetTitle({ className, ...props }) {
99
99
  return ((0, jsx_runtime_1.jsx)(SheetPrimitive.Title, { "data-slot": "sheet-title", className: (0, utils_1.cn)('text-muted-foreground mb-2 flex text-xl font-bold', className), ...props }));
100
100
  }
101
101
  function SheetDescription({ className, ...props }) {
102
- return ((0, jsx_runtime_1.jsx)(SheetPrimitive.Description, { "data-slot": "sheet-description", className: (0, utils_1.cn)('text-shadcn-500 text-sm font-medium', className), ...props }));
102
+ return ((0, jsx_runtime_1.jsx)(SheetPrimitive.Description, { "data-slot": "sheet-description", className: (0, utils_1.cn)('text-muted-foreground text-sm font-medium', className), ...props }));
103
103
  }
@@ -4,6 +4,7 @@ export * from './sidebar-item-icon-button';
4
4
  export * from './sidebar-item-button';
5
5
  export * from './sidebar-item';
6
6
  export * from './sidebar-expand-button';
7
+ export * from './sidebar-trigger';
7
8
  export * from './sidebar-back-button';
8
9
  export * from './sidebar-provider';
9
10
  export * from './sidebar-item-collapsible';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/index.tsx"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/index.tsx"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA"}
@@ -20,6 +20,7 @@ __exportStar(require("./sidebar-item-icon-button"), exports);
20
20
  __exportStar(require("./sidebar-item-button"), exports);
21
21
  __exportStar(require("./sidebar-item"), exports);
22
22
  __exportStar(require("./sidebar-expand-button"), exports);
23
+ __exportStar(require("./sidebar-trigger"), exports);
23
24
  __exportStar(require("./sidebar-back-button"), exports);
24
25
  __exportStar(require("./sidebar-provider"), exports);
25
26
  __exportStar(require("./sidebar-item-collapsible"), exports);
@@ -7,6 +7,6 @@ type SidebarExpandButtonProps = {
7
7
  */
8
8
  tooltip?: string;
9
9
  };
10
- export declare const SidebarExpandButton: ({ tooltip }: SidebarExpandButtonProps) => React.JSX.Element;
10
+ export declare const SidebarExpandButton: ({ tooltip }: SidebarExpandButtonProps) => React.JSX.Element | null;
11
11
  export {};
12
12
  //# sourceMappingURL=sidebar-expand-button.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-expand-button.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/sidebar-expand-button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAYzB,KAAK,wBAAwB,GAAG;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,aAAa,wBAAwB,sBA6CxE,CAAA"}
1
+ {"version":3,"file":"sidebar-expand-button.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/sidebar-expand-button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAYzB,KAAK,wBAAwB,GAAG;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,aAAa,wBAAwB,6BAwExE,CAAA"}
@@ -13,7 +13,37 @@ const sidebar_components_1 = require("./sidebar-components");
13
13
  const tooltip_1 = require("../../ui/tooltip");
14
14
  const icon_button_1 = require("../icon-button");
15
15
  const SidebarExpandButton = ({ tooltip }) => {
16
- const { isCollapsed, toggleSidebar } = (0, sidebar_provider_1.useSidebar)();
17
- return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isCollapsed && ((0, jsx_runtime_1.jsx)("div", { "data-slot": "sidebar-expand-button", className: "border-border bg-card flex w-full", children: (0, jsx_runtime_1.jsx)("div", { className: "absolute right-[-20px] bottom-4", children: (0, jsx_runtime_1.jsx)(icon_button_1.IconButton, { variant: "secondary", rounded: true, onClick: toggleSidebar, "aria-label": tooltip || 'Collapse sidebar', "aria-expanded": true, children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { className: "text-shadcn-400" }) }) }) })), isCollapsed && ((0, jsx_runtime_1.jsx)(sidebar_components_1.SidebarFooter, { children: (0, jsx_runtime_1.jsx)(tooltip_1.TooltipProvider, { children: (0, jsx_runtime_1.jsxs)(tooltip_1.Tooltip, { children: [(0, jsx_runtime_1.jsx)(tooltip_1.TooltipTrigger, { className: "group/expand-button text-shadcn-400 hover:bg-accent rounded-sm bg-transparent p-2", onClick: toggleSidebar, "aria-label": tooltip || 'Expand sidebar', "aria-expanded": false, children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { className: "group-hover/expand-button:text-white dark:text-white" }) }), (0, jsx_runtime_1.jsx)(tooltip_1.TooltipContent, { side: "right", children: tooltip || 'Expand' })] }) }) }))] }));
16
+ const { isCollapsed, isDrawer, toggleSidebar } = (0, sidebar_provider_1.useSidebar)();
17
+ /**
18
+ * Nothing to collapse in a drawer. The expanded branch below hangs its button
19
+ * at `right-[-20px]`, twenty pixels outside the rail — off the canvas of an
20
+ * overlay that has no page beside it — and collapsing to a 72px strip inside
21
+ * a 244px sheet is not a state worth reaching. The drawer's own close control
22
+ * and the backdrop are how it is dismissed.
23
+ *
24
+ * ⚠️ `isDrawer`, NOT `isMobile`. A consumer left on the default
25
+ * `mobile="inline"` still has a real rail below 768px, and its collapse
26
+ * control has to come with it.
27
+ */
28
+ if (isDrawer) {
29
+ return null;
30
+ }
31
+ return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isCollapsed && ((0, jsx_runtime_1.jsx)("div", { "data-slot": "sidebar-expand-button", className: "border-border bg-card flex w-full", children: (0, jsx_runtime_1.jsx)("div", { className: "absolute right-[-20px] bottom-4", children: (0, jsx_runtime_1.jsx)(icon_button_1.IconButton, { variant: "secondary", rounded: true, onClick: toggleSidebar, "aria-label": tooltip || 'Collapse sidebar', "aria-expanded": true, children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { className: "text-muted-foreground" }) }) }) })), isCollapsed && ((0, jsx_runtime_1.jsx)(sidebar_components_1.SidebarFooter, { children: (0, jsx_runtime_1.jsx)(tooltip_1.TooltipProvider, { children: (0, jsx_runtime_1.jsxs)(tooltip_1.Tooltip, { children: [(0, jsx_runtime_1.jsx)(tooltip_1.TooltipTrigger
32
+ // `hover:text-accent-foreground` on the TRIGGER, not only on
33
+ // the glyph below. The base ink here used to be base/400, which
34
+ // no rule paired with anything; now that it is the muted token,
35
+ // it is the ink anything inside this trigger inherits, and the
36
+ // muted token reads 1.07:1 on sunglow in dark. The glyph
37
+ // overrides it today, so this pairs the fill for whatever the
38
+ // trigger holds next.
39
+ , {
40
+ // `hover:text-accent-foreground` on the TRIGGER, not only on
41
+ // the glyph below. The base ink here used to be base/400, which
42
+ // no rule paired with anything; now that it is the muted token,
43
+ // it is the ink anything inside this trigger inherits, and the
44
+ // muted token reads 1.07:1 on sunglow in dark. The glyph
45
+ // overrides it today, so this pairs the fill for whatever the
46
+ // trigger holds next.
47
+ className: "group/expand-button text-muted-foreground hover:bg-accent hover:text-accent-foreground rounded-sm bg-transparent p-2", onClick: toggleSidebar, "aria-label": tooltip || 'Expand sidebar', "aria-expanded": false, children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { className: "group-hover/expand-button:text-accent-foreground dark:text-white" }) }), (0, jsx_runtime_1.jsx)(tooltip_1.TooltipContent, { side: "right", children: tooltip || 'Expand' })] }) }) }))] }));
18
48
  };
19
49
  exports.SidebarExpandButton = SidebarExpandButton;
@@ -9,5 +9,5 @@ export type SidebarItemProps = React.ComponentProps<typeof SidebarItemButton> &
9
9
  disabled?: boolean;
10
10
  children?: React.ReactNode;
11
11
  };
12
- export declare const SidebarItem: ({ active, href, children: _children, ...props }: SidebarItemProps) => React.JSX.Element;
12
+ export declare const SidebarItem: ({ active, href, children: _children, onClick, ...props }: SidebarItemProps) => React.JSX.Element;
13
13
  //# sourceMappingURL=sidebar-item.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-item.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/sidebar-item.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAIlE,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,GAC3E,KAAK,CAAC,cAAc,CAAC,OAAO,qBAAqB,CAAC,GAAG;IACnD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,KAAK,CAAC,SAAS,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B,CAAA;AAEH,eAAO,MAAM,WAAW,GAAI,iDAKzB,gBAAgB,sBA0BlB,CAAA"}
1
+ {"version":3,"file":"sidebar-item.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/sidebar-item.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAIlE,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,GAC3E,KAAK,CAAC,cAAc,CAAC,OAAO,qBAAqB,CAAC,GAAG;IACnD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,KAAK,CAAC,SAAS,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B,CAAA;AAEH,eAAO,MAAM,WAAW,GAAI,0DAMzB,gBAAgB,sBAsDlB,CAAA"}
@@ -7,14 +7,38 @@ const sidebar_item_button_1 = require("./sidebar-item-button");
7
7
  const sidebar_item_icon_button_1 = require("./sidebar-item-icon-button");
8
8
  const sidebar_provider_1 = require("./sidebar-provider");
9
9
  const sidebar_router_1 = require("./sidebar-router");
10
- const SidebarItem = ({ active, href, children: _children, ...props }) => {
10
+ const SidebarItem = ({ active, href, children: _children, onClick, ...props }) => {
11
11
  const { usePathname } = (0, sidebar_router_1.useSidebarRouter)();
12
12
  const pathname = usePathname();
13
- const { isCollapsed } = (0, sidebar_provider_1.useSidebar)();
13
+ const { isCollapsed, isDrawer, setOpenMobile } = (0, sidebar_provider_1.useSidebar)();
14
14
  const isActive = (href) => pathname === href;
15
+ /**
16
+ * ⛔ ACTIVATING A DESTINATION CLOSES THE DRAWER. It is the whole point of the
17
+ * drawer and it was the one interaction that left it open: Escape, the
18
+ * backdrop and the X all dismissed it, a navigation link did not.
19
+ *
20
+ * The overlay is modal, so `document.body` carries `pointer-events: none`
21
+ * while it is up, and a consumer's `SidebarItem` is a client-side `Link`
22
+ * under a provider that survives the route change — so the reader landed on
23
+ * the new page rendered INERT behind a drawer they had to dismiss a second
24
+ * time, on a phone.
25
+ *
26
+ * Here rather than in `SidebarRoot`, because this is the component that knows
27
+ * an activation happened; `SidebarBackButton` and every
28
+ * `SidebarItemCollapsibleContent` leaf render through it, so they are covered
29
+ * by construction. Guarded on `isDrawer` so an inline rail — where nothing is
30
+ * covering the page — behaves exactly as before, and the consumer's own
31
+ * handler still runs either way.
32
+ */
33
+ const handleClick = (event) => {
34
+ onClick?.(event);
35
+ if (isDrawer) {
36
+ setOpenMobile(false);
37
+ }
38
+ };
15
39
  if (isCollapsed) {
16
- return ((0, jsx_runtime_1.jsx)(sidebar_item_icon_button_1.SidebarItemIconButton, { "data-slot": "sidebar-item", href: href, active: isActive(href) || active, ...props }));
40
+ return ((0, jsx_runtime_1.jsx)(sidebar_item_icon_button_1.SidebarItemIconButton, { "data-slot": "sidebar-item", href: href, active: isActive(href) || active, onClick: handleClick, ...props }));
17
41
  }
18
- return ((0, jsx_runtime_1.jsx)(sidebar_item_button_1.SidebarItemButton, { "data-slot": "sidebar-item", href: href, active: isActive(href) || active, ...props }));
42
+ return ((0, jsx_runtime_1.jsx)(sidebar_item_button_1.SidebarItemButton, { "data-slot": "sidebar-item", href: href, active: isActive(href) || active, onClick: handleClick, ...props }));
19
43
  };
20
44
  exports.SidebarItem = SidebarItem;
@@ -1,12 +1,49 @@
1
1
  import React from 'react';
2
+ /**
3
+ * The viewport below which the rail stops being a layout and becomes a drawer.
4
+ *
5
+ * 767px rather than 768px: this is the upper bound of `max-width`, so it is the
6
+ * complement of Tailwind's `md` breakpoint (`min-width: 768px`) and `md:hidden`
7
+ * on `SidebarTrigger` flips at exactly the same pixel the query does.
8
+ */
9
+ export declare const SIDEBAR_MOBILE_QUERY = "(max-width: 767px)";
2
10
  export type SidebarContextProps = {
3
11
  isCollapsed: boolean;
12
+ /**
13
+ * True only inside a drawer that `SidebarRoot` is actually rendering, which
14
+ * needs `mobile="drawer"` as well as a narrow viewport. `SidebarRoot`
15
+ * re-provides the context for that subtree; nothing else sets it.
16
+ */
17
+ isDrawer: boolean;
18
+ /**
19
+ * True while the viewport is narrow enough for a drawer. Reported in BOTH
20
+ * modes, so a consumer still on `mobile="inline"` can build its own
21
+ * responsive behaviour from it.
22
+ */
23
+ isMobile: boolean;
24
+ /** Whether the mobile drawer is showing. Meaningless while `isMobile` is false. */
25
+ openMobile: boolean;
26
+ setOpenMobile: (open: boolean) => void;
27
+ /**
28
+ * Puts focus back on whatever opened the drawer. `SidebarRoot` calls it when
29
+ * the drawer closes; nothing else should need it.
30
+ */
31
+ restoreDrawerFocus: () => void;
32
+ /** The drawer's DOM id, so `SidebarTrigger` can point `aria-controls` at it. */
33
+ sidebarId: string;
4
34
  items: Record<string, boolean>;
5
35
  setItems: React.Dispatch<React.SetStateAction<Record<string, boolean>>>;
6
36
  getItemCollapsed: (key: string) => boolean;
7
37
  setItemCollapsed: (key: string, value: boolean) => void;
8
38
  toggleSidebar: () => void;
9
39
  };
40
+ /**
41
+ * Exported so `SidebarRoot` can re-provide it for the drawer's subtree. That
42
+ * subtree is the only place `isCollapsed` and `isDrawer` differ from the
43
+ * provider's own values, and scoping the override to it is what keeps a
44
+ * consumer on `mobile="inline"` seeing exactly today's rail.
45
+ */
46
+ export declare const SidebarContext: React.Context<SidebarContextProps | undefined>;
10
47
  export declare const useSidebar: () => SidebarContextProps;
11
48
  export declare const SidebarProvider: ({ children }: React.PropsWithChildren) => React.JSX.Element;
12
49
  //# sourceMappingURL=sidebar-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-provider.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/sidebar-provider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACvE,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;IAC1C,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACvD,aAAa,EAAE,MAAM,IAAI,CAAA;CAC1B,CAAA;AAMD,eAAO,MAAM,UAAU,2BAMtB,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,cAAc,KAAK,CAAC,iBAAiB,sBAqDpE,CAAA"}
1
+ {"version":3,"file":"sidebar-provider.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/sidebar-provider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,uBAAuB,CAAA;AAUxD,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAA;IACjB,mFAAmF;IACnF,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC;;;OAGG;IACH,kBAAkB,EAAE,MAAM,IAAI,CAAA;IAC9B,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACvE,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;IAC1C,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACvD,aAAa,EAAE,MAAM,IAAI,CAAA;CAC1B,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,gDAEf,CAAA;AAEZ,eAAO,MAAM,UAAU,2BAMtB,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,cAAc,KAAK,CAAC,iBAAiB,sBAkKpE,CAAA"}
@@ -4,13 +4,34 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.SidebarProvider = exports.useSidebar = void 0;
7
+ exports.SidebarProvider = exports.useSidebar = exports.SidebarContext = exports.SIDEBAR_MOBILE_QUERY = void 0;
8
8
  const jsx_runtime_1 = require("react/jsx-runtime");
9
9
  const react_1 = __importDefault(require("react"));
10
10
  const storage_1 = require("../../../lib/storage");
11
- const SidebarContext = react_1.default.createContext(undefined);
11
+ /**
12
+ * The viewport below which the rail stops being a layout and becomes a drawer.
13
+ *
14
+ * 767px rather than 768px: this is the upper bound of `max-width`, so it is the
15
+ * complement of Tailwind's `md` breakpoint (`min-width: 768px`) and `md:hidden`
16
+ * on `SidebarTrigger` flips at exactly the same pixel the query does.
17
+ */
18
+ exports.SIDEBAR_MOBILE_QUERY = '(max-width: 767px)';
19
+ /**
20
+ * Where focus goes when the rail has to receive it. The rail's own content is
21
+ * links and buttons, so this is deliberately the short list rather than the
22
+ * full tabbable grammar: a `[tabindex]` sweep would have to exclude `-1`, and
23
+ * nothing in a sidebar carries one.
24
+ */
25
+ const FOCUSABLE = 'a[href], button:not([disabled])';
26
+ /**
27
+ * Exported so `SidebarRoot` can re-provide it for the drawer's subtree. That
28
+ * subtree is the only place `isCollapsed` and `isDrawer` differ from the
29
+ * provider's own values, and scoping the override to it is what keeps a
30
+ * consumer on `mobile="inline"` seeing exactly today's rail.
31
+ */
32
+ exports.SidebarContext = react_1.default.createContext(undefined);
12
33
  const useSidebar = () => {
13
- const context = react_1.default.useContext(SidebarContext);
34
+ const context = react_1.default.useContext(exports.SidebarContext);
14
35
  if (!context) {
15
36
  throw new Error('useSidebar must be used within a SidebarProvider');
16
37
  }
@@ -21,6 +42,61 @@ const SidebarProvider = ({ children }) => {
21
42
  const [hydrated, setHydrated] = react_1.default.useState(false);
22
43
  const [collapsed, setCollapsed] = react_1.default.useState(false);
23
44
  const [items, _setItems] = react_1.default.useState({});
45
+ const [isMobile, setIsMobile] = react_1.default.useState(false);
46
+ const [openMobile, _setOpenMobile] = react_1.default.useState(false);
47
+ const sidebarId = react_1.default.useId();
48
+ /**
49
+ * ⛔ RADIX CANNOT RESTORE THIS FOCUS BY ITSELF. `DialogContent` preventDefaults
50
+ * the focus scope's own restore and focuses `triggerRef.current` instead —
51
+ * the ref a `SheetTrigger` would have filled. The drawer is opened from this
52
+ * state rather than from a trigger inside the dialog, so that ref is null and
53
+ * closing dropped focus onto `<body>`: a keyboard reader who opened the
54
+ * navigation and pressed Escape was returned to the top of the document.
55
+ *
56
+ * Captured here rather than in `SidebarTrigger` so that a consumer opening
57
+ * the drawer from its own control gets the same behaviour.
58
+ */
59
+ const opener = react_1.default.useRef(null);
60
+ const setOpenMobile = react_1.default.useCallback((open) => {
61
+ if (open && typeof document !== 'undefined') {
62
+ opener.current = document.activeElement;
63
+ }
64
+ _setOpenMobile(open);
65
+ }, []);
66
+ /**
67
+ * ⛔ THE VIEWPORT AT THE MOMENT FOCUS MOVES, NOT AT THE MOMENT IT OPENED.
68
+ *
69
+ * Radix calls `restoreDrawerFocus` from the focus scope's UNMOUNT handler,
70
+ * which is the last thing in the commit to touch focus — later than any
71
+ * effect in this provider, so the decision has to be made inside the handler
72
+ * rather than beside it. By then `isMobile` has already flipped.
73
+ */
74
+ const isMobileRef = react_1.default.useRef(false);
75
+ isMobileRef.current = isMobile;
76
+ const restoreDrawerFocus = react_1.default.useCallback(() => {
77
+ // `isConnected`: the control that opened the drawer may itself have been
78
+ // unmounted by whatever the reader did inside it.
79
+ //
80
+ // ⛔ AND NOT AT ALL WHEN THE VIEWPORT IS THE ONE THAT DISMISSED IT. A
81
+ // tablet rotated from portrait to landscape with the navigation open
82
+ // crosses 768px, so the drawer is replaced by the rail and the opener is
83
+ // `SidebarTrigger` — which the same breakpoint just hid with `md:hidden`.
84
+ // `.focus()` on a `display: none` element is a silent no-op, and Radix's
85
+ // own restore is already `preventDefault()`ed, so focus fell to `<body>`
86
+ // and the reader lost their place (SC 2.4.3). Measured in Chromium at
87
+ // 390 → 1280: `{"rails":1,"triggerDisplay":"none","focus":"BODY:"}`.
88
+ if (isMobileRef.current && opener.current?.isConnected) {
89
+ opener.current.focus();
90
+ return;
91
+ }
92
+ // The rail is what the drawer became, so that is where the reader goes.
93
+ // Below the breakpoint there is nothing here to find — a closed drawer
94
+ // leaves no navigation in the DOM — and focus stays where Radix left it.
95
+ document
96
+ .getElementById(sidebarId)
97
+ ?.querySelector(FOCUSABLE)
98
+ ?.focus();
99
+ }, [sidebarId]);
24
100
  const toggleSidebar = () => setCollapsed((collapsed) => !collapsed);
25
101
  const getItemCollapsed = (key) => {
26
102
  return items[key] || false;
@@ -34,6 +110,37 @@ const SidebarProvider = ({ children }) => {
34
110
  _setItems((0, storage_1.getStorageObject)('sidebar-items', {}));
35
111
  setHydrated(true);
36
112
  }, []);
113
+ /**
114
+ * ⚠️ FALSE UNTIL THE CLIENT SAYS OTHERWISE. There is no viewport on the
115
+ * server, so the first paint is always the rail and the drawer appears on
116
+ * hydration; starting from a guess would make the markup differ between the
117
+ * two renders. The `matchMedia` guard is the one `theme-provider.tsx` next
118
+ * door already carries: jsdom and some embedded runtimes ship without it, and
119
+ * a missing media API is a desktop, not a crash.
120
+ */
121
+ react_1.default.useEffect(() => {
122
+ if (typeof window.matchMedia !== 'function') {
123
+ return;
124
+ }
125
+ const media = window.matchMedia(exports.SIDEBAR_MOBILE_QUERY);
126
+ const sync = () => setIsMobile(media.matches);
127
+ sync();
128
+ media.addEventListener('change', sync);
129
+ return () => media.removeEventListener('change', sync);
130
+ }, []);
131
+ /**
132
+ * A drawer left open while the viewport grows back would keep an overlay and
133
+ * a focus trap over a layout that is already showing its rail, with nothing
134
+ * on screen to dismiss them.
135
+ *
136
+ * Where focus goes afterwards is `restoreDrawerFocus`'s decision, not this
137
+ * effect's: Radix's unmount handler runs later than anything here.
138
+ */
139
+ react_1.default.useEffect(() => {
140
+ if (!isMobile) {
141
+ _setOpenMobile(false);
142
+ }
143
+ }, [isMobile]);
37
144
  // Only persist to localStorage after hydration to avoid overwriting stored values
38
145
  react_1.default.useEffect(() => {
39
146
  if (!hydrated) {
@@ -47,8 +154,22 @@ const SidebarProvider = ({ children }) => {
47
154
  }
48
155
  localStorage.setItem('sidebar-items', JSON.stringify(items));
49
156
  }, [items, hydrated]);
50
- return ((0, jsx_runtime_1.jsx)(SidebarContext.Provider, { value: {
157
+ return ((0, jsx_runtime_1.jsx)(exports.SidebarContext.Provider, { value: {
158
+ /**
159
+ * ⚠️ A NARROW VIEWPORT DOES NOT TOUCH THIS. It used to be forced false
160
+ * whenever `isMobile`, which silently changed the rail for every
161
+ * consumer — including the ones that never asked for a drawer.
162
+ * `SidebarRoot` overrides it for the drawer's own subtree instead, so
163
+ * the stored preference reaches an inline rail unchanged at every
164
+ * viewport.
165
+ */
51
166
  isCollapsed: collapsed,
167
+ isDrawer: false,
168
+ isMobile,
169
+ openMobile,
170
+ setOpenMobile,
171
+ restoreDrawerFocus,
172
+ sidebarId,
52
173
  items,
53
174
  setItems: _setItems,
54
175
  getItemCollapsed,
@@ -1,3 +1,40 @@
1
1
  import React from 'react';
2
- export declare const SidebarRoot: ({ className, ...props }: React.ComponentProps<"nav">) => React.JSX.Element;
2
+ export type SidebarRootProps = React.ComponentProps<'nav'> & {
3
+ /**
4
+ * What this rail becomes below 768px.
5
+ *
6
+ * - `'inline'` (default): nothing changes. The rail renders at every
7
+ * viewport exactly as it always has, and the reader's collapsed preference
8
+ * is untouched.
9
+ * - `'drawer'`: the inline rail is not rendered below the breakpoint and the
10
+ * navigation moves into an overlay drawer that `SidebarTrigger` opens.
11
+ *
12
+ * ⛔ THE DEFAULT IS NOT A TASTE, IT IS A CONSUMER-SAFETY RULE. `SidebarTrigger`
13
+ * is the only way back into the drawer and it must render inside
14
+ * `SidebarProvider`. A consumer that has not placed one yet — which is every
15
+ * consumer at the moment this shipped — would get a phone with NO navigation
16
+ * rather than a rail that takes 63% of it, and that is strictly worse. Opt in
17
+ * once there is somewhere to put the trigger.
18
+ */
19
+ mobile?: 'inline' | 'drawer';
20
+ /**
21
+ * The drawer's accessible name. A dialog needs one, and it is read out when
22
+ * the drawer opens. Unused while `mobile` is `'inline'`.
23
+ */
24
+ mobileTitle?: string;
25
+ };
26
+ /**
27
+ * ⛔ BELOW 768px A RAIL IS NOT A LAYOUT — once a consumer opts in.
28
+ *
29
+ * The widths above are a fixed share of a flex row, so at 390px the expanded
30
+ * rail took 63% of the screen and left the page 146px, and the only affordance
31
+ * — `SidebarExpandButton` — shrinks it to 72px, which is still 18% and still
32
+ * permanently on screen. There was nothing that removed it.
33
+ *
34
+ * With `mobile="drawer"` the rail is replaced below the breakpoint by an
35
+ * overlay drawer. Escape, the backdrop click, the focus trap and returning
36
+ * focus to whatever opened it are Radix Dialog's, through the kit's own
37
+ * `Sheet`; none of that is re-implemented here.
38
+ */
39
+ export declare const SidebarRoot: ({ className, id, mobile, mobileTitle, ...props }: SidebarRootProps) => React.JSX.Element;
3
40
  //# sourceMappingURL=sidebar-root.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-root.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/sidebar-root.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAoBzB,eAAO,MAAM,WAAW,GAAI,yBAGzB,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,sBAW7B,CAAA"}
1
+ {"version":3,"file":"sidebar-root.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sidebar/sidebar-root.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAqEzB,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC3D;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAI,kDAMzB,gBAAgB,sBA0GlB,CAAA"}