@nadicodeai/ui 8.1.0 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSES/SHADCN-HEATMAP-MIT.txt +21 -0
  2. package/NOTICE +9 -0
  3. package/dist/components/activity-calendar.d.ts +27 -0
  4. package/dist/components/activity-calendar.d.ts.map +1 -0
  5. package/dist/components/activity-calendar.js +56 -0
  6. package/dist/components/agent-orb.d.ts +22 -0
  7. package/dist/components/agent-orb.d.ts.map +1 -0
  8. package/dist/components/agent-orb.js +28 -0
  9. package/dist/components/chart-area-stacked.d.ts +1 -1
  10. package/dist/components/chart-area-stacked.d.ts.map +1 -1
  11. package/dist/components/chart-area-stacked.js +2 -2
  12. package/dist/components/chart-bar-multiple.d.ts +1 -1
  13. package/dist/components/chart-bar-multiple.d.ts.map +1 -1
  14. package/dist/components/chart-bar-multiple.js +2 -2
  15. package/dist/components/chart-bar-stacked.d.ts +1 -1
  16. package/dist/components/chart-bar-stacked.d.ts.map +1 -1
  17. package/dist/components/chart-bar-stacked.js +2 -2
  18. package/dist/components/chart-card.d.ts +24 -3
  19. package/dist/components/chart-card.d.ts.map +1 -1
  20. package/dist/components/chart-card.js +8 -3
  21. package/dist/components/heatmap/calendar-heatmap.d.ts +138 -0
  22. package/dist/components/heatmap/calendar-heatmap.d.ts.map +1 -0
  23. package/dist/components/heatmap/calendar-heatmap.js +449 -0
  24. package/dist/components/model-identity.d.ts +8 -0
  25. package/dist/components/model-identity.d.ts.map +1 -0
  26. package/dist/components/model-identity.js +8 -0
  27. package/dist/components/object-workspace.d.ts +36 -0
  28. package/dist/components/object-workspace.d.ts.map +1 -0
  29. package/dist/components/object-workspace.js +19 -0
  30. package/dist/components/progress.d.ts +2 -1
  31. package/dist/components/progress.d.ts.map +1 -1
  32. package/dist/components/progress.js +5 -4
  33. package/dist/components/settings-facts.d.ts +2 -1
  34. package/dist/components/settings-facts.d.ts.map +1 -1
  35. package/dist/components/settings-facts.js +6 -3
  36. package/dist/components/settings-section.d.ts +3 -1
  37. package/dist/components/settings-section.d.ts.map +1 -1
  38. package/dist/components/settings-section.js +2 -2
  39. package/dist/components/table-value.d.ts +7 -0
  40. package/dist/components/table-value.d.ts.map +1 -0
  41. package/dist/components/table-value.js +6 -0
  42. package/dist/components/table.d.ts +2 -1
  43. package/dist/components/table.d.ts.map +1 -1
  44. package/dist/components/table.js +4 -1
  45. package/dist/index.d.ts +5 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +5 -0
  48. package/dist/internal/agent-orb-motion.d.ts +14 -0
  49. package/dist/internal/agent-orb-motion.d.ts.map +1 -0
  50. package/dist/internal/agent-orb-motion.js +120 -0
  51. package/dist/internal/agent-orb.d.ts +19 -0
  52. package/dist/internal/agent-orb.d.ts.map +1 -0
  53. package/dist/internal/agent-orb.js +151 -0
  54. package/dist/internal/object-identity-support.d.ts +6 -0
  55. package/dist/internal/object-identity-support.d.ts.map +1 -0
  56. package/dist/internal/object-identity-support.js +10 -0
  57. package/dist/lib/format-token-count.d.ts +4 -0
  58. package/dist/lib/format-token-count.d.ts.map +1 -0
  59. package/dist/lib/format-token-count.js +31 -0
  60. package/docs/activity.md +3 -1
  61. package/docs/agent-orb.md +82 -0
  62. package/docs/agent-visual.md +5 -0
  63. package/docs/contract.md +46 -3
  64. package/docs/model-identity.md +18 -0
  65. package/package.json +7 -2
