@hanzo/ui 8.27.9 → 8.27.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 (219) hide show
  1. package/dist/backends/gui/3d-card.cjs +100 -0
  2. package/dist/backends/gui/3d-card.d.ts +59 -0
  3. package/dist/backends/gui/3d-card.d.ts.map +1 -0
  4. package/dist/backends/gui/3d-card.js +92 -0
  5. package/dist/backends/gui/3d-card.js.map +1 -0
  6. package/dist/backends/gui/3d-marquee.cjs +225 -0
  7. package/dist/backends/gui/3d-marquee.d.ts +114 -0
  8. package/dist/backends/gui/3d-marquee.d.ts.map +1 -0
  9. package/dist/backends/gui/3d-marquee.js +190 -0
  10. package/dist/backends/gui/3d-marquee.js.map +1 -0
  11. package/dist/backends/gui/3d-pin.cjs +51 -0
  12. package/dist/backends/gui/3d-pin.d.ts +14 -0
  13. package/dist/backends/gui/3d-pin.d.ts.map +1 -0
  14. package/dist/backends/gui/3d-pin.js +49 -0
  15. package/dist/backends/gui/3d-pin.js.map +1 -0
  16. package/dist/backends/gui/advanced-chart.cjs +61 -0
  17. package/dist/backends/gui/advanced-chart.d.ts +38 -0
  18. package/dist/backends/gui/advanced-chart.d.ts.map +1 -0
  19. package/dist/backends/gui/advanced-chart.js +59 -0
  20. package/dist/backends/gui/advanced-chart.js.map +1 -0
  21. package/dist/backends/gui/alert.cjs +106 -0
  22. package/dist/backends/gui/alert.d.ts +39 -0
  23. package/dist/backends/gui/alert.d.ts.map +1 -0
  24. package/dist/backends/gui/alert.js +102 -0
  25. package/dist/backends/gui/alert.js.map +1 -0
  26. package/dist/backends/gui/android.cjs +52 -0
  27. package/dist/backends/gui/android.d.ts +16 -0
  28. package/dist/backends/gui/android.d.ts.map +1 -0
  29. package/dist/backends/gui/android.js +50 -0
  30. package/dist/backends/gui/android.js.map +1 -0
  31. package/dist/backends/gui/animated-beam.cjs +97 -0
  32. package/dist/backends/gui/animated-beam.d.ts +57 -0
  33. package/dist/backends/gui/animated-beam.d.ts.map +1 -0
  34. package/dist/backends/gui/animated-beam.js +62 -0
  35. package/dist/backends/gui/animated-beam.js.map +1 -0
  36. package/dist/backends/gui/animated-cursor.cjs +183 -0
  37. package/dist/backends/gui/animated-cursor.d.ts +42 -0
  38. package/dist/backends/gui/animated-cursor.d.ts.map +1 -0
  39. package/dist/backends/gui/animated-cursor.js +181 -0
  40. package/dist/backends/gui/animated-cursor.js.map +1 -0
  41. package/dist/backends/gui/animated-testimonials.cjs +109 -0
  42. package/dist/backends/gui/animated-testimonials.d.ts +23 -0
  43. package/dist/backends/gui/animated-testimonials.d.ts.map +1 -0
  44. package/dist/backends/gui/animated-testimonials.js +74 -0
  45. package/dist/backends/gui/animated-testimonials.js.map +1 -0
  46. package/dist/backends/gui/animated-tooltip.cjs +100 -0
  47. package/dist/backends/gui/animated-tooltip.d.ts +15 -0
  48. package/dist/backends/gui/animated-tooltip.d.ts.map +1 -0
  49. package/dist/backends/gui/animated-tooltip.js +65 -0
  50. package/dist/backends/gui/animated-tooltip.js.map +1 -0
  51. package/dist/backends/gui/announcement.cjs +54 -0
  52. package/dist/backends/gui/announcement.d.ts +26 -0
  53. package/dist/backends/gui/announcement.d.ts.map +1 -0
  54. package/dist/backends/gui/announcement.js +52 -0
  55. package/dist/backends/gui/announcement.js.map +1 -0
  56. package/dist/backends/gui/apple-cards-carousel.cjs +198 -0
  57. package/dist/backends/gui/apple-cards-carousel.d.ts +45 -0
  58. package/dist/backends/gui/apple-cards-carousel.d.ts.map +1 -0
  59. package/dist/backends/gui/apple-cards-carousel.js +162 -0
  60. package/dist/backends/gui/apple-cards-carousel.js.map +1 -0
  61. package/dist/backends/gui/apple-hello-effect.cjs +38 -0
  62. package/dist/backends/gui/apple-hello-effect.d.ts +9 -0
  63. package/dist/backends/gui/apple-hello-effect.d.ts.map +1 -0
  64. package/dist/backends/gui/apple-hello-effect.js +36 -0
  65. package/dist/backends/gui/apple-hello-effect.js.map +1 -0
  66. package/dist/backends/gui/banner.cjs +108 -0
  67. package/dist/backends/gui/banner.d.ts +33 -0
  68. package/dist/backends/gui/banner.d.ts.map +1 -0
  69. package/dist/backends/gui/banner.js +106 -0
  70. package/dist/backends/gui/banner.js.map +1 -0
  71. package/dist/backends/gui/calendar.cjs +152 -0
  72. package/dist/backends/gui/calendar.d.ts +41 -0
  73. package/dist/backends/gui/calendar.d.ts.map +1 -0
  74. package/dist/backends/gui/calendar.js +151 -0
  75. package/dist/backends/gui/calendar.js.map +1 -0
  76. package/dist/backends/gui/choicebox.cjs +50 -0
  77. package/dist/backends/gui/choicebox.d.ts +33 -0
  78. package/dist/backends/gui/choicebox.d.ts.map +1 -0
  79. package/dist/backends/gui/choicebox.js +49 -0
  80. package/dist/backends/gui/choicebox.js.map +1 -0
  81. package/dist/backends/gui/code-block.cjs +120 -0
  82. package/dist/backends/gui/code-block.d.ts +22 -0
  83. package/dist/backends/gui/code-block.d.ts.map +1 -0
  84. package/dist/backends/gui/code-block.js +118 -0
  85. package/dist/backends/gui/code-block.js.map +1 -0
  86. package/dist/backends/gui/code-editor.cjs +195 -0
  87. package/dist/backends/gui/code-editor.d.ts +43 -0
  88. package/dist/backends/gui/code-editor.d.ts.map +1 -0
  89. package/dist/backends/gui/code-editor.js +160 -0
  90. package/dist/backends/gui/code-editor.js.map +1 -0
  91. package/dist/backends/gui/code-tabs.cjs +21 -0
  92. package/dist/backends/gui/code-tabs.d.ts +22 -0
  93. package/dist/backends/gui/code-tabs.d.ts.map +1 -0
  94. package/dist/backends/gui/code-tabs.js +19 -0
  95. package/dist/backends/gui/code-tabs.js.map +1 -0
  96. package/dist/backends/gui/color-picker.cjs +141 -0
  97. package/dist/backends/gui/color-picker.d.ts +25 -0
  98. package/dist/backends/gui/color-picker.d.ts.map +1 -0
  99. package/dist/backends/gui/color-picker.js +139 -0
  100. package/dist/backends/gui/color-picker.js.map +1 -0
  101. package/dist/backends/gui/combobox.cjs +42 -0
  102. package/dist/backends/gui/combobox.d.ts +39 -0
  103. package/dist/backends/gui/combobox.d.ts.map +1 -0
  104. package/dist/backends/gui/combobox.js +40 -0
  105. package/dist/backends/gui/combobox.js.map +1 -0
  106. package/dist/backends/gui/company-profile.cjs +43 -0
  107. package/dist/backends/gui/company-profile.d.ts +33 -0
  108. package/dist/backends/gui/company-profile.d.ts.map +1 -0
  109. package/dist/backends/gui/company-profile.js +41 -0
  110. package/dist/backends/gui/company-profile.js.map +1 -0
  111. package/dist/backends/gui/comparison.cjs +43 -0
  112. package/dist/backends/gui/comparison.d.ts +16 -0
  113. package/dist/backends/gui/comparison.d.ts.map +1 -0
  114. package/dist/backends/gui/comparison.js +41 -0
  115. package/dist/backends/gui/comparison.js.map +1 -0
  116. package/dist/backends/gui/credit-card.cjs +80 -0
  117. package/dist/backends/gui/credit-card.d.ts +21 -0
  118. package/dist/backends/gui/credit-card.d.ts.map +1 -0
  119. package/dist/backends/gui/credit-card.js +78 -0
  120. package/dist/backends/gui/credit-card.js.map +1 -0
  121. package/dist/backends/gui/crypto-market.cjs +128 -0
  122. package/dist/backends/gui/crypto-market.d.ts +52 -0
  123. package/dist/backends/gui/crypto-market.d.ts.map +1 -0
  124. package/dist/backends/gui/crypto-market.js +126 -0
  125. package/dist/backends/gui/crypto-market.js.map +1 -0
  126. package/dist/backends/gui/crypto-screener.cjs +55 -0
  127. package/dist/backends/gui/crypto-screener.d.ts +42 -0
  128. package/dist/backends/gui/crypto-screener.d.ts.map +1 -0
  129. package/dist/backends/gui/crypto-screener.js +53 -0
  130. package/dist/backends/gui/crypto-screener.js.map +1 -0
  131. package/dist/backends/gui/cursor.cjs +40 -0
  132. package/dist/backends/gui/cursor.d.ts +16 -0
  133. package/dist/backends/gui/cursor.d.ts.map +1 -0
  134. package/dist/backends/gui/cursor.js +38 -0
  135. package/dist/backends/gui/cursor.js.map +1 -0
  136. package/dist/backends/gui/data-table.cjs +211 -0
  137. package/dist/backends/gui/data-table.d.ts +71 -0
  138. package/dist/backends/gui/data-table.d.ts.map +1 -0
  139. package/dist/backends/gui/data-table.js +175 -0
  140. package/dist/backends/gui/data-table.js.map +1 -0
  141. package/dist/backends/gui/date-picker.cjs +66 -0
  142. package/dist/backends/gui/date-picker.d.ts +29 -0
  143. package/dist/backends/gui/date-picker.d.ts.map +1 -0
  144. package/dist/backends/gui/date-picker.js +64 -0
  145. package/dist/backends/gui/date-picker.js.map +1 -0
  146. package/dist/backends/gui/desktop-spotlight.cjs +46 -0
  147. package/dist/backends/gui/desktop-spotlight.d.ts +34 -0
  148. package/dist/backends/gui/desktop-spotlight.d.ts.map +1 -0
  149. package/dist/backends/gui/desktop-spotlight.js +44 -0
  150. package/dist/backends/gui/desktop-spotlight.js.map +1 -0
  151. package/dist/backends/gui/desktop-window.cjs +180 -0
  152. package/dist/backends/gui/desktop-window.d.ts +51 -0
  153. package/dist/backends/gui/desktop-window.d.ts.map +1 -0
  154. package/dist/backends/gui/desktop-window.js +177 -0
  155. package/dist/backends/gui/desktop-window.js.map +1 -0
  156. package/dist/backends/gui/desktop.cjs +238 -0
  157. package/dist/backends/gui/desktop.d.ts +109 -0
  158. package/dist/backends/gui/desktop.d.ts.map +1 -0
  159. package/dist/backends/gui/desktop.js +199 -0
  160. package/dist/backends/gui/desktop.js.map +1 -0
  161. package/dist/backends/gui/dialog-stack.cjs +26 -0
  162. package/dist/backends/gui/dialog-stack.d.ts +23 -0
  163. package/dist/backends/gui/dialog-stack.d.ts.map +1 -0
  164. package/dist/backends/gui/dialog-stack.js +24 -0
  165. package/dist/backends/gui/dialog-stack.js.map +1 -0
  166. package/dist/backends/gui/dock.cjs +99 -0
  167. package/dist/backends/gui/dock.d.ts +41 -0
  168. package/dist/backends/gui/dock.d.ts.map +1 -0
  169. package/dist/backends/gui/dock.js +96 -0
  170. package/dist/backends/gui/dock.js.map +1 -0
  171. package/dist/backends/gui/dropzone.cjs +142 -0
  172. package/dist/backends/gui/dropzone.d.ts +12 -0
  173. package/dist/backends/gui/dropzone.d.ts.map +1 -0
  174. package/dist/backends/gui/dropzone.js +140 -0
  175. package/dist/backends/gui/dropzone.js.map +1 -0
  176. package/dist/backends/gui/editor.cjs +80 -0
  177. package/dist/backends/gui/editor.d.ts +23 -0
  178. package/dist/backends/gui/editor.d.ts.map +1 -0
  179. package/dist/backends/gui/editor.js +45 -0
  180. package/dist/backends/gui/editor.js.map +1 -0
  181. package/dist/backends/gui/empty.cjs +71 -0
  182. package/dist/backends/gui/empty.d.ts +43 -0
  183. package/dist/backends/gui/empty.d.ts.map +1 -0
  184. package/dist/backends/gui/empty.js +63 -0
  185. package/dist/backends/gui/empty.js.map +1 -0
  186. package/dist/backends/gui/financials.cjs +45 -0
  187. package/dist/backends/gui/financials.d.ts +36 -0
  188. package/dist/backends/gui/financials.d.ts.map +1 -0
  189. package/dist/backends/gui/financials.js +43 -0
  190. package/dist/backends/gui/financials.js.map +1 -0
  191. package/dist/backends/gui/forex-market.cjs +21 -0
  192. package/dist/backends/gui/forex-market.d.ts +17 -0
  193. package/dist/backends/gui/forex-market.d.ts.map +1 -0
  194. package/dist/backends/gui/forex-market.js +19 -0
  195. package/dist/backends/gui/forex-market.js.map +1 -0
  196. package/dist/backends/gui/forex-screener.cjs +57 -0
  197. package/dist/backends/gui/forex-screener.d.ts +45 -0
  198. package/dist/backends/gui/forex-screener.d.ts.map +1 -0
  199. package/dist/backends/gui/forex-screener.js +55 -0
  200. package/dist/backends/gui/forex-screener.js.map +1 -0
  201. package/dist/backends/gui/gantt.cjs +50 -0
  202. package/dist/backends/gui/gantt.d.ts +19 -0
  203. package/dist/backends/gui/gantt.d.ts.map +1 -0
  204. package/dist/backends/gui/gantt.js +49 -0
  205. package/dist/backends/gui/gantt.js.map +1 -0
  206. package/dist/backends/gui/index.cjs +108 -1
  207. package/dist/backends/gui/index.d.ts +41 -0
  208. package/dist/backends/gui/index.d.ts.map +1 -1
  209. package/dist/backends/gui/index.js +41 -0
  210. package/dist/backends/gui/index.js.map +1 -1
  211. package/dist/gallery.html +1 -1
  212. package/dist/index.cjs +70 -1
  213. package/dist/index.d.ts +1 -0
  214. package/dist/index.d.ts.map +1 -1
  215. package/dist/index.js +3 -0
  216. package/dist/index.js.map +1 -1
  217. package/dist/index.node.cjs +70 -1
  218. package/dist/index.node.js +3 -0
  219. package/package.json +1 -1
