@puzzle-ui/ui 0.3.0 → 0.5.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 (240) hide show
  1. package/README.md +70 -70
  2. package/dist/components/actions/button/button.css +5 -2
  3. package/dist/components/actions/button-group/button-group.css +16 -17
  4. package/dist/components/data-display/badge/badge.css +15 -2
  5. package/dist/components/data-display/badge/index.cjs +13 -2
  6. package/dist/components/data-display/badge/index.cjs.map +1 -1
  7. package/dist/components/data-display/badge/index.d.cts +7 -2
  8. package/dist/components/data-display/badge/index.d.ts +7 -2
  9. package/dist/components/data-display/badge/index.js +13 -2
  10. package/dist/components/data-display/badge/index.js.map +1 -1
  11. package/dist/components/data-display/empty-state/empty-state.css +128 -0
  12. package/dist/components/data-display/empty-state/empty-state.utils.cjs +6 -0
  13. package/dist/components/data-display/empty-state/empty-state.utils.cjs.map +1 -0
  14. package/dist/components/data-display/empty-state/empty-state.utils.js +6 -0
  15. package/dist/components/data-display/empty-state/empty-state.utils.js.map +1 -0
  16. package/dist/components/data-display/empty-state/index.cjs +49 -0
  17. package/dist/components/data-display/empty-state/index.cjs.map +1 -0
  18. package/dist/components/data-display/empty-state/index.d.cts +19 -0
  19. package/dist/components/data-display/empty-state/index.d.ts +19 -0
  20. package/dist/components/data-display/empty-state/index.js +44 -0
  21. package/dist/components/data-display/empty-state/index.js.map +1 -0
  22. package/dist/components/data-display/rating/index.cjs +84 -0
  23. package/dist/components/data-display/rating/index.cjs.map +1 -0
  24. package/dist/components/data-display/rating/index.d.cts +3 -0
  25. package/dist/components/data-display/rating/index.d.ts +3 -0
  26. package/dist/components/data-display/rating/index.js +84 -0
  27. package/dist/components/data-display/rating/index.js.map +1 -0
  28. package/dist/components/data-display/rating/rating.css +72 -0
  29. package/dist/components/data-display/rating/rating.types.d.cts +15 -0
  30. package/dist/components/data-display/rating/rating.types.d.ts +15 -0
  31. package/dist/components/data-display/rating/rating.utils.cjs +27 -0
  32. package/dist/components/data-display/rating/rating.utils.cjs.map +1 -0
  33. package/dist/components/data-display/rating/rating.utils.js +25 -0
  34. package/dist/components/data-display/rating/rating.utils.js.map +1 -0
  35. package/dist/components/editors/text-editor/editor.cjs.map +1 -1
  36. package/dist/components/editors/text-editor/editor.js.map +1 -1
  37. package/dist/components/editors/text-editor/text-document.cjs.map +1 -1
  38. package/dist/components/editors/text-editor/text-document.js.map +1 -1
  39. package/dist/components/editors/text-editor/text-parser.cjs.map +1 -1
  40. package/dist/components/editors/text-editor/text-parser.js.map +1 -1
  41. package/dist/components/editors/text-editor/text-renderer.cjs.map +1 -1
  42. package/dist/components/editors/text-editor/text-renderer.js.map +1 -1
  43. package/dist/components/forms/autocomplete/index.cjs.map +1 -1
  44. package/dist/components/forms/autocomplete/index.js.map +1 -1
  45. package/dist/components/forms/checkbox/checkbox.css +2 -10
  46. package/dist/components/forms/color-picker/color-picker.css +351 -0
  47. package/dist/components/forms/color-picker/color-picker.types.d.cts +25 -0
  48. package/dist/components/forms/color-picker/color-picker.types.d.ts +25 -0
  49. package/dist/components/forms/color-picker/color-picker.utils.cjs +116 -0
  50. package/dist/components/forms/color-picker/color-picker.utils.cjs.map +1 -0
  51. package/dist/components/forms/color-picker/color-picker.utils.js +109 -0
  52. package/dist/components/forms/color-picker/color-picker.utils.js.map +1 -0
  53. package/dist/components/forms/color-picker/index.cjs +340 -0
  54. package/dist/components/forms/color-picker/index.cjs.map +1 -0
  55. package/dist/components/forms/color-picker/index.d.cts +3 -0
  56. package/dist/components/forms/color-picker/index.d.ts +3 -0
  57. package/dist/components/forms/color-picker/index.js +340 -0
  58. package/dist/components/forms/color-picker/index.js.map +1 -0
  59. package/dist/components/forms/file-upload/file-upload.utils.cjs.map +1 -1
  60. package/dist/components/forms/file-upload/file-upload.utils.js.map +1 -1
  61. package/dist/components/forms/input/number-input.js +5 -5
  62. package/dist/components/forms/input/number-input.js.map +1 -1
  63. package/dist/components/forms/input-group/index.d.cts +3 -0
  64. package/dist/components/forms/input-group/index.d.ts +3 -0
  65. package/dist/components/forms/input-group/input-group.cjs +18 -0
  66. package/dist/components/forms/input-group/input-group.cjs.map +1 -0
  67. package/dist/components/forms/input-group/input-group.css +62 -0
  68. package/dist/components/forms/input-group/input-group.d.cts +7 -0
  69. package/dist/components/forms/input-group/input-group.d.ts +7 -0
  70. package/dist/components/forms/input-group/input-group.js +18 -0
  71. package/dist/components/forms/input-group/input-group.js.map +1 -0
  72. package/dist/components/forms/input-group/input-group.types.d.cts +7 -0
  73. package/dist/components/forms/input-group/input-group.types.d.ts +7 -0
  74. package/dist/components/forms/input-group/input-group.utils.cjs +5 -0
  75. package/dist/components/forms/input-group/input-group.utils.cjs.map +1 -0
  76. package/dist/components/forms/input-group/input-group.utils.js +5 -0
  77. package/dist/components/forms/input-group/input-group.utils.js.map +1 -0
  78. package/dist/components/forms/radio-group/index.d.cts +2 -1
  79. package/dist/components/forms/radio-group/index.d.ts +2 -1
  80. package/dist/components/forms/select/index.cjs.map +1 -1
  81. package/dist/components/forms/select/index.js.map +1 -1
  82. package/dist/components/forms/slider/index.cjs +1 -1
  83. package/dist/components/forms/slider/index.cjs.map +1 -1
  84. package/dist/components/forms/slider/index.js +1 -1
  85. package/dist/components/forms/slider/index.js.map +1 -1
  86. package/dist/components/forms/stepper/index.d.cts +4 -2
  87. package/dist/components/forms/stepper/index.d.ts +4 -2
  88. package/dist/components/forms/time-picker/index.cjs +108 -0
  89. package/dist/components/forms/time-picker/index.cjs.map +1 -0
  90. package/dist/components/forms/time-picker/index.d.cts +3 -0
  91. package/dist/components/forms/time-picker/index.d.ts +3 -0
  92. package/dist/components/forms/time-picker/index.js +108 -0
  93. package/dist/components/forms/time-picker/index.js.map +1 -0
  94. package/dist/components/forms/time-picker/time-picker.css +166 -0
  95. package/dist/components/forms/time-picker/time-picker.types.d.cts +34 -0
  96. package/dist/components/forms/time-picker/time-picker.types.d.ts +34 -0
  97. package/dist/components/forms/time-picker/time-picker.utils.cjs +25 -0
  98. package/dist/components/forms/time-picker/time-picker.utils.cjs.map +1 -0
  99. package/dist/components/forms/time-picker/time-picker.utils.js +24 -0
  100. package/dist/components/forms/time-picker/time-picker.utils.js.map +1 -0
  101. package/dist/components/forms/token-input/index.cjs +189 -0
  102. package/dist/components/forms/token-input/index.cjs.map +1 -0
  103. package/dist/components/forms/token-input/index.d.cts +3 -0
  104. package/dist/components/forms/token-input/index.d.ts +3 -0
  105. package/dist/components/forms/token-input/index.js +189 -0
  106. package/dist/components/forms/token-input/index.js.map +1 -0
  107. package/dist/components/forms/token-input/token-input.css +145 -0
  108. package/dist/components/forms/token-input/token-input.types.d.cts +48 -0
  109. package/dist/components/forms/token-input/token-input.types.d.ts +48 -0
  110. package/dist/components/forms/token-input/token-input.utils.cjs +30 -0
  111. package/dist/components/forms/token-input/token-input.utils.cjs.map +1 -0
  112. package/dist/components/forms/token-input/token-input.utils.js +24 -0
  113. package/dist/components/forms/token-input/token-input.utils.js.map +1 -0
  114. package/dist/components/layout/aspect-ratio/aspect-ratio.css +14 -0
  115. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs +11 -0
  116. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs.map +1 -0
  117. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js +11 -0
  118. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js.map +1 -0
  119. package/dist/components/layout/aspect-ratio/index.cjs +16 -0
  120. package/dist/components/layout/aspect-ratio/index.cjs.map +1 -0
  121. package/dist/components/layout/aspect-ratio/index.d.cts +11 -0
  122. package/dist/components/layout/aspect-ratio/index.d.ts +11 -0
  123. package/dist/components/layout/aspect-ratio/index.js +16 -0
  124. package/dist/components/layout/aspect-ratio/index.js.map +1 -0
  125. package/dist/components/layout/container/container.css +1 -0
  126. package/dist/components/layout/page-layout/page-layout.css +1 -0
  127. package/dist/components/layout/resizable-panels/index.cjs +1 -1
  128. package/dist/components/layout/resizable-panels/index.cjs.map +1 -1
  129. package/dist/components/layout/resizable-panels/index.js +1 -1
  130. package/dist/components/layout/resizable-panels/index.js.map +1 -1
  131. package/dist/components/layout/resizable-panels/resizable-panels.utils.cjs.map +1 -1
  132. package/dist/components/layout/resizable-panels/resizable-panels.utils.js.map +1 -1
  133. package/dist/components/layout/scroll-area/index.cjs +27 -0
  134. package/dist/components/layout/scroll-area/index.cjs.map +1 -0
  135. package/dist/components/layout/scroll-area/index.d.cts +15 -0
  136. package/dist/components/layout/scroll-area/index.d.ts +15 -0
  137. package/dist/components/layout/scroll-area/index.js +27 -0
  138. package/dist/components/layout/scroll-area/index.js.map +1 -0
  139. package/dist/components/layout/scroll-area/scroll-area.css +25 -0
  140. package/dist/components/layout/scroll-area/scroll-area.utils.cjs +8 -0
  141. package/dist/components/layout/scroll-area/scroll-area.utils.cjs.map +1 -0
  142. package/dist/components/layout/scroll-area/scroll-area.utils.d.cts +2 -0
  143. package/dist/components/layout/scroll-area/scroll-area.utils.d.ts +2 -0
  144. package/dist/components/layout/scroll-area/scroll-area.utils.js +8 -0
  145. package/dist/components/layout/scroll-area/scroll-area.utils.js.map +1 -0
  146. package/dist/components/layout/section/index.cjs +10 -4
  147. package/dist/components/layout/section/index.cjs.map +1 -1
  148. package/dist/components/layout/section/index.d.cts +1 -1
  149. package/dist/components/layout/section/index.d.ts +1 -1
  150. package/dist/components/layout/section/index.js +11 -5
  151. package/dist/components/layout/section/index.js.map +1 -1
  152. package/dist/components/layout/section/section.css +9 -3
  153. package/dist/components/layout/section/types.d.cts +5 -5
  154. package/dist/components/layout/section/types.d.ts +5 -5
  155. package/dist/components/layout/separator/index.cjs +18 -0
  156. package/dist/components/layout/separator/index.cjs.map +1 -0
  157. package/dist/components/layout/separator/index.d.cts +17 -0
  158. package/dist/components/layout/separator/index.d.ts +17 -0
  159. package/dist/components/layout/separator/index.js +18 -0
  160. package/dist/components/layout/separator/index.js.map +1 -0
  161. package/dist/components/layout/separator/separator.css +15 -0
  162. package/dist/components/layout/separator/separator.utils.cjs +11 -0
  163. package/dist/components/layout/separator/separator.utils.cjs.map +1 -0
  164. package/dist/components/layout/separator/separator.utils.d.cts +2 -0
  165. package/dist/components/layout/separator/separator.utils.d.ts +2 -0
  166. package/dist/components/layout/separator/separator.utils.js +11 -0
  167. package/dist/components/layout/separator/separator.utils.js.map +1 -0
  168. package/dist/components/layout/stack/index.cjs +18 -2
  169. package/dist/components/layout/stack/index.cjs.map +1 -1
  170. package/dist/components/layout/stack/index.d.cts +8 -6
  171. package/dist/components/layout/stack/index.d.ts +8 -6
  172. package/dist/components/layout/stack/index.js +18 -2
  173. package/dist/components/layout/stack/index.js.map +1 -1
  174. package/dist/components/layout/stack/stack.css +118 -138
  175. package/dist/components/navigation/accordion/index.cjs.map +1 -1
  176. package/dist/components/navigation/accordion/index.js.map +1 -1
  177. package/dist/components/navigation/carousel/index.cjs +5 -2
  178. package/dist/components/navigation/carousel/index.cjs.map +1 -1
  179. package/dist/components/navigation/carousel/index.js +5 -2
  180. package/dist/components/navigation/carousel/index.js.map +1 -1
  181. package/dist/components/navigation/pagination/index.cjs +146 -0
  182. package/dist/components/navigation/pagination/index.cjs.map +1 -0
  183. package/dist/components/navigation/pagination/index.d.cts +3 -0
  184. package/dist/components/navigation/pagination/index.d.ts +3 -0
  185. package/dist/components/navigation/pagination/index.js +146 -0
  186. package/dist/components/navigation/pagination/index.js.map +1 -0
  187. package/dist/components/navigation/pagination/pagination.css +134 -0
  188. package/dist/components/navigation/pagination/pagination.types.d.cts +38 -0
  189. package/dist/components/navigation/pagination/pagination.types.d.ts +38 -0
  190. package/dist/components/navigation/pagination/pagination.utils.cjs +54 -0
  191. package/dist/components/navigation/pagination/pagination.utils.cjs.map +1 -0
  192. package/dist/components/navigation/pagination/pagination.utils.js +53 -0
  193. package/dist/components/navigation/pagination/pagination.utils.js.map +1 -0
  194. package/dist/components/navigation/tabs/index.d.cts +3 -2
  195. package/dist/components/navigation/tabs/index.d.ts +3 -2
  196. package/dist/components/navigation/tree-view/index.cjs.map +1 -1
  197. package/dist/components/navigation/tree-view/index.js.map +1 -1
  198. package/dist/components/overlays/context-menu/context-menu.css +151 -0
  199. package/dist/components/overlays/context-menu/context-menu.types.d.cts +69 -0
  200. package/dist/components/overlays/context-menu/context-menu.types.d.ts +69 -0
  201. package/dist/components/overlays/context-menu/context-menu.utils.cjs +46 -0
  202. package/dist/components/overlays/context-menu/context-menu.utils.cjs.map +1 -0
  203. package/dist/components/overlays/context-menu/context-menu.utils.js +40 -0
  204. package/dist/components/overlays/context-menu/context-menu.utils.js.map +1 -0
  205. package/dist/components/overlays/context-menu/index.cjs +830 -0
  206. package/dist/components/overlays/context-menu/index.cjs.map +1 -0
  207. package/dist/components/overlays/context-menu/index.d.cts +42 -0
  208. package/dist/components/overlays/context-menu/index.d.ts +42 -0
  209. package/dist/components/overlays/context-menu/index.js +818 -0
  210. package/dist/components/overlays/context-menu/index.js.map +1 -0
  211. package/dist/components/overlays/dropdown-menu/dropdown-menu-content.cjs.map +1 -1
  212. package/dist/components/overlays/dropdown-menu/dropdown-menu-content.js.map +1 -1
  213. package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.cjs.map +1 -1
  214. package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.js.map +1 -1
  215. package/dist/components/typography/heading.cjs +6 -2
  216. package/dist/components/typography/heading.cjs.map +1 -1
  217. package/dist/components/typography/heading.d.cts +3 -2
  218. package/dist/components/typography/heading.d.ts +3 -2
  219. package/dist/components/typography/heading.js +6 -2
  220. package/dist/components/typography/heading.js.map +1 -1
  221. package/dist/components/typography/text.cjs +6 -2
  222. package/dist/components/typography/text.cjs.map +1 -1
  223. package/dist/components/typography/text.d.cts +3 -2
  224. package/dist/components/typography/text.d.ts +3 -2
  225. package/dist/components/typography/text.js +6 -2
  226. package/dist/components/typography/text.js.map +1 -1
  227. package/dist/components/utilities/preview/index.cjs +89 -21
  228. package/dist/components/utilities/preview/index.cjs.map +1 -1
  229. package/dist/components/utilities/preview/index.d.cts +6 -2
  230. package/dist/components/utilities/preview/index.d.ts +6 -2
  231. package/dist/components/utilities/preview/index.js +89 -21
  232. package/dist/components/utilities/preview/index.js.map +1 -1
  233. package/dist/components/utilities/preview/preview.css +26 -11
  234. package/dist/components/utilities/transition/index.d.cts +1 -1
  235. package/dist/components/utilities/transition/index.d.ts +1 -1
  236. package/dist/index.cjs +136 -97
  237. package/dist/index.d.cts +23 -2
  238. package/dist/index.d.ts +23 -2
  239. package/dist/index.js +12 -1
  240. package/package.json +7 -6
