@k2b/ui 0.26.0 → 0.28.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/README.md +1 -1
- package/dist/base.css +147 -2
- package/dist/browser/actions/ContextMenu.js +30 -4
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/Dropdown.js +184 -158
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/GestureMenu.js +71 -138
- package/dist/browser/actions/GestureMenu.js.map +1 -1
- package/dist/browser/actions/Toolbar.js +379 -48
- package/dist/browser/actions/Toolbar.js.map +1 -1
- package/dist/browser/actions/index.js.map +1 -1
- package/dist/browser/actions/menu-rows.js +15 -0
- package/dist/browser/actions/menu-rows.js.map +1 -0
- package/dist/browser/actions/menu-sheet.js +154 -0
- package/dist/browser/actions/menu-sheet.js.map +1 -0
- package/dist/browser/actions/toolbar-messages.js +20 -0
- package/dist/browser/actions/toolbar-messages.js.map +1 -0
- package/dist/browser/chart-inspection.js +3 -0
- package/dist/browser/chart-inspection.js.map +1 -0
- package/dist/browser/chat/ChatComposer.js +1020 -431
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/chat-behavior.js +4 -0
- package/dist/browser/chat/chat-behavior.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +33 -1
- package/dist/browser/chat/chat-messages.js.map +1 -1
- package/dist/browser/chat/command-search.js +173 -0
- package/dist/browser/chat/command-search.js.map +1 -0
- package/dist/browser/chat/composer-document.js +1 -1
- package/dist/browser/chat/composer-document.js.map +1 -1
- package/dist/browser/chat/index.js +2 -0
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/chat/reaction-people.js +15 -0
- package/dist/browser/chat/reaction-people.js.map +1 -0
- package/dist/browser/content/CalendarDayView.js +28 -3
- package/dist/browser/content/CalendarDayView.js.map +1 -1
- package/dist/browser/content/Chart.js +6 -15
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/ChartSnapshotView.js +7 -10
- package/dist/browser/content/ChartSnapshotView.js.map +1 -1
- package/dist/browser/content/MessageRow.js +330 -448
- package/dist/browser/content/MessageRow.js.map +1 -1
- package/dist/browser/content/ReactionBar.js +419 -0
- package/dist/browser/content/ReactionBar.js.map +1 -0
- package/dist/browser/content/chart-inspection-core.js +557 -0
- package/dist/browser/content/chart-inspection-core.js.map +1 -0
- package/dist/browser/content/chart-inspection.js +10 -445
- package/dist/browser/content/chart-inspection.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-snapshot.js +1 -1
- package/dist/browser/content/chart-snapshot.js.map +1 -1
- package/dist/browser/content/index.js +1 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/feedback/dialog-core.js +135 -23
- package/dist/browser/feedback/dialog-core.js.map +1 -1
- package/dist/browser/index.js +1 -0
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/input-mode.js +40 -0
- package/dist/browser/input-mode.js.map +1 -0
- package/dist/browser/inputs/Combobox.js +4 -2
- package/dist/browser/inputs/Combobox.js.map +1 -1
- package/dist/browser/inputs/FileDropTarget.js +24 -9
- package/dist/browser/inputs/FileDropTarget.js.map +1 -1
- package/dist/browser/inputs/FileInputs.js +2 -2
- package/dist/browser/inputs/FileInputs.js.map +1 -1
- package/dist/browser/inputs/SelectChip.js +52 -12
- package/dist/browser/inputs/SelectChip.js.map +1 -1
- package/dist/browser/inputs/emoji/EmojiPicker.js +13 -0
- package/dist/browser/inputs/emoji/EmojiPicker.js.map +1 -1
- package/dist/browser/inputs/file-drop.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +708 -515
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/BottomSheet.js +8 -0
- package/dist/browser/layout/BottomSheet.js.map +1 -1
- package/dist/browser/layout/DetailPanel.js +283 -197
- package/dist/browser/layout/DetailPanel.js.map +1 -1
- package/dist/browser/layout/Discussion.js +233 -185
- package/dist/browser/layout/Discussion.js.map +1 -1
- package/dist/browser/layout/TableOfContents.js +10 -2
- package/dist/browser/layout/TableOfContents.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +155 -23
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/app-workspace-state.js +5 -1
- package/dist/browser/layout/app-workspace-state.js.map +1 -1
- package/dist/browser/layout/detail-panel-messages.js +35 -0
- package/dist/browser/layout/detail-panel-messages.js.map +1 -0
- package/dist/browser/layout/index.js +1 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/surfaces/Avatar.js +50 -20
- package/dist/browser/surfaces/Avatar.js.map +1 -1
- package/dist/browser/surfaces/AvatarStack.js +406 -0
- package/dist/browser/surfaces/AvatarStack.js.map +1 -0
- package/dist/browser/surfaces/avatar-messages.js +8 -2
- package/dist/browser/surfaces/avatar-messages.js.map +1 -1
- package/dist/browser/surfaces/index.js +1 -0
- package/dist/browser/surfaces/index.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +21 -3
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +140 -72
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/GestureMenu.js +52 -106
- package/dist/ssr/actions/GestureMenu.js.map +1 -1
- package/dist/ssr/actions/Toolbar.js +294 -14
- package/dist/ssr/actions/Toolbar.js.map +1 -1
- package/dist/ssr/actions/index.js.map +1 -1
- package/dist/ssr/actions/menu-rows.js +15 -0
- package/dist/ssr/actions/menu-rows.js.map +1 -0
- package/dist/ssr/actions/menu-sheet.js +138 -0
- package/dist/ssr/actions/menu-sheet.js.map +1 -0
- package/dist/ssr/actions/toolbar-messages.js +20 -0
- package/dist/ssr/actions/toolbar-messages.js.map +1 -0
- package/dist/ssr/chart-inspection.js +3 -0
- package/dist/ssr/chart-inspection.js.map +1 -0
- package/dist/ssr/chat/ChatComposer.js +604 -113
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/chat-behavior.js +4 -0
- package/dist/ssr/chat/chat-behavior.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +33 -1
- package/dist/ssr/chat/chat-messages.js.map +1 -1
- package/dist/ssr/chat/command-search.js +173 -0
- package/dist/ssr/chat/command-search.js.map +1 -0
- package/dist/ssr/chat/composer-document.js +1 -1
- package/dist/ssr/chat/composer-document.js.map +1 -1
- package/dist/ssr/chat/index.js +2 -0
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/chat/reaction-people.js +15 -0
- package/dist/ssr/chat/reaction-people.js.map +1 -0
- package/dist/ssr/content/CalendarDayView.js +28 -3
- package/dist/ssr/content/CalendarDayView.js.map +1 -1
- package/dist/ssr/content/Chart.js +6 -15
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/ChartSnapshotView.js +7 -10
- package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
- package/dist/ssr/content/MessageRow.js +98 -152
- package/dist/ssr/content/MessageRow.js.map +1 -1
- package/dist/ssr/content/ReactionBar.js +304 -0
- package/dist/ssr/content/ReactionBar.js.map +1 -0
- package/dist/ssr/content/chart-inspection-core.js +557 -0
- package/dist/ssr/content/chart-inspection-core.js.map +1 -0
- package/dist/ssr/content/chart-inspection.js +10 -445
- package/dist/ssr/content/chart-inspection.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-snapshot.js +1 -1
- package/dist/ssr/content/chart-snapshot.js.map +1 -1
- package/dist/ssr/content/index.js +1 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/feedback/dialog-core.js +135 -23
- package/dist/ssr/feedback/dialog-core.js.map +1 -1
- package/dist/ssr/index.js +1 -0
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/input-mode.js +40 -0
- package/dist/ssr/input-mode.js.map +1 -0
- package/dist/ssr/inputs/Combobox.js +4 -2
- package/dist/ssr/inputs/Combobox.js.map +1 -1
- package/dist/ssr/inputs/FileDropTarget.js +17 -5
- package/dist/ssr/inputs/FileDropTarget.js.map +1 -1
- package/dist/ssr/inputs/FileInputs.js +2 -2
- package/dist/ssr/inputs/FileInputs.js.map +1 -1
- package/dist/ssr/inputs/SelectChip.js +44 -11
- package/dist/ssr/inputs/SelectChip.js.map +1 -1
- package/dist/ssr/inputs/emoji/EmojiPicker.js +12 -0
- package/dist/ssr/inputs/emoji/EmojiPicker.js.map +1 -1
- package/dist/ssr/inputs/file-drop.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +242 -105
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/BottomSheet.js +8 -0
- package/dist/ssr/layout/BottomSheet.js.map +1 -1
- package/dist/ssr/layout/DetailPanel.js +112 -58
- package/dist/ssr/layout/DetailPanel.js.map +1 -1
- package/dist/ssr/layout/Discussion.js +63 -36
- package/dist/ssr/layout/Discussion.js.map +1 -1
- package/dist/ssr/layout/TableOfContents.js +10 -2
- package/dist/ssr/layout/TableOfContents.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +155 -23
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/app-workspace-state.js +5 -1
- package/dist/ssr/layout/app-workspace-state.js.map +1 -1
- package/dist/ssr/layout/detail-panel-messages.js +35 -0
- package/dist/ssr/layout/detail-panel-messages.js.map +1 -0
- package/dist/ssr/layout/index.js +1 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/surfaces/Avatar.js +20 -2
- package/dist/ssr/surfaces/Avatar.js.map +1 -1
- package/dist/ssr/surfaces/AvatarStack.js +286 -0
- package/dist/ssr/surfaces/AvatarStack.js.map +1 -0
- package/dist/ssr/surfaces/avatar-messages.js +8 -2
- package/dist/ssr/surfaces/avatar-messages.js.map +1 -1
- package/dist/ssr/surfaces/index.js +1 -0
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/ContextMenu.d.ts +8 -0
- package/dist/types/actions/Dropdown.d.ts +12 -5
- package/dist/types/actions/GestureMenu.d.ts +6 -4
- package/dist/types/actions/Toolbar.d.ts +20 -0
- package/dist/types/actions/index.d.ts +1 -1
- package/dist/types/actions/menu-rows.d.ts +5 -0
- package/dist/types/actions/menu-sheet.d.ts +22 -0
- package/dist/types/actions/toolbar-messages.d.ts +8 -0
- package/dist/types/chart-inspection.d.ts +2 -0
- package/dist/types/chat/ChatComposer.d.ts +51 -2
- package/dist/types/chat/chat-behavior.d.ts +4 -0
- package/dist/types/chat/chat-messages.d.ts +17 -2
- package/dist/types/chat/command-search.d.ts +41 -0
- package/dist/types/chat/index.d.ts +3 -1
- package/dist/types/chat/reaction-people.d.ts +9 -0
- package/dist/types/content/Chart.d.ts +2 -2
- package/dist/types/content/MessageRow.d.ts +3 -10
- package/dist/types/content/ReactionBar.d.ts +32 -0
- package/dist/types/content/chart-inspection-core.d.ts +61 -0
- package/dist/types/content/chart-inspection.d.ts +4 -20
- package/dist/types/content/chart-snapshot.d.ts +1 -1
- package/dist/types/content/index.d.ts +2 -1
- package/dist/types/feedback/dialog-core.d.ts +16 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/input-mode.d.ts +7 -0
- package/dist/types/inputs/FileDropTarget.d.ts +6 -3
- package/dist/types/inputs/SelectChip.d.ts +6 -0
- package/dist/types/inputs/file-drop.d.ts +2 -0
- package/dist/types/layout/AppWorkspace.d.ts +13 -1
- package/dist/types/layout/BottomSheet.d.ts +8 -0
- package/dist/types/layout/DetailPanel.d.ts +11 -0
- package/dist/types/layout/Discussion.d.ts +8 -0
- package/dist/types/layout/TableOfContents.d.ts +2 -0
- package/dist/types/layout/detail-panel-messages.d.ts +15 -0
- package/dist/types/layout/index.d.ts +1 -1
- package/dist/types/surfaces/Avatar.d.ts +12 -0
- package/dist/types/surfaces/AvatarStack.d.ts +41 -0
- package/dist/types/surfaces/avatar-messages.d.ts +3 -0
- package/dist/types/surfaces/index.d.ts +3 -1
- package/package.json +9 -4
|
@@ -6,33 +6,35 @@ import { escape as _$escape } from "solid-js/web";
|
|
|
6
6
|
import { createComponent as _$createComponent } from "solid-js/web";
|
|
7
7
|
import { memo as _$memo } from "solid-js/web";
|
|
8
8
|
var _tmpl$ = ["<h2", ">", "</h2>"],
|
|
9
|
-
_tmpl$2 = ["<
|
|
10
|
-
_tmpl$3 = ["<
|
|
11
|
-
_tmpl$4 = ["<
|
|
12
|
-
_tmpl$5 = ["<
|
|
13
|
-
_tmpl$6 = ["<
|
|
14
|
-
_tmpl$7 =
|
|
15
|
-
_tmpl$8 = "<
|
|
16
|
-
_tmpl$9 = ["<
|
|
17
|
-
_tmpl$0 = ["<
|
|
18
|
-
_tmpl$1 = ["<
|
|
19
|
-
_tmpl$10 = ["<
|
|
9
|
+
_tmpl$2 = ["<div class=\"k2b-discussion__actions\">", "</div>"],
|
|
10
|
+
_tmpl$3 = ["<header class=\"k2b-discussion__header\">", "", "", "", "</header>"],
|
|
11
|
+
_tmpl$4 = ["<div class=\"k2b-discussion__body\">", "</div>"],
|
|
12
|
+
_tmpl$5 = ["<span class=\"k2b-discussion__icon\" aria-hidden=\"true\"><i", "></i></span>"],
|
|
13
|
+
_tmpl$6 = ["<h3", ">", "</h3>"],
|
|
14
|
+
_tmpl$7 = "<i class=\"ti ti-send\" aria-hidden=\"true\"></i>",
|
|
15
|
+
_tmpl$8 = ["<div class=\"k2b-discussion__composer-field\" data-has-inset-action=\"true\">", "<div class=\"k2b-discussion__composer-inset-action\">", "</div></div>"],
|
|
16
|
+
_tmpl$9 = ["<p class=\"k2b-discussion__status\" role=\"alert\">", "</p>"],
|
|
17
|
+
_tmpl$0 = ["<footer>", "</footer>"],
|
|
18
|
+
_tmpl$1 = ["<p class=\"k2b-discussion__status\" role=\"status\"><i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\"></i> ", "</p>"],
|
|
19
|
+
_tmpl$10 = ["<button type=\"button\" class=\"k2b-discussion__fold\"", "><i class=\"", "\" aria-hidden=\"true\"></i>", "</button>"],
|
|
20
20
|
_tmpl$11 = ["<button type=\"button\" class=\"k2b-discussion__load-more\"", "><i class=\"", "\" aria-hidden=\"true\"></i>", "</button>"],
|
|
21
|
-
_tmpl$12 = ["<div", "><div class=\"k2b-discussion__sentinel\" aria-hidden=\"true\"></div>", "", "", "", "<ol class=\"k2b-discussion__list\">", "</ol></div>"],
|
|
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>"],
|
|
24
24
|
_tmpl$15 = ["<div class=\"k2b-discussion__status\" role=\"alert\"><span>", "</span><button type=\"button\">", "</button></div>"],
|
|
25
25
|
_tmpl$16 = ["<div class=\"k2b-discussion__avatar\">", "</div>"],
|
|
26
|
-
_tmpl$17 = ["<span class=\"k2b-
|
|
27
|
-
_tmpl$18 = ["<
|
|
28
|
-
_tmpl$19 = ["<
|
|
26
|
+
_tmpl$17 = ["<span class=\"k2b-discussion__meta\">", "</span>"],
|
|
27
|
+
_tmpl$18 = ["<div class=\"k2b-discussion__item-actions\"", ">", "</div>"],
|
|
28
|
+
_tmpl$19 = ["<span class=\"k2b-discussion__timestamp\">", "</span>"],
|
|
29
29
|
_tmpl$20 = ["<div class=\"k2b-discussion__reply-context\">", "</div>"],
|
|
30
30
|
_tmpl$21 = ["<div class=\"k2b-discussion__entry\"><header><strong>", "</strong>", "", "", "</header>", "<div class=\"k2b-discussion__content\">", "</div></div>"];
|
|
31
|
-
import { createEffect, createSignal, createUniqueId, onCleanup, onMount, Show, splitProps } from "solid-js";
|
|
31
|
+
import { children, createEffect, createSignal, createUniqueId, onCleanup, onMount, Show, splitProps } from "solid-js";
|
|
32
32
|
import { Button, IconButton } from "../actions/Button";
|
|
33
33
|
import { useChatMessages } from "../chat/chat-messages";
|
|
34
34
|
import { MarkdownEditor } from "../inputs/markdown/MarkdownEditor";
|
|
35
35
|
import { useUiMessages } from "../intl/messages";
|
|
36
|
+
import { DetailPanelCount } from "./DetailPanel";
|
|
37
|
+
import { useDetailPanelMessages } from "./detail-panel-messages";
|
|
36
38
|
const classNames = (base, extra) => extra ? `${base} ${extra}` : base;
|
|
37
39
|
const DiscussionRoot = props => {
|
|
38
40
|
const headingId = `k2b-discussion-${createUniqueId()}`;
|
|
@@ -45,17 +47,17 @@ const DiscussionRoot = props => {
|
|
|
45
47
|
return local.surface ?? "default";
|
|
46
48
|
},
|
|
47
49
|
"aria-labelledby": headingId
|
|
48
|
-
}), [_$ssr(_tmpl$
|
|
50
|
+
}), [_$ssr(_tmpl$3, _$escape(_$createComponent(Show, {
|
|
49
51
|
get when() {
|
|
50
52
|
return _$memo(() => local.icon !== false)() && local.icon;
|
|
51
53
|
},
|
|
52
|
-
children: icon => _$ssr(_tmpl$
|
|
54
|
+
children: icon => _$ssr(_tmpl$5, _$ssrAttribute("class", _$escape(icon(), true), false))
|
|
53
55
|
})), _$escape(_$createComponent(Show, {
|
|
54
56
|
get when() {
|
|
55
57
|
return local.as === "h2";
|
|
56
58
|
},
|
|
57
59
|
get fallback() {
|
|
58
|
-
return _$ssr(_tmpl$
|
|
60
|
+
return _$ssr(_tmpl$6, _$ssrAttribute("id", _$escape(headingId, true), false), _$escape(local.label));
|
|
59
61
|
},
|
|
60
62
|
get children() {
|
|
61
63
|
return _$ssr(_tmpl$, _$ssrAttribute("id", _$escape(headingId, true), false), _$escape(local.label));
|
|
@@ -65,16 +67,20 @@ const DiscussionRoot = props => {
|
|
|
65
67
|
return local.count !== undefined;
|
|
66
68
|
},
|
|
67
69
|
get children() {
|
|
68
|
-
return _$
|
|
70
|
+
return _$createComponent(DetailPanelCount, {
|
|
71
|
+
get count() {
|
|
72
|
+
return local.count ?? 0;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
69
75
|
}
|
|
70
76
|
})), _$escape(_$createComponent(Show, {
|
|
71
77
|
get when() {
|
|
72
78
|
return local.actions !== undefined;
|
|
73
79
|
},
|
|
74
80
|
get children() {
|
|
75
|
-
return _$ssr(_tmpl$
|
|
81
|
+
return _$ssr(_tmpl$2, _$escape(local.actions));
|
|
76
82
|
}
|
|
77
|
-
}))), _$ssr(_tmpl$
|
|
83
|
+
}))), _$ssr(_tmpl$4, _$escape(local.children))], false);
|
|
78
84
|
};
|
|
79
85
|
const DiscussionComposer = props => {
|
|
80
86
|
const messages = useUiMessages();
|
|
@@ -101,7 +107,7 @@ const DiscussionComposer = props => {
|
|
|
101
107
|
get ["class"]() {
|
|
102
108
|
return classNames("k2b-discussion__composer", local.class);
|
|
103
109
|
}
|
|
104
|
-
}), [_$ssr(_tmpl$
|
|
110
|
+
}), [_$ssr(_tmpl$8, _$escape(_$createComponent(MarkdownEditor, {
|
|
105
111
|
get ["aria-label"]() {
|
|
106
112
|
return local.label;
|
|
107
113
|
},
|
|
@@ -140,18 +146,18 @@ const DiscussionComposer = props => {
|
|
|
140
146
|
return submitting() || !message().trim();
|
|
141
147
|
},
|
|
142
148
|
get children() {
|
|
143
|
-
return _$ssr(_tmpl$
|
|
149
|
+
return _$ssr(_tmpl$7);
|
|
144
150
|
}
|
|
145
151
|
}))), _$escape(_$createComponent(Show, {
|
|
146
152
|
get when() {
|
|
147
153
|
return submitError();
|
|
148
154
|
},
|
|
149
|
-
children: error => _$ssr(_tmpl$
|
|
155
|
+
children: error => _$ssr(_tmpl$9, _$escape(error()))
|
|
150
156
|
})), _$escape(_$createComponent(Show, {
|
|
151
157
|
get when() {
|
|
152
158
|
return local.onCancel;
|
|
153
159
|
},
|
|
154
|
-
children: onCancel => _$ssr(_tmpl$
|
|
160
|
+
children: onCancel => _$ssr(_tmpl$0, _$escape(_$createComponent(Button, {
|
|
155
161
|
type: "button",
|
|
156
162
|
variant: "ghost",
|
|
157
163
|
size: "xs",
|
|
@@ -179,6 +185,18 @@ const scrollOwner = element => {
|
|
|
179
185
|
const DiscussionList = props => {
|
|
180
186
|
const messages = useUiMessages();
|
|
181
187
|
const chatMessages = useChatMessages();
|
|
188
|
+
const foldMessages = useDetailPanelMessages();
|
|
189
|
+
const [internalExpanded, setInternalExpanded] = createSignal(false);
|
|
190
|
+
const expanded = () => props.expanded ?? internalExpanded();
|
|
191
|
+
const setExpanded = next => {
|
|
192
|
+
if (props.expanded === undefined) setInternalExpanded(next);
|
|
193
|
+
props.onExpandedChange?.(next);
|
|
194
|
+
};
|
|
195
|
+
const resolved = children(() => props.children);
|
|
196
|
+
const entries = () => resolved.toArray();
|
|
197
|
+
const hidden = () => props.fold !== undefined && !expanded() ? Math.max(0, entries().length - props.fold) : 0;
|
|
198
|
+
const folded = () => props.fold !== undefined && entries().length > props.fold;
|
|
199
|
+
const visible = () => hidden() > 0 ? entries().slice(hidden()) : entries();
|
|
182
200
|
const [loadingMoreInternally, setLoadingMoreInternally] = createSignal(false);
|
|
183
201
|
const [loadMoreError, setLoadMoreError] = createSignal(null);
|
|
184
202
|
const [sentinelVisible, setSentinelVisible] = createSignal(false);
|
|
@@ -189,9 +207,9 @@ const DiscussionList = props => {
|
|
|
189
207
|
let adjustmentFrame;
|
|
190
208
|
let active = true;
|
|
191
209
|
const loadingMore = () => Boolean(props.loadingMore || loadingMoreInternally());
|
|
192
|
-
const canLoadMore = () => Boolean(!props.loading && !props.error && !loadMoreError() && props.hasMore && props.onLoadMore && !loadingMore());
|
|
210
|
+
const canLoadMore = () => Boolean(!props.loading && !props.error && !loadMoreError() && hidden() === 0 && props.hasMore && props.onLoadMore && !loadingMore());
|
|
193
211
|
const loadMore = async (retry = false) => {
|
|
194
|
-
if (props.loading || props.error || !retry && loadMoreError() || !props.onLoadMore || !props.hasMore || loadingMore()) return false;
|
|
212
|
+
if (props.loading || props.error || !retry && loadMoreError() || hidden() > 0 || !props.onLoadMore || !props.hasMore || loadingMore()) return false;
|
|
195
213
|
const owner = listRef ? scrollOwner(listRef) : null;
|
|
196
214
|
const previousScrollHeight = owner?.scrollHeight ?? 0;
|
|
197
215
|
setLoadMoreError(null);
|
|
@@ -242,7 +260,7 @@ const DiscussionList = props => {
|
|
|
242
260
|
return props.loading;
|
|
243
261
|
},
|
|
244
262
|
get children() {
|
|
245
|
-
return _$ssr(_tmpl$
|
|
263
|
+
return _$ssr(_tmpl$1, _$escape(props.loadingLabel ?? chatMessages().loadingMessages));
|
|
246
264
|
}
|
|
247
265
|
})), _$escape(_$createComponent(Show, {
|
|
248
266
|
get when() {
|
|
@@ -261,6 +279,15 @@ const DiscussionList = props => {
|
|
|
261
279
|
return loadMoreError();
|
|
262
280
|
},
|
|
263
281
|
children: error => _$ssr(_tmpl$15, _$escape(error()), _$escape(messages().retry))
|
|
282
|
+
})), _$escape(_$createComponent(Show, {
|
|
283
|
+
get when() {
|
|
284
|
+
return _$memo(() => !!folded())() && !props.loading;
|
|
285
|
+
},
|
|
286
|
+
get children() {
|
|
287
|
+
return _$ssr(_tmpl$10, _$ssrAttribute("aria-expanded", _$escape(hidden(), true) === 0, false), `ti ${hidden() > 0 ? "ti-chevron-down" : "ti-chevron-up"}`, hidden() > 0 ? _$escape(foldMessages().showOlder({
|
|
288
|
+
count: hidden()
|
|
289
|
+
})) : _$escape(foldMessages().showLess));
|
|
290
|
+
}
|
|
264
291
|
})), _$escape(_$createComponent(Show, {
|
|
265
292
|
get when() {
|
|
266
293
|
return _$memo(() => !!(!props.loading && !props.error && !loadMoreError()))() && (canLoadMore() || loadingMore());
|
|
@@ -268,7 +295,7 @@ const DiscussionList = props => {
|
|
|
268
295
|
get children() {
|
|
269
296
|
return _$ssr(_tmpl$11, _$ssrAttribute("disabled", loadingMore(), true), `ti ${loadingMore() ? "ti-loader-2 k2b-spin" : "ti-history"}`, loadingMore() ? _$escape(props.loadingLabel ?? chatMessages().loadingMessages) : _$escape(props.loadMoreLabel ?? chatMessages().loadEarlier));
|
|
270
297
|
}
|
|
271
|
-
})), _$escape(
|
|
298
|
+
})), _$escape(visible()));
|
|
272
299
|
};
|
|
273
300
|
const DiscussionItem = props => {
|
|
274
301
|
const [local, itemProps] = splitProps(props, ["author", "children", "avatar", "timestamp", "meta", "replyContext", "actions", "actionVisibility", "class"]);
|
|
@@ -288,24 +315,24 @@ const DiscussionItem = props => {
|
|
|
288
315
|
}
|
|
289
316
|
})), _$ssr(_tmpl$21, _$escape(local.author), _$escape(_$createComponent(Show, {
|
|
290
317
|
get when() {
|
|
291
|
-
return local.
|
|
318
|
+
return local.meta !== undefined;
|
|
292
319
|
},
|
|
293
320
|
get children() {
|
|
294
|
-
return _$ssr(_tmpl$17, _$escape(local.
|
|
321
|
+
return _$ssr(_tmpl$17, _$escape(local.meta));
|
|
295
322
|
}
|
|
296
323
|
})), _$escape(_$createComponent(Show, {
|
|
297
324
|
get when() {
|
|
298
|
-
return local.
|
|
325
|
+
return local.actions !== undefined;
|
|
299
326
|
},
|
|
300
327
|
get children() {
|
|
301
|
-
return _$ssr(_tmpl$18, _$escape(local.
|
|
328
|
+
return _$ssr(_tmpl$18, _$ssrAttribute("data-visibility", _$escape(local.actionVisibility ?? "progressive", true), false), _$escape(local.actions));
|
|
302
329
|
}
|
|
303
330
|
})), _$escape(_$createComponent(Show, {
|
|
304
331
|
get when() {
|
|
305
|
-
return local.
|
|
332
|
+
return local.timestamp !== undefined;
|
|
306
333
|
},
|
|
307
334
|
get children() {
|
|
308
|
-
return _$ssr(_tmpl$19, _$
|
|
335
|
+
return _$ssr(_tmpl$19, _$escape(local.timestamp));
|
|
309
336
|
}
|
|
310
337
|
})), _$escape(_$createComponent(Show, {
|
|
311
338
|
get when() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["layout/Discussion.tsx"],"sourcesContent":["import { createEffect, createSignal, createUniqueId, type JSX, onCleanup, onMount, Show, splitProps } from \"solid-js\";\nimport { Button, IconButton } from \"../actions/Button\";\nimport { useChatMessages } from \"../chat/chat-messages\";\nimport { MarkdownEditor } from \"../inputs/markdown/MarkdownEditor\";\nimport { useUiMessages } from \"../intl/messages\";\n\nexport type DiscussionProps = Omit<JSX.HTMLAttributes<HTMLElement>, \"children\" | \"class\"> & {\n label: JSX.Element;\n children: JSX.Element;\n icon?: string | false;\n count?: number;\n actions?: JSX.Element;\n as?: \"h2\" | \"h3\";\n surface?: \"default\" | \"bare\";\n class?: string;\n};\n\nexport type DiscussionComposerProps = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, \"children\" | \"class\" | \"onSubmit\"> & {\n label: string;\n onSubmit: (message: string) => boolean | void | Promise<boolean | void>;\n initialValue?: string;\n placeholder?: string;\n submitLabel?: string;\n cancelLabel?: string;\n onCancel?: () => void;\n lines?: number;\n class?: string;\n};\n\nexport type DiscussionListProps = {\n children?: JSX.Element;\n loading?: boolean;\n loadingLabel?: string;\n error?: string | null;\n onRetry?: () => void | Promise<void>;\n hasMore?: boolean;\n loadingMore?: boolean;\n loadMoreLabel?: string;\n onLoadMore?: () => boolean | void | Promise<boolean | void>;\n class?: string;\n};\n\nexport type DiscussionItemProps = Omit<JSX.LiHTMLAttributes<HTMLLIElement>, \"children\" | \"class\"> & {\n author: JSX.Element;\n children: JSX.Element;\n avatar?: JSX.Element;\n timestamp?: JSX.Element;\n meta?: JSX.Element;\n replyContext?: JSX.Element;\n actions?: JSX.Element;\n actionVisibility?: \"always\" | \"progressive\";\n class?: string;\n};\n\ntype DiscussionComponent = ((props: DiscussionProps) => JSX.Element) & {\n Composer: (props: DiscussionComposerProps) => JSX.Element;\n List: (props: DiscussionListProps) => JSX.Element;\n Item: (props: DiscussionItemProps) => JSX.Element;\n};\n\nconst classNames = (base: string, extra?: string): string => (extra ? `${base} ${extra}` : base);\n\nconst DiscussionRoot = (props: DiscussionProps): JSX.Element => {\n const headingId = `k2b-discussion-${createUniqueId()}`;\n const [local, sectionProps] = splitProps(props, [\"label\", \"children\", \"icon\", \"count\", \"actions\", \"as\", \"surface\", \"class\"]);\n\n return (\n <section\n {...sectionProps}\n class={classNames(\"k2b-discussion\", local.class)}\n data-surface={local.surface ?? \"default\"}\n aria-labelledby={headingId}\n >\n <header class=\"k2b-discussion__header\">\n <Show when={local.icon !== false && local.icon}>\n {(icon) => (\n <span class=\"k2b-discussion__icon\" aria-hidden=\"true\">\n <i class={icon()} />\n </span>\n )}\n </Show>\n <Show when={local.as === \"h2\"} fallback={<h3 id={headingId}>{local.label}</h3>}>\n <h2 id={headingId}>{local.label}</h2>\n </Show>\n <Show when={local.count !== undefined}>\n <span class=\"k2b-discussion__count\">{local.count}</span>\n </Show>\n <Show when={local.actions !== undefined}>\n <div class=\"k2b-discussion__actions\">{local.actions}</div>\n </Show>\n </header>\n <div class=\"k2b-discussion__body\">{local.children}</div>\n </section>\n );\n};\n\nconst DiscussionComposer = (props: DiscussionComposerProps): JSX.Element => {\n const messages = useUiMessages();\n const chatMessages = useChatMessages();\n const [local, formProps] = splitProps(props, [\n \"label\",\n \"onSubmit\",\n \"initialValue\",\n \"placeholder\",\n \"submitLabel\",\n \"cancelLabel\",\n \"onCancel\",\n \"lines\",\n \"class\",\n ]);\n const [message, setMessage] = createSignal(local.initialValue ?? \"\");\n const [submitting, setSubmitting] = createSignal(false);\n const [submitError, setSubmitError] = createSignal<string | null>(null);\n\n const submit = async () => {\n const normalized = message().trim();\n if (!normalized || submitting()) return;\n setSubmitting(true);\n setSubmitError(null);\n try {\n const accepted = await local.onSubmit(normalized);\n if (accepted !== false) setMessage(\"\");\n } catch (error) {\n setSubmitError(error instanceof Error ? error.message : chatMessages().couldNotPostMessage);\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <form\n {...formProps}\n class={classNames(\"k2b-discussion__composer\", local.class)}\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n >\n <div class=\"k2b-discussion__composer-field\" data-has-inset-action=\"true\">\n <MarkdownEditor\n aria-label={local.label}\n value={message}\n onValueChange={(value) => {\n // The error belongs to the submitted text; any edit, including clearing it, makes it stale.\n if (value !== message()) setSubmitError(null);\n setMessage(value);\n }}\n placeholder={local.placeholder}\n lines={local.lines ?? 4}\n noToolbar\n showStats={false}\n disabled={submitting()}\n error={submitError() !== null}\n onSubmit={() => void submit()}\n />\n <div class=\"k2b-discussion__composer-inset-action\">\n <IconButton\n type=\"submit\"\n label={local.submitLabel ?? chatMessages().postMessage}\n size=\"sm\"\n variant=\"primary\"\n loading={submitting()}\n disabled={submitting() || !message().trim()}\n >\n <i class=\"ti ti-send\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n </div>\n <Show when={submitError()}>\n {(error) => (\n <p class=\"k2b-discussion__status\" role=\"alert\">\n {error()}\n </p>\n )}\n </Show>\n <Show when={local.onCancel}>\n {(onCancel) => (\n <footer>\n <Button type=\"button\" variant=\"ghost\" size=\"xs\" disabled={submitting()} onClick={onCancel()}>\n {local.cancelLabel ?? messages().cancel}\n </Button>\n </footer>\n )}\n </Show>\n </form>\n );\n};\n\nconst scrollOwner = (element: HTMLElement): HTMLElement | null => {\n let parent = element.parentElement;\n while (parent) {\n const style = getComputedStyle(parent);\n if (style.overflowY === \"auto\" || style.overflowY === \"scroll\" || style.overflow === \"auto\" || style.overflow === \"scroll\")\n return parent;\n parent = parent.parentElement;\n }\n return document.scrollingElement instanceof HTMLElement ? document.scrollingElement : null;\n};\n\nconst DiscussionList = (props: DiscussionListProps): JSX.Element => {\n const messages = useUiMessages();\n const chatMessages = useChatMessages();\n const [loadingMoreInternally, setLoadingMoreInternally] = createSignal(false);\n const [loadMoreError, setLoadMoreError] = createSignal<string | null>(null);\n const [sentinelVisible, setSentinelVisible] = createSignal(false);\n const [automaticLoadAttempted, setAutomaticLoadAttempted] = createSignal(false);\n let listRef: HTMLOListElement | undefined;\n let sentinelRef: HTMLDivElement | undefined;\n let observer: IntersectionObserver | undefined;\n let adjustmentFrame: number | undefined;\n let active = true;\n\n const loadingMore = () => Boolean(props.loadingMore || loadingMoreInternally());\n const canLoadMore = () =>\n Boolean(!props.loading && !props.error && !loadMoreError() && props.hasMore && props.onLoadMore && !loadingMore());\n\n const loadMore = async (retry = false): Promise<boolean> => {\n if (props.loading || props.error || (!retry && loadMoreError()) || !props.onLoadMore || !props.hasMore || loadingMore()) return false;\n const owner = listRef ? scrollOwner(listRef) : null;\n const previousScrollHeight = owner?.scrollHeight ?? 0;\n setLoadMoreError(null);\n setLoadingMoreInternally(true);\n let loaded = false;\n try {\n loaded = (await props.onLoadMore()) !== false;\n } catch (error) {\n if (active) setLoadMoreError(error instanceof Error ? error.message : chatMessages().couldNotLoadEarlierMessages);\n } finally {\n if (active) setLoadingMoreInternally(false);\n }\n if (!active || !loaded || !owner) return false;\n queueMicrotask(() => {\n if (!active) return;\n adjustmentFrame = requestAnimationFrame(() => {\n if (!active) return;\n owner.scrollTop += owner.scrollHeight - previousScrollHeight;\n });\n });\n return true;\n };\n\n createEffect(() => {\n if (!sentinelVisible()) {\n setAutomaticLoadAttempted(false);\n return;\n }\n if (automaticLoadAttempted() || !canLoadMore()) return;\n setAutomaticLoadAttempted(true);\n void loadMore();\n });\n\n onMount(() => {\n if (typeof IntersectionObserver === \"undefined\" || !sentinelRef) return;\n observer = new IntersectionObserver(\n (entries) => {\n setSentinelVisible(entries.some((entry) => entry.isIntersecting));\n },\n { rootMargin: \"160px 0px 0px\" },\n );\n observer.observe(sentinelRef);\n });\n\n onCleanup(() => {\n active = false;\n observer?.disconnect();\n if (adjustmentFrame !== undefined) cancelAnimationFrame(adjustmentFrame);\n });\n\n return (\n <div class={classNames(\"k2b-discussion__list-region\", props.class)} aria-busy={props.loading || loadingMore() ? \"true\" : undefined}>\n <div ref={sentinelRef} class=\"k2b-discussion__sentinel\" aria-hidden=\"true\" />\n <Show when={props.loading}>\n <p class=\"k2b-discussion__status\" role=\"status\">\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" /> {props.loadingLabel ?? chatMessages().loadingMessages}\n </p>\n </Show>\n <Show when={props.error}>\n {(error) => (\n <div class=\"k2b-discussion__status\" role=\"alert\">\n <span>{error()}</span>\n <Show when={props.onRetry}>\n <button type=\"button\" onClick={props.onRetry}>\n {messages().retry}\n </button>\n </Show>\n </div>\n )}\n </Show>\n <Show when={loadMoreError()}>\n {(error) => (\n <div class=\"k2b-discussion__status\" role=\"alert\">\n <span>{error()}</span>\n <button type=\"button\" onClick={() => void loadMore(true)}>\n {messages().retry}\n </button>\n </div>\n )}\n </Show>\n <Show when={!props.loading && !props.error && !loadMoreError() && (canLoadMore() || loadingMore())}>\n <button type=\"button\" class=\"k2b-discussion__load-more\" disabled={loadingMore()} onClick={() => void loadMore()}>\n <i class={`ti ${loadingMore() ? \"ti-loader-2 k2b-spin\" : \"ti-history\"}`} aria-hidden=\"true\" />\n {loadingMore() ? (props.loadingLabel ?? chatMessages().loadingMessages) : (props.loadMoreLabel ?? chatMessages().loadEarlier)}\n </button>\n </Show>\n <ol ref={listRef} class=\"k2b-discussion__list\">\n {props.children}\n </ol>\n </div>\n );\n};\n\nconst DiscussionItem = (props: DiscussionItemProps): JSX.Element => {\n const [local, itemProps] = splitProps(props, [\n \"author\",\n \"children\",\n \"avatar\",\n \"timestamp\",\n \"meta\",\n \"replyContext\",\n \"actions\",\n \"actionVisibility\",\n \"class\",\n ]);\n return (\n <li\n {...itemProps}\n class={classNames(\"k2b-discussion__item\", local.class)}\n data-has-avatar={local.avatar !== undefined ? \"true\" : undefined}\n >\n <Show when={local.avatar !== undefined}>\n <div class=\"k2b-discussion__avatar\">{local.avatar}</div>\n </Show>\n <div class=\"k2b-discussion__entry\">\n <header>\n <strong>{local.author}</strong>\n <Show when={local.timestamp !== undefined}>\n <span class=\"k2b-discussion__timestamp\">{local.timestamp}</span>\n </Show>\n <Show when={local.meta !== undefined}>\n <span class=\"k2b-discussion__meta\">{local.meta}</span>\n </Show>\n <Show when={local.actions !== undefined}>\n <div class=\"k2b-discussion__item-actions\" data-visibility={local.actionVisibility ?? \"progressive\"}>\n {local.actions}\n </div>\n </Show>\n </header>\n <Show when={local.replyContext !== undefined}>\n <div class=\"k2b-discussion__reply-context\">{local.replyContext}</div>\n </Show>\n <div class=\"k2b-discussion__content\">{local.children}</div>\n </div>\n </li>\n );\n};\n\nconst Discussion = DiscussionRoot as DiscussionComponent;\nDiscussion.Composer = DiscussionComposer;\nDiscussion.List = DiscussionList;\nDiscussion.Item = DiscussionItem;\n\nexport default Discussion;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["layout/Discussion.tsx"],"sourcesContent":["import { children, createEffect, createSignal, createUniqueId, type JSX, onCleanup, onMount, Show, splitProps } from \"solid-js\";\nimport { Button, IconButton } from \"../actions/Button\";\nimport { useChatMessages } from \"../chat/chat-messages\";\nimport { MarkdownEditor } from \"../inputs/markdown/MarkdownEditor\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { DetailPanelCount } from \"./DetailPanel\";\nimport { useDetailPanelMessages } from \"./detail-panel-messages\";\n\nexport type DiscussionProps = Omit<JSX.HTMLAttributes<HTMLElement>, \"children\" | \"class\"> & {\n label: JSX.Element;\n children: JSX.Element;\n icon?: string | false;\n count?: number;\n actions?: JSX.Element;\n as?: \"h2\" | \"h3\";\n surface?: \"default\" | \"bare\";\n class?: string;\n};\n\nexport type DiscussionComposerProps = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, \"children\" | \"class\" | \"onSubmit\"> & {\n label: string;\n onSubmit: (message: string) => boolean | void | Promise<boolean | void>;\n initialValue?: string;\n placeholder?: string;\n submitLabel?: string;\n cancelLabel?: string;\n onCancel?: () => void;\n lines?: number;\n class?: string;\n};\n\nexport type DiscussionListProps = {\n children?: JSX.Element;\n loading?: boolean;\n loadingLabel?: string;\n error?: string | null;\n onRetry?: () => void | Promise<void>;\n hasMore?: boolean;\n loadingMore?: boolean;\n loadMoreLabel?: string;\n onLoadMore?: () => boolean | void | Promise<boolean | void>;\n /**\n * Shows only the newest `fold` entries and a \"Show n older\" toggle above them. Expanded, the toggle reads \"Show less\"\n * and earlier pages load as usual. Omit it to show every loaded entry.\n */\n fold?: number;\n /** Controls the fold, for example to reveal an older entry; `onExpandedChange` requests a change. */\n expanded?: boolean;\n onExpandedChange?: (expanded: boolean) => void;\n class?: string;\n};\n\nexport type DiscussionItemProps = Omit<JSX.LiHTMLAttributes<HTMLLIElement>, \"children\" | \"class\"> & {\n author: JSX.Element;\n children: JSX.Element;\n avatar?: JSX.Element;\n timestamp?: JSX.Element;\n meta?: JSX.Element;\n replyContext?: JSX.Element;\n actions?: JSX.Element;\n actionVisibility?: \"always\" | \"progressive\";\n class?: string;\n};\n\ntype DiscussionComponent = ((props: DiscussionProps) => JSX.Element) & {\n Composer: (props: DiscussionComposerProps) => JSX.Element;\n List: (props: DiscussionListProps) => JSX.Element;\n Item: (props: DiscussionItemProps) => JSX.Element;\n};\n\nconst classNames = (base: string, extra?: string): string => (extra ? `${base} ${extra}` : base);\n\nconst DiscussionRoot = (props: DiscussionProps): JSX.Element => {\n const headingId = `k2b-discussion-${createUniqueId()}`;\n const [local, sectionProps] = splitProps(props, [\"label\", \"children\", \"icon\", \"count\", \"actions\", \"as\", \"surface\", \"class\"]);\n\n return (\n <section\n {...sectionProps}\n class={classNames(\"k2b-discussion\", local.class)}\n data-surface={local.surface ?? \"default\"}\n aria-labelledby={headingId}\n >\n <header class=\"k2b-discussion__header\">\n <Show when={local.icon !== false && local.icon}>\n {(icon) => (\n <span class=\"k2b-discussion__icon\" aria-hidden=\"true\">\n <i class={icon()} />\n </span>\n )}\n </Show>\n <Show when={local.as === \"h2\"} fallback={<h3 id={headingId}>{local.label}</h3>}>\n <h2 id={headingId}>{local.label}</h2>\n </Show>\n <Show when={local.count !== undefined}>\n <DetailPanelCount count={local.count ?? 0} />\n </Show>\n <Show when={local.actions !== undefined}>\n <div class=\"k2b-discussion__actions\">{local.actions}</div>\n </Show>\n </header>\n <div class=\"k2b-discussion__body\">{local.children}</div>\n </section>\n );\n};\n\nconst DiscussionComposer = (props: DiscussionComposerProps): JSX.Element => {\n const messages = useUiMessages();\n const chatMessages = useChatMessages();\n const [local, formProps] = splitProps(props, [\n \"label\",\n \"onSubmit\",\n \"initialValue\",\n \"placeholder\",\n \"submitLabel\",\n \"cancelLabel\",\n \"onCancel\",\n \"lines\",\n \"class\",\n ]);\n const [message, setMessage] = createSignal(local.initialValue ?? \"\");\n const [submitting, setSubmitting] = createSignal(false);\n const [submitError, setSubmitError] = createSignal<string | null>(null);\n\n const submit = async () => {\n const normalized = message().trim();\n if (!normalized || submitting()) return;\n setSubmitting(true);\n setSubmitError(null);\n try {\n const accepted = await local.onSubmit(normalized);\n if (accepted !== false) setMessage(\"\");\n } catch (error) {\n setSubmitError(error instanceof Error ? error.message : chatMessages().couldNotPostMessage);\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <form\n {...formProps}\n class={classNames(\"k2b-discussion__composer\", local.class)}\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n >\n <div class=\"k2b-discussion__composer-field\" data-has-inset-action=\"true\">\n <MarkdownEditor\n aria-label={local.label}\n value={message}\n onValueChange={(value) => {\n // The error belongs to the submitted text; any edit, including clearing it, makes it stale.\n if (value !== message()) setSubmitError(null);\n setMessage(value);\n }}\n placeholder={local.placeholder}\n lines={local.lines ?? 4}\n noToolbar\n showStats={false}\n disabled={submitting()}\n error={submitError() !== null}\n onSubmit={() => void submit()}\n />\n <div class=\"k2b-discussion__composer-inset-action\">\n <IconButton\n type=\"submit\"\n label={local.submitLabel ?? chatMessages().postMessage}\n size=\"sm\"\n variant=\"primary\"\n loading={submitting()}\n disabled={submitting() || !message().trim()}\n >\n <i class=\"ti ti-send\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n </div>\n <Show when={submitError()}>\n {(error) => (\n <p class=\"k2b-discussion__status\" role=\"alert\">\n {error()}\n </p>\n )}\n </Show>\n <Show when={local.onCancel}>\n {(onCancel) => (\n <footer>\n <Button type=\"button\" variant=\"ghost\" size=\"xs\" disabled={submitting()} onClick={onCancel()}>\n {local.cancelLabel ?? messages().cancel}\n </Button>\n </footer>\n )}\n </Show>\n </form>\n );\n};\n\nconst scrollOwner = (element: HTMLElement): HTMLElement | null => {\n let parent = element.parentElement;\n while (parent) {\n const style = getComputedStyle(parent);\n if (style.overflowY === \"auto\" || style.overflowY === \"scroll\" || style.overflow === \"auto\" || style.overflow === \"scroll\")\n return parent;\n parent = parent.parentElement;\n }\n return document.scrollingElement instanceof HTMLElement ? document.scrollingElement : null;\n};\n\nconst DiscussionList = (props: DiscussionListProps): JSX.Element => {\n const messages = useUiMessages();\n const chatMessages = useChatMessages();\n const foldMessages = useDetailPanelMessages();\n const [internalExpanded, setInternalExpanded] = createSignal(false);\n const expanded = () => props.expanded ?? internalExpanded();\n const setExpanded = (next: boolean) => {\n if (props.expanded === undefined) setInternalExpanded(next);\n props.onExpandedChange?.(next);\n };\n const resolved = children(() => props.children);\n const entries = () => resolved.toArray();\n const hidden = () => (props.fold !== undefined && !expanded() ? Math.max(0, entries().length - props.fold) : 0);\n const folded = () => props.fold !== undefined && entries().length > props.fold;\n const visible = () => (hidden() > 0 ? entries().slice(hidden()) : entries());\n const [loadingMoreInternally, setLoadingMoreInternally] = createSignal(false);\n const [loadMoreError, setLoadMoreError] = createSignal<string | null>(null);\n const [sentinelVisible, setSentinelVisible] = createSignal(false);\n const [automaticLoadAttempted, setAutomaticLoadAttempted] = createSignal(false);\n let listRef: HTMLOListElement | undefined;\n let sentinelRef: HTMLDivElement | undefined;\n let observer: IntersectionObserver | undefined;\n let adjustmentFrame: number | undefined;\n let active = true;\n\n const loadingMore = () => Boolean(props.loadingMore || loadingMoreInternally());\n const canLoadMore = () =>\n Boolean(!props.loading && !props.error && !loadMoreError() && hidden() === 0 && props.hasMore && props.onLoadMore && !loadingMore());\n\n const loadMore = async (retry = false): Promise<boolean> => {\n if (props.loading || props.error || (!retry && loadMoreError()) || hidden() > 0 || !props.onLoadMore || !props.hasMore || loadingMore())\n return false;\n const owner = listRef ? scrollOwner(listRef) : null;\n const previousScrollHeight = owner?.scrollHeight ?? 0;\n setLoadMoreError(null);\n setLoadingMoreInternally(true);\n let loaded = false;\n try {\n loaded = (await props.onLoadMore()) !== false;\n } catch (error) {\n if (active) setLoadMoreError(error instanceof Error ? error.message : chatMessages().couldNotLoadEarlierMessages);\n } finally {\n if (active) setLoadingMoreInternally(false);\n }\n if (!active || !loaded || !owner) return false;\n queueMicrotask(() => {\n if (!active) return;\n adjustmentFrame = requestAnimationFrame(() => {\n if (!active) return;\n owner.scrollTop += owner.scrollHeight - previousScrollHeight;\n });\n });\n return true;\n };\n\n createEffect(() => {\n if (!sentinelVisible()) {\n setAutomaticLoadAttempted(false);\n return;\n }\n if (automaticLoadAttempted() || !canLoadMore()) return;\n setAutomaticLoadAttempted(true);\n void loadMore();\n });\n\n onMount(() => {\n if (typeof IntersectionObserver === \"undefined\" || !sentinelRef) return;\n observer = new IntersectionObserver(\n (entries) => {\n setSentinelVisible(entries.some((entry) => entry.isIntersecting));\n },\n { rootMargin: \"160px 0px 0px\" },\n );\n observer.observe(sentinelRef);\n });\n\n onCleanup(() => {\n active = false;\n observer?.disconnect();\n if (adjustmentFrame !== undefined) cancelAnimationFrame(adjustmentFrame);\n });\n\n return (\n <div class={classNames(\"k2b-discussion__list-region\", props.class)} aria-busy={props.loading || loadingMore() ? \"true\" : undefined}>\n <div ref={sentinelRef} class=\"k2b-discussion__sentinel\" aria-hidden=\"true\" />\n <Show when={props.loading}>\n <p class=\"k2b-discussion__status\" role=\"status\">\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" /> {props.loadingLabel ?? chatMessages().loadingMessages}\n </p>\n </Show>\n <Show when={props.error}>\n {(error) => (\n <div class=\"k2b-discussion__status\" role=\"alert\">\n <span>{error()}</span>\n <Show when={props.onRetry}>\n <button type=\"button\" onClick={props.onRetry}>\n {messages().retry}\n </button>\n </Show>\n </div>\n )}\n </Show>\n <Show when={loadMoreError()}>\n {(error) => (\n <div class=\"k2b-discussion__status\" role=\"alert\">\n <span>{error()}</span>\n <button type=\"button\" onClick={() => void loadMore(true)}>\n {messages().retry}\n </button>\n </div>\n )}\n </Show>\n {/* The toggle stays above the entries in both states, so nothing above it moves. A failed refresh keeps it:\n the entries it folds are still there. */}\n <Show when={folded() && !props.loading}>\n <button type=\"button\" class=\"k2b-discussion__fold\" aria-expanded={hidden() === 0} onClick={() => setExpanded(hidden() > 0)}>\n <i class={`ti ${hidden() > 0 ? \"ti-chevron-down\" : \"ti-chevron-up\"}`} aria-hidden=\"true\" />\n {hidden() > 0 ? foldMessages().showOlder({ count: hidden() }) : foldMessages().showLess}\n </button>\n </Show>\n <Show when={!props.loading && !props.error && !loadMoreError() && (canLoadMore() || loadingMore())}>\n <button type=\"button\" class=\"k2b-discussion__load-more\" disabled={loadingMore()} onClick={() => void loadMore()}>\n <i class={`ti ${loadingMore() ? \"ti-loader-2 k2b-spin\" : \"ti-history\"}`} aria-hidden=\"true\" />\n {loadingMore() ? (props.loadingLabel ?? chatMessages().loadingMessages) : (props.loadMoreLabel ?? chatMessages().loadEarlier)}\n </button>\n </Show>\n <ol ref={listRef} class=\"k2b-discussion__list\">\n {visible()}\n </ol>\n </div>\n );\n};\n\nconst DiscussionItem = (props: DiscussionItemProps): JSX.Element => {\n const [local, itemProps] = splitProps(props, [\n \"author\",\n \"children\",\n \"avatar\",\n \"timestamp\",\n \"meta\",\n \"replyContext\",\n \"actions\",\n \"actionVisibility\",\n \"class\",\n ]);\n return (\n <li\n {...itemProps}\n class={classNames(\"k2b-discussion__item\", local.class)}\n data-has-avatar={local.avatar !== undefined ? \"true\" : undefined}\n >\n <Show when={local.avatar !== undefined}>\n <div class=\"k2b-discussion__avatar\">{local.avatar}</div>\n </Show>\n <div class=\"k2b-discussion__entry\">\n <header>\n <strong>{local.author}</strong>\n <Show when={local.meta !== undefined}>\n <span class=\"k2b-discussion__meta\">{local.meta}</span>\n </Show>\n {/* Times end on the panel's trailing edge; item actions sit just before them. */}\n <Show when={local.actions !== undefined}>\n <div class=\"k2b-discussion__item-actions\" data-visibility={local.actionVisibility ?? \"progressive\"}>\n {local.actions}\n </div>\n </Show>\n <Show when={local.timestamp !== undefined}>\n <span class=\"k2b-discussion__timestamp\">{local.timestamp}</span>\n </Show>\n </header>\n <Show when={local.replyContext !== undefined}>\n <div class=\"k2b-discussion__reply-context\">{local.replyContext}</div>\n </Show>\n <div class=\"k2b-discussion__content\">{local.children}</div>\n </div>\n </li>\n );\n};\n\nconst Discussion = DiscussionRoot as DiscussionComponent;\nDiscussion.Composer = DiscussionComposer;\nDiscussion.List = DiscussionList;\nDiscussion.Item = DiscussionItem;\n\nexport default Discussion;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -20,6 +20,14 @@ export function TableOfContents(props) {
|
|
|
20
20
|
// Reading every id here makes a changed id or a store update recompute the active section.
|
|
21
21
|
const ids = props.items.map(item => item.id);
|
|
22
22
|
const root = resolveMaybeAccessor(props.scrollRoot);
|
|
23
|
+
const content = resolveMaybeAccessor(props.contentRoot);
|
|
24
|
+
const heading = id => {
|
|
25
|
+
const element = document.getElementById(id);
|
|
26
|
+
if (!content || element && content.contains(element)) return element;
|
|
27
|
+
// The same id elsewhere on the page, or a root outside the document tree, needs a lookup within the root.
|
|
28
|
+
for (const candidate of content.querySelectorAll("[id]")) if (candidate.id === id) return candidate;
|
|
29
|
+
return null;
|
|
30
|
+
};
|
|
23
31
|
const target = root ?? window;
|
|
24
32
|
let frame;
|
|
25
33
|
const update = () => {
|
|
@@ -30,7 +38,7 @@ export function TableOfContents(props) {
|
|
|
30
38
|
const line = top + height / 4;
|
|
31
39
|
const headings = ids.map(id => ({
|
|
32
40
|
id,
|
|
33
|
-
box:
|
|
41
|
+
box: heading(id)?.getBoundingClientRect()
|
|
34
42
|
}));
|
|
35
43
|
let next = ids[0];
|
|
36
44
|
for (const heading of headings) if (heading.box && heading.box.top <= line) next = heading.id;
|
|
@@ -51,7 +59,7 @@ export function TableOfContents(props) {
|
|
|
51
59
|
window.addEventListener("resize", schedule);
|
|
52
60
|
const observer = typeof ResizeObserver === "undefined" ? undefined : new ResizeObserver(schedule);
|
|
53
61
|
// No scroll or window resize happens when the root, a block above a heading, or a heading's own section changes size.
|
|
54
|
-
const observed = new Set([root ?? document.documentElement, ...(root?.children ?? [document.body]), ...ids.map(id =>
|
|
62
|
+
const observed = new Set([root ?? document.documentElement, ...(root?.children ?? [document.body]), ...ids.map(id => heading(id)?.parentElement)]);
|
|
55
63
|
for (const element of observed) if (element) observer?.observe(element);
|
|
56
64
|
untrack(update);
|
|
57
65
|
onCleanup(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["layout/TableOfContents.tsx"],"sourcesContent":["import { createEffect, createSignal, createUniqueId, For, type JSX, onCleanup, Show, untrack } from \"solid-js\";\nimport type { MaybeAccessor } from \"../inputs/field-contract\";\nimport { resolveMaybeAccessor } from \"../inputs/field-contract\";\nimport { assertStableUiId } from \"./stable-id\";\nimport { useTableOfContentsMessages } from \"./table-of-contents-messages\";\n\nexport type TableOfContentsItem = { id: string; label: string };\nexport type TableOfContentsProps = {\n items: readonly TableOfContentsItem[];\n /** Visible heading and navigation name. Defaults to the localized \"On this page\". */\n title?: string;\n /** Element whose scrolling decides the active section. Defaults to the window. */\n scrollRoot?: MaybeAccessor<HTMLElement | undefined>;\n /** Stay in view inside the caller's layout. */\n sticky?: boolean;\n /** Called when another section becomes active. */\n onActiveChange?: (id: string | undefined) => void;\n class?: string;\n};\n\n/**\n * Native section links with a scroll spy on the window or a content container.\n * @example <TableOfContents items={[{ id: \"sharing\", label: \"Sharing\" }]} sticky />\n */\nexport function TableOfContents(props: TableOfContentsProps): JSX.Element {\n const t = useTableOfContentsMessages();\n const headingId = assertStableUiId(`k2b-toc-${createUniqueId().replace(/[^a-zA-Z0-9_-]/g, \"-\")}`, \"TableOfContents heading id\");\n const [active, setActive] = createSignal(props.items[0]?.id);\n createEffect(() => {\n // Reading every id here makes a changed id or a store update recompute the active section.\n const ids = props.items.map((item) => item.id);\n const root = resolveMaybeAccessor(props.scrollRoot);\n const target = root ?? window;\n let frame: number | undefined;\n const update = () => {\n frame = undefined;\n const box = root?.getBoundingClientRect();\n const top = box ? box.top + (root?.clientTop ?? 0) : 0;\n const height = root?.clientHeight ?? window.innerHeight;\n const line = top + height / 4;\n const headings = ids.map((id) => ({ id, box:
|
|
1
|
+
{"version":3,"names":[],"sources":["layout/TableOfContents.tsx"],"sourcesContent":["import { createEffect, createSignal, createUniqueId, For, type JSX, onCleanup, Show, untrack } from \"solid-js\";\nimport type { MaybeAccessor } from \"../inputs/field-contract\";\nimport { resolveMaybeAccessor } from \"../inputs/field-contract\";\nimport { assertStableUiId } from \"./stable-id\";\nimport { useTableOfContentsMessages } from \"./table-of-contents-messages\";\n\nexport type TableOfContentsItem = { id: string; label: string };\nexport type TableOfContentsProps = {\n items: readonly TableOfContentsItem[];\n /** Visible heading and navigation name. Defaults to the localized \"On this page\". */\n title?: string;\n /** Element whose scrolling decides the active section. Defaults to the window. */\n scrollRoot?: MaybeAccessor<HTMLElement | undefined>;\n /** Element that contains the section headings. Defaults to the document. */\n contentRoot?: MaybeAccessor<HTMLElement | undefined>;\n /** Stay in view inside the caller's layout. */\n sticky?: boolean;\n /** Called when another section becomes active. */\n onActiveChange?: (id: string | undefined) => void;\n class?: string;\n};\n\n/**\n * Native section links with a scroll spy on the window or a content container.\n * @example <TableOfContents items={[{ id: \"sharing\", label: \"Sharing\" }]} sticky />\n */\nexport function TableOfContents(props: TableOfContentsProps): JSX.Element {\n const t = useTableOfContentsMessages();\n const headingId = assertStableUiId(`k2b-toc-${createUniqueId().replace(/[^a-zA-Z0-9_-]/g, \"-\")}`, \"TableOfContents heading id\");\n const [active, setActive] = createSignal(props.items[0]?.id);\n createEffect(() => {\n // Reading every id here makes a changed id or a store update recompute the active section.\n const ids = props.items.map((item) => item.id);\n const root = resolveMaybeAccessor(props.scrollRoot);\n const content = resolveMaybeAccessor(props.contentRoot);\n const heading = (id: string): Element | null => {\n const element = document.getElementById(id);\n if (!content || (element && content.contains(element))) return element;\n // The same id elsewhere on the page, or a root outside the document tree, needs a lookup within the root.\n for (const candidate of content.querySelectorAll(\"[id]\")) if (candidate.id === id) return candidate;\n return null;\n };\n const target = root ?? window;\n let frame: number | undefined;\n const update = () => {\n frame = undefined;\n const box = root?.getBoundingClientRect();\n const top = box ? box.top + (root?.clientTop ?? 0) : 0;\n const height = root?.clientHeight ?? window.innerHeight;\n const line = top + height / 4;\n const headings = ids.map((id) => ({ id, box: heading(id)?.getBoundingClientRect() }));\n let next = ids[0];\n for (const heading of headings) if (heading.box && heading.box.top <= line) next = heading.id;\n const last = headings.at(-1);\n const atEnd = root\n ? root.scrollHeight - root.clientHeight - root.scrollTop <= 4\n : document.documentElement.scrollHeight - window.innerHeight - window.scrollY <= 4;\n if (atEnd && last?.box && last.box.top < top + height && last.box.bottom > top) next = last.id;\n if (next !== active()) {\n setActive(next);\n props.onActiveChange?.(next);\n }\n };\n const schedule = () => {\n if (frame === undefined) frame = requestAnimationFrame(update);\n };\n target.addEventListener(\"scroll\", schedule, { passive: true });\n window.addEventListener(\"resize\", schedule);\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(schedule);\n // No scroll or window resize happens when the root, a block above a heading, or a heading's own section changes size.\n const observed = new Set<Element | null | undefined>([\n root ?? document.documentElement,\n ...(root?.children ?? [document.body]),\n ...ids.map((id) => heading(id)?.parentElement),\n ]);\n for (const element of observed) if (element) observer?.observe(element);\n untrack(update);\n onCleanup(() => {\n target.removeEventListener(\"scroll\", schedule);\n window.removeEventListener(\"resize\", schedule);\n observer?.disconnect();\n if (frame !== undefined) cancelAnimationFrame(frame);\n });\n });\n return (\n <Show when={props.items.length > 0}>\n <nav\n class={`k2b-toc${props.class ? ` ${props.class}` : \"\"}`}\n data-sticky={props.sticky ? \"true\" : undefined}\n aria-labelledby={headingId}\n >\n <p class=\"k2b-toc__title\" id={headingId}>\n {props.title ?? t().title}\n </p>\n <ol class=\"k2b-toc__list\">\n <For each={props.items}>\n {(item) => (\n <li>\n <a class=\"k2b-toc__link\" href={`#${item.id}`} aria-current={active() === item.id ? \"location\" : undefined}>\n {item.label}\n </a>\n </li>\n )}\n </For>\n </ol>\n </nav>\n </Show>\n );\n}\nexport default TableOfContents;\n"],"mappings":"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","ignoreList":[]}
|