@@ -0,0 +1,152 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Calendar = Calendar;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * Calendar — a month grid for picking one date, several dates, or a range.
8
+ *
9
+ * `mode` names the selection: `single` hands back a `Date`, `multiple` a
10
+ * `Date[]`, `range` a `{ from, to }` that each pick grows and a pick on either
11
+ * end shrinks back to that one day; picking the one selected day clears it.
12
+ * A `disabled` predicate says which days cannot be picked. Every day and both
13
+ * month controls are the backend `Button`, so hover, focus and the 44px touch
14
+ * floor are the ones every control has. One day at a time is in the tab order
15
+ * — the selected day, else today, else the first of the month — and from it
16
+ * the arrow keys move a day or a week, Home and End go to the ends of the
17
+ * week, PageUp and PageDown change the month, paging the view whenever the
18
+ * target lies off it. The seven-column week is `Grid`/`Cell`, a real CSS
19
+ * grid, so the columns are the container's and no label can widen its own.
20
+ */
21
+ const gui_1 = require("@hanzo/gui");
22
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
23
+ const react_1 = require("react");
24
+ const grid_1 = require("../../grid.cjs");
25
+ const sx_1 = require("../../sx.cjs");
26
+ const button_1 = require("./button.cjs");
27
+ const slot_1 = require("./slot.cjs");
28
+ const MONTHS = [
29
+ 'January', 'February', 'March', 'April', 'May', 'June',
30
+ 'July', 'August', 'September', 'October', 'November', 'December',
31
+ ];
32
+ const WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
33
+ const day = (y, m, d) => new Date(y, m, d);
34
+ /** The calendar day as a key, local and free of any time a `selected` carries. */
35
+ const key = (d) => `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
36
+ const same = (a, b) => !!a && !!b && key(a) === key(b);
37
+ const at = (d) => day(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
38
+ const shift = (d, days) => day(d.getFullYear(), d.getMonth(), d.getDate() + days);
39
+ const first = (d, months = 0) => day(d.getFullYear(), d.getMonth() + months, 1);
40
+ /** `months` over, on the same day of the month or the last one it has. */
41
+ const page = (d, months) => {
42
+ const last = day(d.getFullYear(), d.getMonth() + months + 1, 0);
43
+ return day(last.getFullYear(), last.getMonth(), Math.min(d.getDate(), last.getDate()));
44
+ };
45
+ /** A month's grid in row order, whole weeks; `null` where an outside day is hidden. */
46
+ const cells = (m, weekStartsOn, outside) => {
47
+ const lead = (m.getDay() - weekStartsOn + 7) % 7;
48
+ const total = day(m.getFullYear(), m.getMonth() + 1, 0).getDate();
49
+ return Array.from({ length: Math.ceil((lead + total) / 7) * 7 }, (_, i) => {
50
+ const n = i - lead + 1;
51
+ return outside || (n >= 1 && n <= total) ? day(m.getFullYear(), m.getMonth(), n) : null;
52
+ });
53
+ };
54
+ const picked = (props, d) => {
55
+ if (props.mode === 'multiple')
56
+ return (props.selected ?? []).some((s) => same(s, d));
57
+ if (props.mode === 'range') {
58
+ const { from, to } = props.selected ?? {};
59
+ return !!from && (to ? at(from) <= at(d) && at(d) <= at(to) : same(from, d));
60
+ }
61
+ return same(props.selected, d);
62
+ };
63
+ const extend = (r, d) => {
64
+ const { from, to } = r ?? {};
65
+ if (!from)
66
+ return { from: d, to: d };
67
+ if (!to)
68
+ return at(d) < at(from) ? { from: d, to: from } : { from, to: d };
69
+ if (same(from, d) && same(to, d))
70
+ return undefined;
71
+ if (same(from, d))
72
+ return { from, to: d };
73
+ if (same(to, d))
74
+ return { from: d, to: d };
75
+ return at(d) < at(from) ? { from: d, to } : { from, to: d };
76
+ };
77
+ const pick = (props, d) => {
78
+ if (props.mode === 'multiple') {
79
+ const now = props.selected ?? [];
80
+ props.onSelect?.(now.some((s) => same(s, d)) ? now.filter((s) => !same(s, d)) : [...now, d]);
81
+ }
82
+ else if (props.mode === 'range')
83
+ props.onSelect?.(extend(props.selected, d));
84
+ else
85
+ props.onSelect?.(same(props.selected, d) ? undefined : d);
86
+ };
87
+ /** Where a key moves focus from `d`, or nothing for a key that does not. */
88
+ const step = (k, d, weekStartsOn) => {
89
+ const dow = (d.getDay() - weekStartsOn + 7) % 7;
90
+ return k === 'ArrowLeft' ? shift(d, -1)
91
+ : k === 'ArrowRight' ? shift(d, 1)
92
+ : k === 'ArrowUp' ? shift(d, -7)
93
+ : k === 'ArrowDown' ? shift(d, 7)
94
+ : k === 'Home' ? shift(d, -dow)
95
+ : k === 'End' ? shift(d, 6 - dow)
96
+ : k === 'PageUp' ? page(d, -1)
97
+ : k === 'PageDown' ? page(d, 1)
98
+ : undefined;
99
+ };
100
+ function Calendar(props) {
101
+ const { month: monthProp, defaultMonth, onMonthChange, numberOfMonths = 1, weekStartsOn = 0, showOutsideDays = true, disabled, initialFocus, className, } = props;
102
+ const [own, setOwn] = (0, react_1.useState)(() => first(defaultMonth ?? new Date()));
103
+ const head = monthProp ? first(monthProp) : own;
104
+ const months = Array.from({ length: numberOfMonths }, (_, i) => first(head, i));
105
+ const grid = months.map((m) => cells(m, weekStartsOn, showOutsideDays));
106
+ const inside = (d) => !!d && at(d) >= at(head) && at(d) < at(first(head, numberOfMonths));
107
+ const shown = (d) => grid.some((g) => g.some((c) => same(c, d)));
108
+ const labels = [...WEEKDAYS.slice(weekStartsOn), ...WEEKDAYS.slice(0, weekStartsOn)];
109
+ const today = new Date();
110
+ const range = props.mode === 'range' ? (props.selected ?? {}) : {};
111
+ const [focused, setFocused] = (0, react_1.useState)();
112
+ const picks = props.mode === 'multiple' ? (props.selected ?? [])
113
+ : props.mode === 'range' ? [props.selected?.from]
114
+ : [props.selected];
115
+ const focus = focused && shown(focused) ? focused : (picks.find(inside) ?? (inside(today) ? today : head));
116
+ const root = (0, react_1.useRef)(null);
117
+ const pending = (0, react_1.useRef)(!!initialFocus);
118
+ (0, react_1.useEffect)(() => {
119
+ const node = root.current;
120
+ if (!pending.current || typeof HTMLElement === 'undefined' || !(node instanceof HTMLElement))
121
+ return;
122
+ pending.current = false;
123
+ const k = `[data-date="${key(focus)}"]`;
124
+ (node.querySelector(`${k}:not([data-outside])`) ?? node.querySelector(k))?.focus();
125
+ });
126
+ const navigate = (n) => {
127
+ const next = first(head, n);
128
+ setOwn(next);
129
+ onMonthChange?.(next);
130
+ };
131
+ const move = (e, from) => {
132
+ const next = step(e.key, from, weekStartsOn);
133
+ if (!next)
134
+ return;
135
+ e.preventDefault();
136
+ pending.current = true;
137
+ setFocused(next);
138
+ if (!shown(next))
139
+ navigate(at(next) < at(head) ? -1 : 1);
140
+ };
141
+ return ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ref: root, ...(0, slot_1.slot)('calendar'), flexWrap: "wrap", gap: "$4", p: "$3", ...(0, sx_1.sx)(className), children: months.map((m, i) => ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('calendar-month'), gap: "$4", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('calendar-caption'), items: "center", justify: "space-between", children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { width: 32, children: i === 0 && ((0, jsx_runtime_1.jsx)(button_1.Button, { ...(0, slot_1.slot)('calendar-nav-previous'), "aria-label": "Previous month", variant: "outline", size: "icon-sm", onClick: () => navigate(-1), children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronLeft, { size: 16 }) })) }), (0, jsx_runtime_1.jsxs)(gui_1.SizableText, { ...(0, slot_1.slot)('calendar-caption-label'), size: "$3", fontWeight: "500", children: [MONTHS[m.getMonth()], " ", m.getFullYear()] }), (0, jsx_runtime_1.jsx)(gui_1.YStack, { width: 32, items: "flex-end", children: i === months.length - 1 && ((0, jsx_runtime_1.jsx)(button_1.Button, { ...(0, slot_1.slot)('calendar-nav-next'), "aria-label": "Next month", variant: "outline", size: "icon-sm", onClick: () => navigate(1), children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronRight, { size: 16 }) })) })] }), (0, jsx_runtime_1.jsxs)(grid_1.Grid, { columns: 7, gap: "$1", children: [labels.map((label) => ((0, jsx_runtime_1.jsx)(grid_1.Cell, { style: { textAlign: 'center' }, children: (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$quiet", children: label }) }, label))), grid[i].map((d, j) => {
142
+ if (!d)
143
+ return (0, jsx_runtime_1.jsx)(grid_1.Cell, {}, j);
144
+ const outside = d.getMonth() !== m.getMonth();
145
+ const selected = picked(props, d);
146
+ const start = same(range.from, d);
147
+ const end = same(range.to, d);
148
+ const middle = selected && props.mode === 'range' && !start && !end;
149
+ const isToday = same(d, today);
150
+ return ((0, jsx_runtime_1.jsx)(grid_1.Cell, { children: (0, jsx_runtime_1.jsx)(button_1.Button, { ...(0, slot_1.slot)('calendar-day'), "data-date": key(d), "data-today": isToday || undefined, "data-outside": outside || undefined, "data-selected": selected || undefined, "data-range-start": start || undefined, "data-range-end": end || undefined, "data-range-middle": middle || undefined, "aria-selected": selected, "aria-label": d.toDateString(), variant: selected && !middle ? 'primary' : middle || isToday ? 'secondary' : 'ghost', size: "icon", width: "100%", opacity: outside ? 0.5 : 1, disabled: !!disabled?.(d), tabIndex: same(d, focus) && (!outside || !inside(focus)) ? 0 : -1, onFocus: () => setFocused(d), onKeyDown: (e) => move(e, d), onClick: () => pick(props, d), children: d.getDate() }) }, j));
151
+ })] })] }, i))) }));
152
+ }
@@ -0,0 +1,41 @@
1
+ type Weekday = 0 | 1 | 2 | 3 | 4 | 5 | 6;
2
+ export type CalendarRange = {
3
+ from?: Date;
4
+ to?: Date;
5
+ };
6
+ interface CalendarSharedProps {
7
+ /** The month shown, controlled. Uncontrolled starts at `defaultMonth`, else today's. */
8
+ month?: Date;
9
+ defaultMonth?: Date;
10
+ onMonthChange?: (month: Date) => void;
11
+ /** How many consecutive months to lay out. Default 1. */
12
+ numberOfMonths?: number;
13
+ /** Fill the first and last week with the neighbouring months' days, dimmed. Default true. */
14
+ showOutsideDays?: boolean;
15
+ /** First column of the week: `0` Sunday (default) through `6` Saturday. */
16
+ weekStartsOn?: Weekday;
17
+ /** A day this returns true for cannot be picked. */
18
+ disabled?: (date: Date) => boolean;
19
+ /** Focus the tab-stop day on mount — a calendar opened inside a popover. */
20
+ initialFocus?: boolean;
21
+ className?: string;
22
+ }
23
+ export interface CalendarSingleProps extends CalendarSharedProps {
24
+ mode?: 'single';
25
+ selected?: Date;
26
+ onSelect?: (date: Date | undefined) => void;
27
+ }
28
+ export interface CalendarMultipleProps extends CalendarSharedProps {
29
+ mode: 'multiple';
30
+ selected?: Date[];
31
+ onSelect?: (dates: Date[] | undefined) => void;
32
+ }
33
+ export interface CalendarRangeProps extends CalendarSharedProps {
34
+ mode: 'range';
35
+ selected?: CalendarRange;
36
+ onSelect?: (range: CalendarRange | undefined) => void;
37
+ }
38
+ export type CalendarProps = CalendarSingleProps | CalendarMultipleProps | CalendarRangeProps;
39
+ declare function Calendar(props: CalendarProps): import("react").JSX.Element;
40
+ export { Calendar };
41
+ //# sourceMappingURL=calendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/calendar.tsx"],"names":[],"mappings":"AAkCA,KAAK,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAExC,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,IAAI,CAAC;IAAC,EAAE,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AAEtD,UAAU,mBAAmB;IAC3B,wFAAwF;IACxF,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,YAAY,CAAC,EAAE,IAAI,CAAA;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAA;IACrC,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,6FAA6F;IAC7F,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAA;IAClC,4EAA4E;IAC5E,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,QAAQ,CAAC,EAAE,IAAI,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,KAAK,IAAI,CAAA;CAC5C;AAED,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IAChE,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAA;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,KAAK,IAAI,CAAA;CAC/C;AAED,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,KAAK,IAAI,CAAA;CACtD;AAED,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,kBAAkB,CAAA;AAkE5F,iBAAS,QAAQ,CAAC,KAAK,EAAE,aAAa,+BA8IrC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,151 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Calendar — a month grid for picking one date, several dates, or a range.
5
+ *
6
+ * `mode` names the selection: `single` hands back a `Date`, `multiple` a
7
+ * `Date[]`, `range` a `{ from, to }` that each pick grows and a pick on either
8
+ * end shrinks back to that one day; picking the one selected day clears it.
9
+ * A `disabled` predicate says which days cannot be picked. Every day and both
10
+ * month controls are the backend `Button`, so hover, focus and the 44px touch
11
+ * floor are the ones every control has. One day at a time is in the tab order
12
+ * — the selected day, else today, else the first of the month — and from it
13
+ * the arrow keys move a day or a week, Home and End go to the ends of the
14
+ * week, PageUp and PageDown change the month, paging the view whenever the
15
+ * target lies off it. The seven-column week is `Grid`/`Cell`, a real CSS
16
+ * grid, so the columns are the container's and no label can widen its own.
17
+ */
18
+ import { SizableText, XStack, YStack } from '@hanzo/gui';
19
+ import { ChevronLeft, ChevronRight } from '@hanzogui/lucide-icons-2';
20
+ import { useEffect, useRef, useState } from 'react';
21
+ import { Cell, Grid } from '../../grid.js';
22
+ import { sx } from '../../sx.js';
23
+ import { Button } from './button.js';
24
+ import { slot } from './slot.js';
25
+ const MONTHS = [
26
+ 'January', 'February', 'March', 'April', 'May', 'June',
27
+ 'July', 'August', 'September', 'October', 'November', 'December',
28
+ ];
29
+ const WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
30
+ const day = (y, m, d) => new Date(y, m, d);
31
+ /** The calendar day as a key, local and free of any time a `selected` carries. */
32
+ const key = (d) => `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
33
+ const same = (a, b) => !!a && !!b && key(a) === key(b);
34
+ const at = (d) => day(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
35
+ const shift = (d, days) => day(d.getFullYear(), d.getMonth(), d.getDate() + days);
36
+ const first = (d, months = 0) => day(d.getFullYear(), d.getMonth() + months, 1);
37
+ /** `months` over, on the same day of the month or the last one it has. */
38
+ const page = (d, months) => {
39
+ const last = day(d.getFullYear(), d.getMonth() + months + 1, 0);
40
+ return day(last.getFullYear(), last.getMonth(), Math.min(d.getDate(), last.getDate()));
41
+ };
42
+ /** A month's grid in row order, whole weeks; `null` where an outside day is hidden. */
43
+ const cells = (m, weekStartsOn, outside) => {
44
+ const lead = (m.getDay() - weekStartsOn + 7) % 7;
45
+ const total = day(m.getFullYear(), m.getMonth() + 1, 0).getDate();
46
+ return Array.from({ length: Math.ceil((lead + total) / 7) * 7 }, (_, i) => {
47
+ const n = i - lead + 1;
48
+ return outside || (n >= 1 && n <= total) ? day(m.getFullYear(), m.getMonth(), n) : null;
49
+ });
50
+ };
51
+ const picked = (props, d) => {
52
+ if (props.mode === 'multiple')
53
+ return (props.selected ?? []).some((s) => same(s, d));
54
+ if (props.mode === 'range') {
55
+ const { from, to } = props.selected ?? {};
56
+ return !!from && (to ? at(from) <= at(d) && at(d) <= at(to) : same(from, d));
57
+ }
58
+ return same(props.selected, d);
59
+ };
60
+ const extend = (r, d) => {
61
+ const { from, to } = r ?? {};
62
+ if (!from)
63
+ return { from: d, to: d };
64
+ if (!to)
65
+ return at(d) < at(from) ? { from: d, to: from } : { from, to: d };
66
+ if (same(from, d) && same(to, d))
67
+ return undefined;
68
+ if (same(from, d))
69
+ return { from, to: d };
70
+ if (same(to, d))
71
+ return { from: d, to: d };
72
+ return at(d) < at(from) ? { from: d, to } : { from, to: d };
73
+ };
74
+ const pick = (props, d) => {
75
+ if (props.mode === 'multiple') {
76
+ const now = props.selected ?? [];
77
+ props.onSelect?.(now.some((s) => same(s, d)) ? now.filter((s) => !same(s, d)) : [...now, d]);
78
+ }
79
+ else if (props.mode === 'range')
80
+ props.onSelect?.(extend(props.selected, d));
81
+ else
82
+ props.onSelect?.(same(props.selected, d) ? undefined : d);
83
+ };
84
+ /** Where a key moves focus from `d`, or nothing for a key that does not. */
85
+ const step = (k, d, weekStartsOn) => {
86
+ const dow = (d.getDay() - weekStartsOn + 7) % 7;
87
+ return k === 'ArrowLeft' ? shift(d, -1)
88
+ : k === 'ArrowRight' ? shift(d, 1)
89
+ : k === 'ArrowUp' ? shift(d, -7)
90
+ : k === 'ArrowDown' ? shift(d, 7)
91
+ : k === 'Home' ? shift(d, -dow)
92
+ : k === 'End' ? shift(d, 6 - dow)
93
+ : k === 'PageUp' ? page(d, -1)
94
+ : k === 'PageDown' ? page(d, 1)
95
+ : undefined;
96
+ };
97
+ function Calendar(props) {
98
+ const { month: monthProp, defaultMonth, onMonthChange, numberOfMonths = 1, weekStartsOn = 0, showOutsideDays = true, disabled, initialFocus, className, } = props;
99
+ const [own, setOwn] = useState(() => first(defaultMonth ?? new Date()));
100
+ const head = monthProp ? first(monthProp) : own;
101
+ const months = Array.from({ length: numberOfMonths }, (_, i) => first(head, i));
102
+ const grid = months.map((m) => cells(m, weekStartsOn, showOutsideDays));
103
+ const inside = (d) => !!d && at(d) >= at(head) && at(d) < at(first(head, numberOfMonths));
104
+ const shown = (d) => grid.some((g) => g.some((c) => same(c, d)));
105
+ const labels = [...WEEKDAYS.slice(weekStartsOn), ...WEEKDAYS.slice(0, weekStartsOn)];
106
+ const today = new Date();
107
+ const range = props.mode === 'range' ? (props.selected ?? {}) : {};
108
+ const [focused, setFocused] = useState();
109
+ const picks = props.mode === 'multiple' ? (props.selected ?? [])
110
+ : props.mode === 'range' ? [props.selected?.from]
111
+ : [props.selected];
112
+ const focus = focused && shown(focused) ? focused : (picks.find(inside) ?? (inside(today) ? today : head));
113
+ const root = useRef(null);
114
+ const pending = useRef(!!initialFocus);
115
+ useEffect(() => {
116
+ const node = root.current;
117
+ if (!pending.current || typeof HTMLElement === 'undefined' || !(node instanceof HTMLElement))
118
+ return;
119
+ pending.current = false;
120
+ const k = `[data-date="${key(focus)}"]`;
121
+ (node.querySelector(`${k}:not([data-outside])`) ?? node.querySelector(k))?.focus();
122
+ });
123
+ const navigate = (n) => {
124
+ const next = first(head, n);
125
+ setOwn(next);
126
+ onMonthChange?.(next);
127
+ };
128
+ const move = (e, from) => {
129
+ const next = step(e.key, from, weekStartsOn);
130
+ if (!next)
131
+ return;
132
+ e.preventDefault();
133
+ pending.current = true;
134
+ setFocused(next);
135
+ if (!shown(next))
136
+ navigate(at(next) < at(head) ? -1 : 1);
137
+ };
138
+ return (_jsx(XStack, { ref: root, ...slot('calendar'), flexWrap: "wrap", gap: "$4", p: "$3", ...sx(className), children: months.map((m, i) => (_jsxs(YStack, { ...slot('calendar-month'), gap: "$4", children: [_jsxs(XStack, { ...slot('calendar-caption'), items: "center", justify: "space-between", children: [_jsx(YStack, { width: 32, children: i === 0 && (_jsx(Button, { ...slot('calendar-nav-previous'), "aria-label": "Previous month", variant: "outline", size: "icon-sm", onClick: () => navigate(-1), children: _jsx(ChevronLeft, { size: 16 }) })) }), _jsxs(SizableText, { ...slot('calendar-caption-label'), size: "$3", fontWeight: "500", children: [MONTHS[m.getMonth()], " ", m.getFullYear()] }), _jsx(YStack, { width: 32, items: "flex-end", children: i === months.length - 1 && (_jsx(Button, { ...slot('calendar-nav-next'), "aria-label": "Next month", variant: "outline", size: "icon-sm", onClick: () => navigate(1), children: _jsx(ChevronRight, { size: 16 }) })) })] }), _jsxs(Grid, { columns: 7, gap: "$1", children: [labels.map((label) => (_jsx(Cell, { style: { textAlign: 'center' }, children: _jsx(SizableText, { size: "$1", color: "$quiet", children: label }) }, label))), grid[i].map((d, j) => {
139
+ if (!d)
140
+ return _jsx(Cell, {}, j);
141
+ const outside = d.getMonth() !== m.getMonth();
142
+ const selected = picked(props, d);
143
+ const start = same(range.from, d);
144
+ const end = same(range.to, d);
145
+ const middle = selected && props.mode === 'range' && !start && !end;
146
+ const isToday = same(d, today);
147
+ return (_jsx(Cell, { children: _jsx(Button, { ...slot('calendar-day'), "data-date": key(d), "data-today": isToday || undefined, "data-outside": outside || undefined, "data-selected": selected || undefined, "data-range-start": start || undefined, "data-range-end": end || undefined, "data-range-middle": middle || undefined, "aria-selected": selected, "aria-label": d.toDateString(), variant: selected && !middle ? 'primary' : middle || isToday ? 'secondary' : 'ghost', size: "icon", width: "100%", opacity: outside ? 0.5 : 1, disabled: !!disabled?.(d), tabIndex: same(d, focus) && (!outside || !inside(focus)) ? 0 : -1, onFocus: () => setFocused(d), onKeyDown: (e) => move(e, d), onClick: () => pick(props, d), children: d.getDate() }) }, j));
148
+ })] })] }, i))) }));
149
+ }
150
+ export { Calendar };
151
+ //# sourceMappingURL=calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.js","sourceRoot":"","sources":["../../../src/backends/gui/calendar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Choicebox = Choicebox;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * Choicebox — a list of full-width cards, one of which (or several, under
8
+ * `multiple`) is the chosen answer. Each card carries a label, an optional
9
+ * description and a circular indicator that fills in when the card is picked.
10
+ *
11
+ * Built directly on `@hanzo/gui`'s `ToggleGroup`, the same group primitive
12
+ * `./toggle-group` wraps for the segmented control: the selection is driven
13
+ * through `value`/`onValueChange` exactly as that file drives it, so rove
14
+ * focus, keyboard selection and the group's own click handling all come from
15
+ * gui rather than being reimplemented here. The frame names the roles a
16
+ * choice group needs and `ToggleGroup` leaves to the caller —
17
+ * `radiogroup`/`radio` for a single answer, `group` with `role="checkbox"` per
18
+ * card for several. A single answer never clears itself
19
+ * (`disableDeactivation`), because an exclusive choice that can go empty is a
20
+ * different control.
21
+ */
22
+ const gui_1 = require("@hanzo/gui");
23
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
24
+ const ink_1 = require("./ink.cjs");
25
+ const slot_1 = require("./slot.cjs");
26
+ const DOT = 20;
27
+ /** `"a,b"` <-> `["a", "b"]` — the wire shape stays the single joined string the
28
+ * original API returned; only the group's own bookkeeping is an array. */
29
+ const toList = (value) => (value ? value.split(',').filter(Boolean) : []);
30
+ function Choicebox({ options, value, defaultValue, onChange, multiple = false, ...props }) {
31
+ const [selected, setSelected] = (0, gui_1.useControllableState)({
32
+ prop: value !== undefined ? toList(value) : undefined,
33
+ defaultProp: toList(defaultValue),
34
+ onChange: (next) => onChange?.(next.join(',')),
35
+ });
36
+ const picked = selected ?? [];
37
+ return ((0, jsx_runtime_1.jsx)(gui_1.ToggleGroup, { ...(0, slot_1.slot)('choicebox'), ...{
38
+ type: multiple ? 'multiple' : 'single',
39
+ value: multiple ? picked : (picked[0] ?? ''),
40
+ onValueChange: multiple
41
+ ? (next) => setSelected(next)
42
+ : (next) => setSelected(next ? [next] : []),
43
+ disableDeactivation: !multiple,
44
+ }, role: multiple ? 'group' : 'radiogroup', orientation: "vertical", flexDirection: "column", gap: "$2", ...props, children: options.map((option) => {
45
+ const on = picked.includes(option.value);
46
+ return ((0, jsx_runtime_1.jsxs)(gui_1.ToggleGroup.Item, { ...(0, slot_1.slot)('choicebox-item'), value: option.value, role: multiple ? 'checkbox' : 'radio', "aria-checked": on, "data-state": on ? 'checked' : 'unchecked', unstyled: true, flexDirection: "row", items: "flex-start", gap: "$3", width: "100%", rounded: "$4", borderWidth: 2, borderColor: on ? '$ink' : '$borderColor', backgroundColor: on ? '$raised' : 'transparent', px: "$4", py: "$3.5", cursor: "pointer", hoverStyle: { backgroundColor: on ? '$raised' : '$hover' }, children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('choicebox-indicator'), width: DOT, height: DOT, shrink: 0, mt: 2, rounded: 1000, borderWidth: 2, borderColor: on ? '$ink' : '$bound', bg: on ? '$ink' : 'transparent', items: "center", justify: "center", children: on && (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Check, { size: DOT - 8, color: "white" }) }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, gap: "$1", children: [(0, ink_1.ink)(option.label, gui_1.SizableText, { size: '$3', fontWeight: '600' }), option.description
47
+ ? (0, ink_1.ink)(option.description, gui_1.SizableText, { size: '$2', color: '$quiet' })
48
+ : null] })] }, option.value));
49
+ }) }));
50
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Choicebox — a list of full-width cards, one of which (or several, under
3
+ * `multiple`) is the chosen answer. Each card carries a label, an optional
4
+ * description and a circular indicator that fills in when the card is picked.
5
+ *
6
+ * Built directly on `@hanzo/gui`'s `ToggleGroup`, the same group primitive
7
+ * `./toggle-group` wraps for the segmented control: the selection is driven
8
+ * through `value`/`onValueChange` exactly as that file drives it, so rove
9
+ * focus, keyboard selection and the group's own click handling all come from
10
+ * gui rather than being reimplemented here. The frame names the roles a
11
+ * choice group needs and `ToggleGroup` leaves to the caller —
12
+ * `radiogroup`/`radio` for a single answer, `group` with `role="checkbox"` per
13
+ * card for several. A single answer never clears itself
14
+ * (`disableDeactivation`), because an exclusive choice that can go empty is a
15
+ * different control.
16
+ */
17
+ import { ToggleGroup as GuiToggleGroup } from '@hanzo/gui';
18
+ import type { ComponentProps, ReactNode } from 'react';
19
+ export type ChoiceboxOption = {
20
+ value: string;
21
+ label: ReactNode;
22
+ description?: ReactNode;
23
+ };
24
+ export type ChoiceboxProps = Omit<ComponentProps<typeof GuiToggleGroup>, 'type' | 'value' | 'defaultValue' | 'onValueChange' | 'onChange' | 'children'> & {
25
+ options: ChoiceboxOption[];
26
+ value?: string;
27
+ defaultValue?: string;
28
+ onChange?: (value: string) => void;
29
+ multiple?: boolean;
30
+ };
31
+ declare function Choicebox({ options, value, defaultValue, onChange, multiple, ...props }: ChoiceboxProps): import("react").JSX.Element;
32
+ export { Choicebox };
33
+ //# sourceMappingURL=choicebox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choicebox.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/choicebox.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,WAAW,IAAI,cAAc,EAI9B,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItD,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,CAAA;IAChB,WAAW,CAAC,EAAE,SAAS,CAAA;CACxB,CAAA;AAID,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,cAAc,CAAC,OAAO,cAAc,CAAC,EACrC,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,eAAe,GAAG,UAAU,GAAG,UAAU,CAC9E,GAAG;IACF,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAMD,iBAAS,SAAS,CAAC,EACjB,OAAO,EACP,KAAK,EACL,YAAY,EACZ,QAAQ,EACR,QAAgB,EAChB,GAAG,KAAK,EACT,EAAE,cAAc,+BA8EhB;AAED,OAAO,EAAE,SAAS,EAAE,CAAA"}
@@ -0,0 +1,49 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Choicebox — a list of full-width cards, one of which (or several, under
5
+ * `multiple`) is the chosen answer. Each card carries a label, an optional
6
+ * description and a circular indicator that fills in when the card is picked.
7
+ *
8
+ * Built directly on `@hanzo/gui`'s `ToggleGroup`, the same group primitive
9
+ * `./toggle-group` wraps for the segmented control: the selection is driven
10
+ * through `value`/`onValueChange` exactly as that file drives it, so rove
11
+ * focus, keyboard selection and the group's own click handling all come from
12
+ * gui rather than being reimplemented here. The frame names the roles a
13
+ * choice group needs and `ToggleGroup` leaves to the caller —
14
+ * `radiogroup`/`radio` for a single answer, `group` with `role="checkbox"` per
15
+ * card for several. A single answer never clears itself
16
+ * (`disableDeactivation`), because an exclusive choice that can go empty is a
17
+ * different control.
18
+ */
19
+ import { ToggleGroup as GuiToggleGroup, SizableText, YStack, useControllableState, } from '@hanzo/gui';
20
+ import { Check } from '@hanzogui/lucide-icons-2';
21
+ import { ink } from './ink.js';
22
+ import { slot } from './slot.js';
23
+ const DOT = 20;
24
+ /** `"a,b"` <-> `["a", "b"]` — the wire shape stays the single joined string the
25
+ * original API returned; only the group's own bookkeeping is an array. */
26
+ const toList = (value) => (value ? value.split(',').filter(Boolean) : []);
27
+ function Choicebox({ options, value, defaultValue, onChange, multiple = false, ...props }) {
28
+ const [selected, setSelected] = useControllableState({
29
+ prop: value !== undefined ? toList(value) : undefined,
30
+ defaultProp: toList(defaultValue),
31
+ onChange: (next) => onChange?.(next.join(',')),
32
+ });
33
+ const picked = selected ?? [];
34
+ return (_jsx(GuiToggleGroup, { ...slot('choicebox'), ...{
35
+ type: multiple ? 'multiple' : 'single',
36
+ value: multiple ? picked : (picked[0] ?? ''),
37
+ onValueChange: multiple
38
+ ? (next) => setSelected(next)
39
+ : (next) => setSelected(next ? [next] : []),
40
+ disableDeactivation: !multiple,
41
+ }, role: multiple ? 'group' : 'radiogroup', orientation: "vertical", flexDirection: "column", gap: "$2", ...props, children: options.map((option) => {
42
+ const on = picked.includes(option.value);
43
+ return (_jsxs(GuiToggleGroup.Item, { ...slot('choicebox-item'), value: option.value, role: multiple ? 'checkbox' : 'radio', "aria-checked": on, "data-state": on ? 'checked' : 'unchecked', unstyled: true, flexDirection: "row", items: "flex-start", gap: "$3", width: "100%", rounded: "$4", borderWidth: 2, borderColor: on ? '$ink' : '$borderColor', backgroundColor: on ? '$raised' : 'transparent', px: "$4", py: "$3.5", cursor: "pointer", hoverStyle: { backgroundColor: on ? '$raised' : '$hover' }, children: [_jsx(YStack, { ...slot('choicebox-indicator'), width: DOT, height: DOT, shrink: 0, mt: 2, rounded: 1000, borderWidth: 2, borderColor: on ? '$ink' : '$bound', bg: on ? '$ink' : 'transparent', items: "center", justify: "center", children: on && _jsx(Check, { size: DOT - 8, color: "white" }) }), _jsxs(YStack, { flex: 1, gap: "$1", children: [ink(option.label, SizableText, { size: '$3', fontWeight: '600' }), option.description
44
+ ? ink(option.description, SizableText, { size: '$2', color: '$quiet' })
45
+ : null] })] }, option.value));
46
+ }) }));
47
+ }
48
+ export { Choicebox };
49
+ //# sourceMappingURL=choicebox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choicebox.js","sourceRoot":"","sources":["../../../src/backends/gui/choicebox.tsx"],"names":[],"mappings":"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"}