@@ -0,0 +1,145 @@
1
+ .puzzle-token-input {
2
+ align-items: flex-start;
3
+ gap: var(--puzzle-space-2, .5rem);
4
+ flex-direction: column;
5
+ width: fit-content;
6
+ min-width: 0;
7
+ max-width: 100%;
8
+ display: flex;
9
+ }
10
+
11
+ .puzzle-token-input__label {
12
+ color: var(--puzzle-color-text);
13
+ font-size: var(--puzzle-font-size-sm, .875rem);
14
+ font-weight: var(--puzzle-font-weight-medium, 500);
15
+ line-height: var(--puzzle-font-line-height-normal, 1.5);
16
+ }
17
+
18
+ .puzzle-token-input__slots {
19
+ align-items: center;
20
+ gap: var(--puzzle-space-2, .5rem);
21
+ direction: ltr;
22
+ flex-wrap: nowrap;
23
+ max-width: 100%;
24
+ display: flex;
25
+ }
26
+
27
+ .puzzle-token-input__slot {
28
+ box-sizing: border-box;
29
+ border: var(--puzzle-border-width, 1px) solid var(--puzzle-color-border);
30
+ border-radius: var(--puzzle-radius-md, .5rem);
31
+ background: var(--puzzle-color-surface);
32
+ width: 2.5rem;
33
+ min-width: 0;
34
+ height: 2.75rem;
35
+ color: var(--puzzle-color-text);
36
+ font: inherit;
37
+ font-size: 1.125rem;
38
+ font-weight: var(--puzzle-font-weight-medium, 500);
39
+ text-align: center;
40
+ font-variant-numeric: tabular-nums;
41
+ caret-color: var(--puzzle-color-ring);
42
+ touch-action: manipulation;
43
+ -webkit-tap-highlight-color: transparent;
44
+ transition: border-color var(--puzzle-duration-fast, .15s) var(--puzzle-easing-standard, ease),
45
+ box-shadow var(--puzzle-duration-fast, .15s) var(--puzzle-easing-standard, ease),
46
+ background-color var(--puzzle-duration-fast, .15s) var(--puzzle-easing-standard, ease);
47
+ outline: none;
48
+ flex: none;
49
+ padding: 0;
50
+ line-height: 1;
51
+ display: block;
52
+ }
53
+
54
+ .puzzle-token-input__slot:hover:not(:disabled) {
55
+ border-color: var(--puzzle-color-text-muted);
56
+ }
57
+
58
+ .puzzle-token-input__slot:focus {
59
+ border-color: var(--puzzle-color-ring);
60
+ }
61
+
62
+ .puzzle-token-input__slot:focus-visible {
63
+ outline: 2px solid var(--puzzle-color-ring);
64
+ outline-offset: 2px;
65
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--puzzle-color-ring), transparent 82%);
66
+ }
67
+
68
+ .puzzle-token-input[data-invalid="true"] .puzzle-token-input__slot {
69
+ border-color: var(--puzzle-color-danger);
70
+ }
71
+
72
+ .puzzle-token-input[data-invalid="true"] .puzzle-token-input__slot:focus-visible {
73
+ outline-color: var(--puzzle-color-danger);
74
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--puzzle-color-danger), transparent 82%);
75
+ }
76
+
77
+ .puzzle-token-input[data-disabled="true"] {
78
+ cursor: not-allowed;
79
+ }
80
+
81
+ .puzzle-token-input[data-disabled="true"] .puzzle-token-input__slot {
82
+ opacity: .6;
83
+ cursor: not-allowed;
84
+ background: var(--puzzle-color-surface-sunken);
85
+ }
86
+
87
+ .puzzle-token-input[data-readonly="true"] .puzzle-token-input__slot {
88
+ cursor: default;
89
+ }
90
+
91
+ .puzzle-token-input[data-size="sm"] .puzzle-token-input__slot {
92
+ width: 2rem;
93
+ height: 2.25rem;
94
+ font-size: var(--puzzle-font-size-sm, .875rem);
95
+ }
96
+
97
+ .puzzle-token-input[data-size="md"] .puzzle-token-input__slot {
98
+ width: 2.5rem;
99
+ height: 2.75rem;
100
+ }
101
+
102
+ .puzzle-token-input[data-size="lg"] .puzzle-token-input__slot {
103
+ width: 3rem;
104
+ height: 3.25rem;
105
+ font-size: 1.375rem;
106
+ }
107
+
108
+ @media (width <= 360px) {
109
+ .puzzle-token-input__slots {
110
+ gap: var(--puzzle-space-1, .25rem);
111
+ }
112
+
113
+ .puzzle-token-input[data-size="md"] .puzzle-token-input__slot {
114
+ width: 2.25rem;
115
+ }
116
+ }
117
+
118
+ @media (forced-colors: active) {
119
+ .puzzle-token-input__slot {
120
+ color: fieldtext;
121
+ forced-color-adjust: auto;
122
+ background: field;
123
+ border-color: fieldtext;
124
+ }
125
+
126
+ .puzzle-token-input__slot:focus-visible {
127
+ outline-offset: 2px;
128
+ outline: 2px solid highlight;
129
+ }
130
+
131
+ .puzzle-token-input__slot:disabled {
132
+ color: graytext;
133
+ border-color: graytext;
134
+ }
135
+
136
+ .puzzle-token-input[data-invalid="true"] .puzzle-token-input__slot {
137
+ border-color: mark;
138
+ }
139
+ }
140
+
141
+ @media (prefers-reduced-motion: reduce) {
142
+ .puzzle-token-input__slot {
143
+ transition: none;
144
+ }
145
+ }
@@ -0,0 +1,48 @@
1
+ import { ComponentPropsWithoutRef, FocusEventHandler, InputHTMLAttributes, KeyboardEventHandler, ReactNode, Ref } from "react";
2
+ type TokenInputMode = "numeric" | "alphanumeric";
3
+ type TokenInputSize = "sm" | "md" | "lg";
4
+ type TokenInputProps = Omit<ComponentPropsWithoutRef<"div">, "children" | "id" | "onChange" | "onFocus" | "onBlur" | "onKeyDown"> & {
5
+ /** Number of characters in the token. Defaults to 6. */
6
+ length?: number;
7
+ /** Controlled token value. */
8
+ value?: string;
9
+ /** Initial value for uncontrolled usage. */
10
+ defaultValue?: string;
11
+ /** Called whenever the token value changes. */
12
+ onValueChange?: (value: string) => void;
13
+ /** Called when the token transitions from incomplete to complete. */
14
+ onComplete?: (value: string) => void;
15
+ /** Allowed characters. Defaults to numeric. */
16
+ mode?: TokenInputMode;
17
+ /** Masks the entered characters. */
18
+ mask?: boolean;
19
+ /** Disables all inputs. */
20
+ disabled?: boolean;
21
+ /** Makes all inputs read-only. */
22
+ readOnly?: boolean;
23
+ /** Marks every character input as required. */
24
+ required?: boolean;
25
+ /** Visual size of the individual character slots. */
26
+ size?: TokenInputSize;
27
+ /** Visible label associated with the first input. */
28
+ label?: ReactNode;
29
+ /** ID applied to the first native input. */
30
+ id?: string;
31
+ /** Name used for native form submission. */
32
+ name?: string;
33
+ /** Associates the hidden form input with a form. */
34
+ form?: string;
35
+ /** Input mode for the native character inputs. */
36
+ inputMode?: InputHTMLAttributes<HTMLInputElement>["inputMode"];
37
+ /** Autocomplete mode for the first character input. */
38
+ autoComplete?: InputHTMLAttributes<HTMLInputElement>["autoComplete"];
39
+ /** Ref forwarded to the first native input. */
40
+ ref?: Ref<HTMLInputElement>;
41
+ /** Called when an individual character input receives focus. */
42
+ onFocus?: FocusEventHandler<HTMLInputElement>;
43
+ /** Called when an individual character input loses focus. */
44
+ onBlur?: FocusEventHandler<HTMLInputElement>;
45
+ /** Called when an individual character input receives a key event. */
46
+ onKeyDown?: KeyboardEventHandler<HTMLInputElement>;
47
+ };
48
+ export type { TokenInputMode, TokenInputProps, TokenInputSize };
@@ -0,0 +1,48 @@
1
+ import { ComponentPropsWithoutRef, FocusEventHandler, InputHTMLAttributes, KeyboardEventHandler, ReactNode, Ref } from "react";
2
+ type TokenInputMode = "numeric" | "alphanumeric";
3
+ type TokenInputSize = "sm" | "md" | "lg";
4
+ type TokenInputProps = Omit<ComponentPropsWithoutRef<"div">, "children" | "id" | "onChange" | "onFocus" | "onBlur" | "onKeyDown"> & {
5
+ /** Number of characters in the token. Defaults to 6. */
6
+ length?: number;
7
+ /** Controlled token value. */
8
+ value?: string;
9
+ /** Initial value for uncontrolled usage. */
10
+ defaultValue?: string;
11
+ /** Called whenever the token value changes. */
12
+ onValueChange?: (value: string) => void;
13
+ /** Called when the token transitions from incomplete to complete. */
14
+ onComplete?: (value: string) => void;
15
+ /** Allowed characters. Defaults to numeric. */
16
+ mode?: TokenInputMode;
17
+ /** Masks the entered characters. */
18
+ mask?: boolean;
19
+ /** Disables all inputs. */
20
+ disabled?: boolean;
21
+ /** Makes all inputs read-only. */
22
+ readOnly?: boolean;
23
+ /** Marks every character input as required. */
24
+ required?: boolean;
25
+ /** Visual size of the individual character slots. */
26
+ size?: TokenInputSize;
27
+ /** Visible label associated with the first input. */
28
+ label?: ReactNode;
29
+ /** ID applied to the first native input. */
30
+ id?: string;
31
+ /** Name used for native form submission. */
32
+ name?: string;
33
+ /** Associates the hidden form input with a form. */
34
+ form?: string;
35
+ /** Input mode for the native character inputs. */
36
+ inputMode?: InputHTMLAttributes<HTMLInputElement>["inputMode"];
37
+ /** Autocomplete mode for the first character input. */
38
+ autoComplete?: InputHTMLAttributes<HTMLInputElement>["autoComplete"];
39
+ /** Ref forwarded to the first native input. */
40
+ ref?: Ref<HTMLInputElement>;
41
+ /** Called when an individual character input receives focus. */
42
+ onFocus?: FocusEventHandler<HTMLInputElement>;
43
+ /** Called when an individual character input loses focus. */
44
+ onBlur?: FocusEventHandler<HTMLInputElement>;
45
+ /** Called when an individual character input receives a key event. */
46
+ onKeyDown?: KeyboardEventHandler<HTMLInputElement>;
47
+ };
48
+ export type { TokenInputMode, TokenInputProps, TokenInputSize };
@@ -0,0 +1,30 @@
1
+ // src/components/forms/token-input/token-input.utils.ts
2
+ const sanitizeToken = (value, length, mode = "numeric") => {
3
+ return (mode === "numeric" ? value.replace(/[^0-9]/g, "") : value.replace(/[^a-zA-Z0-9]/g, "")).slice(0, Math.max(0, length));
4
+ };
5
+ const getNextActiveIndex = (value, length) => Math.min(value.length, length - 1);
6
+ const getPreviousActiveIndex = (index) => Math.max(0, index - 1);
7
+ const isTokenComplete = (value, length) => value.length === length;
8
+ const removeTokenCharacter = (value, index) => value.slice(0, index) + value.slice(index + 1);
9
+ const replaceTokenCharacter = (value, index, character, length, mode) => {
10
+ const normalized = sanitizeToken(character, length, mode);
11
+ if (!normalized) return removeTokenCharacter(value, index);
12
+ return sanitizeToken(value.slice(0, index) + normalized[0] + value.slice(index + 1), length, mode);
13
+ };
14
+ const insertTokenCharacters = (value, index, insertedValue, length, mode) => {
15
+ const normalized = sanitizeToken(insertedValue, length, mode);
16
+ if (!normalized) return value;
17
+ if (normalized.length >= length) return normalized.slice(0, length);
18
+ if (normalized.length === 1) return replaceTokenCharacter(value, index, normalized, length, mode);
19
+ const start = Math.max(0, Math.min(index, length));
20
+ return sanitizeToken(value.slice(0, start) + normalized + value.slice(start + normalized.length), length, mode);
21
+ };
22
+ exports.getNextActiveIndex = getNextActiveIndex;
23
+ exports.getPreviousActiveIndex = getPreviousActiveIndex;
24
+ exports.insertTokenCharacters = insertTokenCharacters;
25
+ exports.isTokenComplete = isTokenComplete;
26
+ exports.removeTokenCharacter = removeTokenCharacter;
27
+ exports.replaceTokenCharacter = replaceTokenCharacter;
28
+ exports.sanitizeToken = sanitizeToken;
29
+
30
+ //# sourceMappingURL=token-input.utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-input.utils.cjs","names":[],"sources":["../../../../src/components/forms/token-input/token-input.utils.ts"],"sourcesContent":["import type { TokenInputMode } from \"./token-input.types\";\n\nconst sanitizeToken = (\n value: string,\n length: number,\n mode: TokenInputMode = \"numeric\",\n): string => {\n const normalized =\n mode === \"numeric\"\n ? value.replace(/[^0-9]/g, \"\")\n : value.replace(/[^a-zA-Z0-9]/g, \"\");\n\n return normalized.slice(0, Math.max(0, length));\n};\n\nconst getNextActiveIndex = (value: string, length: number): number =>\n Math.min(value.length, length - 1);\n\nconst getPreviousActiveIndex = (index: number): number =>\n Math.max(0, index - 1);\n\nconst isTokenComplete = (value: string, length: number): boolean =>\n value.length === length;\n\nconst removeTokenCharacter = (value: string, index: number): string =>\n value.slice(0, index) + value.slice(index + 1);\n\nconst replaceTokenCharacter = (\n value: string,\n index: number,\n character: string,\n length: number,\n mode: TokenInputMode,\n): string => {\n const normalized = sanitizeToken(character, length, mode);\n\n if (!normalized) {\n return removeTokenCharacter(value, index);\n }\n\n return sanitizeToken(\n value.slice(0, index) + normalized[0] + value.slice(index + 1),\n length,\n mode,\n );\n};\n\nconst insertTokenCharacters = (\n value: string,\n index: number,\n insertedValue: string,\n length: number,\n mode: TokenInputMode,\n): string => {\n const normalized = sanitizeToken(insertedValue, length, mode);\n\n if (!normalized) {\n return value;\n }\n\n // A complete token always replaces the existing token.\n if (normalized.length >= length) {\n return normalized.slice(0, length);\n }\n\n // A single character replaces the current position.\n if (normalized.length === 1) {\n return replaceTokenCharacter(value, index, normalized, length, mode);\n }\n\n // Multiple characters are inserted at the current position.\n const start = Math.max(0, Math.min(index, length));\n\n return sanitizeToken(\n value.slice(0, start) + normalized + value.slice(start + normalized.length),\n length,\n mode,\n );\n};\n\nexport {\n sanitizeToken,\n getNextActiveIndex,\n getPreviousActiveIndex,\n isTokenComplete,\n removeTokenCharacter,\n replaceTokenCharacter,\n insertTokenCharacters,\n};\n"],"mappings":";AAEA,MAAM,iBACJ,OACA,QACA,OAAuB,cACZ;CAMX,QAJE,SAAS,YACL,MAAM,QAAQ,WAAW,EAAE,IAC3B,MAAM,QAAQ,iBAAiB,EAAE,EAAA,CAErB,MAAM,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AAChD;AAEA,MAAM,sBAAsB,OAAe,WACzC,KAAK,IAAI,MAAM,QAAQ,SAAS,CAAC;AAEnC,MAAM,0BAA0B,UAC9B,KAAK,IAAI,GAAG,QAAQ,CAAC;AAEvB,MAAM,mBAAmB,OAAe,WACtC,MAAM,WAAW;AAEnB,MAAM,wBAAwB,OAAe,UAC3C,MAAM,MAAM,GAAG,KAAK,IAAI,MAAM,MAAM,QAAQ,CAAC;AAE/C,MAAM,yBACJ,OACA,OACA,WACA,QACA,SACW;CACX,MAAM,aAAa,cAAc,WAAW,QAAQ,IAAI;CAExD,IAAI,CAAC,YACH,OAAO,qBAAqB,OAAO,KAAK;CAG1C,OAAO,cACL,MAAM,MAAM,GAAG,KAAK,IAAI,WAAW,KAAK,MAAM,MAAM,QAAQ,CAAC,GAC7D,QACA,IACF;AACF;AAEA,MAAM,yBACJ,OACA,OACA,eACA,QACA,SACW;CACX,MAAM,aAAa,cAAc,eAAe,QAAQ,IAAI;CAE5D,IAAI,CAAC,YACH,OAAO;CAIT,IAAI,WAAW,UAAU,QACvB,OAAO,WAAW,MAAM,GAAG,MAAM;CAInC,IAAI,WAAW,WAAW,GACxB,OAAO,sBAAsB,OAAO,OAAO,YAAY,QAAQ,IAAI;CAIrE,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,MAAM,CAAC;CAEjD,OAAO,cACL,MAAM,MAAM,GAAG,KAAK,IAAI,aAAa,MAAM,MAAM,QAAQ,WAAW,MAAM,GAC1E,QACA,IACF;AACF"}
@@ -0,0 +1,24 @@
1
+ // src/components/forms/token-input/token-input.utils.ts
2
+ const sanitizeToken = (value, length, mode = "numeric") => {
3
+ return (mode === "numeric" ? value.replace(/[^0-9]/g, "") : value.replace(/[^a-zA-Z0-9]/g, "")).slice(0, Math.max(0, length));
4
+ };
5
+ const getNextActiveIndex = (value, length) => Math.min(value.length, length - 1);
6
+ const getPreviousActiveIndex = (index) => Math.max(0, index - 1);
7
+ const isTokenComplete = (value, length) => value.length === length;
8
+ const removeTokenCharacter = (value, index) => value.slice(0, index) + value.slice(index + 1);
9
+ const replaceTokenCharacter = (value, index, character, length, mode) => {
10
+ const normalized = sanitizeToken(character, length, mode);
11
+ if (!normalized) return removeTokenCharacter(value, index);
12
+ return sanitizeToken(value.slice(0, index) + normalized[0] + value.slice(index + 1), length, mode);
13
+ };
14
+ const insertTokenCharacters = (value, index, insertedValue, length, mode) => {
15
+ const normalized = sanitizeToken(insertedValue, length, mode);
16
+ if (!normalized) return value;
17
+ if (normalized.length >= length) return normalized.slice(0, length);
18
+ if (normalized.length === 1) return replaceTokenCharacter(value, index, normalized, length, mode);
19
+ const start = Math.max(0, Math.min(index, length));
20
+ return sanitizeToken(value.slice(0, start) + normalized + value.slice(start + normalized.length), length, mode);
21
+ };
22
+ export { getNextActiveIndex, getPreviousActiveIndex, insertTokenCharacters, isTokenComplete, removeTokenCharacter, replaceTokenCharacter, sanitizeToken };
23
+
24
+ //# sourceMappingURL=token-input.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-input.utils.js","names":[],"sources":["../../../../src/components/forms/token-input/token-input.utils.ts"],"sourcesContent":["import type { TokenInputMode } from \"./token-input.types\";\n\nconst sanitizeToken = (\n value: string,\n length: number,\n mode: TokenInputMode = \"numeric\",\n): string => {\n const normalized =\n mode === \"numeric\"\n ? value.replace(/[^0-9]/g, \"\")\n : value.replace(/[^a-zA-Z0-9]/g, \"\");\n\n return normalized.slice(0, Math.max(0, length));\n};\n\nconst getNextActiveIndex = (value: string, length: number): number =>\n Math.min(value.length, length - 1);\n\nconst getPreviousActiveIndex = (index: number): number =>\n Math.max(0, index - 1);\n\nconst isTokenComplete = (value: string, length: number): boolean =>\n value.length === length;\n\nconst removeTokenCharacter = (value: string, index: number): string =>\n value.slice(0, index) + value.slice(index + 1);\n\nconst replaceTokenCharacter = (\n value: string,\n index: number,\n character: string,\n length: number,\n mode: TokenInputMode,\n): string => {\n const normalized = sanitizeToken(character, length, mode);\n\n if (!normalized) {\n return removeTokenCharacter(value, index);\n }\n\n return sanitizeToken(\n value.slice(0, index) + normalized[0] + value.slice(index + 1),\n length,\n mode,\n );\n};\n\nconst insertTokenCharacters = (\n value: string,\n index: number,\n insertedValue: string,\n length: number,\n mode: TokenInputMode,\n): string => {\n const normalized = sanitizeToken(insertedValue, length, mode);\n\n if (!normalized) {\n return value;\n }\n\n // A complete token always replaces the existing token.\n if (normalized.length >= length) {\n return normalized.slice(0, length);\n }\n\n // A single character replaces the current position.\n if (normalized.length === 1) {\n return replaceTokenCharacter(value, index, normalized, length, mode);\n }\n\n // Multiple characters are inserted at the current position.\n const start = Math.max(0, Math.min(index, length));\n\n return sanitizeToken(\n value.slice(0, start) + normalized + value.slice(start + normalized.length),\n length,\n mode,\n );\n};\n\nexport {\n sanitizeToken,\n getNextActiveIndex,\n getPreviousActiveIndex,\n isTokenComplete,\n removeTokenCharacter,\n replaceTokenCharacter,\n insertTokenCharacters,\n};\n"],"mappings":";AAEA,MAAM,iBACJ,OACA,QACA,OAAuB,cACZ;CAMX,QAJE,SAAS,YACL,MAAM,QAAQ,WAAW,EAAE,IAC3B,MAAM,QAAQ,iBAAiB,EAAE,EAAA,CAErB,MAAM,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AAChD;AAEA,MAAM,sBAAsB,OAAe,WACzC,KAAK,IAAI,MAAM,QAAQ,SAAS,CAAC;AAEnC,MAAM,0BAA0B,UAC9B,KAAK,IAAI,GAAG,QAAQ,CAAC;AAEvB,MAAM,mBAAmB,OAAe,WACtC,MAAM,WAAW;AAEnB,MAAM,wBAAwB,OAAe,UAC3C,MAAM,MAAM,GAAG,KAAK,IAAI,MAAM,MAAM,QAAQ,CAAC;AAE/C,MAAM,yBACJ,OACA,OACA,WACA,QACA,SACW;CACX,MAAM,aAAa,cAAc,WAAW,QAAQ,IAAI;CAExD,IAAI,CAAC,YACH,OAAO,qBAAqB,OAAO,KAAK;CAG1C,OAAO,cACL,MAAM,MAAM,GAAG,KAAK,IAAI,WAAW,KAAK,MAAM,MAAM,QAAQ,CAAC,GAC7D,QACA,IACF;AACF;AAEA,MAAM,yBACJ,OACA,OACA,eACA,QACA,SACW;CACX,MAAM,aAAa,cAAc,eAAe,QAAQ,IAAI;CAE5D,IAAI,CAAC,YACH,OAAO;CAIT,IAAI,WAAW,UAAU,QACvB,OAAO,WAAW,MAAM,GAAG,MAAM;CAInC,IAAI,WAAW,WAAW,GACxB,OAAO,sBAAsB,OAAO,OAAO,YAAY,QAAQ,IAAI;CAIrE,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,MAAM,CAAC;CAEjD,OAAO,cACL,MAAM,MAAM,GAAG,KAAK,IAAI,aAAa,MAAM,MAAM,QAAQ,WAAW,MAAM,GAC1E,QACA,IACF;AACF"}
@@ -0,0 +1,14 @@
1
+ .puzzle-aspect-ratio {
2
+ box-sizing: border-box;
3
+ aspect-ratio: 1;
4
+ width: 100%;
5
+ display: block;
6
+ position: relative;
7
+ }
8
+
9
+ .puzzle-aspect-ratio > * {
10
+ width: 100%;
11
+ height: 100%;
12
+ position: absolute;
13
+ inset: 0;
14
+ }
@@ -0,0 +1,11 @@
1
+ // src/components/layout/aspect-ratio/aspect-ratio.utils.ts
2
+ const getAspectRatioStyle = (ratio, style) => {
3
+ if (!Number.isFinite(ratio) || ratio <= 0) throw new RangeError("AspectRatio: ratio must be a positive finite number.");
4
+ return {
5
+ ...style,
6
+ aspectRatio: ratio
7
+ };
8
+ };
9
+ exports.getAspectRatioStyle = getAspectRatioStyle;
10
+
11
+ //# sourceMappingURL=aspect-ratio.utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aspect-ratio.utils.cjs","names":[],"sources":["../../../../src/components/layout/aspect-ratio/aspect-ratio.utils.ts"],"sourcesContent":["import type { CSSProperties } from \"react\";\n\nconst getAspectRatioStyle = (\n ratio: number,\n style?: CSSProperties,\n): CSSProperties => {\n if (!Number.isFinite(ratio) || ratio <= 0) {\n throw new RangeError(\n \"AspectRatio: ratio must be a positive finite number.\",\n );\n }\n\n return {\n ...style,\n aspectRatio: ratio,\n };\n};\n\nexport { getAspectRatioStyle };\n"],"mappings":";AAEA,MAAM,uBACJ,OACA,UACkB;CAClB,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GACtC,MAAM,IAAI,WACR,sDACF;CAGF,OAAO;EACL,GAAG;EACH,aAAa;CACf;AACF"}
@@ -0,0 +1,11 @@
1
+ // src/components/layout/aspect-ratio/aspect-ratio.utils.ts
2
+ const getAspectRatioStyle = (ratio, style) => {
3
+ if (!Number.isFinite(ratio) || ratio <= 0) throw new RangeError("AspectRatio: ratio must be a positive finite number.");
4
+ return {
5
+ ...style,
6
+ aspectRatio: ratio
7
+ };
8
+ };
9
+ export { getAspectRatioStyle };
10
+
11
+ //# sourceMappingURL=aspect-ratio.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aspect-ratio.utils.js","names":[],"sources":["../../../../src/components/layout/aspect-ratio/aspect-ratio.utils.ts"],"sourcesContent":["import type { CSSProperties } from \"react\";\n\nconst getAspectRatioStyle = (\n ratio: number,\n style?: CSSProperties,\n): CSSProperties => {\n if (!Number.isFinite(ratio) || ratio <= 0) {\n throw new RangeError(\n \"AspectRatio: ratio must be a positive finite number.\",\n );\n }\n\n return {\n ...style,\n aspectRatio: ratio,\n };\n};\n\nexport { getAspectRatioStyle };\n"],"mappings":";AAEA,MAAM,uBACJ,OACA,UACkB;CAClB,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GACtC,MAAM,IAAI,WACR,sDACF;CAGF,OAAO;EACL,GAAG;EACH,aAAa;CACf;AACF"}
@@ -0,0 +1,16 @@
1
+ const require_aspect_ratio_utils = require("./aspect-ratio.utils.cjs");
2
+ ;/* empty css */
3
+ let _puzzle_ui_core = require("@puzzle-ui/core");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ // src/components/layout/aspect-ratio/index.tsx
6
+ const AspectRatio = ({ as, ratio = 1, className, style, children, ...rest }) => {
7
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(as ?? "div", {
8
+ className: (0, _puzzle_ui_core.cn)("puzzle-aspect-ratio", className),
9
+ style: require_aspect_ratio_utils.getAspectRatioStyle(ratio, style),
10
+ ...rest,
11
+ children
12
+ });
13
+ };
14
+ exports.AspectRatio = AspectRatio;
15
+
16
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["cn","getAspectRatioStyle"],"sources":["../../../../src/components/layout/aspect-ratio/index.tsx"],"sourcesContent":["import type {\n ComponentPropsWithRef,\n CSSProperties,\n ElementType,\n ReactNode,\n} from \"react\";\nimport { cn } from \"@puzzle-ui/core\";\nimport { getAspectRatioStyle } from \"./aspect-ratio.utils\";\nimport \"./aspect-ratio.css\";\n\ntype AspectRatioOwnProps<C extends ElementType> = {\n as?: C;\n ratio?: number;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n};\n\ntype AspectRatioProps<C extends ElementType = \"div\"> = AspectRatioOwnProps<C> &\n Omit<ComponentPropsWithRef<C>, keyof AspectRatioOwnProps<C> | \"as\">;\n\nconst AspectRatio = <C extends ElementType = \"div\">({\n as,\n ratio = 1,\n className,\n style,\n children,\n ...rest\n}: AspectRatioProps<C>) => {\n const Component = (as ?? \"div\") as ElementType;\n\n return (\n <Component\n className={cn(\"puzzle-aspect-ratio\", className)}\n style={getAspectRatioStyle(ratio, style)}\n {...rest}\n >\n {children}\n </Component>\n );\n};\n\nexport { AspectRatio, type AspectRatioProps };\n"],"mappings":";;;;;AAqBA,MAAM,eAA8C,EAClD,IACA,QAAQ,GACR,WACA,OACA,UACA,GAAG,WACsB;CAGzB,OACE,iBAAA,GAAA,kBAAA,IAAA,CAHiB,MAAM,OAGvB;EACE,YAAA,GAAWA,gBAAAA,GAAAA,CAAG,uBAAuB,SAAS;EAC9C,OAAOC,2BAAAA,oBAAoB,OAAO,KAAK;EACvC,GAAI;EAEH;CACQ,CAAA;AAEf"}
@@ -0,0 +1,11 @@
1
+ import { CSSProperties, ComponentPropsWithRef, ElementType, ReactNode } from "react";
2
+ type AspectRatioOwnProps<C extends ElementType> = {
3
+ as?: C;
4
+ ratio?: number;
5
+ className?: string;
6
+ style?: CSSProperties;
7
+ children?: ReactNode;
8
+ };
9
+ type AspectRatioProps<C extends ElementType = "div"> = AspectRatioOwnProps<C> & Omit<ComponentPropsWithRef<C>, keyof AspectRatioOwnProps<C> | "as">;
10
+ declare const AspectRatio: <C extends ElementType = "div">({ as, ratio, className, style, children, ...rest }: AspectRatioProps<C>) => import("react").JSX.Element;
11
+ export { AspectRatio, type AspectRatioProps };
@@ -0,0 +1,11 @@
1
+ import { CSSProperties, ComponentPropsWithRef, ElementType, ReactNode } from "react";
2
+ type AspectRatioOwnProps<C extends ElementType> = {
3
+ as?: C;
4
+ ratio?: number;
5
+ className?: string;
6
+ style?: CSSProperties;
7
+ children?: ReactNode;
8
+ };
9
+ type AspectRatioProps<C extends ElementType = "div"> = AspectRatioOwnProps<C> & Omit<ComponentPropsWithRef<C>, keyof AspectRatioOwnProps<C> | "as">;
10
+ declare const AspectRatio: <C extends ElementType = "div">({ as, ratio, className, style, children, ...rest }: AspectRatioProps<C>) => import("react").JSX.Element;
11
+ export { AspectRatio, type AspectRatioProps };
@@ -0,0 +1,16 @@
1
+ import { getAspectRatioStyle } from "./aspect-ratio.utils.js";
2
+ import "./aspect-ratio.css";
3
+ import { cn } from "@puzzle-ui/core";
4
+ import { jsx } from "react/jsx-runtime";
5
+ // src/components/layout/aspect-ratio/index.tsx
6
+ const AspectRatio = ({ as, ratio = 1, className, style, children, ...rest }) => {
7
+ return /* @__PURE__ */ jsx(as ?? "div", {
8
+ className: cn("puzzle-aspect-ratio", className),
9
+ style: getAspectRatioStyle(ratio, style),
10
+ ...rest,
11
+ children
12
+ });
13
+ };
14
+ export { AspectRatio };
15
+
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/layout/aspect-ratio/index.tsx"],"sourcesContent":["import type {\n ComponentPropsWithRef,\n CSSProperties,\n ElementType,\n ReactNode,\n} from \"react\";\nimport { cn } from \"@puzzle-ui/core\";\nimport { getAspectRatioStyle } from \"./aspect-ratio.utils\";\nimport \"./aspect-ratio.css\";\n\ntype AspectRatioOwnProps<C extends ElementType> = {\n as?: C;\n ratio?: number;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n};\n\ntype AspectRatioProps<C extends ElementType = \"div\"> = AspectRatioOwnProps<C> &\n Omit<ComponentPropsWithRef<C>, keyof AspectRatioOwnProps<C> | \"as\">;\n\nconst AspectRatio = <C extends ElementType = \"div\">({\n as,\n ratio = 1,\n className,\n style,\n children,\n ...rest\n}: AspectRatioProps<C>) => {\n const Component = (as ?? \"div\") as ElementType;\n\n return (\n <Component\n className={cn(\"puzzle-aspect-ratio\", className)}\n style={getAspectRatioStyle(ratio, style)}\n {...rest}\n >\n {children}\n </Component>\n );\n};\n\nexport { AspectRatio, type AspectRatioProps };\n"],"mappings":";;;;;AAqBA,MAAM,eAA8C,EAClD,IACA,QAAQ,GACR,WACA,OACA,UACA,GAAG,WACsB;CAGzB,OACE,oBAHiB,MAAM,OAGvB;EACE,WAAW,GAAG,uBAAuB,SAAS;EAC9C,OAAO,oBAAoB,OAAO,KAAK;EACvC,GAAI;EAEH;CACQ,CAAA;AAEf"}
@@ -2,6 +2,7 @@
2
2
  --_container-gutter: var(--puzzle-container-gutter, clamp(1rem, 3vw, 3rem));
