@k2b/ui 0.50.0 → 0.51.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.
- package/dist/base.css +32 -1
- package/dist/browser/actions/Button.js.map +1 -1
- package/dist/browser/actions/CommandList.js +861 -0
- package/dist/browser/actions/CommandList.js.map +1 -0
- package/dist/browser/actions/CommandMenu.js +237 -0
- package/dist/browser/actions/CommandMenu.js.map +1 -0
- package/dist/browser/actions/Dropdown.js +43 -10
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/command-dock.js +47 -0
- package/dist/browser/actions/command-dock.js.map +1 -0
- package/dist/browser/actions/command-items.js +84 -0
- package/dist/browser/actions/command-items.js.map +1 -0
- package/dist/browser/actions/command-messages.js +42 -0
- package/dist/browser/actions/command-messages.js.map +1 -0
- package/dist/browser/actions/index.js +1 -0
- package/dist/browser/actions/index.js.map +1 -1
- package/dist/browser/charts/core/area.js +3 -5
- package/dist/browser/charts/core/area.js.map +1 -1
- package/dist/browser/charts/core/calendar.js +1 -1
- package/dist/browser/charts/core/calendar.js.map +1 -1
- package/dist/browser/charts/core/chart-messages.js +17 -0
- package/dist/browser/charts/core/chart-messages.js.map +1 -0
- package/dist/browser/charts/core/hbar-layout.js +118 -0
- package/dist/browser/charts/core/hbar-layout.js.map +1 -0
- package/dist/browser/charts/core/hbar.js +39 -0
- package/dist/browser/charts/core/hbar.js.map +1 -0
- package/dist/browser/charts/core/index.js +7 -2
- package/dist/browser/charts/core/index.js.map +1 -1
- package/dist/browser/charts/core/map.js +116 -0
- package/dist/browser/charts/core/map.js.map +1 -0
- package/dist/browser/charts/core/registry.js +22 -15
- package/dist/browser/charts/core/registry.js.map +1 -1
- package/dist/browser/charts/core/render-size.js +13 -0
- package/dist/browser/charts/core/render-size.js.map +1 -0
- package/dist/browser/charts/core/render.js +20 -10
- package/dist/browser/charts/core/render.js.map +1 -1
- package/dist/browser/charts/core/snapshot.js +3 -3
- package/dist/browser/charts/core/snapshot.js.map +1 -1
- package/dist/browser/charts/core/svg-renderers.js +2406 -0
- package/dist/browser/charts/core/svg-renderers.js.map +1 -0
- package/dist/browser/charts/core/svg.js +4 -2525
- package/dist/browser/charts/core/svg.js.map +1 -1
- package/dist/browser/charts/core/types.js +0 -2
- package/dist/browser/charts/core/types.js.map +1 -1
- package/dist/browser/charts/core/waterfall.js +162 -0
- package/dist/browser/charts/core/waterfall.js.map +1 -0
- package/dist/browser/charts/description.js +2 -0
- package/dist/browser/charts/description.js.map +1 -0
- package/dist/browser/charts.js.map +1 -1
- package/dist/browser/content/Chart.js +14 -628
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/ChartRoot.js +632 -0
- package/dist/browser/content/ChartRoot.js.map +1 -0
- package/dist/browser/content/ChartSparkline.js +24 -0
- package/dist/browser/content/ChartSparkline.js.map +1 -0
- package/dist/browser/content/FileView.js +111 -61
- package/dist/browser/content/FileView.js.map +1 -1
- package/dist/browser/content/Lightbox.js +8 -8
- package/dist/browser/content/Lightbox.js.map +1 -1
- package/dist/browser/content/MapView.js +30 -28
- package/dist/browser/content/MapView.js.map +1 -1
- package/dist/browser/content/PdfPreview.js +84 -52
- package/dist/browser/content/PdfPreview.js.map +1 -1
- package/dist/browser/content/PdfViewer.js +588 -0
- package/dist/browser/content/PdfViewer.js.map +1 -0
- package/dist/browser/content/chart-bar.js +246 -16
- package/dist/browser/content/chart-bar.js.map +1 -1
- package/dist/browser/content/chart-inspection-core.js +22 -21
- package/dist/browser/content/chart-inspection-core.js.map +1 -1
- package/dist/browser/content/chart-line-gaps.js +1 -1
- package/dist/browser/content/chart-line-gaps.js.map +1 -1
- package/dist/browser/content/chart-message-catalog.js +10 -0
- package/dist/browser/content/chart-message-catalog.js.map +1 -1
- package/dist/browser/content/chart-state-timeline.js +1 -1
- package/dist/browser/content/chart-state-timeline.js.map +1 -1
- package/dist/browser/content/chart-svg.js +2 -1
- package/dist/browser/content/chart-svg.js.map +1 -1
- package/dist/browser/content/index.js +1 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/pdf-document.js +29 -0
- package/dist/browser/content/pdf-document.js.map +1 -0
- package/dist/browser/content/pdf-limits.js +31 -0
- package/dist/browser/content/pdf-limits.js.map +1 -0
- package/dist/browser/content/pdf-messages.js +34 -2
- package/dist/browser/content/pdf-messages.js.map +1 -1
- package/dist/browser/content/pdf-viewer-engine.js +57 -0
- package/dist/browser/content/pdf-viewer-worker.js +28 -0
- package/dist/browser/inputs/ChoiceInputs.js +94 -51
- package/dist/browser/inputs/ChoiceInputs.js.map +1 -1
- package/dist/browser/inputs/ChoiceSlider.js +75 -58
- package/dist/browser/inputs/ChoiceSlider.js.map +1 -1
- package/dist/browser/inputs/DatePicker.js +113 -98
- package/dist/browser/inputs/DatePicker.js.map +1 -1
- package/dist/browser/inputs/PeriodPicker.js +874 -0
- package/dist/browser/inputs/PeriodPicker.js.map +1 -0
- package/dist/browser/inputs/index.js +4 -1
- package/dist/browser/inputs/index.js.map +1 -1
- package/dist/browser/inputs/input-messages.js +8 -2
- package/dist/browser/inputs/input-messages.js.map +1 -1
- package/dist/browser/inputs/markdown/MarkdownEditor.js +14 -10
- package/dist/browser/inputs/markdown/MarkdownEditor.js.map +1 -1
- package/dist/browser/inputs/markdown/SlashCommands.js +402 -0
- package/dist/browser/inputs/markdown/SlashCommands.js.map +1 -0
- package/dist/browser/inputs/period-picker-messages.js +71 -0
- package/dist/browser/inputs/period-picker-messages.js.map +1 -0
- package/dist/browser/inputs/period.js +263 -0
- package/dist/browser/inputs/period.js.map +1 -0
- package/dist/browser/layout/DetailPanel.js +147 -120
- package/dist/browser/layout/DetailPanel.js.map +1 -1
- package/dist/browser/layout/Discussion.js +101 -108
- package/dist/browser/layout/Discussion.js.map +1 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/surfaces/DescriptionList.js +5 -2
- package/dist/browser/surfaces/DescriptionList.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +19 -14
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- package/dist/browser/surfaces/delta-badge.js +16 -2
- package/dist/browser/surfaces/delta-badge.js.map +1 -1
- package/dist/browser/widgets/DashboardFrame.js +310 -0
- package/dist/browser/widgets/DashboardFrame.js.map +1 -0
- package/dist/browser/widgets/index.js +1 -0
- package/dist/browser/widgets/index.js.map +1 -1
- package/dist/licenses/pdfjs-dist.txt +177 -0
- package/dist/ssr/actions/Button.js.map +1 -1
- package/dist/ssr/actions/CommandList.js +638 -0
- package/dist/ssr/actions/CommandList.js.map +1 -0
- package/dist/ssr/actions/CommandMenu.js +197 -0
- package/dist/ssr/actions/CommandMenu.js.map +1 -0
- package/dist/ssr/actions/Dropdown.js +43 -10
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/command-dock.js +47 -0
- package/dist/ssr/actions/command-dock.js.map +1 -0
- package/dist/ssr/actions/command-items.js +84 -0
- package/dist/ssr/actions/command-items.js.map +1 -0
- package/dist/ssr/actions/command-messages.js +42 -0
- package/dist/ssr/actions/command-messages.js.map +1 -0
- package/dist/ssr/actions/index.js +1 -0
- package/dist/ssr/actions/index.js.map +1 -1
- package/dist/ssr/charts/core/area.js +3 -5
- package/dist/ssr/charts/core/area.js.map +1 -1
- package/dist/ssr/charts/core/calendar.js +1 -1
- package/dist/ssr/charts/core/calendar.js.map +1 -1
- package/dist/ssr/charts/core/chart-messages.js +17 -0
- package/dist/ssr/charts/core/chart-messages.js.map +1 -0
- package/dist/ssr/charts/core/hbar-layout.js +118 -0
- package/dist/ssr/charts/core/hbar-layout.js.map +1 -0
- package/dist/ssr/charts/core/hbar.js +39 -0
- package/dist/ssr/charts/core/hbar.js.map +1 -0
- package/dist/ssr/charts/core/index.js +7 -2
- package/dist/ssr/charts/core/index.js.map +1 -1
- package/dist/ssr/charts/core/map.js +116 -0
- package/dist/ssr/charts/core/map.js.map +1 -0
- package/dist/ssr/charts/core/registry.js +22 -15
- package/dist/ssr/charts/core/registry.js.map +1 -1
- package/dist/ssr/charts/core/render-size.js +13 -0
- package/dist/ssr/charts/core/render-size.js.map +1 -0
- package/dist/ssr/charts/core/render.js +20 -10
- package/dist/ssr/charts/core/render.js.map +1 -1
- package/dist/ssr/charts/core/snapshot.js +3 -3
- package/dist/ssr/charts/core/snapshot.js.map +1 -1
- package/dist/ssr/charts/core/svg-renderers.js +2406 -0
- package/dist/ssr/charts/core/svg-renderers.js.map +1 -0
- package/dist/ssr/charts/core/svg.js +4 -2525
- package/dist/ssr/charts/core/svg.js.map +1 -1
- package/dist/ssr/charts/core/types.js +0 -2
- package/dist/ssr/charts/core/types.js.map +1 -1
- package/dist/ssr/charts/core/waterfall.js +162 -0
- package/dist/ssr/charts/core/waterfall.js.map +1 -0
- package/dist/ssr/charts/description.js +2 -0
- package/dist/ssr/charts/description.js.map +1 -0
- package/dist/ssr/charts.js.map +1 -1
- package/dist/ssr/content/Chart.js +14 -471
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/ChartRoot.js +475 -0
- package/dist/ssr/content/ChartRoot.js.map +1 -0
- package/dist/ssr/content/ChartSparkline.js +24 -0
- package/dist/ssr/content/ChartSparkline.js.map +1 -0
- package/dist/ssr/content/FileView.js +56 -7
- package/dist/ssr/content/FileView.js.map +1 -1
- package/dist/ssr/content/Lightbox.js +8 -8
- package/dist/ssr/content/Lightbox.js.map +1 -1
- package/dist/ssr/content/MapView.js +9 -9
- package/dist/ssr/content/MapView.js.map +1 -1
- package/dist/ssr/content/PdfPreview.js +49 -20
- package/dist/ssr/content/PdfPreview.js.map +1 -1
- package/dist/ssr/content/PdfViewer.js +484 -0
- package/dist/ssr/content/PdfViewer.js.map +1 -0
- package/dist/ssr/content/chart-bar.js +246 -16
- package/dist/ssr/content/chart-bar.js.map +1 -1
- package/dist/ssr/content/chart-inspection-core.js +22 -21
- package/dist/ssr/content/chart-inspection-core.js.map +1 -1
- package/dist/ssr/content/chart-line-gaps.js +1 -1
- package/dist/ssr/content/chart-line-gaps.js.map +1 -1
- package/dist/ssr/content/chart-message-catalog.js +10 -0
- package/dist/ssr/content/chart-message-catalog.js.map +1 -1
- package/dist/ssr/content/chart-state-timeline.js +1 -1
- package/dist/ssr/content/chart-state-timeline.js.map +1 -1
- package/dist/ssr/content/chart-svg.js +2 -1
- package/dist/ssr/content/chart-svg.js.map +1 -1
- package/dist/ssr/content/index.js +1 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/pdf-document.js +29 -0
- package/dist/ssr/content/pdf-document.js.map +1 -0
- package/dist/ssr/content/pdf-limits.js +31 -0
- package/dist/ssr/content/pdf-limits.js.map +1 -0
- package/dist/ssr/content/pdf-messages.js +34 -2
- package/dist/ssr/content/pdf-messages.js.map +1 -1
- package/dist/ssr/inputs/ChoiceInputs.js +49 -12
- package/dist/ssr/inputs/ChoiceInputs.js.map +1 -1
- package/dist/ssr/inputs/ChoiceSlider.js +17 -12
- package/dist/ssr/inputs/ChoiceSlider.js.map +1 -1
- package/dist/ssr/inputs/DatePicker.js +14 -9
- package/dist/ssr/inputs/DatePicker.js.map +1 -1
- package/dist/ssr/inputs/PeriodPicker.js +598 -0
- package/dist/ssr/inputs/PeriodPicker.js.map +1 -0
- package/dist/ssr/inputs/index.js +4 -1
- package/dist/ssr/inputs/index.js.map +1 -1
- package/dist/ssr/inputs/input-messages.js +8 -2
- package/dist/ssr/inputs/input-messages.js.map +1 -1
- package/dist/ssr/inputs/markdown/MarkdownEditor.js +3 -2
- package/dist/ssr/inputs/markdown/MarkdownEditor.js.map +1 -1
- package/dist/ssr/inputs/markdown/SlashCommands.js +339 -0
- package/dist/ssr/inputs/markdown/SlashCommands.js.map +1 -0
- package/dist/ssr/inputs/period-picker-messages.js +71 -0
- package/dist/ssr/inputs/period-picker-messages.js.map +1 -0
- package/dist/ssr/inputs/period.js +263 -0
- package/dist/ssr/inputs/period.js.map +1 -0
- package/dist/ssr/layout/DetailPanel.js +27 -4
- package/dist/ssr/layout/DetailPanel.js.map +1 -1
- package/dist/ssr/layout/Discussion.js +16 -2
- package/dist/ssr/layout/Discussion.js.map +1 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/surfaces/DescriptionList.js +1 -1
- package/dist/ssr/surfaces/DescriptionList.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +4 -5
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- package/dist/ssr/surfaces/delta-badge.js +16 -2
- package/dist/ssr/surfaces/delta-badge.js.map +1 -1
- package/dist/ssr/widgets/DashboardFrame.js +200 -0
- package/dist/ssr/widgets/DashboardFrame.js.map +1 -0
- package/dist/ssr/widgets/index.js +1 -0
- package/dist/ssr/widgets/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/Button.d.ts +1 -1
- package/dist/types/actions/CommandList.d.ts +120 -0
- package/dist/types/actions/CommandMenu.d.ts +39 -0
- package/dist/types/actions/Dropdown.d.ts +17 -0
- package/dist/types/actions/command-dock.d.ts +8 -0
- package/dist/types/actions/command-items.d.ts +134 -0
- package/dist/types/actions/command-messages.d.ts +19 -0
- package/dist/types/actions/index.d.ts +3 -0
- package/dist/types/charts/core/calendar.d.ts +1 -1
- package/dist/types/charts/core/chart-messages.d.ts +5 -0
- package/dist/types/charts/core/hbar-layout.d.ts +74 -0
- package/dist/types/charts/core/hbar.d.ts +13 -0
- package/dist/types/charts/core/index.d.ts +7 -2
- package/dist/types/charts/core/map.d.ts +3 -0
- package/dist/types/charts/core/registry.d.ts +17 -11
- package/dist/types/charts/core/render-size.d.ts +7 -0
- package/dist/types/charts/core/render.d.ts +1 -4
- package/dist/types/charts/core/snapshot.d.ts +2 -2
- package/dist/types/charts/core/svg-renderers.d.ts +722 -0
- package/dist/types/charts/core/svg.d.ts +4 -698
- package/dist/types/charts/core/types.d.ts +1 -12
- package/dist/types/charts/core/waterfall.d.ts +68 -0
- package/dist/types/charts/description.d.ts +226 -0
- package/dist/types/charts.d.ts +1 -0
- package/dist/types/content/Chart.d.ts +3 -91
- package/dist/types/content/ChartRoot.d.ts +92 -0
- package/dist/types/content/ChartSparkline.d.ts +5 -0
- package/dist/types/content/PdfViewer.d.ts +32 -0
- package/dist/types/content/chart-bar.d.ts +95 -2
- package/dist/types/content/index.d.ts +2 -0
- package/dist/types/content/pdf-document.d.ts +5 -0
- package/dist/types/content/pdf-engine.d.ts +9 -0
- package/dist/types/content/pdf-limits.d.ts +43 -0
- package/dist/types/content/pdf-messages.d.ts +16 -0
- package/dist/types/inputs/ChoiceInputs.d.ts +4 -0
- package/dist/types/inputs/ChoiceSlider.d.ts +12 -0
- package/dist/types/inputs/DatePicker.d.ts +22 -0
- package/dist/types/inputs/PeriodPicker.d.ts +24 -0
- package/dist/types/inputs/index.d.ts +8 -2
- package/dist/types/inputs/input-messages.d.ts +3 -0
- package/dist/types/inputs/markdown/MarkdownEditor.d.ts +5 -0
- package/dist/types/inputs/markdown/SlashCommands.d.ts +20 -0
- package/dist/types/inputs/period-picker-messages.d.ts +34 -0
- package/dist/types/inputs/period.d.ts +134 -0
- package/dist/types/layout/DetailPanel.d.ts +12 -0
- package/dist/types/layout/index.d.ts +1 -1
- package/dist/types/surfaces/DescriptionList.d.ts +5 -0
- package/dist/types/surfaces/StatCell.d.ts +6 -1
- package/dist/types/widgets/DashboardFrame.d.ts +58 -0
- package/dist/types/widgets/index.d.ts +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { dates } from "@k2b/stdlib";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A period as an app stores it: a preset key that stays relative ("this month" is next month's month too), or two
|
|
5
|
+
* explicit days. Days are date keys such as `2026-11-01`; `end` is inclusive.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Inclusive days of a period. `null` is an open edge, for example "All time" without a known first day. */
|
|
9
|
+
|
|
10
|
+
/** What a preset resolves against: today in the period's time zone and the first day of the week. */
|
|
11
|
+
|
|
12
|
+
/** The clock a period is resolved with. Server and browser pass the same values so the first render agrees. */
|
|
13
|
+
|
|
14
|
+
const keyDate = key => new Date(`${key}T00:00:00Z`);
|
|
15
|
+
const dateKeyOf = date => date.toISOString().slice(0, 10);
|
|
16
|
+
const day = (year, month, date) => dateKeyOf(new Date(Date.UTC(year, month, date)));
|
|
17
|
+
const parts = key => ({
|
|
18
|
+
year: Number(key.slice(0, 4)),
|
|
19
|
+
month: Number(key.slice(5, 7)) - 1,
|
|
20
|
+
date: Number(key.slice(8, 10))
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/** Adds whole days to a date key; calendar days, so a DST change never moves it. */
|
|
24
|
+
export const addPeriodDays = (key, count) => {
|
|
25
|
+
const date = keyDate(key);
|
|
26
|
+
date.setUTCDate(date.getUTCDate() + count);
|
|
27
|
+
return dateKeyOf(date);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Number of days in an inclusive range of date keys. */
|
|
31
|
+
export const periodDayCount = range => Math.round((keyDate(range.end).getTime() - keyDate(range.start).getTime()) / 86_400_000) + 1;
|
|
32
|
+
const month = (key, offset) => {
|
|
33
|
+
const {
|
|
34
|
+
year,
|
|
35
|
+
month
|
|
36
|
+
} = parts(key);
|
|
37
|
+
return {
|
|
38
|
+
start: day(year, month + offset, 1),
|
|
39
|
+
end: day(year, month + offset + 1, 0)
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
const quarter = (key, offset) => {
|
|
43
|
+
const {
|
|
44
|
+
year,
|
|
45
|
+
month
|
|
46
|
+
} = parts(key);
|
|
47
|
+
const first = Math.floor(month / 3) * 3 + offset * 3;
|
|
48
|
+
return {
|
|
49
|
+
start: day(year, first, 1),
|
|
50
|
+
end: day(year, first + 3, 0)
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const year = (key, offset) => {
|
|
54
|
+
const value = parts(key).year + offset;
|
|
55
|
+
return {
|
|
56
|
+
start: `${value}-01-01`,
|
|
57
|
+
end: `${value}-12-31`
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const week = (context, offset) => {
|
|
61
|
+
const weekday = keyDate(context.today).getUTCDay();
|
|
62
|
+
const start = addPeriodDays(context.today, -((weekday - context.weekStartsOn + 7) % 7) + offset * 7);
|
|
63
|
+
return {
|
|
64
|
+
start,
|
|
65
|
+
end: addPeriodDays(start, 6)
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Built-in presets. Each covers its whole calendar period ("This month" is the 1st to the last day, not up to
|
|
71
|
+
* today) in the period's time zone; weeks start on the context's first day of the week.
|
|
72
|
+
*/
|
|
73
|
+
export const periodPresets = {
|
|
74
|
+
today: {
|
|
75
|
+
key: "today",
|
|
76
|
+
resolve: ({
|
|
77
|
+
today
|
|
78
|
+
}) => ({
|
|
79
|
+
start: today,
|
|
80
|
+
end: today
|
|
81
|
+
})
|
|
82
|
+
},
|
|
83
|
+
yesterday: {
|
|
84
|
+
key: "yesterday",
|
|
85
|
+
resolve: ({
|
|
86
|
+
today
|
|
87
|
+
}) => ({
|
|
88
|
+
start: addPeriodDays(today, -1),
|
|
89
|
+
end: addPeriodDays(today, -1)
|
|
90
|
+
})
|
|
91
|
+
},
|
|
92
|
+
thisWeek: {
|
|
93
|
+
key: "this-week",
|
|
94
|
+
resolve: context => week(context, 0)
|
|
95
|
+
},
|
|
96
|
+
lastWeek: {
|
|
97
|
+
key: "last-week",
|
|
98
|
+
resolve: context => week(context, -1)
|
|
99
|
+
},
|
|
100
|
+
thisMonth: {
|
|
101
|
+
key: "this-month",
|
|
102
|
+
resolve: ({
|
|
103
|
+
today
|
|
104
|
+
}) => month(today, 0)
|
|
105
|
+
},
|
|
106
|
+
lastMonth: {
|
|
107
|
+
key: "last-month",
|
|
108
|
+
resolve: ({
|
|
109
|
+
today
|
|
110
|
+
}) => month(today, -1)
|
|
111
|
+
},
|
|
112
|
+
thisQuarter: {
|
|
113
|
+
key: "this-quarter",
|
|
114
|
+
resolve: ({
|
|
115
|
+
today
|
|
116
|
+
}) => quarter(today, 0)
|
|
117
|
+
},
|
|
118
|
+
lastQuarter: {
|
|
119
|
+
key: "last-quarter",
|
|
120
|
+
resolve: ({
|
|
121
|
+
today
|
|
122
|
+
}) => quarter(today, -1)
|
|
123
|
+
},
|
|
124
|
+
thisYear: {
|
|
125
|
+
key: "this-year",
|
|
126
|
+
resolve: ({
|
|
127
|
+
today
|
|
128
|
+
}) => year(today, 0)
|
|
129
|
+
},
|
|
130
|
+
lastYear: {
|
|
131
|
+
key: "last-year",
|
|
132
|
+
resolve: ({
|
|
133
|
+
today
|
|
134
|
+
}) => year(today, -1)
|
|
135
|
+
},
|
|
136
|
+
/** Everything up to today; `since` is the first day with data when the app knows it, else the start stays open. */
|
|
137
|
+
all: (options = {}) => ({
|
|
138
|
+
key: "all",
|
|
139
|
+
resolve: ({
|
|
140
|
+
today
|
|
141
|
+
}) => ({
|
|
142
|
+
start: options.since ?? null,
|
|
143
|
+
end: today
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
const dateKeyPattern = /^\d{4}-\d{2}-\d{2}$/;
|
|
148
|
+
/** A real calendar day key, not only the shape (`2026-02-30` is refused). */
|
|
149
|
+
export const isPeriodDay = value => {
|
|
150
|
+
if (typeof value !== "string" || !dateKeyPattern.test(value)) return false;
|
|
151
|
+
const date = keyDate(value);
|
|
152
|
+
return !Number.isNaN(date.getTime()) && dateKeyOf(date) === value;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/** Accepts a stored or URL value only when it is a known preset key or two real days in order. */
|
|
156
|
+
export const parsePeriodValue = (value, presets) => {
|
|
157
|
+
if (!value || typeof value !== "object") return undefined;
|
|
158
|
+
const candidate = value;
|
|
159
|
+
if (typeof candidate.preset === "string") return presets.some(preset => preset.key === candidate.preset) ? {
|
|
160
|
+
preset: candidate.preset
|
|
161
|
+
} : undefined;
|
|
162
|
+
if (isPeriodDay(candidate.start) && isPeriodDay(candidate.end) && candidate.start <= candidate.end) return {
|
|
163
|
+
start: candidate.start,
|
|
164
|
+
end: candidate.end
|
|
165
|
+
};
|
|
166
|
+
return undefined;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** The context presets resolve against: today in the clock's time zone. */
|
|
170
|
+
export const periodContext = (clock = {}) => ({
|
|
171
|
+
today: dates.formatDateKey(clock.now ?? new Date(), {
|
|
172
|
+
timeZone: clock.timeZone
|
|
173
|
+
}),
|
|
174
|
+
weekStartsOn: clock.weekStartsOn ?? clock.firstDayOfWeek ?? 1
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Resolves a value to inclusive days. Returns `undefined` for a preset key the list does not contain, so a stored
|
|
179
|
+
* period that no longer exists is never silently replaced.
|
|
180
|
+
*/
|
|
181
|
+
export const resolvePeriod = (value, presets, clock = {}) => {
|
|
182
|
+
if (!("preset" in value)) return {
|
|
183
|
+
start: value.start,
|
|
184
|
+
end: value.end
|
|
185
|
+
};
|
|
186
|
+
return presets.find(preset => preset.key === value.preset)?.resolve(periodContext(clock));
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The instants a query uses for a resolved period: `from` is the start of the first day and `to` the start of the
|
|
191
|
+
* day after the last one (exclusive), both in the time zone. Days are never assumed to last 24 hours.
|
|
192
|
+
*/
|
|
193
|
+
export const periodInstants = (range, timeZone) => {
|
|
194
|
+
const midnight = key => dates.zonedDateTimeToInstant(`${key}T00:00`, timeZone, {
|
|
195
|
+
disambiguation: "compatible"
|
|
196
|
+
});
|
|
197
|
+
return {
|
|
198
|
+
from: range.start ? midnight(range.start) : null,
|
|
199
|
+
to: range.end ? midnight(addPeriodDays(range.end, 1)) : null
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
const utcFormat = (locale, options) => new Intl.DateTimeFormat(locale, {
|
|
203
|
+
...options,
|
|
204
|
+
timeZone: "UTC"
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Short days of a preset, for the list and the trigger: "Sat, Nov 7", "Nov 1 – 30", "2025", "since 3/14/2019".
|
|
209
|
+
* The year is added only when the period is not in today's year.
|
|
210
|
+
*/
|
|
211
|
+
export const formatPeriodDays = (range, today, locale, since) => {
|
|
212
|
+
if (!range.start) return "";
|
|
213
|
+
if (!range.end) return since(utcFormat(locale, {
|
|
214
|
+
day: "2-digit",
|
|
215
|
+
month: "2-digit",
|
|
216
|
+
year: "numeric"
|
|
217
|
+
}).format(keyDate(range.start)));
|
|
218
|
+
const start = keyDate(range.start);
|
|
219
|
+
const end = keyDate(range.end);
|
|
220
|
+
const sameYear = range.start.slice(0, 4) === range.end.slice(0, 4);
|
|
221
|
+
if (sameYear && range.start.endsWith("-01-01") && range.end.endsWith("-12-31")) return range.start.slice(0, 4);
|
|
222
|
+
if (range.end === today && range.start.slice(0, 4) !== today.slice(0, 4)) return since(utcFormat(locale, {
|
|
223
|
+
day: "2-digit",
|
|
224
|
+
month: "2-digit",
|
|
225
|
+
year: "numeric"
|
|
226
|
+
}).format(start));
|
|
227
|
+
const withYear = !sameYear || range.start.slice(0, 4) !== today.slice(0, 4);
|
|
228
|
+
if (range.start === range.end) return utcFormat(locale, {
|
|
229
|
+
weekday: "short",
|
|
230
|
+
day: "numeric",
|
|
231
|
+
month: "short",
|
|
232
|
+
...(withYear ? {
|
|
233
|
+
year: "numeric"
|
|
234
|
+
} : {})
|
|
235
|
+
}).format(start);
|
|
236
|
+
return utcFormat(locale, {
|
|
237
|
+
day: "numeric",
|
|
238
|
+
month: "short",
|
|
239
|
+
...(withYear ? {
|
|
240
|
+
year: "numeric"
|
|
241
|
+
} : {})
|
|
242
|
+
}).formatRange(start, end);
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
/** Explicit days as numbers with the year: "01.–07.11.2026" in German, "11/1/2026 – 11/7/2026" in English. */
|
|
246
|
+
export const formatPeriodRange = (range, locale) => {
|
|
247
|
+
const format = utcFormat(locale, {
|
|
248
|
+
day: "2-digit",
|
|
249
|
+
month: "2-digit",
|
|
250
|
+
year: "numeric"
|
|
251
|
+
});
|
|
252
|
+
return range.start === range.end ? format.format(keyDate(range.start)) : format.formatRange(keyDate(range.start), keyDate(range.end));
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
/** The widest explicit range within today's year, all of it (two-digit days, a three-digit count), so a trigger can reserve its width. */
|
|
256
|
+
export const widePeriodRangeSample = today => {
|
|
257
|
+
const year = today.slice(0, 4);
|
|
258
|
+
return {
|
|
259
|
+
start: `${year}-01-01`,
|
|
260
|
+
end: `${year}-12-31`
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
//# sourceMappingURL=period.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/period.ts"],"sourcesContent":["import { dates } from \"@k2b/stdlib\";\n\n/**\n * A period as an app stores it: a preset key that stays relative (\"this month\" is next month's month too), or two\n * explicit days. Days are date keys such as `2026-11-01`; `end` is inclusive.\n */\nexport type PeriodValue = { preset: string } | { start: string; end: string };\n\n/** Inclusive days of a period. `null` is an open edge, for example \"All time\" without a known first day. */\nexport type PeriodRange = { start: string | null; end: string | null };\n\n/** What a preset resolves against: today in the period's time zone and the first day of the week. */\nexport type PeriodContext = { today: string; weekStartsOn: 0 | 1 };\n\nexport type PeriodPreset = {\n key: string;\n /** Shown in the list and the trigger. Built-in presets bring a translated label; app presets name their own. */\n label?: string;\n resolve: (context: PeriodContext) => PeriodRange;\n};\n\n/** The clock a period is resolved with. Server and browser pass the same values so the first render agrees. */\nexport type PeriodClock = {\n /** The instant \"today\" is read from; defaults to now. */\n now?: Date;\n /** IANA time zone the days belong to, for example a base's zone; defaults to the runtime zone. */\n timeZone?: string;\n /** First day of the week, as in the calendar's date config; Monday by default. */\n weekStartsOn?: 0 | 1;\n /** Alias of `weekStartsOn`, accepted from a shared date config. */\n firstDayOfWeek?: 0 | 1;\n};\n\nconst keyDate = (key: string): Date => new Date(`${key}T00:00:00Z`);\nconst dateKeyOf = (date: Date): string => date.toISOString().slice(0, 10);\nconst day = (year: number, month: number, date: number): string => dateKeyOf(new Date(Date.UTC(year, month, date)));\nconst parts = (key: string) => ({ year: Number(key.slice(0, 4)), month: Number(key.slice(5, 7)) - 1, date: Number(key.slice(8, 10)) });\n\n/** Adds whole days to a date key; calendar days, so a DST change never moves it. */\nexport const addPeriodDays = (key: string, count: number): string => {\n const date = keyDate(key);\n date.setUTCDate(date.getUTCDate() + count);\n return dateKeyOf(date);\n};\n\n/** Number of days in an inclusive range of date keys. */\nexport const periodDayCount = (range: { start: string; end: string }): number =>\n Math.round((keyDate(range.end).getTime() - keyDate(range.start).getTime()) / 86_400_000) + 1;\n\nconst month = (key: string, offset: number): PeriodRange => {\n const { year, month } = parts(key);\n return { start: day(year, month + offset, 1), end: day(year, month + offset + 1, 0) };\n};\nconst quarter = (key: string, offset: number): PeriodRange => {\n const { year, month } = parts(key);\n const first = Math.floor(month / 3) * 3 + offset * 3;\n return { start: day(year, first, 1), end: day(year, first + 3, 0) };\n};\nconst year = (key: string, offset: number): PeriodRange => {\n const value = parts(key).year + offset;\n return { start: `${value}-01-01`, end: `${value}-12-31` };\n};\nconst week = (context: PeriodContext, offset: number): PeriodRange => {\n const weekday = keyDate(context.today).getUTCDay();\n const start = addPeriodDays(context.today, -((weekday - context.weekStartsOn + 7) % 7) + offset * 7);\n return { start, end: addPeriodDays(start, 6) };\n};\n\n/**\n * Built-in presets. Each covers its whole calendar period (\"This month\" is the 1st to the last day, not up to\n * today) in the period's time zone; weeks start on the context's first day of the week.\n */\nexport const periodPresets = {\n today: { key: \"today\", resolve: ({ today }) => ({ start: today, end: today }) },\n yesterday: { key: \"yesterday\", resolve: ({ today }) => ({ start: addPeriodDays(today, -1), end: addPeriodDays(today, -1) }) },\n thisWeek: { key: \"this-week\", resolve: (context) => week(context, 0) },\n lastWeek: { key: \"last-week\", resolve: (context) => week(context, -1) },\n thisMonth: { key: \"this-month\", resolve: ({ today }) => month(today, 0) },\n lastMonth: { key: \"last-month\", resolve: ({ today }) => month(today, -1) },\n thisQuarter: { key: \"this-quarter\", resolve: ({ today }) => quarter(today, 0) },\n lastQuarter: { key: \"last-quarter\", resolve: ({ today }) => quarter(today, -1) },\n thisYear: { key: \"this-year\", resolve: ({ today }) => year(today, 0) },\n lastYear: { key: \"last-year\", resolve: ({ today }) => year(today, -1) },\n /** Everything up to today; `since` is the first day with data when the app knows it, else the start stays open. */\n all: (options: { since?: string | null } = {}): PeriodPreset => ({\n key: \"all\",\n resolve: ({ today }) => ({ start: options.since ?? null, end: today }),\n }),\n} satisfies Record<string, PeriodPreset | ((options?: { since?: string | null }) => PeriodPreset)>;\n\nconst dateKeyPattern = /^\\d{4}-\\d{2}-\\d{2}$/;\n/** A real calendar day key, not only the shape (`2026-02-30` is refused). */\nexport const isPeriodDay = (value: unknown): value is string => {\n if (typeof value !== \"string\" || !dateKeyPattern.test(value)) return false;\n const date = keyDate(value);\n return !Number.isNaN(date.getTime()) && dateKeyOf(date) === value;\n};\n\n/** Accepts a stored or URL value only when it is a known preset key or two real days in order. */\nexport const parsePeriodValue = (value: unknown, presets: readonly PeriodPreset[]): PeriodValue | undefined => {\n if (!value || typeof value !== \"object\") return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.preset === \"string\")\n return presets.some((preset) => preset.key === candidate.preset) ? { preset: candidate.preset } : undefined;\n if (isPeriodDay(candidate.start) && isPeriodDay(candidate.end) && candidate.start <= candidate.end)\n return { start: candidate.start, end: candidate.end };\n return undefined;\n};\n\n/** The context presets resolve against: today in the clock's time zone. */\nexport const periodContext = (clock: PeriodClock = {}): PeriodContext => ({\n today: dates.formatDateKey(clock.now ?? new Date(), { timeZone: clock.timeZone }),\n weekStartsOn: clock.weekStartsOn ?? clock.firstDayOfWeek ?? 1,\n});\n\n/**\n * Resolves a value to inclusive days. Returns `undefined` for a preset key the list does not contain, so a stored\n * period that no longer exists is never silently replaced.\n */\nexport const resolvePeriod = (value: PeriodValue, presets: readonly PeriodPreset[], clock: PeriodClock = {}): PeriodRange | undefined => {\n if (!(\"preset\" in value)) return { start: value.start, end: value.end };\n return presets.find((preset) => preset.key === value.preset)?.resolve(periodContext(clock));\n};\n\n/**\n * The instants a query uses for a resolved period: `from` is the start of the first day and `to` the start of the\n * day after the last one (exclusive), both in the time zone. Days are never assumed to last 24 hours.\n */\nexport const periodInstants = (range: PeriodRange, timeZone: string): { from: string | null; to: string | null } => {\n const midnight = (key: string) => dates.zonedDateTimeToInstant(`${key}T00:00`, timeZone, { disambiguation: \"compatible\" });\n return { from: range.start ? midnight(range.start) : null, to: range.end ? midnight(addPeriodDays(range.end, 1)) : null };\n};\n\nconst utcFormat = (locale: string, options: Intl.DateTimeFormatOptions) => new Intl.DateTimeFormat(locale, { ...options, timeZone: \"UTC\" });\n\n/**\n * Short days of a preset, for the list and the trigger: \"Sat, Nov 7\", \"Nov 1 – 30\", \"2025\", \"since 3/14/2019\".\n * The year is added only when the period is not in today's year.\n */\nexport const formatPeriodDays = (range: PeriodRange, today: string, locale: string, since: (date: string) => string): string => {\n if (!range.start) return \"\";\n if (!range.end) return since(utcFormat(locale, { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" }).format(keyDate(range.start)));\n const start = keyDate(range.start);\n const end = keyDate(range.end);\n const sameYear = range.start.slice(0, 4) === range.end.slice(0, 4);\n if (sameYear && range.start.endsWith(\"-01-01\") && range.end.endsWith(\"-12-31\")) return range.start.slice(0, 4);\n if (range.end === today && range.start.slice(0, 4) !== today.slice(0, 4))\n return since(utcFormat(locale, { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" }).format(start));\n const withYear = !sameYear || range.start.slice(0, 4) !== today.slice(0, 4);\n if (range.start === range.end)\n return utcFormat(locale, { weekday: \"short\", day: \"numeric\", month: \"short\", ...(withYear ? { year: \"numeric\" } : {}) }).format(start);\n return utcFormat(locale, { day: \"numeric\", month: \"short\", ...(withYear ? { year: \"numeric\" } : {}) }).formatRange(start, end);\n};\n\n/** Explicit days as numbers with the year: \"01.–07.11.2026\" in German, \"11/1/2026 – 11/7/2026\" in English. */\nexport const formatPeriodRange = (range: { start: string; end: string }, locale: string): string => {\n const format = utcFormat(locale, { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" });\n return range.start === range.end ? format.format(keyDate(range.start)) : format.formatRange(keyDate(range.start), keyDate(range.end));\n};\n\n/** The widest explicit range within today's year, all of it (two-digit days, a three-digit count), so a trigger can reserve its width. */\nexport const widePeriodRangeSample = (today: string): { start: string; end: string } => {\n const year = today.slice(0, 4);\n return { start: `${year}-01-01`, end: `${year}-12-31` };\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -27,7 +27,7 @@ var _tmpl$ = "<i class=\"ti ti-dots\" aria-hidden=\"true\"></i>",
|
|
|
27
27
|
_tmpl$19 = ["<span class=\"k2b-detail-panel__action-description\">", "</span>"],
|
|
28
28
|
_tmpl$20 = ["<span class=\"k2b-detail-panel__action-copy\"><span class=\"k2b-detail-panel__action-title\">", "</span>", "</span>"],
|
|
29
29
|
_tmpl$21 = ["<span class=\"k2b-detail-panel__action-trailing\">", "</span>"],
|
|
30
|
-
_tmpl$22 = ["<div class=\"k2b-detail-panel__action-row\">", "", "", "</div>"],
|
|
30
|
+
_tmpl$22 = ["<div class=\"k2b-detail-panel__action-row\"", ">", "", "", "", "</div>"],
|
|
31
31
|
_tmpl$23 = ["<i", " aria-hidden=\"true\"></i>"],
|
|
32
32
|
_tmpl$24 = ["<span class=\"k2b-detail-panel__section-preview k2b-truncate-fade\">", "</span>"],
|
|
33
33
|
_tmpl$25 = ["<span class=\"k2b-detail-panel__section-description\">", "</span>"],
|
|
@@ -42,11 +42,17 @@ var _tmpl$ = "<i class=\"ti ti-dots\" aria-hidden=\"true\"></i>",
|
|
|
42
42
|
import { children, createEffect, createSignal, createUniqueId, Show, splitProps } from "solid-js";
|
|
43
43
|
import { Button, ButtonLink, IconButton } from "../actions/Button";
|
|
44
44
|
import { Dropdown } from "../actions/Dropdown";
|
|
45
|
+
import { Checkbox } from "../inputs/Checkbox";
|
|
45
46
|
import { useDetailPanelMessages } from "./detail-panel-messages";
|
|
46
47
|
import { createScrollFade } from "./scroll-fade";
|
|
47
48
|
|
|
48
49
|
/** One direct secondary command, rendered as a sibling icon button at the end of the row. */
|
|
49
50
|
|
|
51
|
+
/**
|
|
52
|
+
* A checkbox before the row that toggles on its own, such as "done" for a task the row opens. It always shows its
|
|
53
|
+
* state, unlike a secondary action, which waits for hover.
|
|
54
|
+
*/
|
|
55
|
+
|
|
50
56
|
/** A row that only shows something, such as a person and their role: the columns of an action, without a command. */
|
|
51
57
|
|
|
52
58
|
const classNames = (base, extra) => extra ? `${base} ${extra}` : base;
|
|
@@ -241,7 +247,7 @@ const DetailPanelActionContent = props => [_$ssr(_tmpl$18, _$escape(props.leadin
|
|
|
241
247
|
}
|
|
242
248
|
})];
|
|
243
249
|
const DetailPanelAction = props => {
|
|
244
|
-
const [local, rest] = splitProps(props, ["class", "current", "description", "href", "leading", "menuItems", "menuLabel", "secondaryAction", "title", "trailing", "wrap"]);
|
|
250
|
+
const [local, rest] = splitProps(props, ["class", "current", "description", "href", "leading", "menuItems", "menuLabel", "secondaryAction", "checkbox", "title", "trailing", "wrap"]);
|
|
245
251
|
const className = classNames("k2b-detail-panel__action", local.class);
|
|
246
252
|
const content = () => _$createComponent(DetailPanelActionContent, {
|
|
247
253
|
get title() {
|
|
@@ -305,13 +311,30 @@ const DetailPanelAction = props => {
|
|
|
305
311
|
});
|
|
306
312
|
return _$createComponent(Show, {
|
|
307
313
|
get when() {
|
|
308
|
-
return local.secondaryAction || local.menuItems?.length;
|
|
314
|
+
return local.secondaryAction || local.menuItems?.length || local.checkbox;
|
|
309
315
|
},
|
|
310
316
|
get fallback() {
|
|
311
317
|
return action();
|
|
312
318
|
},
|
|
313
319
|
get children() {
|
|
314
|
-
return _$ssr(_tmpl$22, _$escape(
|
|
320
|
+
return _$ssr(_tmpl$22, _$ssrAttribute("data-checkbox", local.checkbox ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
|
|
321
|
+
get when() {
|
|
322
|
+
return local.checkbox;
|
|
323
|
+
},
|
|
324
|
+
children: checkbox => _$createComponent(Checkbox, {
|
|
325
|
+
"class": "k2b-detail-panel__action-check",
|
|
326
|
+
get ["aria-label"]() {
|
|
327
|
+
return checkbox().label;
|
|
328
|
+
},
|
|
329
|
+
get value() {
|
|
330
|
+
return checkbox().checked;
|
|
331
|
+
},
|
|
332
|
+
get disabled() {
|
|
333
|
+
return checkbox().disabled;
|
|
334
|
+
},
|
|
335
|
+
onValueChange: checked => checkbox().onChange(checked)
|
|
336
|
+
})
|
|
337
|
+
})), _$escape(action()), _$escape(_$createComponent(Show, {
|
|
315
338
|
get when() {
|
|
316
339
|
return local.secondaryAction;
|
|
317
340
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["layout/DetailPanel.tsx"],"sourcesContent":["import { children, createEffect, createSignal, createUniqueId, type JSX, Show, splitProps } from \"solid-js\";\nimport { Button, ButtonLink, type ButtonLinkProps, type ButtonProps, IconButton } from \"../actions/Button\";\nimport { Dropdown, type DropdownItem } from \"../actions/Dropdown\";\nimport { useDetailPanelMessages } from \"./detail-panel-messages\";\nimport { createScrollFade } from \"./scroll-fade\";\n\nexport type DetailPanelProps = {\n /** Plain sections share their host surface, as in AppWorkspace.Detail. */\n surface?: \"default\" | \"plain\";\n children: JSX.Element;\n class?: string;\n};\n\ntype DetailPanelHeaderBaseProps = {\n /** A short line above the title that names what is shown, such as \"Conversation\", followed by its state. */\n kind?: JSX.Element;\n title: JSX.Element;\n subtitle?: JSX.Element;\n meta?: JSX.Element;\n /**\n * The resource's \"…\" menu, shown before `actions`. Pass every less frequent command on the shown resource here,\n * so each panel opens its menu from the same place; an empty list shows no button.\n */\n menu?: readonly DropdownItem[];\n /** Accessible name of the \"…\" button. Defaults to \"More actions\". */\n menuLabel?: string;\n actions?: JSX.Element;\n primaryActions?: JSX.Element;\n class?: string;\n};\n\nexport type DetailPanelHeaderProps = DetailPanelHeaderBaseProps &\n (\n | {\n leading?: JSX.Element;\n icon?: never;\n }\n | {\n leading?: never;\n icon?: string;\n }\n );\n\nexport type DetailPanelBodyProps = {\n scrollFade?: boolean;\n children: JSX.Element;\n scrollPreserveKey?: string;\n class?: string;\n};\n\nexport type DetailPanelSummaryProps = {\n title: JSX.Element;\n children: JSX.Element;\n actions?: JSX.Element;\n class?: string;\n};\n\nexport type DetailPanelGroupProps = {\n children: JSX.Element;\n label?: string;\n /**\n * A visible quiet title, such as \"More about this conversation\". Its sections then stand flush as rows below\n * it, which suits collapsed secondary sections with a `summary`.\n */\n title?: JSX.Element;\n class?: string;\n};\n\nexport type DetailPanelTone = \"accent\" | \"neutral\" | \"success\" | \"warning\" | \"danger\";\n\ntype DetailPanelSectionBaseProps = {\n title: JSX.Element;\n icon?: string;\n tone?: DetailPanelTone;\n description?: JSX.Element;\n /** How many things the section lists, as a chip after the title; `0` reads \"None yet\". */\n count?: number;\n /** Short state after the title, such as \"2 of 4 done\". */\n meta?: JSX.Element;\n class?: string;\n};\n\n/** One direct secondary command, rendered as a sibling icon button at the end of the row. */\nexport type DetailPanelActionSecondary = {\n /** Icon class, for example `ti ti-trash`. */\n icon: string;\n /** Accessible name and tooltip of the icon button. */\n label: string;\n onClick: () => void;\n variant?: \"danger\";\n};\n\ntype DetailPanelActionBaseProps = {\n title: JSX.Element;\n description?: JSX.Element;\n leading?: JSX.Element;\n trailing?: JSX.Element;\n secondaryAction?: DetailPanelActionSecondary;\n /** Marks the row of the current place, such as the section in view, in the panel's accent. */\n current?: boolean;\n /** Lets the title wrap to two lines instead of ending with an ellipsis. */\n wrap?: boolean;\n class?: string;\n};\n\ntype DetailPanelActionMenuProps =\n | {\n menuItems?: never;\n menuLabel?: never;\n }\n | {\n menuItems: readonly DropdownItem[];\n menuLabel: string;\n };\n\nexport type DetailPanelActionLinkProps = DetailPanelActionBaseProps &\n DetailPanelActionMenuProps &\n Omit<ButtonLinkProps, \"children\" | \"class\" | \"size\" | \"title\" | \"variant\"> & {\n href: string;\n };\n\nexport type DetailPanelActionButtonProps = DetailPanelActionBaseProps &\n DetailPanelActionMenuProps &\n Omit<ButtonProps, \"children\" | \"class\" | \"size\" | \"title\" | \"variant\"> & {\n href?: never;\n };\n\nexport type DetailPanelActionProps = DetailPanelActionLinkProps | DetailPanelActionButtonProps;\n\n/** A row that only shows something, such as a person and their role: the columns of an action, without a command. */\nexport type DetailPanelRowProps = {\n title: JSX.Element;\n description?: JSX.Element;\n leading?: JSX.Element;\n trailing?: JSX.Element;\n class?: string;\n};\n\nexport type DetailPanelSectionProps = DetailPanelSectionBaseProps &\n (\n | {\n children?: JSX.Element;\n actions?: JSX.Element;\n collapsible?: false;\n summary?: never;\n defaultOpen?: never;\n open?: never;\n onOpenChange?: never;\n disabled?: never;\n }\n | {\n children: JSX.Element;\n actions?: never;\n collapsible: true;\n /** One line that says what the closed section holds, such as its newest entry; hidden while open. */\n summary?: JSX.Element;\n defaultOpen?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n disabled?: boolean;\n }\n );\n\ntype DetailPanelComponent = ((props: DetailPanelProps) => JSX.Element) & {\n Header: (props: DetailPanelHeaderProps) => JSX.Element;\n Body: (props: DetailPanelBodyProps) => JSX.Element;\n Summary: (props: DetailPanelSummaryProps) => JSX.Element;\n Group: (props: DetailPanelGroupProps) => JSX.Element;\n Section: (props: DetailPanelSectionProps) => JSX.Element;\n Action: (props: DetailPanelActionProps) => JSX.Element;\n Row: (props: DetailPanelRowProps) => JSX.Element;\n};\n\nconst classNames = (base: string, extra?: string): string => (extra ? `${base} ${extra}` : base);\n\nconst showTruncatedTitle = (event: PointerEvent & { currentTarget: HTMLHeadingElement }) => {\n const heading = event.currentTarget;\n if (heading.scrollHeight > heading.clientHeight + 1) heading.title = heading.textContent ?? \"\";\n else heading.removeAttribute(\"title\");\n};\n\nconst DetailPanelHeader = (props: DetailPanelHeaderProps): JSX.Element => {\n const t = useDetailPanelMessages();\n const menuLabel = () => props.menuLabel ?? t().moreActions;\n const menuTrigger = () => (\n <Dropdown.Root items={props.menu ?? []} align=\"end\" label={menuLabel()} phone=\"sheet\">\n <Dropdown.Trigger iconOnly size=\"sm\" variant=\"ghost\" label={menuLabel()} tooltip={menuLabel()}>\n <i class=\"ti ti-dots\" aria-hidden=\"true\" />\n </Dropdown.Trigger>\n </Dropdown.Root>\n );\n // With primary actions, \"…\" ends their row, next to the commands it extends; otherwise it sits beside close.\n const menuInActions = () => Boolean(props.menu?.length) && !props.primaryActions;\n return (\n <header class={classNames(\"k2b-detail-panel__header\", props.class)}>\n <div class=\"k2b-detail-panel__header-main\" data-identity={props.icon || props.leading ? \"true\" : undefined}>\n <Show when={props.icon}>\n {(icon) => (\n <span class=\"k2b-detail-panel__header-icon\" aria-hidden=\"true\">\n <i class={icon()} />\n </span>\n )}\n </Show>\n <Show when={props.leading}>\n <div class=\"k2b-detail-panel__header-leading\">{props.leading}</div>\n </Show>\n <div class=\"k2b-detail-panel__heading\">\n <Show when={props.kind}>\n <div class=\"k2b-detail-panel__kind\">{props.kind}</div>\n </Show>\n {/* A long title wraps to two lines and ends with an ellipsis; then the native hint shows all of it. */}\n <h2 onPointerEnter={showTruncatedTitle}>{props.title}</h2>\n <Show when={props.subtitle || props.meta}>\n <div class=\"k2b-detail-panel__supporting\">\n <Show when={props.subtitle}>\n <p>{props.subtitle}</p>\n </Show>\n <Show when={props.meta}>\n <div class=\"k2b-detail-panel__meta\">{props.meta}</div>\n </Show>\n </div>\n </Show>\n </div>\n <Show when={menuInActions() || props.actions}>\n <div class=\"k2b-detail-panel__actions\">\n <Show when={menuInActions()}>{menuTrigger()}</Show>\n {props.actions}\n </div>\n </Show>\n </div>\n <Show when={props.primaryActions}>\n <div class=\"k2b-detail-panel__primary-actions\">\n {props.primaryActions}\n <Show when={props.menu?.length}>{menuTrigger()}</Show>\n </div>\n </Show>\n </header>\n );\n};\n\nconst DetailPanelBody = (props: DetailPanelBodyProps): JSX.Element => {\n let body!: HTMLDivElement;\n createScrollFade(\n () => body,\n () => props.scrollFade !== false,\n );\n return (\n <div\n ref={body}\n class={classNames(\"k2b-detail-panel__body\", props.class)}\n data-scroll-fade-mode={props.scrollFade !== false ? \"both\" : undefined}\n data-scroll-preserve={props.scrollPreserveKey}\n >\n {props.children}\n </div>\n );\n};\n\nconst DetailPanelSummary = (props: DetailPanelSummaryProps): JSX.Element => {\n const headingId = `k2b-detail-panel-summary-${createUniqueId()}`;\n\n return (\n <section class={classNames(\"k2b-detail-panel__summary\", props.class)} aria-labelledby={headingId}>\n <header class=\"k2b-detail-panel__summary-header\">\n <h3 id={headingId}>{props.title}</h3>\n <Show when={props.actions}>\n <div class=\"k2b-detail-panel__summary-actions\">{props.actions}</div>\n </Show>\n </header>\n <div class=\"k2b-detail-panel__summary-body\">{props.children}</div>\n </section>\n );\n};\n\nconst DetailPanelGroup = (props: DetailPanelGroupProps): JSX.Element => {\n const titleId = `k2b-detail-panel-group-${createUniqueId()}`;\n return (\n <div\n class={classNames(\"k2b-detail-panel__group\", props.class)}\n role=\"group\"\n aria-label={props.title ? undefined : props.label}\n aria-labelledby={props.title ? titleId : undefined}\n data-titled={props.title ? \"true\" : undefined}\n >\n <Show when={props.title}>\n <div class=\"k2b-detail-panel__group-title\" id={titleId}>\n {props.title}\n </div>\n </Show>\n {props.children}\n </div>\n );\n};\n\nconst DetailPanelSectionIcon = (props: Pick<DetailPanelSectionBaseProps, \"icon\" | \"tone\">): JSX.Element => (\n <Show when={props.icon}>\n {(icon) => (\n <span class=\"k2b-detail-panel__section-icon\" data-tone={props.tone ?? \"neutral\"} aria-hidden=\"true\">\n <i class={icon()} />\n </span>\n )}\n </Show>\n);\n\n/** A count chip, or \"None yet\" for zero; shared by sections and discussions. */\nexport const DetailPanelCount = (props: { count: number }): JSX.Element => {\n const messages = useDetailPanelMessages();\n return (\n <Show when={props.count > 0} fallback={<span class=\"k2b-detail-panel__none\">{messages().noneYet}</span>}>\n <span class=\"k2b-count-chip\">{props.count}</span>\n </Show>\n );\n};\n\n/** Title, then its count and state right after it, so every section reads the same way. */\nconst SectionTitleMeta = (props: Pick<DetailPanelSectionBaseProps, \"count\" | \"meta\">): JSX.Element => (\n <>\n <Show when={props.count !== undefined}>\n <DetailPanelCount count={props.count ?? 0} />\n </Show>\n <Show when={props.meta}>\n <span class=\"k2b-detail-panel__section-meta\">{props.meta}</span>\n </Show>\n </>\n);\n\nconst DetailPanelActionContent = (props: DetailPanelActionBaseProps): JSX.Element => (\n <>\n {/* Hidden while empty: a row's icon, or its text when it has none, starts on the section's text edge. */}\n <span class=\"k2b-detail-panel__action-leading\">{props.leading}</span>\n <span class=\"k2b-detail-panel__action-copy\">\n <span class=\"k2b-detail-panel__action-title\">{props.title}</span>\n <Show when={props.description}>\n <span class=\"k2b-detail-panel__action-description\">{props.description}</span>\n </Show>\n </span>\n <Show when={props.trailing}>\n <span class=\"k2b-detail-panel__action-trailing\">{props.trailing}</span>\n </Show>\n </>\n);\n\nconst DetailPanelAction = (props: DetailPanelActionProps): JSX.Element => {\n const [local, rest] = splitProps(props, [\n \"class\",\n \"current\",\n \"description\",\n \"href\",\n \"leading\",\n \"menuItems\",\n \"menuLabel\",\n \"secondaryAction\",\n \"title\",\n \"trailing\",\n \"wrap\",\n ]);\n const className = classNames(\"k2b-detail-panel__action\", local.class);\n const content = () => (\n <DetailPanelActionContent title={local.title} description={local.description} leading={local.leading} trailing={local.trailing} />\n );\n\n const action = () => (\n <Show\n when={local.href !== undefined}\n fallback={\n <Button\n {...(rest as Omit<DetailPanelActionButtonProps, keyof DetailPanelActionBaseProps>)}\n class={className}\n aria-current={local.current ? \"true\" : undefined}\n data-current={local.current ? \"true\" : undefined}\n data-wrap={local.wrap ? \"true\" : undefined}\n variant=\"ghost\"\n size=\"sm\"\n >\n {content()}\n </Button>\n }\n >\n <ButtonLink\n {...(rest as Omit<DetailPanelActionLinkProps, keyof DetailPanelActionBaseProps | \"href\">)}\n href={local.href as string}\n class={className}\n aria-current={local.current ? \"location\" : undefined}\n data-current={local.current ? \"true\" : undefined}\n data-wrap={local.wrap ? \"true\" : undefined}\n variant=\"ghost\"\n size=\"sm\"\n >\n {content()}\n </ButtonLink>\n </Show>\n );\n\n return (\n <Show when={local.secondaryAction || local.menuItems?.length} fallback={action()}>\n <div class=\"k2b-detail-panel__action-row\">\n {action()}\n <Show when={local.secondaryAction}>\n {(secondary) => (\n <IconButton\n size=\"sm\"\n variant=\"ghost\"\n label={secondary().label}\n class=\"k2b-detail-panel__action-secondary\"\n data-tone={secondary().variant}\n onClick={() => secondary().onClick()}\n >\n <i class={secondary().icon} aria-hidden=\"true\" />\n </IconButton>\n )}\n </Show>\n <Show when={local.menuItems?.length}>\n <Dropdown.Root items={local.menuItems ?? []} align=\"end\" label={local.menuLabel} class=\"k2b-detail-panel__action-menu\">\n <Dropdown.Trigger iconOnly size=\"sm\" variant=\"ghost\" label={local.menuLabel} class=\"k2b-detail-panel__action-menu-trigger\">\n <i class=\"ti ti-dots\" aria-hidden=\"true\" />\n </Dropdown.Trigger>\n </Dropdown.Root>\n </Show>\n </div>\n </Show>\n );\n};\n\nconst DetailPanelRow = (props: DetailPanelRowProps): JSX.Element => (\n <div class={classNames(\"k2b-detail-panel__row\", props.class)}>\n <DetailPanelActionContent title={props.title} description={props.description} leading={props.leading} trailing={props.trailing} />\n </div>\n);\n\nconst DetailPanelSection = (props: DetailPanelSectionProps): JSX.Element => {\n const headingId = `k2b-detail-panel-section-${createUniqueId()}`;\n const bodyId = `${headingId}-body`;\n const [internalOpen, setInternalOpen] = createSignal(props.defaultOpen ?? false);\n const open = () => props.open ?? internalOpen();\n let expand: HTMLButtonElement | undefined;\n let collapse: HTMLButtonElement | undefined;\n let body: HTMLDivElement | undefined;\n const toggle = (next: boolean) => {\n if (props.disabled) return;\n if (props.open === undefined) setInternalOpen(next);\n props.onOpenChange?.(next);\n };\n createEffect(() => {\n const expanded = open();\n // Restore focus only when its current control becomes hidden, including\n // a parent-controlled collapse while focus is inside an editor.\n queueMicrotask(() => {\n if (expanded !== open()) return;\n const active = expand?.ownerDocument.activeElement;\n if (expanded && active === expand) collapse?.focus();\n if (!expanded && (active === collapse || (active && body?.contains(active)))) expand?.focus();\n });\n });\n const className = () => classNames(\"k2b-detail-panel__section\", props.class);\n // Resolve once: reading `props.children` twice would instantiate the section body twice.\n const resolved = children(() => props.children);\n\n return (\n <Show\n when={props.collapsible}\n fallback={\n <section class={className()} aria-labelledby={headingId} data-icon={props.icon ? \"true\" : undefined}>\n <header class=\"k2b-detail-panel__section-header\">\n <DetailPanelSectionIcon icon={props.icon} tone={props.tone} />\n <div class=\"k2b-detail-panel__section-copy\">\n <div class=\"k2b-detail-panel__section-heading\">\n <h3 id={headingId}>{props.title}</h3>\n <SectionTitleMeta count={props.count} meta={props.meta} />\n </div>\n <Show when={props.description}>\n <p class=\"k2b-detail-panel__section-description\">{props.description}</p>\n </Show>\n </div>\n <Show when={props.actions}>\n <div class=\"k2b-detail-panel__section-actions\">{props.actions}</div>\n </Show>\n </header>\n <Show when={resolved()}>\n <div class=\"k2b-detail-panel__section-body\">{resolved()}</div>\n </Show>\n </section>\n }\n >\n <section\n class={className()}\n aria-labelledby={open() ? headingId : `${headingId}-closed`}\n data-open={open()}\n data-icon={props.icon ? \"true\" : undefined}\n data-summary={props.summary ? \"true\" : undefined}\n >\n <div hidden={open()}>\n <Button\n ref={expand}\n variant=\"ghost\"\n class=\"k2b-detail-panel__section-summary\"\n disabled={props.disabled}\n aria-expanded={false}\n aria-controls={bodyId}\n onClick={() => toggle(true)}\n >\n <DetailPanelSectionIcon icon={props.icon} tone={props.tone} />\n <span class=\"k2b-detail-panel__section-copy\">\n <span class=\"k2b-detail-panel__section-heading\">\n <span id={`${headingId}-closed`} class=\"k2b-detail-panel__section-title\">\n {props.title}\n </span>\n <SectionTitleMeta count={props.count} meta={props.meta} />\n <Show when={props.summary}>\n <span class=\"k2b-detail-panel__section-preview k2b-truncate-fade\">{props.summary}</span>\n </Show>\n </span>\n <Show when={props.description}>\n <span class=\"k2b-detail-panel__section-description\">{props.description}</span>\n </Show>\n </span>\n {/* Same column as the open header's collapse button, so nothing moves between the states. */}\n <span class=\"k2b-detail-panel__section-toggle\" aria-hidden=\"true\">\n <i class=\"ti ti-chevron-down\" />\n </span>\n </Button>\n </div>\n <div hidden={!open()}>\n <header class=\"k2b-detail-panel__section-header\">\n <DetailPanelSectionIcon icon={props.icon} tone={props.tone} />\n <div class=\"k2b-detail-panel__section-copy\">\n <div class=\"k2b-detail-panel__section-heading\">\n <h3 id={headingId}>{props.title}</h3>\n <SectionTitleMeta count={props.count} meta={props.meta} />\n </div>\n <Show when={props.description}>\n <p class=\"k2b-detail-panel__section-description\">{props.description}</p>\n </Show>\n </div>\n <Button\n ref={collapse}\n variant=\"ghost\"\n size=\"sm\"\n class=\"k2b-detail-panel__section-toggle\"\n disabled={props.disabled}\n aria-labelledby={headingId}\n aria-expanded={true}\n aria-controls={bodyId}\n onClick={() => toggle(false)}\n >\n <i class=\"ti ti-chevron-up\" aria-hidden=\"true\" />\n </Button>\n </header>\n </div>\n <div ref={body} id={bodyId} hidden={!open()} class=\"k2b-detail-panel__section-body\">\n {resolved()}\n </div>\n </section>\n </Show>\n );\n};\n\nconst DetailPanel = ((props: DetailPanelProps): JSX.Element => (\n <div class={classNames(\"k2b-detail-panel\", props.class)} data-surface={props.surface}>\n {props.children}\n </div>\n)) as DetailPanelComponent;\n\nDetailPanel.Header = DetailPanelHeader;\nDetailPanel.Body = DetailPanelBody;\nDetailPanel.Summary = DetailPanelSummary;\nDetailPanel.Group = DetailPanelGroup;\nDetailPanel.Section = DetailPanelSection;\nDetailPanel.Action = DetailPanelAction;\nDetailPanel.Row = DetailPanelRow;\n\nexport default DetailPanel;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["layout/DetailPanel.tsx"],"sourcesContent":["import { children, createEffect, createSignal, createUniqueId, type JSX, Show, splitProps } from \"solid-js\";\nimport { Button, ButtonLink, type ButtonLinkProps, type ButtonProps, IconButton } from \"../actions/Button\";\nimport { Dropdown, type DropdownItem } from \"../actions/Dropdown\";\nimport { Checkbox } from \"../inputs/Checkbox\";\nimport { useDetailPanelMessages } from \"./detail-panel-messages\";\nimport { createScrollFade } from \"./scroll-fade\";\n\nexport type DetailPanelProps = {\n /** Plain sections share their host surface, as in AppWorkspace.Detail. */\n surface?: \"default\" | \"plain\";\n children: JSX.Element;\n class?: string;\n};\n\ntype DetailPanelHeaderBaseProps = {\n /** A short line above the title that names what is shown, such as \"Conversation\", followed by its state. */\n kind?: JSX.Element;\n title: JSX.Element;\n subtitle?: JSX.Element;\n meta?: JSX.Element;\n /**\n * The resource's \"…\" menu, shown before `actions`. Pass every less frequent command on the shown resource here,\n * so each panel opens its menu from the same place; an empty list shows no button.\n */\n menu?: readonly DropdownItem[];\n /** Accessible name of the \"…\" button. Defaults to \"More actions\". */\n menuLabel?: string;\n actions?: JSX.Element;\n primaryActions?: JSX.Element;\n class?: string;\n};\n\nexport type DetailPanelHeaderProps = DetailPanelHeaderBaseProps &\n (\n | {\n leading?: JSX.Element;\n icon?: never;\n }\n | {\n leading?: never;\n icon?: string;\n }\n );\n\nexport type DetailPanelBodyProps = {\n scrollFade?: boolean;\n children: JSX.Element;\n scrollPreserveKey?: string;\n class?: string;\n};\n\nexport type DetailPanelSummaryProps = {\n title: JSX.Element;\n children: JSX.Element;\n actions?: JSX.Element;\n class?: string;\n};\n\nexport type DetailPanelGroupProps = {\n children: JSX.Element;\n label?: string;\n /**\n * A visible quiet title, such as \"More about this conversation\". Its sections then stand flush as rows below\n * it, which suits collapsed secondary sections with a `summary`.\n */\n title?: JSX.Element;\n class?: string;\n};\n\nexport type DetailPanelTone = \"accent\" | \"neutral\" | \"success\" | \"warning\" | \"danger\";\n\ntype DetailPanelSectionBaseProps = {\n title: JSX.Element;\n icon?: string;\n tone?: DetailPanelTone;\n description?: JSX.Element;\n /** How many things the section lists, as a chip after the title; `0` reads \"None yet\". */\n count?: number;\n /** Short state after the title, such as \"2 of 4 done\". */\n meta?: JSX.Element;\n class?: string;\n};\n\n/** One direct secondary command, rendered as a sibling icon button at the end of the row. */\nexport type DetailPanelActionSecondary = {\n /** Icon class, for example `ti ti-trash`. */\n icon: string;\n /** Accessible name and tooltip of the icon button. */\n label: string;\n onClick: () => void;\n variant?: \"danger\";\n};\n\n/**\n * A checkbox before the row that toggles on its own, such as \"done\" for a task the row opens. It always shows its\n * state, unlike a secondary action, which waits for hover.\n */\nexport type DetailPanelActionCheckbox = {\n checked: boolean;\n /** Accessible name, after the row, such as \"Done: Call Mrs. Weber\". */\n label: string;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n};\n\ntype DetailPanelActionBaseProps = {\n title: JSX.Element;\n description?: JSX.Element;\n leading?: JSX.Element;\n trailing?: JSX.Element;\n secondaryAction?: DetailPanelActionSecondary;\n checkbox?: DetailPanelActionCheckbox;\n /** Marks the row of the current place, such as the section in view, in the panel's accent. */\n current?: boolean;\n /** Lets the title wrap to two lines instead of ending with an ellipsis. */\n wrap?: boolean;\n class?: string;\n};\n\ntype DetailPanelActionMenuProps =\n | {\n menuItems?: never;\n menuLabel?: never;\n }\n | {\n menuItems: readonly DropdownItem[];\n menuLabel: string;\n };\n\nexport type DetailPanelActionLinkProps = DetailPanelActionBaseProps &\n DetailPanelActionMenuProps &\n Omit<ButtonLinkProps, \"children\" | \"class\" | \"size\" | \"title\" | \"variant\"> & {\n href: string;\n };\n\nexport type DetailPanelActionButtonProps = DetailPanelActionBaseProps &\n DetailPanelActionMenuProps &\n Omit<ButtonProps, \"children\" | \"class\" | \"size\" | \"title\" | \"variant\"> & {\n href?: never;\n };\n\nexport type DetailPanelActionProps = DetailPanelActionLinkProps | DetailPanelActionButtonProps;\n\n/** A row that only shows something, such as a person and their role: the columns of an action, without a command. */\nexport type DetailPanelRowProps = {\n title: JSX.Element;\n description?: JSX.Element;\n leading?: JSX.Element;\n trailing?: JSX.Element;\n class?: string;\n};\n\nexport type DetailPanelSectionProps = DetailPanelSectionBaseProps &\n (\n | {\n children?: JSX.Element;\n actions?: JSX.Element;\n collapsible?: false;\n summary?: never;\n defaultOpen?: never;\n open?: never;\n onOpenChange?: never;\n disabled?: never;\n }\n | {\n children: JSX.Element;\n actions?: never;\n collapsible: true;\n /** One line that says what the closed section holds, such as its newest entry; hidden while open. */\n summary?: JSX.Element;\n defaultOpen?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n disabled?: boolean;\n }\n );\n\ntype DetailPanelComponent = ((props: DetailPanelProps) => JSX.Element) & {\n Header: (props: DetailPanelHeaderProps) => JSX.Element;\n Body: (props: DetailPanelBodyProps) => JSX.Element;\n Summary: (props: DetailPanelSummaryProps) => JSX.Element;\n Group: (props: DetailPanelGroupProps) => JSX.Element;\n Section: (props: DetailPanelSectionProps) => JSX.Element;\n Action: (props: DetailPanelActionProps) => JSX.Element;\n Row: (props: DetailPanelRowProps) => JSX.Element;\n};\n\nconst classNames = (base: string, extra?: string): string => (extra ? `${base} ${extra}` : base);\n\nconst showTruncatedTitle = (event: PointerEvent & { currentTarget: HTMLHeadingElement }) => {\n const heading = event.currentTarget;\n if (heading.scrollHeight > heading.clientHeight + 1) heading.title = heading.textContent ?? \"\";\n else heading.removeAttribute(\"title\");\n};\n\nconst DetailPanelHeader = (props: DetailPanelHeaderProps): JSX.Element => {\n const t = useDetailPanelMessages();\n const menuLabel = () => props.menuLabel ?? t().moreActions;\n const menuTrigger = () => (\n <Dropdown.Root items={props.menu ?? []} align=\"end\" label={menuLabel()} phone=\"sheet\">\n <Dropdown.Trigger iconOnly size=\"sm\" variant=\"ghost\" label={menuLabel()} tooltip={menuLabel()}>\n <i class=\"ti ti-dots\" aria-hidden=\"true\" />\n </Dropdown.Trigger>\n </Dropdown.Root>\n );\n // With primary actions, \"…\" ends their row, next to the commands it extends; otherwise it sits beside close.\n const menuInActions = () => Boolean(props.menu?.length) && !props.primaryActions;\n return (\n <header class={classNames(\"k2b-detail-panel__header\", props.class)}>\n <div class=\"k2b-detail-panel__header-main\" data-identity={props.icon || props.leading ? \"true\" : undefined}>\n <Show when={props.icon}>\n {(icon) => (\n <span class=\"k2b-detail-panel__header-icon\" aria-hidden=\"true\">\n <i class={icon()} />\n </span>\n )}\n </Show>\n <Show when={props.leading}>\n <div class=\"k2b-detail-panel__header-leading\">{props.leading}</div>\n </Show>\n <div class=\"k2b-detail-panel__heading\">\n <Show when={props.kind}>\n <div class=\"k2b-detail-panel__kind\">{props.kind}</div>\n </Show>\n {/* A long title wraps to two lines and ends with an ellipsis; then the native hint shows all of it. */}\n <h2 onPointerEnter={showTruncatedTitle}>{props.title}</h2>\n <Show when={props.subtitle || props.meta}>\n <div class=\"k2b-detail-panel__supporting\">\n <Show when={props.subtitle}>\n <p>{props.subtitle}</p>\n </Show>\n <Show when={props.meta}>\n <div class=\"k2b-detail-panel__meta\">{props.meta}</div>\n </Show>\n </div>\n </Show>\n </div>\n <Show when={menuInActions() || props.actions}>\n <div class=\"k2b-detail-panel__actions\">\n <Show when={menuInActions()}>{menuTrigger()}</Show>\n {props.actions}\n </div>\n </Show>\n </div>\n <Show when={props.primaryActions}>\n <div class=\"k2b-detail-panel__primary-actions\">\n {props.primaryActions}\n <Show when={props.menu?.length}>{menuTrigger()}</Show>\n </div>\n </Show>\n </header>\n );\n};\n\nconst DetailPanelBody = (props: DetailPanelBodyProps): JSX.Element => {\n let body!: HTMLDivElement;\n createScrollFade(\n () => body,\n () => props.scrollFade !== false,\n );\n return (\n <div\n ref={body}\n class={classNames(\"k2b-detail-panel__body\", props.class)}\n data-scroll-fade-mode={props.scrollFade !== false ? \"both\" : undefined}\n data-scroll-preserve={props.scrollPreserveKey}\n >\n {props.children}\n </div>\n );\n};\n\nconst DetailPanelSummary = (props: DetailPanelSummaryProps): JSX.Element => {\n const headingId = `k2b-detail-panel-summary-${createUniqueId()}`;\n\n return (\n <section class={classNames(\"k2b-detail-panel__summary\", props.class)} aria-labelledby={headingId}>\n <header class=\"k2b-detail-panel__summary-header\">\n <h3 id={headingId}>{props.title}</h3>\n <Show when={props.actions}>\n <div class=\"k2b-detail-panel__summary-actions\">{props.actions}</div>\n </Show>\n </header>\n <div class=\"k2b-detail-panel__summary-body\">{props.children}</div>\n </section>\n );\n};\n\nconst DetailPanelGroup = (props: DetailPanelGroupProps): JSX.Element => {\n const titleId = `k2b-detail-panel-group-${createUniqueId()}`;\n return (\n <div\n class={classNames(\"k2b-detail-panel__group\", props.class)}\n role=\"group\"\n aria-label={props.title ? undefined : props.label}\n aria-labelledby={props.title ? titleId : undefined}\n data-titled={props.title ? \"true\" : undefined}\n >\n <Show when={props.title}>\n <div class=\"k2b-detail-panel__group-title\" id={titleId}>\n {props.title}\n </div>\n </Show>\n {props.children}\n </div>\n );\n};\n\nconst DetailPanelSectionIcon = (props: Pick<DetailPanelSectionBaseProps, \"icon\" | \"tone\">): JSX.Element => (\n <Show when={props.icon}>\n {(icon) => (\n <span class=\"k2b-detail-panel__section-icon\" data-tone={props.tone ?? \"neutral\"} aria-hidden=\"true\">\n <i class={icon()} />\n </span>\n )}\n </Show>\n);\n\n/** A count chip, or \"None yet\" for zero; shared by sections and discussions. */\nexport const DetailPanelCount = (props: { count: number }): JSX.Element => {\n const messages = useDetailPanelMessages();\n return (\n <Show when={props.count > 0} fallback={<span class=\"k2b-detail-panel__none\">{messages().noneYet}</span>}>\n <span class=\"k2b-count-chip\">{props.count}</span>\n </Show>\n );\n};\n\n/** Title, then its count and state right after it, so every section reads the same way. */\nconst SectionTitleMeta = (props: Pick<DetailPanelSectionBaseProps, \"count\" | \"meta\">): JSX.Element => (\n <>\n <Show when={props.count !== undefined}>\n <DetailPanelCount count={props.count ?? 0} />\n </Show>\n <Show when={props.meta}>\n <span class=\"k2b-detail-panel__section-meta\">{props.meta}</span>\n </Show>\n </>\n);\n\nconst DetailPanelActionContent = (props: DetailPanelActionBaseProps): JSX.Element => (\n <>\n {/* Hidden while empty: a row's icon, or its text when it has none, starts on the section's text edge. */}\n <span class=\"k2b-detail-panel__action-leading\">{props.leading}</span>\n <span class=\"k2b-detail-panel__action-copy\">\n <span class=\"k2b-detail-panel__action-title\">{props.title}</span>\n <Show when={props.description}>\n <span class=\"k2b-detail-panel__action-description\">{props.description}</span>\n </Show>\n </span>\n <Show when={props.trailing}>\n <span class=\"k2b-detail-panel__action-trailing\">{props.trailing}</span>\n </Show>\n </>\n);\n\nconst DetailPanelAction = (props: DetailPanelActionProps): JSX.Element => {\n const [local, rest] = splitProps(props, [\n \"class\",\n \"current\",\n \"description\",\n \"href\",\n \"leading\",\n \"menuItems\",\n \"menuLabel\",\n \"secondaryAction\",\n \"checkbox\",\n \"title\",\n \"trailing\",\n \"wrap\",\n ]);\n const className = classNames(\"k2b-detail-panel__action\", local.class);\n const content = () => (\n <DetailPanelActionContent title={local.title} description={local.description} leading={local.leading} trailing={local.trailing} />\n );\n\n const action = () => (\n <Show\n when={local.href !== undefined}\n fallback={\n <Button\n {...(rest as Omit<DetailPanelActionButtonProps, keyof DetailPanelActionBaseProps>)}\n class={className}\n aria-current={local.current ? \"true\" : undefined}\n data-current={local.current ? \"true\" : undefined}\n data-wrap={local.wrap ? \"true\" : undefined}\n variant=\"ghost\"\n size=\"sm\"\n >\n {content()}\n </Button>\n }\n >\n <ButtonLink\n {...(rest as Omit<DetailPanelActionLinkProps, keyof DetailPanelActionBaseProps | \"href\">)}\n href={local.href as string}\n class={className}\n aria-current={local.current ? \"location\" : undefined}\n data-current={local.current ? \"true\" : undefined}\n data-wrap={local.wrap ? \"true\" : undefined}\n variant=\"ghost\"\n size=\"sm\"\n >\n {content()}\n </ButtonLink>\n </Show>\n );\n\n return (\n <Show when={local.secondaryAction || local.menuItems?.length || local.checkbox} fallback={action()}>\n <div class=\"k2b-detail-panel__action-row\" data-checkbox={local.checkbox ? \"true\" : undefined}>\n <Show when={local.checkbox}>\n {(checkbox) => (\n <Checkbox\n class=\"k2b-detail-panel__action-check\"\n aria-label={checkbox().label}\n value={checkbox().checked}\n disabled={checkbox().disabled}\n onValueChange={(checked) => checkbox().onChange(checked)}\n />\n )}\n </Show>\n {action()}\n <Show when={local.secondaryAction}>\n {(secondary) => (\n <IconButton\n size=\"sm\"\n variant=\"ghost\"\n label={secondary().label}\n class=\"k2b-detail-panel__action-secondary\"\n data-tone={secondary().variant}\n onClick={() => secondary().onClick()}\n >\n <i class={secondary().icon} aria-hidden=\"true\" />\n </IconButton>\n )}\n </Show>\n <Show when={local.menuItems?.length}>\n <Dropdown.Root items={local.menuItems ?? []} align=\"end\" label={local.menuLabel} class=\"k2b-detail-panel__action-menu\">\n <Dropdown.Trigger iconOnly size=\"sm\" variant=\"ghost\" label={local.menuLabel} class=\"k2b-detail-panel__action-menu-trigger\">\n <i class=\"ti ti-dots\" aria-hidden=\"true\" />\n </Dropdown.Trigger>\n </Dropdown.Root>\n </Show>\n </div>\n </Show>\n );\n};\n\nconst DetailPanelRow = (props: DetailPanelRowProps): JSX.Element => (\n <div class={classNames(\"k2b-detail-panel__row\", props.class)}>\n <DetailPanelActionContent title={props.title} description={props.description} leading={props.leading} trailing={props.trailing} />\n </div>\n);\n\nconst DetailPanelSection = (props: DetailPanelSectionProps): JSX.Element => {\n const headingId = `k2b-detail-panel-section-${createUniqueId()}`;\n const bodyId = `${headingId}-body`;\n const [internalOpen, setInternalOpen] = createSignal(props.defaultOpen ?? false);\n const open = () => props.open ?? internalOpen();\n let expand: HTMLButtonElement | undefined;\n let collapse: HTMLButtonElement | undefined;\n let body: HTMLDivElement | undefined;\n const toggle = (next: boolean) => {\n if (props.disabled) return;\n if (props.open === undefined) setInternalOpen(next);\n props.onOpenChange?.(next);\n };\n createEffect(() => {\n const expanded = open();\n // Restore focus only when its current control becomes hidden, including\n // a parent-controlled collapse while focus is inside an editor.\n queueMicrotask(() => {\n if (expanded !== open()) return;\n const active = expand?.ownerDocument.activeElement;\n if (expanded && active === expand) collapse?.focus();\n if (!expanded && (active === collapse || (active && body?.contains(active)))) expand?.focus();\n });\n });\n const className = () => classNames(\"k2b-detail-panel__section\", props.class);\n // Resolve once: reading `props.children` twice would instantiate the section body twice.\n const resolved = children(() => props.children);\n\n return (\n <Show\n when={props.collapsible}\n fallback={\n <section class={className()} aria-labelledby={headingId} data-icon={props.icon ? \"true\" : undefined}>\n <header class=\"k2b-detail-panel__section-header\">\n <DetailPanelSectionIcon icon={props.icon} tone={props.tone} />\n <div class=\"k2b-detail-panel__section-copy\">\n <div class=\"k2b-detail-panel__section-heading\">\n <h3 id={headingId}>{props.title}</h3>\n <SectionTitleMeta count={props.count} meta={props.meta} />\n </div>\n <Show when={props.description}>\n <p class=\"k2b-detail-panel__section-description\">{props.description}</p>\n </Show>\n </div>\n <Show when={props.actions}>\n <div class=\"k2b-detail-panel__section-actions\">{props.actions}</div>\n </Show>\n </header>\n <Show when={resolved()}>\n <div class=\"k2b-detail-panel__section-body\">{resolved()}</div>\n </Show>\n </section>\n }\n >\n <section\n class={className()}\n aria-labelledby={open() ? headingId : `${headingId}-closed`}\n data-open={open()}\n data-icon={props.icon ? \"true\" : undefined}\n data-summary={props.summary ? \"true\" : undefined}\n >\n <div hidden={open()}>\n <Button\n ref={expand}\n variant=\"ghost\"\n class=\"k2b-detail-panel__section-summary\"\n disabled={props.disabled}\n aria-expanded={false}\n aria-controls={bodyId}\n onClick={() => toggle(true)}\n >\n <DetailPanelSectionIcon icon={props.icon} tone={props.tone} />\n <span class=\"k2b-detail-panel__section-copy\">\n <span class=\"k2b-detail-panel__section-heading\">\n <span id={`${headingId}-closed`} class=\"k2b-detail-panel__section-title\">\n {props.title}\n </span>\n <SectionTitleMeta count={props.count} meta={props.meta} />\n <Show when={props.summary}>\n <span class=\"k2b-detail-panel__section-preview k2b-truncate-fade\">{props.summary}</span>\n </Show>\n </span>\n <Show when={props.description}>\n <span class=\"k2b-detail-panel__section-description\">{props.description}</span>\n </Show>\n </span>\n {/* Same column as the open header's collapse button, so nothing moves between the states. */}\n <span class=\"k2b-detail-panel__section-toggle\" aria-hidden=\"true\">\n <i class=\"ti ti-chevron-down\" />\n </span>\n </Button>\n </div>\n <div hidden={!open()}>\n <header class=\"k2b-detail-panel__section-header\">\n <DetailPanelSectionIcon icon={props.icon} tone={props.tone} />\n <div class=\"k2b-detail-panel__section-copy\">\n <div class=\"k2b-detail-panel__section-heading\">\n <h3 id={headingId}>{props.title}</h3>\n <SectionTitleMeta count={props.count} meta={props.meta} />\n </div>\n <Show when={props.description}>\n <p class=\"k2b-detail-panel__section-description\">{props.description}</p>\n </Show>\n </div>\n <Button\n ref={collapse}\n variant=\"ghost\"\n size=\"sm\"\n class=\"k2b-detail-panel__section-toggle\"\n disabled={props.disabled}\n aria-labelledby={headingId}\n aria-expanded={true}\n aria-controls={bodyId}\n onClick={() => toggle(false)}\n >\n <i class=\"ti ti-chevron-up\" aria-hidden=\"true\" />\n </Button>\n </header>\n </div>\n <div ref={body} id={bodyId} hidden={!open()} class=\"k2b-detail-panel__section-body\">\n {resolved()}\n </div>\n </section>\n </Show>\n );\n};\n\nconst DetailPanel = ((props: DetailPanelProps): JSX.Element => (\n <div class={classNames(\"k2b-detail-panel\", props.class)} data-surface={props.surface}>\n {props.children}\n </div>\n)) as DetailPanelComponent;\n\nDetailPanel.Header = DetailPanelHeader;\nDetailPanel.Body = DetailPanelBody;\nDetailPanel.Summary = DetailPanelSummary;\nDetailPanel.Group = DetailPanelGroup;\nDetailPanel.Section = DetailPanelSection;\nDetailPanel.Action = DetailPanelAction;\nDetailPanel.Row = DetailPanelRow;\n\nexport default DetailPanel;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -17,7 +17,7 @@ var _tmpl$ = ["<h2", ">", "</h2>"],
|
|
|
17
17
|
_tmpl$0 = ["<footer>", "</footer>"],
|
|
18
18
|
_tmpl$1 = ["<p class=\"k2b-discussion__status\" role=\"status\"><i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\"></i> ", "</p>"],
|
|
19
19
|
_tmpl$10 = ["<button type=\"button\" class=\"k2b-discussion__fold\"", "><i class=\"", "\" aria-hidden=\"true\"></i>", "</button>"],
|
|
20
|
-
_tmpl$11 =
|
|
20
|
+
_tmpl$11 = "<i class=\"ti ti-chevron-up\" aria-hidden=\"true\"></i>",
|
|
21
21
|
_tmpl$12 = ["<div", "><div class=\"k2b-discussion__sentinel\" aria-hidden=\"true\"></div>", "", "", "", "", "<ol class=\"k2b-discussion__list\">", "</ol></div>"],
|
|
22
22
|
_tmpl$13 = ["<button type=\"button\">", "</button>"],
|
|
23
23
|
_tmpl$14 = ["<div class=\"k2b-discussion__status\" role=\"alert\"><span>", "</span>", "</div>"],
|
|
@@ -296,7 +296,21 @@ const DiscussionList = props => {
|
|
|
296
296
|
return _$memo(() => !!(!props.loading && !props.error && !loadMoreError()))() && (canLoadMore() || loadingMore());
|
|
297
297
|
},
|
|
298
298
|
get children() {
|
|
299
|
-
return _$
|
|
299
|
+
return _$createComponent(Button, {
|
|
300
|
+
variant: "link",
|
|
301
|
+
size: "sm",
|
|
302
|
+
"class": "k2b-discussion__load-more",
|
|
303
|
+
get loading() {
|
|
304
|
+
return loadingMore();
|
|
305
|
+
},
|
|
306
|
+
get loadingLabel() {
|
|
307
|
+
return props.loadingLabel ?? chatMessages().loadingMessages;
|
|
308
|
+
},
|
|
309
|
+
onClick: () => void loadMore(),
|
|
310
|
+
get children() {
|
|
311
|
+
return [_$ssr(_tmpl$11), props.loadMoreLabel ?? chatMessages().loadEarlier];
|
|
312
|
+
}
|
|
313
|
+
});
|
|
300
314
|
}
|
|
301
315
|
})), _$escape(visible()));
|
|
302
316
|
};
|