@@ -0,0 +1,449 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { differenceInCalendarDays, eachDayOfInterval, format, formatISO, getDay, getMonth, getYear, nextDay, parseISO, subWeeks, } from "date-fns";
3
+ import { createContext, Fragment, use, useMemo } from "react";
4
+ import { cn } from "../../lib/utils.js";
5
+ // Non-normalized: 1 empty + (levels-1) colored steps. Normalized: levels colored steps, no empty.
6
+ const colorStepCount = (levels, isNormalized) => Math.max(1, isNormalized ? levels : levels - 1);
7
+ const getLevelFill = (level, levels, isNormalized, measured, highlighted = false, colors) => {
8
+ const emptyColor = colors?.empty ?? "var(--color-secondary)";
9
+ const scaleColor = colors?.scale ?? "var(--color-chart-1)";
10
+ if (!measured)
11
+ return colors?.unavailable ?? "transparent";
12
+ if (level === 0)
13
+ return emptyColor;
14
+ const steps = colorStepCount(levels, isNormalized);
15
+ const opacity = steps === 1 ? 100 : Math.round(20 + ((level - 1) * 80) / (steps - 1));
16
+ const finalOpacity = highlighted ? Math.round(opacity * 0.6) : opacity;
17
+ return `color-mix(in oklch, ${scaleColor} ${finalOpacity}%, transparent)`;
18
+ };
19
+ const calculateLevel = (value, minValue, maxValue, levels, isNormalized) => {
20
+ const steps = colorStepCount(levels, isNormalized);
21
+ if (!Number.isFinite(value))
22
+ return isNormalized ? 1 : 0;
23
+ if (isNormalized) {
24
+ if (maxValue <= minValue)
25
+ return 1;
26
+ const percentage = (value - minValue) / (maxValue - minValue);
27
+ return Math.max(1, Math.min(steps, Math.ceil(percentage * steps)));
28
+ }
29
+ if (value <= 0 || maxValue <= 0)
30
+ return 0;
31
+ const percentage = value / maxValue;
32
+ return Math.max(1, Math.min(steps, Math.ceil(percentage * steps)));
33
+ };
34
+ const generateMonthLabels = (locale) => {
35
+ return Array.from({ length: 12 }, (_, i) => {
36
+ const date = new Date(2000, i, 1);
37
+ if (locale)
38
+ return format(date, "LLL", { locale });
39
+ return date.toLocaleString("en-US", { month: "short" });
40
+ });
41
+ };
42
+ const generateWeekdayLabels = (locale) => {
43
+ return Array.from({ length: 7 }, (_, i) => {
44
+ const date = new Date(2000, 0, 2 + i);
45
+ if (locale)
46
+ return format(date, "EEE", { locale });
47
+ return date.toLocaleString("en-US", { weekday: "short" });
48
+ });
49
+ };
50
+ const EMPTY_STYLE = {};
51
+ const LABEL_MARGIN = 8;
52
+ const CalendarHeatmapContext = createContext(null);
53
+ const useCalendarHeatmap = () => {
54
+ const context = use(CalendarHeatmapContext);
55
+ if (!context) {
56
+ throw new Error("CalendarHeatmap components must be used within a CalendarHeatmap");
57
+ }
58
+ return context;
59
+ };
60
+ const fillHoles = (activities) => {
61
+ if (activities.length === 0) {
62
+ return [];
63
+ }
64
+ const sortedActivities = [...activities].sort((a, b) => a.date.localeCompare(b.date));
65
+ const calendar = new Map(activities.map((a) => [a.date, a]));
66
+ const firstActivity = sortedActivities[0];
67
+ const lastActivity = sortedActivities.at(-1);
68
+ if (!lastActivity) {
69
+ return [];
70
+ }
71
+ return eachDayOfInterval({
72
+ start: parseISO(firstActivity.date),
73
+ end: parseISO(lastActivity.date),
74
+ }).map((day) => {
75
+ const date = formatISO(day, { representation: "date" });
76
+ if (calendar.has(date)) {
77
+ return calendar.get(date);
78
+ }
79
+ return {
80
+ date,
81
+ value: null,
82
+ level: 0,
83
+ measured: false,
84
+ };
85
+ });
86
+ };
87
+ const groupByYearAndMonth = (activities, weekStart = 0, hasEmptyColumn = false) => {
88
+ if (activities.length === 0) {
89
+ return [];
90
+ }
91
+ const normalizedActivities = fillHoles(activities);
92
+ const activitiesByYearMonth = new Map();
93
+ for (const activity of normalizedActivities) {
94
+ const date = parseISO(activity.date);
95
+ const year = getYear(date);
96
+ const month = getMonth(date);
97
+ const key = `${year}-${String(month).padStart(2, "0")}`;
98
+ if (!activitiesByYearMonth.has(key)) {
99
+ activitiesByYearMonth.set(key, []);
100
+ }
101
+ activitiesByYearMonth.get(key)?.push(activity);
102
+ }
103
+ const sortedKeys = Array.from(activitiesByYearMonth.keys()).sort();
104
+ if (sortedKeys.length === 0) {
105
+ return [];
106
+ }
107
+ const firstKey = sortedKeys[0];
108
+ const [firstYearStr, firstMonthStr] = firstKey.split("-");
109
+ const startYear = parseInt(firstYearStr, 10);
110
+ const startMonth = parseInt(firstMonthStr, 10);
111
+ const yearRows = [];
112
+ let currentYear = startYear;
113
+ let currentMonth = startMonth;
114
+ while (true) {
115
+ const rowWeeks = [];
116
+ let hasData = false;
117
+ for (let monthOffset = 0; monthOffset < 12; monthOffset++) {
118
+ const monthIndex = (currentMonth + monthOffset) % 12;
119
+ const yearOffset = Math.floor((currentMonth + monthOffset) / 12);
120
+ const year = currentYear + yearOffset;
121
+ const key = `${year}-${String(monthIndex).padStart(2, "0")}`;
122
+ const monthActivities = activitiesByYearMonth.get(key) || [];
123
+ if (monthActivities.length > 0) {
124
+ hasData = true;
125
+ const firstActivity = monthActivities[0];
126
+ const firstDate = parseISO(firstActivity.date);
127
+ const firstCalendarDate = getDay(firstDate) === weekStart ? firstDate : subWeeks(nextDay(firstDate, weekStart), 1);
128
+ const paddedActivities = [
129
+ ...new Array(differenceInCalendarDays(firstDate, firstCalendarDate)).fill(undefined),
130
+ ...monthActivities,
131
+ ];
132
+ const numberOfWeeks = Math.ceil(paddedActivities.length / 7);
133
+ const monthWeeks = new Array(numberOfWeeks)
134
+ .fill(undefined)
135
+ .map((_, weekIndex) => paddedActivities.slice(weekIndex * 7, weekIndex * 7 + 7));
136
+ if (hasEmptyColumn && rowWeeks.length > 0) {
137
+ rowWeeks.push(new Array(7).fill(undefined));
138
+ }
139
+ rowWeeks.push(...monthWeeks);
140
+ }
141
+ }
142
+ if (!hasData) {
143
+ break;
144
+ }
145
+ yearRows.push({
146
+ year: currentYear,
147
+ startMonth: currentMonth,
148
+ weeks: rowWeeks,
149
+ });
150
+ currentYear++;
151
+ currentMonth = startMonth;
152
+ const hasNextYearData = sortedKeys.some((key) => {
153
+ const [yearStr] = key.split("-");
154
+ return parseInt(yearStr, 10) >= currentYear;
155
+ });
156
+ if (!hasNextYearData) {
157
+ break;
158
+ }
159
+ }
160
+ return yearRows;
161
+ };
162
+ const groupContinuous = (activities, weekStart = 0, singleRow = false) => {
163
+ if (activities.length === 0)
164
+ return [];
165
+ const normalizedActivities = fillHoles(activities);
166
+ const first = normalizedActivities[0];
167
+ const firstDate = parseISO(first.date);
168
+ const firstCalendarDate = getDay(firstDate) === weekStart ? firstDate : subWeeks(nextDay(firstDate, weekStart), 1);
169
+ const leadingPad = differenceInCalendarDays(firstDate, firstCalendarDate);
170
+ const padded = [
171
+ ...new Array(leadingPad).fill(undefined),
172
+ ...normalizedActivities,
173
+ ];
174
+ const numberOfWeeks = Math.ceil(padded.length / 7);
175
+ const allWeeks = new Array(numberOfWeeks)
176
+ .fill(undefined)
177
+ .map((_, i) => padded.slice(i * 7, i * 7 + 7));
178
+ if (singleRow) {
179
+ return [
180
+ {
181
+ year: getYear(firstDate),
182
+ startMonth: getMonth(firstDate),
183
+ weeks: allWeeks,
184
+ },
185
+ ];
186
+ }
187
+ const yearMap = new Map();
188
+ for (const week of allWeeks) {
189
+ const firstActivity = week.find((a) => a !== undefined);
190
+ const year = firstActivity ? getYear(parseISO(firstActivity.date)) : undefined;
191
+ if (year !== undefined) {
192
+ if (!yearMap.has(year))
193
+ yearMap.set(year, []);
194
+ yearMap.get(year)?.push(week);
195
+ }
196
+ }
197
+ return Array.from(yearMap.entries())
198
+ .sort(([a], [b]) => a - b)
199
+ .map(([year, weeks]) => ({
200
+ year,
201
+ startMonth: 0,
202
+ weeks,
203
+ }));
204
+ };
205
+ const getMonthLabels = (weeks, monthNames = generateMonthLabels()) => {
206
+ return weeks
207
+ .reduce((labels, week, weekIndex) => {
208
+ const firstActivity = week.find((activity) => activity !== undefined);
209
+ if (!firstActivity) {
210
+ return labels;
211
+ }
212
+ const month = monthNames[getMonth(parseISO(firstActivity.date))];
213
+ if (!month) {
214
+ const monthName = new Date(firstActivity.date).toLocaleString("en-US", {
215
+ month: "short",
216
+ });
217
+ throw new Error(`Unexpected error: undefined month label for ${monthName}.`);
218
+ }
219
+ const prevLabel = labels.at(-1);
220
+ if (weekIndex === 0 || !prevLabel || prevLabel.label !== month) {
221
+ labels.push({ weekIndex, label: month });
222
+ }
223
+ return labels;
224
+ }, [])
225
+ .filter(({ weekIndex }, index, labels) => {
226
+ const minWeeks = 3;
227
+ if (index === 0) {
228
+ return labels[1] && labels[1].weekIndex - weekIndex >= minWeeks;
229
+ }
230
+ if (index === labels.length - 1) {
231
+ return weeks.slice(weekIndex).length >= minWeeks;
232
+ }
233
+ return true;
234
+ });
235
+ };
236
+ /**
237
+ * Calendar Heatmap
238
+ *
239
+ * A GitHub-style contribution calendar showing daily activity over months and years.
240
+ * Each cell represents one day, arranged in weeks (rows) and months (columns).
241
+ *
242
+ * @example
243
+ * ```tsx
244
+ * <CalendarHeatmap data={data} weekStart={1} continuousMonths>
245
+ * <CalendarHeatmapBody>
246
+ * {({ activity, dayIndex, weekIndex }) => (
247
+ * <CalendarHeatmapBlock
248
+ * activity={activity}
249
+ * dayIndex={dayIndex}
250
+ * weekIndex={weekIndex}
251
+ * />
252
+ * )}
253
+ * </CalendarHeatmapBody>
254
+ * <CalendarHeatmapFooter>
255
+ * <CalendarHeatmapStat />
256
+ * <CalendarHeatmapLegend />
257
+ * </CalendarHeatmapFooter>
258
+ * </CalendarHeatmap>
259
+ * ```
260
+ *
261
+ * @param data - Array of activities with date (YYYY-MM-DD) and value
262
+ * @param weekStart - First day of week (0=Sunday, 1=Monday). Default: 0
263
+ * @param continuousMonths - Display months continuously vs. grouped by year. Default: true
264
+ * @param singleRow - Keep a continuous range in one row across year boundaries. Default: false
265
+ * @param hasEmptyColumn - Add empty column between months. Default: false
266
+ * @param blockAspectRatio - Width/height ratio of blocks. Default: 1
267
+ * @param levels - Total number of legend cells (including empty when not normalized). Default: 5
268
+ * @param isNormalized - When true, uses min-max normalization across the dataset (suitable for signed values). When false (default), treats 0 as empty and scales from 0 to max.
269
+ */
270
+ export const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, singleRow = false, hasEmptyColumn = false, blockSize = 12, blockMargin = 4, blockRadius = 2, blockAspectRatio = 1, levels: levelsProp = 5, isNormalized = false, colors, locale, labels: labelsProp, fontSize = 14, emptyState, totalCount: totalCountProp, style = EMPTY_STYLE, className, children, ...props }) => {
271
+ const levels = Math.max(1, levelsProp);
272
+ const dataWithLevels = useMemo(() => {
273
+ if (data.length === 0)
274
+ return [];
275
+ const measuredValues = data.flatMap((activity) => typeof activity.value === "number" && Number.isFinite(activity.value) ? [activity.value] : []);
276
+ const maxCount = measuredValues.reduce((max, value) => Math.max(max, value), 1);
277
+ const minCount = isNormalized
278
+ ? measuredValues.reduce((min, value) => Math.min(min, value), Infinity)
279
+ : 0;
280
+ return data.map((activity) => {
281
+ const value = activity.value;
282
+ const measured = typeof value === "number" && Number.isFinite(value);
283
+ return {
284
+ ...activity,
285
+ measured,
286
+ level: measured ? calculateLevel(value, minCount, maxCount, levels, isNormalized) : 0,
287
+ };
288
+ });
289
+ }, [data, levels, isNormalized]);
290
+ const yearRows = useMemo(() => continuousMonths
291
+ ? groupContinuous(dataWithLevels, weekStart, singleRow)
292
+ : groupByYearAndMonth(dataWithLevels, weekStart, hasEmptyColumn), [dataWithLevels, weekStart, hasEmptyColumn, continuousMonths, singleRow]);
293
+ const weeks = useMemo(() => yearRows.flatMap((r) => r.weeks), [yearRows]);
294
+ const labels = useMemo(() => ({
295
+ months: generateMonthLabels(locale),
296
+ weekdays: generateWeekdayLabels(locale),
297
+ cellLabel: "{{date}}: {{value}} contributions",
298
+ unavailable: "No data",
299
+ heatmapLabel: "Contribution heatmap for {{year}}",
300
+ legendLabel: "Activity intensity legend",
301
+ legendLevelLabel: "{{level}} contributions",
302
+ ...labelsProp,
303
+ }), [locale, labelsProp]);
304
+ const labelHeight = fontSize + LABEL_MARGIN;
305
+ const year = data.length > 0 ? getYear(parseISO(data[0].date)) : new Date().getFullYear();
306
+ const totalCount = typeof totalCountProp === "number"
307
+ ? totalCountProp
308
+ : dataWithLevels.reduce((sum, activity) => sum + (activity.value ?? 0), 0);
309
+ const blockWidth = blockSize * blockAspectRatio;
310
+ const width = weeks.length * (blockWidth + blockMargin) - blockMargin;
311
+ const height = labelHeight + (blockSize + blockMargin) * 7 - blockMargin;
312
+ const contextValue = useMemo(() => ({
313
+ data: dataWithLevels,
314
+ weeks,
315
+ yearRows,
316
+ blockMargin,
317
+ blockRadius,
318
+ blockSize,
319
+ blockAspectRatio,
320
+ blockWidth,
321
+ fontSize,
322
+ labels,
323
+ labelHeight,
324
+ levels,
325
+ isNormalized,
326
+ totalCount,
327
+ weekStart,
328
+ year,
329
+ width,
330
+ height,
331
+ hasEmptyColumn,
332
+ continuousMonths,
333
+ locale,
334
+ colors,
335
+ }), [
336
+ dataWithLevels,
337
+ weeks,
338
+ yearRows,
339
+ blockMargin,
340
+ blockRadius,
341
+ blockSize,
342
+ blockAspectRatio,
343
+ blockWidth,
344
+ fontSize,
345
+ labels,
346
+ labelHeight,
347
+ levels,
348
+ isNormalized,
349
+ totalCount,
350
+ weekStart,
351
+ year,
352
+ width,
353
+ height,
354
+ hasEmptyColumn,
355
+ continuousMonths,
356
+ locale,
357
+ colors,
358
+ ]);
359
+ if (data.length === 0) {
360
+ return emptyState ? emptyState : null;
361
+ }
362
+ return (_jsx(CalendarHeatmapContext, { value: contextValue, children: _jsx("div", { "data-slot": "calendar-heatmap", className: cn("flex w-max max-w-full flex-col gap-2 p-4", className), style: { fontSize, ...style }, ...props, children: children }) }));
363
+ };
364
+ export const CalendarHeatmapBlock = ({ ref, activity, dayIndex, weekIndex, highlighted = false, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }) => {
365
+ const { blockSize, blockWidth, blockMargin, blockRadius, labelHeight, labels, levels, isNormalized, colors, } = useCalendarHeatmap();
366
+ const level = Math.max(0, Math.min(colorStepCount(levels, isNormalized), activity.level));
367
+ const cellLabel = labels.cellLabel ?? "{{date}}: {{value}} contributions";
368
+ const ariaLabel = typeof cellLabel === "function"
369
+ ? cellLabel(activity)
370
+ : cellLabel
371
+ .replace("{{date}}", activity.date)
372
+ .replace("{{value}}", activity.measured ? String(activity.value) : (labels.unavailable ?? "No data"));
373
+ return (_jsx("rect", { ref: ref, "data-slot": "calendar-heatmap-block", role: onCellClick ? "button" : "img", tabIndex: onCellClick ? 0 : -1, "aria-label": ariaLabel, className: cn("motion-safe:transition-opacity motion-safe:hover:opacity-70", onCellClick && "cursor-pointer focus-visible:nc-focus-outline focus-visible:outline-ring", className), "data-value": activity.value ?? undefined, "data-measured": activity.measured, "data-date": activity.date, "data-level": level, "data-highlighted": highlighted || undefined, height: blockSize, rx: blockRadius, ry: blockRadius, width: blockWidth, x: (blockWidth + blockMargin) * weekIndex, y: labelHeight + (blockSize + blockMargin) * dayIndex, style: {
374
+ fill: getLevelFill(level, levels, isNormalized, activity.measured, highlighted, colors),
375
+ ...styleProp,
376
+ }, onClick: (event) => {
377
+ onCellClick?.(activity);
378
+ onClick?.(event);
379
+ }, onKeyDown: (event) => {
380
+ if (onCellClick && (event.key === "Enter" || event.key === " ")) {
381
+ event.preventDefault();
382
+ onCellClick(activity);
383
+ }
384
+ onKeyDown?.(event);
385
+ }, onMouseEnter: (event) => {
386
+ onCellHover?.(activity);
387
+ onMouseEnter?.(event);
388
+ }, onMouseLeave: (event) => {
389
+ onCellHover?.(null);
390
+ onMouseLeave?.(event);
391
+ }, ...props, children: _jsx("title", { children: ariaLabel }) }));
392
+ };
393
+ CalendarHeatmapBlock.displayName = "CalendarHeatmapBlock";
394
+ export const CalendarHeatmapBody = ({ hideMonthLabels = false, hideWeekdayLabels = false, hideYearLabels = false, className, labelClassName, yearClassName, children, renderYearFooter, ...props }) => {
395
+ const { yearRows, blockSize, blockWidth, blockMargin, labels, labelHeight, fontSize, weekStart, data, } = useCalendarHeatmap();
396
+ const weekdayLabelWidth = hideWeekdayLabels ? 0 : 40;
397
+ const strokePadding = 3;
398
+ const rowData = useMemo(() => {
399
+ return yearRows.map((yearRow) => {
400
+ const width = yearRow.weeks.length * (blockWidth + blockMargin) - blockMargin;
401
+ const height = labelHeight + (blockSize + blockMargin) * 7 - blockMargin;
402
+ const monthLabels = getMonthLabels(yearRow.weeks, labels.months);
403
+ const yearTotalCount = data
404
+ .filter((activity) => getYear(parseISO(activity.date)) === yearRow.year)
405
+ .reduce((sum, activity) => sum + (activity.value ?? 0), 0);
406
+ return {
407
+ yearRow,
408
+ width,
409
+ height,
410
+ monthLabels,
411
+ yearTotalCount,
412
+ };
413
+ });
414
+ }, [yearRows, blockSize, blockWidth, blockMargin, labelHeight, labels.months, data]);
415
+ const maxWidth = Math.max(...rowData.map((r) => r.width));
416
+ const totalWidth = weekdayLabelWidth + maxWidth + strokePadding * 2;
417
+ return (_jsx("div", { "data-slot": "calendar-heatmap-body", className: cn("flex max-w-full flex-col gap-6 overflow-x-auto overflow-y-hidden py-4", className), ...props, children: rowData.map(({ yearRow, height, monthLabels, yearTotalCount }) => (_jsxs("div", { children: [!hideYearLabels && (_jsx("div", { className: cn("mb-2 text-muted-foreground", yearClassName), children: yearRow.year })), _jsx("svg", { role: "img", "aria-label": (labels.heatmapLabel ?? "Contribution heatmap for {{year}}").replace("{{year}}", String(yearRow.year)), className: "block overflow-visible rounded-sm focus-visible:nc-focus-outline focus-visible:outline-ring", height: height + strokePadding * 2, viewBox: `0 0 ${totalWidth} ${height + strokePadding * 2}`, width: totalWidth, children: _jsxs("g", { transform: `translate(0, ${strokePadding})`, children: [!hideMonthLabels && (_jsx("g", { className: cn("fill-current font-mono", labelClassName), children: monthLabels.map(({ label, weekIndex }) => (_jsx("text", { dominantBaseline: "hanging", x: weekdayLabelWidth + strokePadding + (blockWidth + blockMargin) * weekIndex, style: { fontSize: `${fontSize * 0.75}px` }, children: label }, `${yearRow.year}-${weekIndex}`))) })), !hideWeekdayLabels && (_jsx("g", { className: cn("fill-current font-mono text-xs", labelClassName), children: labels.weekdays?.map((label, dayIndex) => {
418
+ const adjustedIndex = (dayIndex + weekStart) % 7;
419
+ const adjustedLabel = labels.weekdays?.[adjustedIndex] || label;
420
+ return (_jsx("text", { x: 0, y: labelHeight + (blockSize + blockMargin) * dayIndex + blockSize / 2, dominantBaseline: "middle", textAnchor: "start", style: { fontSize: `${fontSize * 0.75}px` }, children: adjustedLabel }, `weekday-${yearRow.year}-${label}`));
421
+ }) })), _jsx("g", { transform: `translate(${weekdayLabelWidth + strokePadding}, 0)`, children: yearRow.weeks.map((week, weekIndex) => week.map((activity, dayIndex) => {
422
+ if (!activity) {
423
+ return null;
424
+ }
425
+ return (_jsx(Fragment, { children: children({ activity, dayIndex, weekIndex }) }, `${yearRow.year}-${activity.date}`));
426
+ })) })] }) }), renderYearFooter?.({
427
+ year: yearRow.year,
428
+ totalCount: yearTotalCount,
429
+ })] }, `year-row-${yearRow.year}`))) }));
430
+ };
431
+ export const CalendarHeatmapFooter = ({ className, ...props }) => (_jsx("div", { "data-slot": "calendar-heatmap-footer", className: cn("flex flex-wrap gap-1 whitespace-nowrap sm:gap-x-4", className), ...props }));
432
+ export const CalendarHeatmapStat = ({ compute, label, className, children, ...props }) => {
433
+ const { data, totalCount, year, labels } = useCalendarHeatmap();
434
+ const value = compute ? compute(data) : totalCount;
435
+ if (children) {
436
+ return _jsx(_Fragment, { children: children({ value, data, year }) });
437
+ }
438
+ const template = label ?? labels.stat ?? "{{value}} contributions in {{year}}";
439
+ return (_jsx("div", { "data-slot": "calendar-heatmap-stat", className: cn("text-muted-foreground tabular-nums", className), ...props, children: template.replace("{{value}}", String(value)).replace("{{year}}", String(year)) }));
440
+ };
441
+ export const CalendarHeatmapLegend = ({ labels: labelsProp, className, children, ...props }) => {
442
+ const { levels, isNormalized, blockSize, blockWidth, blockRadius, colors, labels } = useCalendarHeatmap();
443
+ const lessLabel = labelsProp?.less ?? "Less";
444
+ const moreLabel = labelsProp?.more ?? "More";
445
+ const legendLevels = Array.from({ length: levels }, (_, i) => (isNormalized ? i + 1 : i));
446
+ return (_jsxs("fieldset", { "data-slot": "calendar-heatmap-legend", "aria-label": labels.legendLabel ?? "Activity intensity legend", className: cn("ml-auto flex items-center gap-1 text-muted-foreground", className), ...props, children: [_jsx("span", { className: "mr-1 font-medium text-xs", children: lessLabel }), legendLevels.map((level) => children ? (_jsx(Fragment, { children: children({ level }) }, `legend-level-${level}`)) : (_jsx("svg", { role: "img", "aria-label": (labels.legendLevelLabel ?? "{{level}} contributions").replace("{{level}}", String(level)), height: blockSize, width: blockWidth, children: _jsx("rect", { "data-level": level, height: blockSize, rx: blockRadius, ry: blockRadius, width: blockWidth, style: {
447
+ fill: getLevelFill(level, levels, isNormalized, true, false, colors),
448
+ } }) }, `legend-level-${level}`))), _jsx("span", { className: "ml-1 font-medium text-xs", children: moreLabel })] }));
449
+ };
@@ -0,0 +1,8 @@
1
+ import type { ComponentPropsWithoutRef, ReactNode } from "react";
2
+ export type ModelIdentityProps = Omit<ComponentPropsWithoutRef<"span">, "children"> & {
3
+ label?: ReactNode;
4
+ model: string;
5
+ markSize?: number;
6
+ };
7
+ export declare function ModelIdentity({ label, model, markSize, ...props }: ModelIdentityProps): import("react").JSX.Element;
8
+ //# sourceMappingURL=model-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-identity.d.ts","sourceRoot":"","sources":["../../src/components/model-identity.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIjE,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG;IACpF,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,+BAcrF"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ModelMark } from "./model-mark.js";
3
+ export function ModelIdentity({ label, model, markSize, ...props }) {
4
+ const separator = model.indexOf("/");
5
+ const author = separator === -1 ? "" : model.slice(0, separator);
6
+ const name = typeof label === "string" ? label : separator === -1 ? model : model.slice(separator + 1);
7
+ return (_jsx(ModelMark, { author: author, name: name, ...(markSize === undefined ? {} : { size: markSize }), ...props }));
8
+ }
@@ -0,0 +1,36 @@
1
+ import type { ReactNode } from "react";
2
+ export type ObjectFact = {
3
+ label: string;
4
+ value: ReactNode;
5
+ icon?: ReactNode;
6
+ };
7
+ export type ObjectIdentitySupportFacts = {
8
+ facts: readonly ObjectFact[];
9
+ label: string;
10
+ };
11
+ export declare function ObjectIdentity({ visual, title, description, metadata, action, editAction, layout, support, }: {
12
+ visual: ReactNode;
13
+ title: ReactNode;
14
+ description?: ReactNode;
15
+ metadata?: ReactNode;
16
+ action?: ReactNode;
17
+ editAction?: ReactNode;
18
+ layout?: "inline" | "stacked";
19
+ support?: ObjectIdentitySupportFacts;
20
+ }): import("react").JSX.Element;
21
+ export declare function ObjectOverview({ primary, supporting, }: {
22
+ primary: ReactNode;
23
+ supporting: ReactNode;
24
+ }): import("react").JSX.Element;
25
+ export declare function ObjectSection({ title, description, action, icon, children, }: {
26
+ title: string;
27
+ description?: ReactNode;
28
+ action?: ReactNode;
29
+ icon?: ReactNode;
30
+ children: ReactNode;
31
+ }): import("react").JSX.Element;
32
+ export declare function ObjectFacts({ facts, density, }: {
33
+ facts: readonly ObjectFact[];
34
+ density?: "compact" | "default";
35
+ }): import("react").JSX.Element;
36
+ //# sourceMappingURL=object-workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-workspace.d.ts","sourceRoot":"","sources":["../../src/components/object-workspace.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,MAAM,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAE/E,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,WAAW,EACX,QAAQ,EACR,MAAM,EACN,UAAU,EACV,MAAiB,EACjB,OAAO,GACR,EAAE;IACD,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B,OAAO,CAAC,EAAE,0BAA0B,CAAC;CACtC,+BAwCA;AAED,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,UAAU,GACX,EAAE;IACD,OAAO,EAAE,SAAS,CAAC;IACnB,UAAU,EAAE,SAAS,CAAC;CACvB,+BAUA;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,MAAM,EACN,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB,+BAoBA;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,OAAmB,GACpB,EAAE;IACD,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC,+BA6BA"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "./card.js";
3
+ import { ObjectIdentitySupport } from "../internal/object-identity-support.js";
4
+ export function ObjectIdentity({ visual, title, description, metadata, action, editAction, layout = "inline", support, }) {
5
+ return (_jsxs(Card, { className: layout === "inline"
6
+ ? "min-w-0 lg:grid lg:grid-cols-[minmax(0,1fr)_minmax(0,1.25fr)] lg:items-center"
7
+ : "min-w-0", render: _jsx("header", { "data-slot": "object-identity" }), size: "sm", children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex min-w-0 items-center gap-4", children: [_jsx("div", { className: "shrink-0", children: visual }), _jsxs("div", { className: "grid min-w-0 gap-1.5", children: [_jsx(CardTitle, { children: _jsx("h2", { className: "wrap-anywhere", children: title }) }), description ? _jsx(CardDescription, { children: description }) : null, metadata ? (_jsx("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground", children: metadata })) : null] })] }), editAction ? _jsx(CardAction, { children: editAction }) : null] }), support || action ? (_jsxs(CardContent, { className: "flex min-w-0 flex-wrap items-start gap-4", children: [support ? (_jsx(ObjectIdentitySupport, { label: support.label, children: _jsx(ObjectFacts, { density: "compact", facts: support.facts }) })) : null, action ? _jsx("div", { className: "min-w-0 flex-1 basis-full", children: action }) : null] })) : null] }));
8
+ }
9
+ export function ObjectOverview({ primary, supporting, }) {
10
+ return (_jsxs("div", { "data-slot": "object-overview", className: "grid min-w-0 items-start gap-6 xl:grid-cols-[minmax(0,1.6fr)_minmax(0,1fr)]", children: [_jsx("div", { className: "grid min-w-0 gap-6", children: primary }), _jsx("div", { className: "grid min-w-0 gap-6", children: supporting })] }));
11
+ }
12
+ export function ObjectSection({ title, description, action, icon, children, }) {
13
+ return (_jsxs(Card, { "data-slot": "object-section", children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: _jsxs("h3", { className: "flex items-center gap-2", children: [icon ? (_jsx("span", { "aria-hidden": "true", className: "text-muted-foreground [&_svg]:size-4", children: icon })) : null, title] }) }), description ? _jsx(CardDescription, { children: description }) : null, action ? _jsx(CardAction, { children: action }) : null] }), _jsx(CardContent, { children: children })] }));
14
+ }
15
+ export function ObjectFacts({ facts, density = "default", }) {
16
+ return (_jsx("dl", { "data-density": density, "data-slot": "object-facts", className: density === "compact"
17
+ ? "grid min-w-0 grid-cols-2 gap-x-6 gap-y-2"
18
+ : "grid min-w-0 gap-x-6 gap-y-5 sm:grid-cols-2", children: facts.map((fact) => (_jsxs("div", { className: density === "compact" ? "grid min-w-0 gap-0.5" : "grid min-w-0 gap-1.5", children: [_jsxs("dt", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [fact.icon ? (_jsx("span", { "aria-hidden": "true", className: "[&_svg]:size-3.5", children: fact.icon })) : null, fact.label] }), _jsx("dd", { className: "text-sm wrap-anywhere", children: fact.value })] }, fact.label))) }));
19
+ }
@@ -12,8 +12,9 @@ declare const progressIndicatorVariants: (props?: ({
12
12
  tone?: "default" | "warning" | "critical" | null | undefined;
13
13
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
14
14
  type ProgressTone = NonNullable<VariantProps<typeof progressIndicatorVariants>["tone"]>;
15
- declare function Progress({ className, children, value, min, max, tone, ...props }: ProgressPrimitive.Root.Props & {
15
+ declare function Progress({ className, children, value, min, max, tone, indicatorColor, ...props }: ProgressPrimitive.Root.Props & {
16
16
  tone?: ProgressTone;
17
+ indicatorColor?: string;
17
18
  }): import("react").JSX.Element;
18
19
  declare function ProgressTrack({ className, ...props }: ProgressPrimitive.Track.Props): import("react").JSX.Element;
19
20
  declare function ProgressIndicator({ className, style, ...props }: ProgressPrimitive.Indicator.Props): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/components/progress.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE;;;;;;;GAOG;AAEH,QAAA,MAAM,yBAAyB;;8EAc9B,CAAC;AAEF,KAAK,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAYxF,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,QAAQ,EACR,KAAK,EACL,GAAO,EACP,GAAS,EACT,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,GAAG;IAAE,IAAI,CAAC,EAAE,YAAY,CAAA;CAAE,+BAwBxD;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,+BAW5E;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,SAAS,CAAC,KAAK,+BA6B3F;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,+BAQ5E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,+BAQ5E;AAED,OAAO,EACL,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,yBAAyB,GAC1B,CAAC;AACF,YAAY,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/components/progress.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE;;;;;;;GAOG;AAEH,QAAA,MAAM,yBAAyB;;8EAc9B,CAAC;AAEF,KAAK,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAiBxF,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,QAAQ,EACR,KAAK,EACL,GAAO,EACP,GAAS,EACT,IAAgB,EAChB,cAAc,EACd,GAAG,KAAK,EACT,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,GAAG;IAAE,IAAI,CAAC,EAAE,YAAY,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,+BAwBjF;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,+BAW5E;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,SAAS,CAAC,KAAK,+BAkC3F;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,+BAQ5E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,+BAQ5E;AAED,OAAO,EACL,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,yBAAyB,GAC1B,CAAC;AACF,YAAY,EAAE,YAAY,EAAE,CAAC"}
@@ -30,26 +30,27 @@ const ProgressStateContext = createContext({
30
30
  tone: "default",
31
31
  overCap: false,
32
32
  });
33
- function Progress({ className, children, value, min = 0, max = 100, tone = "default", ...props }) {
33
+ function Progress({ className, children, value, min = 0, max = 100, tone = "default", indicatorColor, ...props }) {
34
34
  const measured = typeof value === "number" && Number.isFinite(value);
35
35
  const scale = measured && max > min ? Math.min(1, Math.max(0, (value - min) / (max - min))) : 0;
36
36
  const overCap = measured && value > max;
37
- return (_jsx(ProgressPrimitive.Root, { value: value, min: min, max: max, "data-slot": "progress", "data-tone": tone, "data-over-cap": overCap || undefined, className: cn("flex flex-wrap gap-3", className), ...props, children: _jsxs(ProgressStateContext.Provider, { value: { scale, tone, overCap }, children: [children, _jsx(ProgressTrack, { children: _jsx(ProgressIndicator, {}) })] }) }));
37
+ return (_jsx(ProgressPrimitive.Root, { value: value, min: min, max: max, "data-slot": "progress", "data-tone": tone, "data-over-cap": overCap || undefined, className: cn("flex flex-wrap gap-3", className), ...props, children: _jsxs(ProgressStateContext.Provider, { value: { scale, tone, overCap, indicatorColor }, children: [children, _jsx(ProgressTrack, { children: _jsx(ProgressIndicator, {}) })] }) }));
38
38
  }
39
39
  function ProgressTrack({ className, ...props }) {
40
40
  return (_jsx(ProgressPrimitive.Track, { className: cn("relative flex h-1 w-full items-center overflow-x-hidden rounded-full bg-muted", className), "data-slot": "progress-track", ...props }));
41
41
  }
42
42
  function ProgressIndicator({ className, style, ...props }) {
43
- const { scale, tone, overCap } = useContext(ProgressStateContext);
43
+ const { scale, tone, overCap, indicatorColor } = useContext(ProgressStateContext);
44
44
  const indicatorStyle = (state) => {
45
45
  const resolvedStyle = typeof style === "function" ? style(state) : style;
46
46
  return {
47
47
  width: "100%",
48
48
  "--progress-scale": scale,
49
+ ...(indicatorColor ? { "--progress-indicator-color": indicatorColor } : {}),
49
50
  ...resolvedStyle,
50
51
  };
51
52
  };
52
- return (_jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", "data-over-cap": overCap || undefined, className: cn(progressIndicatorVariants({ tone }),
53
+ return (_jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", "data-over-cap": overCap || undefined, className: cn(progressIndicatorVariants({ tone }), indicatorColor && "bg-(--progress-indicator-color)",
53
54
  // After the variant, so the merge keeps this one paint: an allowance
54
55
  // spent reads the same whatever tone the product chose for approaching
55
56
  // it.
@@ -23,6 +23,7 @@ export type SettingsFactsSectionProps = Omit<ComponentPropsWithoutRef<"section">
23
23
  headingId: string;
24
24
  title: string;
25
25
  surface?: CardSurface;
26
+ factLayout?: "cells" | "plain";
26
27
  /**
27
28
  * The card's density. `sm` is the settings sidebar's compact card; a caller
28
29
  * that sits beside full-size cards passes the default so its title and
@@ -30,5 +31,5 @@ export type SettingsFactsSectionProps = Omit<ComponentPropsWithoutRef<"section">
30
31
  */
31
32
  size?: ComponentPropsWithoutRef<typeof Card>["size"];
32
33
  };
33
- export declare function SettingsFactsSection({ action, description, facts, footer, missingValueLabel, headingId, title, surface, size, ...props }: SettingsFactsSectionProps): import("react").JSX.Element;
34
+ export declare function SettingsFactsSection({ action, description, facts, footer, missingValueLabel, headingId, title, surface, factLayout, size, ...props }: SettingsFactsSectionProps): import("react").JSX.Element;
34
35
  //# sourceMappingURL=settings-facts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings-facts.d.ts","sourceRoot":"","sources":["../../src/components/settings-facts.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKjE,OAAO,EACL,IAAI,EAOJ,KAAK,WAAW,EACjB,MAAM,QAAQ,CAAC;AAEhB,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC1C,wBAAwB,CAAC,SAAS,CAAC,EACnC,UAAU,GAAG,WAAW,CACzB,GAAG;IACF,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;;OAIG;IACH,IAAI,CAAC,EAAE,wBAAwB,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;CACtD,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,KAAK,EACL,MAAM,EACN,iBAAiB,EACjB,SAAS,EACT,KAAK,EACL,OAAmB,EACnB,IAAW,EACX,GAAG,KAAK,EACT,EAAE,yBAAyB,+BA8C3B"}
1
+ {"version":3,"file":"settings-facts.d.ts","sourceRoot":"","sources":["../../src/components/settings-facts.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKjE,OAAO,EACL,IAAI,EAOJ,KAAK,WAAW,EACjB,MAAM,QAAQ,CAAC;AAEhB,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC1C,wBAAwB,CAAC,SAAS,CAAC,EACnC,UAAU,GAAG,WAAW,CACzB,GAAG;IACF,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,wBAAwB,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;CACtD,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,KAAK,EACL,MAAM,EACN,iBAAiB,EACjB,SAAS,EACT,KAAK,EACL,OAAmB,EACnB,UAAoB,EACpB,IAAW,EACX,GAAG,KAAK,EACT,EAAE,yBAAyB,+BAiE3B"}
@@ -1,7 +1,10 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Separator } from "./separator.js";
3
3
  import { cn } from "../lib/utils.js";
4
4
  import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "./card.js";
5
- export function SettingsFactsSection({ action, description, facts, footer, missingValueLabel, headingId, title, surface = "resting", size = "sm", ...props }) {
6
- return (_jsxs(Card, { render: _jsx("section", {}), ...props, "aria-labelledby": headingId, surface: surface, size: size, className: "min-w-0", children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: _jsx("h2", { id: headingId, tabIndex: -1, children: title }) }), description ? _jsx(CardDescription, { children: description }) : null, action ? _jsx(CardAction, { children: action }) : null] }), _jsx(Separator, {}), _jsx(CardContent, { children: _jsx("dl", { className: "grid min-w-0 grid-cols-1 gap-3 nc-type-body-sm sm:grid-cols-2", children: facts.map((fact) => (_jsxs(Card, { className: cn("min-w-0 gap-1 px-(--card-spacing)", fact.block && "col-span-full"), size: "sm", surface: "outlined", children: [_jsx("dt", { className: "text-xs text-muted-foreground", children: fact.label }), _jsx("dd", { className: cn("min-w-0 wrap-anywhere", fact.block && "whitespace-pre-wrap", (fact.value == null || fact.value === "") && "text-muted-foreground"), children: fact.value == null || fact.value === "" ? missingValueLabel : fact.value })] }, fact.label))) }) }), footer ? _jsx(CardFooter, { className: "flex-wrap gap-3", children: footer }) : null] }));
5
+ export function SettingsFactsSection({ action, description, facts, footer, missingValueLabel, headingId, title, surface = "resting", factLayout = "cells", size = "sm", ...props }) {
6
+ return (_jsxs(Card, { render: _jsx("section", {}), ...props, "aria-labelledby": headingId, surface: surface, size: size, className: "min-w-0", children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: _jsx("h2", { id: headingId, tabIndex: -1, children: title }) }), description ? _jsx(CardDescription, { children: description }) : null, action ? _jsx(CardAction, { children: action }) : null] }), _jsx(Separator, {}), _jsx(CardContent, { children: _jsx("dl", { className: cn("grid min-w-0 grid-cols-1 nc-type-body-sm sm:grid-cols-2", factLayout === "plain" ? "gap-x-8 gap-y-5" : "gap-3"), children: facts.map((fact) => {
7
+ const content = (_jsxs(_Fragment, { children: [_jsx("dt", { className: "text-xs text-muted-foreground", children: fact.label }), _jsx("dd", { className: cn("min-w-0 wrap-anywhere", fact.block && "whitespace-pre-wrap", (fact.value == null || fact.value === "") && "text-muted-foreground"), children: fact.value == null || fact.value === "" ? missingValueLabel : fact.value })] }));
8
+ return factLayout === "plain" ? (_jsx("div", { className: cn("flex min-w-0 flex-col gap-1", fact.block && "col-span-full"), children: content }, fact.label)) : (_jsx(Card, { className: cn("min-w-0 gap-1 px-(--card-spacing)", fact.block && "col-span-full"), size: "sm", surface: "outlined", children: content }, fact.label));
9
+ }) }) }), footer ? _jsx(CardFooter, { className: "flex-wrap gap-3", children: footer }) : null] }));
7
10
  }