3
3
  box-sizing: border-box;
4
4
  width: 100%;
5
+ max-width: var(--puzzle-container-width, 80rem);
5
6
  padding-inline: var(--_container-gutter);
6
7
  min-width: 0;
7
8
  margin-inline: auto;
@@ -32,6 +32,7 @@
32
32
  order: 0;
33
33
  flex: var(--puzzle-page-main-flex);
34
34
  box-sizing: border-box;
35
+ background-color: var(--puzzle-color-background);
35
36
  min-width: 0;
36
37
  }
37
38
 
@@ -115,7 +115,7 @@ const ResizablePanelsRoot = ({ children, orientation = "horizontal", sizes, defa
115
115
  const pointerDragRef = (0, react.useRef)(null);
116
116
  const updateSizes = (nextSizes) => {
117
117
  const normalized = require_resizable_panels_utils.normalizePanelSizes(nextSizes, panelConstraints);
118
- if (!normalized.some((size, index) => Math.abs(size - currentSizes[index]) > 1e-6)) return;
118
+ if (!normalized.some((size, index) => Math.abs(size - (currentSizes[index] ?? 0)) > 1e-6)) return;
119
119
  if (sizes === void 0) setUncontrolledSizes(normalized);
120
120
  onSizesChange?.(normalized);
121
121
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["isValidElement","cn","useId","Children","useState","normalizePanelSizes","useRef","resizePanelPair","getPanelPairBounds","cloneElement"],"sources":["../../../../src/components/layout/resizable-panels/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@puzzle-ui/core\";\n\nimport {\n Children,\n cloneElement,\n isValidElement,\n useId,\n useRef,\n useState,\n type ComponentPropsWithRef,\n type KeyboardEvent as ReactKeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport {\n getPanelPairBounds,\n normalizePanelSizes,\n resizePanelPair,\n type PanelSizeConstraint,\n} from \"./resizable-panels.utils\";\n\nimport \"./resizable-panels.css\";\n\ntype ResizablePanelsOrientation = \"horizontal\" | \"vertical\";\n\ntype ResizablePanelsProps = Omit<ComponentPropsWithRef<\"div\">, \"children\"> & {\n /** Layout direction. Defaults to horizontal. */\n orientation?: ResizablePanelsOrientation;\n\n /** Controlled panel sizes, expressed as percentages. */\n sizes?: readonly number[];\n\n /** Initial panel sizes for uncontrolled usage. */\n defaultSizes?: readonly number[];\n\n /** Called whenever the panel layout changes. */\n onSizesChange?: (sizes: number[]) => void;\n\n /** Disables all resizing interactions. */\n disabled?: boolean;\n\n /** Percentage change per keyboard interaction. Defaults to 1. */\n keyboardStep?: number;\n\n /** Panels and handles that make up the group. */\n children: ReactNode;\n};\n\ntype ResizablePanelProps = ComponentPropsWithRef<\"div\"> & {\n /** Minimum panel size in percentages. Defaults to 0. */\n minSize?: number;\n\n /** Maximum panel size in percentages. Defaults to 100. */\n maxSize?: number;\n};\n\ntype ResizableHandleProps = ComponentPropsWithRef<\"div\"> & {\n /** Renders a visible grip inside the resize handle. */\n withGrip?: boolean;\n\n /** Disables resizing through this handle. */\n disabled?: boolean;\n};\n\ntype ResizePointerHandler = (\n event: ReactPointerEvent<HTMLDivElement>,\n handleIndex: number,\n) => void;\n\ntype ResizeKeyboardHandler = (\n event: ReactKeyboardEvent<HTMLDivElement>,\n handleIndex: number,\n) => void;\n\ntype InternalResizablePanelProps = {\n panelIndex?: number;\n panelSize?: number;\n panelId?: string;\n};\n\ntype InternalResizableHandleProps = {\n handleIndex?: number;\n orientation?: ResizablePanelsOrientation;\n value?: number;\n minValue?: number;\n maxValue?: number;\n panelIds?: [string, string];\n inheritedDisabled?: boolean;\n\n onResizeStart?: ResizePointerHandler;\n onResizeMove?: ResizePointerHandler;\n onResizeEnd?: ResizePointerHandler;\n onResizeKeyDown?: ResizeKeyboardHandler;\n};\n\ntype PointerDragState = {\n handleIndex: number;\n pointerId: number;\n startCoordinate: number;\n availableSize: number;\n direction: number;\n sizes: number[];\n};\n\nconst isResizablePanelElement = (\n child: ReactNode,\n): child is ReactElement<ResizablePanelProps> =>\n isValidElement(child) && child.type === ResizablePanel;\n\nconst isResizableHandleElement = (\n child: ReactNode,\n): child is ReactElement<ResizableHandleProps> =>\n isValidElement(child) && child.type === ResizableHandle;\n\nconst parsePixels = (value: string | undefined) =>\n Number.parseFloat(value ?? \"\") || 0;\n\nconst getAvailableSize = (\n group: HTMLDivElement,\n orientation: ResizablePanelsOrientation,\n) => {\n const computedStyle =\n group.ownerDocument.defaultView?.getComputedStyle(group);\n\n const isHorizontal = orientation === \"horizontal\";\n\n const totalSize = isHorizontal ? group.clientWidth : group.clientHeight;\n\n const paddingSize = computedStyle\n ? isHorizontal\n ? parsePixels(computedStyle.paddingLeft) +\n parsePixels(computedStyle.paddingRight)\n : parsePixels(computedStyle.paddingTop) +\n parsePixels(computedStyle.paddingBottom)\n : 0;\n\n const handleSize = Array.from(group.children).reduce((total, child) => {\n const element = child as HTMLElement;\n\n if (!element.hasAttribute(\"data-puzzle-resizable-handle\")) {\n return total;\n }\n\n const rect = element.getBoundingClientRect();\n\n return total + (isHorizontal ? rect.width : rect.height);\n }, 0);\n\n return Math.max(0, totalSize - paddingSize - handleSize);\n};\n\nconst getResizeDirection = (\n element: HTMLElement,\n orientation: ResizablePanelsOrientation,\n) => {\n if (orientation !== \"horizontal\") {\n return 1;\n }\n\n const direction =\n element.ownerDocument.defaultView?.getComputedStyle(element).direction;\n\n return direction === \"rtl\" ? -1 : 1;\n};\n\nconst getPointerCoordinate = (\n event: ReactPointerEvent<HTMLDivElement>,\n orientation: ResizablePanelsOrientation,\n) => (orientation === \"horizontal\" ? event.clientX : event.clientY);\n\nconst ResizablePanel = ({\n id,\n minSize = 0,\n maxSize = 100,\n panelIndex = 0,\n panelSize = 1,\n panelId,\n className,\n style,\n ...props\n}: ResizablePanelProps & InternalResizablePanelProps) => (\n <div\n {...props}\n id={panelId ?? id}\n className={cn(\"puzzle-resizable-panels__panel\", className)}\n style={{\n ...style,\n flex: `${panelSize} 1 0%`,\n }}\n data-panel-index={panelIndex}\n data-panel-size={panelSize}\n data-panel-min-size={minSize}\n data-panel-max-size={maxSize}\n />\n);\n\nconst ResizableHandle = ({\n withGrip = false,\n disabled = false,\n handleIndex = -1,\n orientation = \"horizontal\",\n value,\n minValue,\n maxValue,\n panelIds,\n inheritedDisabled = false,\n onResizeStart,\n onResizeMove,\n onResizeEnd,\n onResizeKeyDown,\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n onLostPointerCapture,\n onKeyDown,\n className,\n children,\n tabIndex,\n \"aria-label\": ariaLabel,\n ...props\n}: ResizableHandleProps & InternalResizableHandleProps) => {\n const isDisabled = disabled || inheritedDisabled;\n\n const handlePointerDown = (event: ReactPointerEvent<HTMLDivElement>) => {\n onPointerDown?.(event);\n\n if (!event.defaultPrevented && !isDisabled) {\n onResizeStart?.(event, handleIndex);\n }\n };\n\n const handlePointerMove = (event: ReactPointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event);\n\n if (!event.defaultPrevented && !isDisabled) {\n onResizeMove?.(event, handleIndex);\n }\n };\n\n const handlePointerUp = (event: ReactPointerEvent<HTMLDivElement>) => {\n onResizeEnd?.(event, handleIndex);\n onPointerUp?.(event);\n };\n\n const handlePointerCancel = (event: ReactPointerEvent<HTMLDivElement>) => {\n onResizeEnd?.(event, handleIndex);\n onPointerCancel?.(event);\n };\n\n const handleLostPointerCapture = (\n event: ReactPointerEvent<HTMLDivElement>,\n ) => {\n onResizeEnd?.(event, handleIndex);\n onLostPointerCapture?.(event);\n };\n\n const handleKeyDown = (event: ReactKeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n if (!event.defaultPrevented && !isDisabled) {\n onResizeKeyDown?.(event, handleIndex);\n }\n };\n\n return (\n <div\n {...props}\n className={cn(\"puzzle-resizable-panels__handle\", className)}\n role=\"separator\"\n tabIndex={isDisabled ? -1 : (tabIndex ?? 0)}\n aria-label={ariaLabel ?? \"Resize panels\"}\n aria-orientation={\n orientation === \"horizontal\" ? \"vertical\" : \"horizontal\"\n }\n aria-controls={panelIds?.join(\" \")}\n aria-valuenow={value}\n aria-valuemin={minValue}\n aria-valuemax={maxValue}\n aria-valuetext={\n value === undefined ? undefined : `${Math.round(value * 100) / 100}%`\n }\n aria-disabled={isDisabled || undefined}\n data-puzzle-resizable-handle=\"\"\n data-orientation={orientation}\n data-disabled={isDisabled ? \"true\" : undefined}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerCancel}\n onLostPointerCapture={handleLostPointerCapture}\n onKeyDown={handleKeyDown}\n >\n {withGrip ? (\n <span\n className=\"puzzle-resizable-panels__handle-grip\"\n aria-hidden=\"true\"\n />\n ) : (\n children\n )}\n </div>\n );\n};\n\nconst ResizablePanelsRoot = ({\n children,\n orientation = \"horizontal\",\n sizes,\n defaultSizes,\n onSizesChange,\n disabled = false,\n keyboardStep = 1,\n id,\n role,\n className,\n style,\n ref: forwardedRef,\n ...rootProps\n}: ResizablePanelsProps) => {\n const generatedId = useId();\n\n const groupId = id ?? `puzzle-resizable-panels-${generatedId}`;\n\n if (!Number.isFinite(keyboardStep) || keyboardStep <= 0) {\n throw new RangeError(\"keyboardStep must be a positive finite number.\");\n }\n\n const childrenArray = Children.toArray(children);\n\n const validChildren =\n childrenArray.length >= 3 &&\n childrenArray.length % 2 === 1 &&\n childrenArray.every((child, index) =>\n index % 2 === 0\n ? isResizablePanelElement(child)\n : isResizableHandleElement(child),\n );\n\n if (!validChildren) {\n throw new Error(\n \"ResizablePanels requires alternating Panel and Handle children, starting and ending with a Panel. At least two panels are required.\",\n );\n }\n\n const panelElements = childrenArray.filter(isResizablePanelElement);\n\n const panelCount = panelElements.length;\n\n const panelConstraints: PanelSizeConstraint[] = panelElements.map(\n (panel) => ({\n minSize: panel.props.minSize,\n maxSize: panel.props.maxSize,\n }),\n );\n\n const panelIds = panelElements.map(\n (panel, index) => panel.props.id ?? `${groupId}-panel-${index}`,\n );\n\n if (new Set(panelIds).size !== panelIds.length) {\n throw new Error(\"ResizablePanels requires unique panel IDs.\");\n }\n\n const [uncontrolledSizes, setUncontrolledSizes] = useState<number[]>(() =>\n normalizePanelSizes(\n sizes === undefined ? defaultSizes : undefined,\n panelConstraints,\n ),\n );\n\n const layoutInput =\n sizes ??\n (uncontrolledSizes.length === panelCount ? uncontrolledSizes : undefined);\n\n const currentSizes = normalizePanelSizes(layoutInput, panelConstraints);\n\n const [isResizing, setIsResizing] = useState(false);\n\n const groupRef = useRef<HTMLDivElement | null>(null);\n\n const pointerDragRef = useRef<PointerDragState | null>(null);\n\n const updateSizes = (nextSizes: readonly number[]) => {\n const normalized = normalizePanelSizes(nextSizes, panelConstraints);\n\n const hasChanged = normalized.some(\n (size, index) => Math.abs(size - currentSizes[index]) > 0.000001,\n );\n\n if (!hasChanged) {\n return;\n }\n\n if (sizes === undefined) {\n setUncontrolledSizes(normalized);\n }\n\n onSizesChange?.(normalized);\n };\n\n const handlePointerDown: ResizePointerHandler = (event, handleIndex) => {\n const group = groupRef.current;\n\n if (!group || disabled) {\n return;\n }\n\n if (\n event.button !== 0 &&\n event.pointerType !== \"touch\" &&\n event.pointerType !== \"pen\"\n ) {\n return;\n }\n\n const availableSize = getAvailableSize(group, orientation);\n\n if (availableSize <= 0) {\n return;\n }\n\n pointerDragRef.current = {\n handleIndex,\n pointerId: event.pointerId,\n startCoordinate: getPointerCoordinate(event, orientation),\n availableSize,\n direction: getResizeDirection(group, orientation),\n sizes: [...currentSizes],\n };\n\n try {\n event.currentTarget.setPointerCapture(event.pointerId);\n } catch {\n // Synthetic pointer events and detached elements may not\n // support pointer capture.\n }\n\n event.preventDefault();\n setIsResizing(true);\n };\n\n const handlePointerMove: ResizePointerHandler = (event, handleIndex) => {\n const drag = pointerDragRef.current;\n\n if (\n !drag ||\n drag.pointerId !== event.pointerId ||\n drag.handleIndex !== handleIndex\n ) {\n return;\n }\n\n const currentCoordinate = getPointerCoordinate(event, orientation);\n\n const delta =\n ((currentCoordinate - drag.startCoordinate) / drag.availableSize) *\n 100 *\n drag.direction;\n\n const nextSizes = resizePanelPair(\n drag.sizes,\n panelConstraints,\n handleIndex,\n delta,\n );\n\n event.preventDefault();\n updateSizes(nextSizes);\n };\n\n const handlePointerEnd: ResizePointerHandler = (event, handleIndex) => {\n const drag = pointerDragRef.current;\n\n if (\n !drag ||\n drag.pointerId !== event.pointerId ||\n drag.handleIndex !== handleIndex\n ) {\n return;\n }\n\n pointerDragRef.current = null;\n setIsResizing(false);\n };\n\n const handleKeyDown: ResizeKeyboardHandler = (event, handleIndex) => {\n if (disabled) {\n return;\n }\n\n const currentSize = currentSizes[handleIndex];\n\n const bounds = getPanelPairBounds(\n currentSizes,\n panelConstraints,\n handleIndex,\n );\n\n const group = groupRef.current;\n\n const direction = group ? getResizeDirection(group, orientation) : 1;\n\n const step = keyboardStep * (event.shiftKey ? 10 : 1);\n\n let nextSize: number | undefined;\n\n if (event.key === \"Home\") {\n nextSize = bounds.minSize;\n } else if (event.key === \"End\") {\n nextSize = bounds.maxSize;\n } else if (orientation === \"horizontal\") {\n if (event.key === \"ArrowRight\") {\n nextSize = currentSize + step * direction;\n } else if (event.key === \"ArrowLeft\") {\n nextSize = currentSize - step * direction;\n }\n } else {\n if (event.key === \"ArrowDown\") {\n nextSize = currentSize + step;\n } else if (event.key === \"ArrowUp\") {\n nextSize = currentSize - step;\n }\n }\n\n if (nextSize === undefined) {\n return;\n }\n\n event.preventDefault();\n\n updateSizes(\n resizePanelPair(\n currentSizes,\n panelConstraints,\n handleIndex,\n nextSize - currentSize,\n ),\n );\n };\n\n let panelIndex = 0;\n\n const enhancedChildren = childrenArray.map((child) => {\n if (isResizablePanelElement(child)) {\n const index = panelIndex++;\n\n return cloneElement(\n child as ReactElement<\n ResizablePanelProps & InternalResizablePanelProps\n >,\n {\n panelIndex: index,\n panelSize: currentSizes[index],\n panelId: panelIds[index],\n },\n );\n }\n\n const handleIndex = panelIndex - 1;\n\n const bounds = getPanelPairBounds(\n currentSizes,\n panelConstraints,\n handleIndex,\n );\n\n return cloneElement(\n child as ReactElement<\n ResizableHandleProps & InternalResizableHandleProps\n >,\n {\n handleIndex,\n orientation,\n value: currentSizes[handleIndex],\n minValue: bounds.minSize,\n maxValue: bounds.maxSize,\n panelIds: [panelIds[handleIndex], panelIds[handleIndex + 1]],\n inheritedDisabled: disabled,\n onResizeStart: handlePointerDown,\n onResizeMove: handlePointerMove,\n onResizeEnd: handlePointerEnd,\n onResizeKeyDown: handleKeyDown,\n },\n );\n });\n\n return (\n <div\n {...rootProps}\n ref={(node) => {\n groupRef.current = node;\n\n if (typeof forwardedRef === \"function\") {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n id={groupId}\n role={role ?? \"group\"}\n className={cn(\"puzzle-resizable-panels\", className)}\n style={style}\n data-orientation={orientation}\n data-disabled={disabled ? \"true\" : undefined}\n data-resizing={isResizing ? \"true\" : undefined}\n >\n {enhancedChildren}\n </div>\n );\n};\n\ntype ResizablePanelsComponent = typeof ResizablePanelsRoot & {\n Panel: typeof ResizablePanel;\n Handle: typeof ResizableHandle;\n};\n\nconst ResizablePanels = Object.assign(ResizablePanelsRoot, {\n Panel: ResizablePanel,\n Handle: ResizableHandle,\n}) as ResizablePanelsComponent;\n\nexport {\n ResizablePanels,\n ResizablePanel,\n ResizableHandle,\n type ResizablePanelsProps,\n type ResizablePanelProps,\n type ResizableHandleProps,\n type ResizablePanelsOrientation,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["isValidElement","cn","useId","Children","useState","normalizePanelSizes","useRef","resizePanelPair","getPanelPairBounds","cloneElement"],"sources":["../../../../src/components/layout/resizable-panels/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@puzzle-ui/core\";\n\nimport {\n Children,\n cloneElement,\n isValidElement,\n useId,\n useRef,\n useState,\n type ComponentPropsWithRef,\n type KeyboardEvent as ReactKeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport {\n getPanelPairBounds,\n normalizePanelSizes,\n resizePanelPair,\n type PanelSizeConstraint,\n} from \"./resizable-panels.utils\";\n\nimport \"./resizable-panels.css\";\n\ntype ResizablePanelsOrientation = \"horizontal\" | \"vertical\";\n\ntype ResizablePanelsProps = Omit<ComponentPropsWithRef<\"div\">, \"children\"> & {\n /** Layout direction. Defaults to horizontal. */\n orientation?: ResizablePanelsOrientation;\n\n /** Controlled panel sizes, expressed as percentages. */\n sizes?: readonly number[];\n\n /** Initial panel sizes for uncontrolled usage. */\n defaultSizes?: readonly number[];\n\n /** Called whenever the panel layout changes. */\n onSizesChange?: (sizes: number[]) => void;\n\n /** Disables all resizing interactions. */\n disabled?: boolean;\n\n /** Percentage change per keyboard interaction. Defaults to 1. */\n keyboardStep?: number;\n\n /** Panels and handles that make up the group. */\n children: ReactNode;\n};\n\ntype ResizablePanelProps = ComponentPropsWithRef<\"div\"> & {\n /** Minimum panel size in percentages. Defaults to 0. */\n minSize?: number;\n\n /** Maximum panel size in percentages. Defaults to 100. */\n maxSize?: number;\n};\n\ntype ResizableHandleProps = ComponentPropsWithRef<\"div\"> & {\n /** Renders a visible grip inside the resize handle. */\n withGrip?: boolean;\n\n /** Disables resizing through this handle. */\n disabled?: boolean;\n};\n\ntype ResizePointerHandler = (\n event: ReactPointerEvent<HTMLDivElement>,\n handleIndex: number,\n) => void;\n\ntype ResizeKeyboardHandler = (\n event: ReactKeyboardEvent<HTMLDivElement>,\n handleIndex: number,\n) => void;\n\ntype InternalResizablePanelProps = {\n panelIndex?: number;\n panelSize?: number;\n panelId?: string;\n};\n\ntype InternalResizableHandleProps = {\n handleIndex?: number;\n orientation?: ResizablePanelsOrientation;\n value?: number;\n minValue?: number;\n maxValue?: number;\n panelIds?: [string, string];\n inheritedDisabled?: boolean;\n\n onResizeStart?: ResizePointerHandler;\n onResizeMove?: ResizePointerHandler;\n onResizeEnd?: ResizePointerHandler;\n onResizeKeyDown?: ResizeKeyboardHandler;\n};\n\ntype PointerDragState = {\n handleIndex: number;\n pointerId: number;\n startCoordinate: number;\n availableSize: number;\n direction: number;\n sizes: number[];\n};\n\nconst isResizablePanelElement = (\n child: ReactNode,\n): child is ReactElement<ResizablePanelProps> =>\n isValidElement(child) && child.type === ResizablePanel;\n\nconst isResizableHandleElement = (\n child: ReactNode,\n): child is ReactElement<ResizableHandleProps> =>\n isValidElement(child) && child.type === ResizableHandle;\n\nconst parsePixels = (value: string | undefined) =>\n Number.parseFloat(value ?? \"\") || 0;\n\nconst getAvailableSize = (\n group: HTMLDivElement,\n orientation: ResizablePanelsOrientation,\n) => {\n const computedStyle =\n group.ownerDocument.defaultView?.getComputedStyle(group);\n\n const isHorizontal = orientation === \"horizontal\";\n\n const totalSize = isHorizontal ? group.clientWidth : group.clientHeight;\n\n const paddingSize = computedStyle\n ? isHorizontal\n ? parsePixels(computedStyle.paddingLeft) +\n parsePixels(computedStyle.paddingRight)\n : parsePixels(computedStyle.paddingTop) +\n parsePixels(computedStyle.paddingBottom)\n : 0;\n\n const handleSize = Array.from(group.children).reduce((total, child) => {\n const element = child as HTMLElement;\n\n if (!element.hasAttribute(\"data-puzzle-resizable-handle\")) {\n return total;\n }\n\n const rect = element.getBoundingClientRect();\n\n return total + (isHorizontal ? rect.width : rect.height);\n }, 0);\n\n return Math.max(0, totalSize - paddingSize - handleSize);\n};\n\nconst getResizeDirection = (\n element: HTMLElement,\n orientation: ResizablePanelsOrientation,\n) => {\n if (orientation !== \"horizontal\") {\n return 1;\n }\n\n const direction =\n element.ownerDocument.defaultView?.getComputedStyle(element).direction;\n\n return direction === \"rtl\" ? -1 : 1;\n};\n\nconst getPointerCoordinate = (\n event: ReactPointerEvent<HTMLDivElement>,\n orientation: ResizablePanelsOrientation,\n) => (orientation === \"horizontal\" ? event.clientX : event.clientY);\n\nconst ResizablePanel = ({\n id,\n minSize = 0,\n maxSize = 100,\n panelIndex = 0,\n panelSize = 1,\n panelId,\n className,\n style,\n ...props\n}: ResizablePanelProps & InternalResizablePanelProps) => (\n <div\n {...props}\n id={panelId ?? id}\n className={cn(\"puzzle-resizable-panels__panel\", className)}\n style={{\n ...style,\n flex: `${panelSize} 1 0%`,\n }}\n data-panel-index={panelIndex}\n data-panel-size={panelSize}\n data-panel-min-size={minSize}\n data-panel-max-size={maxSize}\n />\n);\n\nconst ResizableHandle = ({\n withGrip = false,\n disabled = false,\n handleIndex = -1,\n orientation = \"horizontal\",\n value,\n minValue,\n maxValue,\n panelIds,\n inheritedDisabled = false,\n onResizeStart,\n onResizeMove,\n onResizeEnd,\n onResizeKeyDown,\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n onLostPointerCapture,\n onKeyDown,\n className,\n children,\n tabIndex,\n \"aria-label\": ariaLabel,\n ...props\n}: ResizableHandleProps & InternalResizableHandleProps) => {\n const isDisabled = disabled || inheritedDisabled;\n\n const handlePointerDown = (event: ReactPointerEvent<HTMLDivElement>) => {\n onPointerDown?.(event);\n\n if (!event.defaultPrevented && !isDisabled) {\n onResizeStart?.(event, handleIndex);\n }\n };\n\n const handlePointerMove = (event: ReactPointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event);\n\n if (!event.defaultPrevented && !isDisabled) {\n onResizeMove?.(event, handleIndex);\n }\n };\n\n const handlePointerUp = (event: ReactPointerEvent<HTMLDivElement>) => {\n onResizeEnd?.(event, handleIndex);\n onPointerUp?.(event);\n };\n\n const handlePointerCancel = (event: ReactPointerEvent<HTMLDivElement>) => {\n onResizeEnd?.(event, handleIndex);\n onPointerCancel?.(event);\n };\n\n const handleLostPointerCapture = (\n event: ReactPointerEvent<HTMLDivElement>,\n ) => {\n onResizeEnd?.(event, handleIndex);\n onLostPointerCapture?.(event);\n };\n\n const handleKeyDown = (event: ReactKeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n if (!event.defaultPrevented && !isDisabled) {\n onResizeKeyDown?.(event, handleIndex);\n }\n };\n\n return (\n <div\n {...props}\n className={cn(\"puzzle-resizable-panels__handle\", className)}\n role=\"separator\"\n tabIndex={isDisabled ? -1 : (tabIndex ?? 0)}\n aria-label={ariaLabel ?? \"Resize panels\"}\n aria-orientation={\n orientation === \"horizontal\" ? \"vertical\" : \"horizontal\"\n }\n aria-controls={panelIds?.join(\" \")}\n aria-valuenow={value}\n aria-valuemin={minValue}\n aria-valuemax={maxValue}\n aria-valuetext={\n value === undefined ? undefined : `${Math.round(value * 100) / 100}%`\n }\n aria-disabled={isDisabled || undefined}\n data-puzzle-resizable-handle=\"\"\n data-orientation={orientation}\n data-disabled={isDisabled ? \"true\" : undefined}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerCancel}\n onLostPointerCapture={handleLostPointerCapture}\n onKeyDown={handleKeyDown}\n >\n {withGrip ? (\n <span\n className=\"puzzle-resizable-panels__handle-grip\"\n aria-hidden=\"true\"\n />\n ) : (\n children\n )}\n </div>\n );\n};\n\nconst ResizablePanelsRoot = ({\n children,\n orientation = \"horizontal\",\n sizes,\n defaultSizes,\n onSizesChange,\n disabled = false,\n keyboardStep = 1,\n id,\n role,\n className,\n style,\n ref: forwardedRef,\n ...rootProps\n}: ResizablePanelsProps) => {\n const generatedId = useId();\n\n const groupId = id ?? `puzzle-resizable-panels-${generatedId}`;\n\n if (!Number.isFinite(keyboardStep) || keyboardStep <= 0) {\n throw new RangeError(\"keyboardStep must be a positive finite number.\");\n }\n\n const childrenArray = Children.toArray(children);\n\n const validChildren =\n childrenArray.length >= 3 &&\n childrenArray.length % 2 === 1 &&\n childrenArray.every((child, index) =>\n index % 2 === 0\n ? isResizablePanelElement(child)\n : isResizableHandleElement(child),\n );\n\n if (!validChildren) {\n throw new Error(\n \"ResizablePanels requires alternating Panel and Handle children, starting and ending with a Panel. At least two panels are required.\",\n );\n }\n\n const panelElements = childrenArray.filter(isResizablePanelElement);\n\n const panelCount = panelElements.length;\n\n const panelConstraints: PanelSizeConstraint[] = panelElements.map(\n (panel) => ({\n minSize: panel.props.minSize,\n maxSize: panel.props.maxSize,\n }),\n );\n\n const panelIds = panelElements.map(\n (panel, index) => panel.props.id ?? `${groupId}-panel-${index}`,\n );\n\n if (new Set(panelIds).size !== panelIds.length) {\n throw new Error(\"ResizablePanels requires unique panel IDs.\");\n }\n\n const [uncontrolledSizes, setUncontrolledSizes] = useState<number[]>(() =>\n normalizePanelSizes(\n sizes === undefined ? defaultSizes : undefined,\n panelConstraints,\n ),\n );\n\n const layoutInput =\n sizes ??\n (uncontrolledSizes.length === panelCount ? uncontrolledSizes : undefined);\n\n const currentSizes = normalizePanelSizes(layoutInput, panelConstraints);\n\n const [isResizing, setIsResizing] = useState(false);\n\n const groupRef = useRef<HTMLDivElement | null>(null);\n\n const pointerDragRef = useRef<PointerDragState | null>(null);\n\n const updateSizes = (nextSizes: readonly number[]) => {\n const normalized = normalizePanelSizes(nextSizes, panelConstraints);\n\n const hasChanged = normalized.some(\n (size, index) => Math.abs(size - (currentSizes[index] ?? 0)) > 0.000001,\n );\n\n if (!hasChanged) {\n return;\n }\n\n if (sizes === undefined) {\n setUncontrolledSizes(normalized);\n }\n\n onSizesChange?.(normalized);\n };\n\n const handlePointerDown: ResizePointerHandler = (event, handleIndex) => {\n const group = groupRef.current;\n\n if (!group || disabled) {\n return;\n }\n\n if (\n event.button !== 0 &&\n event.pointerType !== \"touch\" &&\n event.pointerType !== \"pen\"\n ) {\n return;\n }\n\n const availableSize = getAvailableSize(group, orientation);\n\n if (availableSize <= 0) {\n return;\n }\n\n pointerDragRef.current = {\n handleIndex,\n pointerId: event.pointerId,\n startCoordinate: getPointerCoordinate(event, orientation),\n availableSize,\n direction: getResizeDirection(group, orientation),\n sizes: [...currentSizes],\n };\n\n try {\n event.currentTarget.setPointerCapture(event.pointerId);\n } catch {\n // Synthetic pointer events and detached elements may not\n // support pointer capture.\n }\n\n event.preventDefault();\n setIsResizing(true);\n };\n\n const handlePointerMove: ResizePointerHandler = (event, handleIndex) => {\n const drag = pointerDragRef.current;\n\n if (\n !drag ||\n drag.pointerId !== event.pointerId ||\n drag.handleIndex !== handleIndex\n ) {\n return;\n }\n\n const currentCoordinate = getPointerCoordinate(event, orientation);\n\n const delta =\n ((currentCoordinate - drag.startCoordinate) / drag.availableSize) *\n 100 *\n drag.direction;\n\n const nextSizes = resizePanelPair(\n drag.sizes,\n panelConstraints,\n handleIndex,\n delta,\n );\n\n event.preventDefault();\n updateSizes(nextSizes);\n };\n\n const handlePointerEnd: ResizePointerHandler = (event, handleIndex) => {\n const drag = pointerDragRef.current;\n\n if (\n !drag ||\n drag.pointerId !== event.pointerId ||\n drag.handleIndex !== handleIndex\n ) {\n return;\n }\n\n pointerDragRef.current = null;\n setIsResizing(false);\n };\n\n const handleKeyDown: ResizeKeyboardHandler = (event, handleIndex) => {\n if (disabled) {\n return;\n }\n\n const currentSize = currentSizes[handleIndex]!;\n\n const bounds = getPanelPairBounds(\n currentSizes,\n panelConstraints,\n handleIndex,\n );\n\n const group = groupRef.current;\n\n const direction = group ? getResizeDirection(group, orientation) : 1;\n\n const step = keyboardStep * (event.shiftKey ? 10 : 1);\n\n let nextSize: number | undefined;\n\n if (event.key === \"Home\") {\n nextSize = bounds.minSize;\n } else if (event.key === \"End\") {\n nextSize = bounds.maxSize;\n } else if (orientation === \"horizontal\") {\n if (event.key === \"ArrowRight\") {\n nextSize = currentSize + step * direction;\n } else if (event.key === \"ArrowLeft\") {\n nextSize = currentSize - step * direction;\n }\n } else {\n if (event.key === \"ArrowDown\") {\n nextSize = currentSize + step;\n } else if (event.key === \"ArrowUp\") {\n nextSize = currentSize - step;\n }\n }\n\n if (nextSize === undefined) {\n return;\n }\n\n event.preventDefault();\n\n updateSizes(\n resizePanelPair(\n currentSizes,\n panelConstraints,\n handleIndex,\n nextSize - currentSize,\n ),\n );\n };\n\n let panelIndex = 0;\n\n const enhancedChildren = childrenArray.map((child) => {\n if (isResizablePanelElement(child)) {\n const index = panelIndex++;\n\n return cloneElement(\n child as ReactElement<\n ResizablePanelProps & InternalResizablePanelProps\n >,\n {\n panelIndex: index,\n panelSize: currentSizes[index],\n panelId: panelIds[index],\n },\n );\n }\n\n const handleIndex = panelIndex - 1;\n\n const bounds = getPanelPairBounds(\n currentSizes,\n panelConstraints,\n handleIndex,\n );\n\n return cloneElement(\n child as ReactElement<\n ResizableHandleProps & InternalResizableHandleProps\n >,\n {\n handleIndex,\n orientation,\n value: currentSizes[handleIndex],\n minValue: bounds.minSize,\n maxValue: bounds.maxSize,\n panelIds: [panelIds[handleIndex]!, panelIds[handleIndex + 1]!],\n inheritedDisabled: disabled,\n onResizeStart: handlePointerDown,\n onResizeMove: handlePointerMove,\n onResizeEnd: handlePointerEnd,\n onResizeKeyDown: handleKeyDown,\n },\n );\n });\n\n return (\n <div\n {...rootProps}\n ref={(node) => {\n groupRef.current = node;\n\n if (typeof forwardedRef === \"function\") {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n id={groupId}\n role={role ?? \"group\"}\n className={cn(\"puzzle-resizable-panels\", className)}\n style={style}\n data-orientation={orientation}\n data-disabled={disabled ? \"true\" : undefined}\n data-resizing={isResizing ? \"true\" : undefined}\n >\n {enhancedChildren}\n </div>\n );\n};\n\ntype ResizablePanelsComponent = typeof ResizablePanelsRoot & {\n Panel: typeof ResizablePanel;\n Handle: typeof ResizableHandle;\n};\n\nconst ResizablePanels = Object.assign(ResizablePanelsRoot, {\n Panel: ResizablePanel,\n Handle: ResizableHandle,\n}) as ResizablePanelsComponent;\n\nexport {\n ResizablePanels,\n ResizablePanel,\n ResizableHandle,\n type ResizablePanelsProps,\n type ResizablePanelProps,\n type ResizableHandleProps,\n type ResizablePanelsOrientation,\n};\n"],"mappings":"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"}
@@ -115,7 +115,7 @@ const ResizablePanelsRoot = ({ children, orientation = "horizontal", sizes, defa
115
115
  const pointerDragRef = useRef(null);
116
116
  const updateSizes = (nextSizes) => {
117
117
  const normalized = normalizePanelSizes(nextSizes, panelConstraints);
118
- if (!normalized.some((size, index) => Math.abs(size - currentSizes[index]) > 1e-6)) return;
118
+ if (!normalized.some((size, index) => Math.abs(size - (currentSizes[index] ?? 0)) > 1e-6)) return;
119
119
  if (sizes === void 0) setUncontrolledSizes(normalized);
120
120
  onSizesChange?.(normalized);
121
121
  };