@k2b/ui 0.27.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 +581 -397
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +19 -1
- package/dist/browser/chat/chat-messages.js.map +1 -1
- package/dist/browser/chat/command-search.js +3 -0
- package/dist/browser/chat/command-search.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/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/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 +9 -0
- 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/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/detail-panel-messages.js +35 -0
- package/dist/browser/layout/detail-panel-messages.js.map +1 -0
- 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 +263 -89
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +19 -1
- package/dist/ssr/chat/chat-messages.js.map +1 -1
- package/dist/ssr/chat/command-search.js +3 -0
- package/dist/ssr/chat/command-search.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/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/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 +9 -0
- 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/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/detail-panel-messages.js +35 -0
- package/dist/ssr/layout/detail-panel-messages.js.map +1 -0
- 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 +7 -0
- package/dist/types/chat/chat-messages.d.ts +10 -2
- package/dist/types/chat/command-search.d.ts +2 -0
- package/dist/types/chat/index.d.ts +2 -0
- 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 +2 -0
- package/dist/types/inputs/file-drop.d.ts +2 -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/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 +6 -1
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import { template as _$template } from "solid-js/web";
|
|
2
|
+
import { delegateEvents as _$delegateEvents } from "solid-js/web";
|
|
3
|
+
import { runHydrationEvents as _$runHydrationEvents } from "solid-js/web";
|
|
4
|
+
import { use as _$use } from "solid-js/web";
|
|
5
|
+
import { setAttribute as _$setAttribute } from "solid-js/web";
|
|
6
|
+
import { className as _$className } from "solid-js/web";
|
|
7
|
+
import { effect as _$effect } from "solid-js/web";
|
|
8
|
+
import { getNextMarker as _$getNextMarker } from "solid-js/web";
|
|
9
|
+
import { getNextElement as _$getNextElement } from "solid-js/web";
|
|
10
|
+
import { insert as _$insert } from "solid-js/web";
|
|
11
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
12
|
+
var _tmpl$ = /*#__PURE__*/_$template(`<span class=k2b-avatar-stack__row-badge>`),
|
|
13
|
+
_tmpl$2 = /*#__PURE__*/_$template(`<span class=k2b-avatar-stack__row-detail><!$><!/><span>`),
|
|
14
|
+
_tmpl$3 = /*#__PURE__*/_$template(`<span class=k2b-avatar-stack__row-copy><span class=k2b-avatar-stack__row-name><span></span><!$><!/></span><!$><!/>`),
|
|
15
|
+
_tmpl$4 = /*#__PURE__*/_$template(`<span class=k2b-avatar-stack__row-trailing>`),
|
|
16
|
+
_tmpl$5 = /*#__PURE__*/_$template(`<i aria-hidden=true>`),
|
|
17
|
+
_tmpl$6 = /*#__PURE__*/_$template(`<li>`),
|
|
18
|
+
_tmpl$7 = /*#__PURE__*/_$template(`<div class=k2b-avatar-stack__row>`),
|
|
19
|
+
_tmpl$8 = /*#__PURE__*/_$template(`<button type=button class=k2b-avatar-stack__row>`),
|
|
20
|
+
_tmpl$9 = /*#__PURE__*/_$template(`<ul class=k2b-avatar-stack__rows tabindex=-1><!$><!/><!$><!/>`),
|
|
21
|
+
_tmpl$0 = /*#__PURE__*/_$template(`<header class=k2b-avatar-stack__header><h3></h3><span class=k2b-count-chip>`),
|
|
22
|
+
_tmpl$1 = /*#__PURE__*/_$template(`<p class=k2b-avatar-stack__hint>`),
|
|
23
|
+
_tmpl$10 = /*#__PURE__*/_$template(`<div class=k2b-avatar-stack__sheet role=group>`),
|
|
24
|
+
_tmpl$11 = /*#__PURE__*/_$template(`<span class=k2b-avatar-stack__more aria-hidden=true>+<!$><!/>`),
|
|
25
|
+
_tmpl$12 = /*#__PURE__*/_$template(`<span><button type=button class=k2b-avatar-stack__trigger aria-haspopup=dialog><span class=k2b-avatar-stack__faces aria-hidden=true></span><!$><!/></button><div popover=auto role=dialog class=k2b-avatar-stack__popover>`);
|
|
26
|
+
import { createMemo, createSignal, createUniqueId, For, onCleanup, onMount, Show } from "solid-js";
|
|
27
|
+
import { dropdownPosition } from "../actions/Dropdown";
|
|
28
|
+
import { prefersMenuSheet } from "../actions/menu-sheet";
|
|
29
|
+
import { dialogCore } from "../feedback/dialog-core";
|
|
30
|
+
import { LocaleProvider, useLocale } from "../intl/locale";
|
|
31
|
+
import BottomSheet, { bottomSheetOptions } from "../layout/BottomSheet";
|
|
32
|
+
import { Avatar } from "./Avatar";
|
|
33
|
+
import { useAvatarMessages } from "./avatar-messages";
|
|
34
|
+
const PersonRows = props => {
|
|
35
|
+
let list;
|
|
36
|
+
/**
|
|
37
|
+
* A focused row that stops being a button (the person can no longer be chosen) or leaves hands focus to the nearest
|
|
38
|
+
* row that still is one, else to the list, so focus never drops out of the open list.
|
|
39
|
+
*/
|
|
40
|
+
const keepFocus = button => {
|
|
41
|
+
if (!button.contains(document.activeElement)) return;
|
|
42
|
+
const buttons = Array.from(list.querySelectorAll("button.k2b-avatar-stack__row"));
|
|
43
|
+
const index = buttons.indexOf(button);
|
|
44
|
+
const candidates = [...buttons.slice(index + 1), ...buttons.slice(0, Math.max(0, index)).reverse()];
|
|
45
|
+
queueMicrotask(() => {
|
|
46
|
+
if (!list.isConnected) return;
|
|
47
|
+
(candidates.find(candidate => candidate.isConnected) ?? list).focus();
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const others = () => props.people.filter(person => !person.self);
|
|
51
|
+
const selves = () => props.people.filter(person => person.self);
|
|
52
|
+
// A row reads its person through an accessor, so a live update changes the row in place and a focused row keeps focus.
|
|
53
|
+
const row = person => {
|
|
54
|
+
const content = [_$createComponent(Avatar, {
|
|
55
|
+
get name() {
|
|
56
|
+
return person().name;
|
|
57
|
+
},
|
|
58
|
+
get src() {
|
|
59
|
+
return person().src;
|
|
60
|
+
},
|
|
61
|
+
get icon() {
|
|
62
|
+
return person().icon;
|
|
63
|
+
},
|
|
64
|
+
get shape() {
|
|
65
|
+
return person().shape;
|
|
66
|
+
},
|
|
67
|
+
size: "sm"
|
|
68
|
+
}), (() => {
|
|
69
|
+
var _el$ = _$getNextElement(_tmpl$3),
|
|
70
|
+
_el$2 = _el$.firstChild,
|
|
71
|
+
_el$3 = _el$2.firstChild,
|
|
72
|
+
_el$5 = _el$3.nextSibling,
|
|
73
|
+
[_el$6, _co$] = _$getNextMarker(_el$5.nextSibling),
|
|
74
|
+
_el$1 = _el$2.nextSibling,
|
|
75
|
+
[_el$10, _co$3] = _$getNextMarker(_el$1.nextSibling);
|
|
76
|
+
_$insert(_el$3, () => person().name);
|
|
77
|
+
_$insert(_el$2, _$createComponent(Show, {
|
|
78
|
+
get when() {
|
|
79
|
+
return person().badge;
|
|
80
|
+
},
|
|
81
|
+
get children() {
|
|
82
|
+
var _el$4 = _$getNextElement(_tmpl$);
|
|
83
|
+
_$insert(_el$4, () => person().badge);
|
|
84
|
+
return _el$4;
|
|
85
|
+
}
|
|
86
|
+
}), _el$6, _co$);
|
|
87
|
+
_$insert(_el$, _$createComponent(Show, {
|
|
88
|
+
get when() {
|
|
89
|
+
return person().detail;
|
|
90
|
+
},
|
|
91
|
+
get children() {
|
|
92
|
+
var _el$7 = _$getNextElement(_tmpl$2),
|
|
93
|
+
_el$9 = _el$7.firstChild,
|
|
94
|
+
[_el$0, _co$2] = _$getNextMarker(_el$9.nextSibling),
|
|
95
|
+
_el$8 = _el$0.nextSibling;
|
|
96
|
+
_$insert(_el$7, _$createComponent(Show, {
|
|
97
|
+
get when() {
|
|
98
|
+
return person().detailIcon;
|
|
99
|
+
},
|
|
100
|
+
children: icon => (() => {
|
|
101
|
+
var _el$12 = _$getNextElement(_tmpl$5);
|
|
102
|
+
_$effect(() => _$className(_el$12, icon()));
|
|
103
|
+
return _el$12;
|
|
104
|
+
})()
|
|
105
|
+
}), _el$0, _co$2);
|
|
106
|
+
_$insert(_el$8, () => person().detail);
|
|
107
|
+
return _el$7;
|
|
108
|
+
}
|
|
109
|
+
}), _el$10, _co$3);
|
|
110
|
+
return _el$;
|
|
111
|
+
})(), _$createComponent(Show, {
|
|
112
|
+
get when() {
|
|
113
|
+
return person().trailing;
|
|
114
|
+
},
|
|
115
|
+
get children() {
|
|
116
|
+
var _el$11 = _$getNextElement(_tmpl$4);
|
|
117
|
+
_$insert(_el$11, () => person().trailing);
|
|
118
|
+
return _el$11;
|
|
119
|
+
}
|
|
120
|
+
})];
|
|
121
|
+
return (() => {
|
|
122
|
+
var _el$13 = _$getNextElement(_tmpl$6);
|
|
123
|
+
_$insert(_el$13, _$createComponent(Show, {
|
|
124
|
+
get when() {
|
|
125
|
+
return Boolean(person().onSelect);
|
|
126
|
+
},
|
|
127
|
+
get fallback() {
|
|
128
|
+
return (() => {
|
|
129
|
+
var _el$14 = _$getNextElement(_tmpl$7);
|
|
130
|
+
_$insert(_el$14, content);
|
|
131
|
+
return _el$14;
|
|
132
|
+
})();
|
|
133
|
+
},
|
|
134
|
+
get children() {
|
|
135
|
+
return (() => {
|
|
136
|
+
let button;
|
|
137
|
+
// Browser only: a server render never mounts the button.
|
|
138
|
+
onMount(() => onCleanup(() => keepFocus(button)));
|
|
139
|
+
return (() => {
|
|
140
|
+
var _el$15 = _$getNextElement(_tmpl$8);
|
|
141
|
+
_el$15.$$click = () => props.choose(person());
|
|
142
|
+
var _ref$ = button;
|
|
143
|
+
typeof _ref$ === "function" ? _$use(_ref$, _el$15) : button = _el$15;
|
|
144
|
+
_$insert(_el$15, content);
|
|
145
|
+
_$runHydrationEvents();
|
|
146
|
+
return _el$15;
|
|
147
|
+
})();
|
|
148
|
+
})();
|
|
149
|
+
}
|
|
150
|
+
}));
|
|
151
|
+
_$effect(() => _$setAttribute(_el$13, "data-self", person().self ? "true" : undefined));
|
|
152
|
+
return _el$13;
|
|
153
|
+
})();
|
|
154
|
+
};
|
|
155
|
+
// Rows follow each person by id: a row stays with its person when others leave or the order changes, and still
|
|
156
|
+
// shows that person's latest details.
|
|
157
|
+
const byId = createMemo(() => new Map(props.people.map(person => [person.id, person])));
|
|
158
|
+
const keyed = id => row(() => byId().get(id) ?? {
|
|
159
|
+
id,
|
|
160
|
+
name: ""
|
|
161
|
+
});
|
|
162
|
+
return (() => {
|
|
163
|
+
var _el$16 = _$getNextElement(_tmpl$9),
|
|
164
|
+
_el$17 = _el$16.firstChild,
|
|
165
|
+
[_el$18, _co$4] = _$getNextMarker(_el$17.nextSibling),
|
|
166
|
+
_el$19 = _el$18.nextSibling,
|
|
167
|
+
[_el$20, _co$5] = _$getNextMarker(_el$19.nextSibling);
|
|
168
|
+
var _ref$2 = list;
|
|
169
|
+
typeof _ref$2 === "function" ? _$use(_ref$2, _el$16) : list = _el$16;
|
|
170
|
+
_$insert(_el$16, _$createComponent(For, {
|
|
171
|
+
get each() {
|
|
172
|
+
return others().map(person => person.id);
|
|
173
|
+
},
|
|
174
|
+
children: keyed
|
|
175
|
+
}), _el$18, _co$4);
|
|
176
|
+
_$insert(_el$16, _$createComponent(For, {
|
|
177
|
+
get each() {
|
|
178
|
+
return selves().map(person => person.id);
|
|
179
|
+
},
|
|
180
|
+
children: keyed
|
|
181
|
+
}), _el$20, _co$5);
|
|
182
|
+
return _el$16;
|
|
183
|
+
})();
|
|
184
|
+
};
|
|
185
|
+
const PeopleList = props => [(() => {
|
|
186
|
+
var _el$21 = _$getNextElement(_tmpl$0),
|
|
187
|
+
_el$22 = _el$21.firstChild,
|
|
188
|
+
_el$23 = _el$22.nextSibling;
|
|
189
|
+
_$insert(_el$22, () => props.title);
|
|
190
|
+
_$insert(_el$23, () => props.people.length);
|
|
191
|
+
_$effect(() => _$setAttribute(_el$22, "id", props.titleId));
|
|
192
|
+
return _el$21;
|
|
193
|
+
})(), _$createComponent(PersonRows, {
|
|
194
|
+
get people() {
|
|
195
|
+
return props.people;
|
|
196
|
+
},
|
|
197
|
+
get choose() {
|
|
198
|
+
return props.choose;
|
|
199
|
+
}
|
|
200
|
+
}), _$createComponent(Show, {
|
|
201
|
+
get when() {
|
|
202
|
+
return props.hint;
|
|
203
|
+
},
|
|
204
|
+
get children() {
|
|
205
|
+
var _el$24 = _$getNextElement(_tmpl$1);
|
|
206
|
+
_$insert(_el$24, () => props.hint);
|
|
207
|
+
return _el$24;
|
|
208
|
+
}
|
|
209
|
+
})];
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* A few overlapping faces, then "+n", as one button. It opens the full list of people beside it, or as a bottom sheet
|
|
213
|
+
* on phones. People with `self` are listed last and never shown in the stack.
|
|
214
|
+
*/
|
|
215
|
+
export function AvatarStack(props) {
|
|
216
|
+
const locale = useLocale();
|
|
217
|
+
const messages = useAvatarMessages();
|
|
218
|
+
const id = createUniqueId().replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
219
|
+
const popoverId = `k2b-avatar-stack-${id}`;
|
|
220
|
+
const titleId = `${popoverId}-title`;
|
|
221
|
+
const [open, setOpen] = createSignal(false);
|
|
222
|
+
let trigger;
|
|
223
|
+
let popover;
|
|
224
|
+
let sheetOpen = false;
|
|
225
|
+
const disposed = new AbortController();
|
|
226
|
+
onCleanup(() => disposed.abort());
|
|
227
|
+
const faces = () => props.people.filter(person => !person.self);
|
|
228
|
+
const max = () => Math.max(1, props.max ?? 3);
|
|
229
|
+
const shown = () => faces().slice(0, max());
|
|
230
|
+
const more = () => Math.max(0, faces().length - max());
|
|
231
|
+
const place = () => {
|
|
232
|
+
const rect = dropdownPosition(trigger.getBoundingClientRect(), popover.getBoundingClientRect(), "bottom-left", {
|
|
233
|
+
width: window.innerWidth,
|
|
234
|
+
height: window.innerHeight
|
|
235
|
+
});
|
|
236
|
+
popover.style.left = `${rect.left}px`;
|
|
237
|
+
popover.style.top = `${rect.top}px`;
|
|
238
|
+
};
|
|
239
|
+
// Like a dropdown menu, the open list follows its trigger when the window resizes or scrolls, and its own size.
|
|
240
|
+
let resizeObserver;
|
|
241
|
+
const follow = on => {
|
|
242
|
+
const method = on ? "addEventListener" : "removeEventListener";
|
|
243
|
+
window[method]("resize", place);
|
|
244
|
+
window[method]("scroll", place, true);
|
|
245
|
+
if (on && typeof ResizeObserver !== "undefined") {
|
|
246
|
+
resizeObserver ??= new ResizeObserver(place);
|
|
247
|
+
resizeObserver.observe(popover);
|
|
248
|
+
} else resizeObserver?.disconnect();
|
|
249
|
+
};
|
|
250
|
+
// Only the browser ever follows; a server render has no window to let go of.
|
|
251
|
+
onMount(() => onCleanup(() => follow(false)));
|
|
252
|
+
const openSheet = () => {
|
|
253
|
+
if (sheetOpen) return;
|
|
254
|
+
sheetOpen = true;
|
|
255
|
+
setOpen(true);
|
|
256
|
+
let chosen;
|
|
257
|
+
const current = locale();
|
|
258
|
+
void dialogCore.open((close, context) => _$createComponent(LocaleProvider, {
|
|
259
|
+
locale: current,
|
|
260
|
+
get children() {
|
|
261
|
+
return _$createComponent(BottomSheet, {
|
|
262
|
+
get onDismiss() {
|
|
263
|
+
return context.requestDismiss;
|
|
264
|
+
},
|
|
265
|
+
get children() {
|
|
266
|
+
return _$createComponent(BottomSheet.Body, {
|
|
267
|
+
get children() {
|
|
268
|
+
var _el$25 = _$getNextElement(_tmpl$10);
|
|
269
|
+
_$setAttribute(_el$25, "aria-labelledby", `${titleId}-sheet`);
|
|
270
|
+
_$insert(_el$25, _$createComponent(PeopleList, {
|
|
271
|
+
get people() {
|
|
272
|
+
return props.people;
|
|
273
|
+
},
|
|
274
|
+
get title() {
|
|
275
|
+
return props.title;
|
|
276
|
+
},
|
|
277
|
+
titleId: `${titleId}-sheet`,
|
|
278
|
+
get hint() {
|
|
279
|
+
return props.hint;
|
|
280
|
+
},
|
|
281
|
+
choose: person => {
|
|
282
|
+
chosen = person;
|
|
283
|
+
close();
|
|
284
|
+
}
|
|
285
|
+
}));
|
|
286
|
+
return _el$25;
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}), {
|
|
293
|
+
...bottomSheetOptions,
|
|
294
|
+
ariaLabel: props.title,
|
|
295
|
+
history: true,
|
|
296
|
+
signal: disposed.signal
|
|
297
|
+
}).then(() => chosen?.onSelect?.()).finally(() => {
|
|
298
|
+
sheetOpen = false;
|
|
299
|
+
setOpen(false);
|
|
300
|
+
});
|
|
301
|
+
};
|
|
302
|
+
const toggle = () => {
|
|
303
|
+
if (prefersMenuSheet()) {
|
|
304
|
+
openSheet();
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (popover.matches(":popover-open")) {
|
|
308
|
+
popover.hidePopover();
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
popover.showPopover();
|
|
312
|
+
place();
|
|
313
|
+
};
|
|
314
|
+
return (() => {
|
|
315
|
+
var _el$26 = _$getNextElement(_tmpl$12),
|
|
316
|
+
_el$27 = _el$26.firstChild,
|
|
317
|
+
_el$28 = _el$27.firstChild,
|
|
318
|
+
_el$33 = _el$28.nextSibling,
|
|
319
|
+
[_el$34, _co$7] = _$getNextMarker(_el$33.nextSibling),
|
|
320
|
+
_el$35 = _el$27.nextSibling;
|
|
321
|
+
_el$27.$$click = toggle;
|
|
322
|
+
var _ref$3 = trigger;
|
|
323
|
+
typeof _ref$3 === "function" ? _$use(_ref$3, _el$27) : trigger = _el$27;
|
|
324
|
+
_$setAttribute(_el$27, "aria-controls", popoverId);
|
|
325
|
+
_$insert(_el$28, _$createComponent(For, {
|
|
326
|
+
get each() {
|
|
327
|
+
return shown();
|
|
328
|
+
},
|
|
329
|
+
children: person => _$createComponent(Avatar, {
|
|
330
|
+
get name() {
|
|
331
|
+
return person.name;
|
|
332
|
+
},
|
|
333
|
+
get src() {
|
|
334
|
+
return person.src;
|
|
335
|
+
},
|
|
336
|
+
get icon() {
|
|
337
|
+
return person.icon;
|
|
338
|
+
},
|
|
339
|
+
get shape() {
|
|
340
|
+
return person.shape;
|
|
341
|
+
},
|
|
342
|
+
size: "xs",
|
|
343
|
+
alt: ""
|
|
344
|
+
})
|
|
345
|
+
}));
|
|
346
|
+
_$insert(_el$27, _$createComponent(Show, {
|
|
347
|
+
get when() {
|
|
348
|
+
return more() > 0;
|
|
349
|
+
},
|
|
350
|
+
get children() {
|
|
351
|
+
var _el$29 = _$getNextElement(_tmpl$11),
|
|
352
|
+
_el$30 = _el$29.firstChild,
|
|
353
|
+
_el$31 = _el$30.nextSibling,
|
|
354
|
+
[_el$32, _co$6] = _$getNextMarker(_el$31.nextSibling);
|
|
355
|
+
_$insert(_el$29, more, _el$32, _co$6);
|
|
356
|
+
_$effect(() => _$setAttribute(_el$29, "title", messages().moreCount({
|
|
357
|
+
count: more()
|
|
358
|
+
})));
|
|
359
|
+
return _el$29;
|
|
360
|
+
}
|
|
361
|
+
}), _el$34, _co$7);
|
|
362
|
+
_el$35.addEventListener("toggle", event => {
|
|
363
|
+
const next = event.newState === "open";
|
|
364
|
+
setOpen(next);
|
|
365
|
+
follow(next);
|
|
366
|
+
if (!next && document.activeElement && popover.contains(document.activeElement)) trigger.focus();
|
|
367
|
+
});
|
|
368
|
+
var _ref$4 = popover;
|
|
369
|
+
typeof _ref$4 === "function" ? _$use(_ref$4, _el$35) : popover = _el$35;
|
|
370
|
+
_$setAttribute(_el$35, "id", popoverId);
|
|
371
|
+
_$setAttribute(_el$35, "aria-labelledby", titleId);
|
|
372
|
+
_$insert(_el$35, _$createComponent(PeopleList, {
|
|
373
|
+
get people() {
|
|
374
|
+
return props.people;
|
|
375
|
+
},
|
|
376
|
+
get title() {
|
|
377
|
+
return props.title;
|
|
378
|
+
},
|
|
379
|
+
titleId: titleId,
|
|
380
|
+
get hint() {
|
|
381
|
+
return props.hint;
|
|
382
|
+
},
|
|
383
|
+
choose: person => {
|
|
384
|
+
if (open()) popover.hidePopover();
|
|
385
|
+
person.onSelect?.();
|
|
386
|
+
}
|
|
387
|
+
}));
|
|
388
|
+
_$effect(_p$ => {
|
|
389
|
+
var _v$ = `k2b-avatar-stack ${props.class ?? ""}`,
|
|
390
|
+
_v$2 = props.label,
|
|
391
|
+
_v$3 = open();
|
|
392
|
+
_v$ !== _p$.e && _$className(_el$26, _p$.e = _v$);
|
|
393
|
+
_v$2 !== _p$.t && _$setAttribute(_el$27, "aria-label", _p$.t = _v$2);
|
|
394
|
+
_v$3 !== _p$.a && _$setAttribute(_el$27, "aria-expanded", _p$.a = _v$3);
|
|
395
|
+
return _p$;
|
|
396
|
+
}, {
|
|
397
|
+
e: undefined,
|
|
398
|
+
t: undefined,
|
|
399
|
+
a: undefined
|
|
400
|
+
});
|
|
401
|
+
_$runHydrationEvents();
|
|
402
|
+
return _el$26;
|
|
403
|
+
})();
|
|
404
|
+
}
|
|
405
|
+
_$delegateEvents(["click"]);
|
|
406
|
+
//# sourceMappingURL=AvatarStack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/AvatarStack.tsx"],"sourcesContent":["import { createMemo, createSignal, createUniqueId, For, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { dropdownPosition } from \"../actions/Dropdown\";\nimport { prefersMenuSheet } from \"../actions/menu-sheet\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { LocaleProvider, useLocale } from \"../intl/locale\";\nimport BottomSheet, { bottomSheetOptions } from \"../layout/BottomSheet\";\nimport { Avatar, type AvatarShape } from \"./Avatar\";\nimport { useAvatarMessages } from \"./avatar-messages\";\n\nexport type AvatarStackPerson = {\n /** Stable key, such as the account id. */\n id: string;\n name: string;\n src?: string | null;\n /** Shown instead of initials when there is no picture. */\n icon?: string;\n /** `square` for agents and service accounts. */\n shape?: AvatarShape;\n /** A short tag after the name, such as \"Agent\". */\n badge?: JSX.Element;\n /** One line below the name; it ends with an ellipsis instead of wrapping. */\n detail?: JSX.Element;\n /** Icon class before `detail`. */\n detailIcon?: string;\n /** Short text at the end of the row, such as \"2 tabs\". */\n trailing?: JSX.Element;\n /** The person viewing: listed last, below a gap, and never in the stack. */\n self?: boolean;\n /** Makes the row a button. The list closes first. */\n onSelect?: () => void;\n};\n\nexport type AvatarStackProps = {\n people: readonly AvatarStackPerson[];\n /** Title of the list that the stack opens, such as \"Here now\". */\n title: string;\n /** Accessible name of the stack button, such as \"Here now: Jana Berger and 2 more\". */\n label: string;\n /** One quiet line below the list. */\n hint?: JSX.Element;\n /** Faces before \"+n\". Defaults to 3. */\n max?: number;\n class?: string;\n};\n\nconst PersonRows = (props: { people: readonly AvatarStackPerson[]; choose: (person: AvatarStackPerson) => void }): JSX.Element => {\n let list!: HTMLUListElement;\n /**\n * A focused row that stops being a button (the person can no longer be chosen) or leaves hands focus to the nearest\n * row that still is one, else to the list, so focus never drops out of the open list.\n */\n const keepFocus = (button: HTMLButtonElement) => {\n if (!button.contains(document.activeElement)) return;\n const buttons = Array.from(list.querySelectorAll<HTMLButtonElement>(\"button.k2b-avatar-stack__row\"));\n const index = buttons.indexOf(button);\n const candidates = [...buttons.slice(index + 1), ...buttons.slice(0, Math.max(0, index)).reverse()];\n queueMicrotask(() => {\n if (!list.isConnected) return;\n (candidates.find((candidate) => candidate.isConnected) ?? list).focus();\n });\n };\n const others = () => props.people.filter((person) => !person.self);\n const selves = () => props.people.filter((person) => person.self);\n // A row reads its person through an accessor, so a live update changes the row in place and a focused row keeps focus.\n const row = (person: () => AvatarStackPerson) => {\n const content = (\n <>\n <Avatar name={person().name} src={person().src} icon={person().icon} shape={person().shape} size=\"sm\" />\n <span class=\"k2b-avatar-stack__row-copy\">\n <span class=\"k2b-avatar-stack__row-name\">\n <span>{person().name}</span>\n <Show when={person().badge}>\n <span class=\"k2b-avatar-stack__row-badge\">{person().badge}</span>\n </Show>\n </span>\n <Show when={person().detail}>\n <span class=\"k2b-avatar-stack__row-detail\">\n <Show when={person().detailIcon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>\n <span>{person().detail}</span>\n </span>\n </Show>\n </span>\n <Show when={person().trailing}>\n <span class=\"k2b-avatar-stack__row-trailing\">{person().trailing}</span>\n </Show>\n </>\n );\n return (\n <li data-self={person().self ? \"true\" : undefined}>\n <Show when={Boolean(person().onSelect)} fallback={<div class=\"k2b-avatar-stack__row\">{content}</div>}>\n {(() => {\n let button!: HTMLButtonElement;\n // Browser only: a server render never mounts the button.\n onMount(() => onCleanup(() => keepFocus(button)));\n return (\n <button ref={button} type=\"button\" class=\"k2b-avatar-stack__row\" onClick={() => props.choose(person())}>\n {content}\n </button>\n );\n })()}\n </Show>\n </li>\n );\n };\n // Rows follow each person by id: a row stays with its person when others leave or the order changes, and still\n // shows that person's latest details.\n const byId = createMemo(() => new Map(props.people.map((person) => [person.id, person])));\n const keyed = (id: string) => row(() => byId().get(id) ?? { id, name: \"\" });\n return (\n <ul ref={list} class=\"k2b-avatar-stack__rows\" tabIndex={-1}>\n <For each={others().map((person) => person.id)}>{keyed}</For>\n <For each={selves().map((person) => person.id)}>{keyed}</For>\n </ul>\n );\n};\n\nconst PeopleList = (props: {\n people: readonly AvatarStackPerson[];\n title: string;\n titleId: string;\n hint?: JSX.Element;\n choose: (person: AvatarStackPerson) => void;\n}): JSX.Element => (\n <>\n <header class=\"k2b-avatar-stack__header\">\n <h3 id={props.titleId}>{props.title}</h3>\n <span class=\"k2b-count-chip\">{props.people.length}</span>\n </header>\n <PersonRows people={props.people} choose={props.choose} />\n <Show when={props.hint}>\n <p class=\"k2b-avatar-stack__hint\">{props.hint}</p>\n </Show>\n </>\n);\n\n/**\n * A few overlapping faces, then \"+n\", as one button. It opens the full list of people beside it, or as a bottom sheet\n * on phones. People with `self` are listed last and never shown in the stack.\n */\nexport function AvatarStack(props: AvatarStackProps): JSX.Element {\n const locale = useLocale();\n const messages = useAvatarMessages();\n const id = createUniqueId().replace(/[^a-zA-Z0-9_-]/g, \"-\");\n const popoverId = `k2b-avatar-stack-${id}`;\n const titleId = `${popoverId}-title`;\n const [open, setOpen] = createSignal(false);\n let trigger!: HTMLButtonElement;\n let popover!: HTMLDivElement;\n let sheetOpen = false;\n const disposed = new AbortController();\n onCleanup(() => disposed.abort());\n\n const faces = () => props.people.filter((person) => !person.self);\n const max = () => Math.max(1, props.max ?? 3);\n const shown = () => faces().slice(0, max());\n const more = () => Math.max(0, faces().length - max());\n\n const place = () => {\n const rect = dropdownPosition(trigger.getBoundingClientRect(), popover.getBoundingClientRect(), \"bottom-left\", {\n width: window.innerWidth,\n height: window.innerHeight,\n });\n popover.style.left = `${rect.left}px`;\n popover.style.top = `${rect.top}px`;\n };\n // Like a dropdown menu, the open list follows its trigger when the window resizes or scrolls, and its own size.\n let resizeObserver: ResizeObserver | undefined;\n const follow = (on: boolean) => {\n const method = on ? \"addEventListener\" : \"removeEventListener\";\n window[method](\"resize\", place);\n window[method](\"scroll\", place, true);\n if (on && typeof ResizeObserver !== \"undefined\") {\n resizeObserver ??= new ResizeObserver(place);\n resizeObserver.observe(popover);\n } else resizeObserver?.disconnect();\n };\n // Only the browser ever follows; a server render has no window to let go of.\n onMount(() => onCleanup(() => follow(false)));\n\n const openSheet = () => {\n if (sheetOpen) return;\n sheetOpen = true;\n setOpen(true);\n let chosen: AvatarStackPerson | undefined;\n const current = locale();\n void dialogCore\n .open<void>(\n (close, context) => (\n <LocaleProvider locale={current}>\n <BottomSheet onDismiss={context.requestDismiss}>\n <BottomSheet.Body>\n <div class=\"k2b-avatar-stack__sheet\" role=\"group\" aria-labelledby={`${titleId}-sheet`}>\n <PeopleList\n people={props.people}\n title={props.title}\n titleId={`${titleId}-sheet`}\n hint={props.hint}\n choose={(person) => {\n chosen = person;\n close();\n }}\n />\n </div>\n </BottomSheet.Body>\n </BottomSheet>\n </LocaleProvider>\n ),\n { ...bottomSheetOptions, ariaLabel: props.title, history: true, signal: disposed.signal },\n )\n .then(() => chosen?.onSelect?.())\n .finally(() => {\n sheetOpen = false;\n setOpen(false);\n });\n };\n\n const toggle = () => {\n if (prefersMenuSheet()) {\n openSheet();\n return;\n }\n if (popover.matches(\":popover-open\")) {\n popover.hidePopover();\n return;\n }\n popover.showPopover();\n place();\n };\n\n return (\n <span class={`k2b-avatar-stack ${props.class ?? \"\"}`}>\n <button\n ref={trigger}\n type=\"button\"\n class=\"k2b-avatar-stack__trigger\"\n aria-label={props.label}\n aria-haspopup=\"dialog\"\n aria-expanded={open()}\n aria-controls={popoverId}\n onClick={toggle}\n >\n <span class=\"k2b-avatar-stack__faces\" aria-hidden=\"true\">\n <For each={shown()}>\n {(person) => <Avatar name={person.name} src={person.src} icon={person.icon} shape={person.shape} size=\"xs\" alt=\"\" />}\n </For>\n </span>\n <Show when={more() > 0}>\n <span class=\"k2b-avatar-stack__more\" aria-hidden=\"true\" title={messages().moreCount({ count: more() })}>\n +{more()}\n </span>\n </Show>\n </button>\n <div\n ref={popover}\n id={popoverId}\n popover=\"auto\"\n role=\"dialog\"\n aria-labelledby={titleId}\n class=\"k2b-avatar-stack__popover\"\n onToggle={(event) => {\n const next = (event as ToggleEvent).newState === \"open\";\n setOpen(next);\n follow(next);\n if (!next && document.activeElement && popover.contains(document.activeElement)) trigger.focus();\n }}\n >\n <PeopleList\n people={props.people}\n title={props.title}\n titleId={titleId}\n hint={props.hint}\n choose={(person) => {\n if (open()) popover.hidePopover();\n person.onSelect?.();\n }}\n />\n </div>\n </span>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -7,13 +7,19 @@ const avatarMessages = i18n.define({
|
|
|
7
7
|
avatarLabel: ({
|
|
8
8
|
name
|
|
9
9
|
}) => `${name} avatar`,
|
|
10
|
-
unknownUser: "Unknown user"
|
|
10
|
+
unknownUser: "Unknown user",
|
|
11
|
+
moreCount: ({
|
|
12
|
+
count
|
|
13
|
+
}) => `${count} more`
|
|
11
14
|
},
|
|
12
15
|
de: {
|
|
13
16
|
avatarLabel: ({
|
|
14
17
|
name
|
|
15
18
|
}) => `Avatar von ${name}`,
|
|
16
|
-
unknownUser: "Unbekannte Person"
|
|
19
|
+
unknownUser: "Unbekannte Person",
|
|
20
|
+
moreCount: ({
|
|
21
|
+
count
|
|
22
|
+
}) => `${count} weitere`
|
|
17
23
|
}
|
|
18
24
|
}
|
|
19
25
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["surfaces/avatar-messages.ts"],"sourcesContent":["import { i18n } from \"@k2b/stdlib\";\nimport { useLocale } from \"../intl/locale\";\n\nconst avatarMessages = i18n.define({\n baseLocale: \"en\",\n messages: {\n en: {\n avatarLabel: ({ name }: { name: string }) => `${name} avatar`,\n unknownUser: \"Unknown user\",\n },\n de: {\n avatarLabel: ({ name }) => `Avatar von ${name}`,\n unknownUser: \"Unbekannte Person\",\n },\n },\n});\n\nexport type AvatarMessages = ReturnType<(typeof avatarMessages)[\"resolve\"]>[\"t\"];\n\n/** Resolved from the inherited render locale. */\nexport const useAvatarMessages = (): (() => AvatarMessages) => {\n const locale = useLocale();\n return () => avatarMessages.resolve([locale()]).t;\n};\n\nexport const checkAvatarMessages = () => avatarMessages.check();\n"],"mappings":"AAAA,SAAS,IAAI,QAAQ,aAAa;AAClC,SAAS,SAAS,QAAQ,gBAAgB;AAE1C,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;EACjC,UAAU,EAAE,IAAI;EAChB,QAAQ,EAAE;IACR,EAAE,EAAE;MACF,WAAW,EAAE,CAAC;QAAE;MAAuB,CAAC,KAAK,GAAG,IAAI,SAAS;MAC7D,WAAW,EAAE;
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/avatar-messages.ts"],"sourcesContent":["import { i18n } from \"@k2b/stdlib\";\nimport { useLocale } from \"../intl/locale\";\n\nconst avatarMessages = i18n.define({\n baseLocale: \"en\",\n messages: {\n en: {\n avatarLabel: ({ name }: { name: string }) => `${name} avatar`,\n unknownUser: \"Unknown user\",\n moreCount: ({ count }: { count: number }) => `${count} more`,\n },\n de: {\n avatarLabel: ({ name }) => `Avatar von ${name}`,\n unknownUser: \"Unbekannte Person\",\n moreCount: ({ count }) => `${count} weitere`,\n },\n },\n});\n\nexport type AvatarMessages = ReturnType<(typeof avatarMessages)[\"resolve\"]>[\"t\"];\n\n/** Resolved from the inherited render locale. */\nexport const useAvatarMessages = (): (() => AvatarMessages) => {\n const locale = useLocale();\n return () => avatarMessages.resolve([locale()]).t;\n};\n\nexport const checkAvatarMessages = () => avatarMessages.check();\n"],"mappings":"AAAA,SAAS,IAAI,QAAQ,aAAa;AAClC,SAAS,SAAS,QAAQ,gBAAgB;AAE1C,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;EACjC,UAAU,EAAE,IAAI;EAChB,QAAQ,EAAE;IACR,EAAE,EAAE;MACF,WAAW,EAAE,CAAC;QAAE;MAAuB,CAAC,KAAK,GAAG,IAAI,SAAS;MAC7D,WAAW,EAAE,cAAc;MAC3B,SAAS,EAAE,CAAC;QAAE;MAAyB,CAAC,KAAK,GAAG,KAAK;IACvD,CAAC;IACD,EAAE,EAAE;MACF,WAAW,EAAE,CAAC;QAAE;MAAK,CAAC,KAAK,cAAc,IAAI,EAAE;MAC/C,WAAW,EAAE,mBAAmB;MAChC,SAAS,EAAE,CAAC;QAAE;MAAM,CAAC,KAAK,GAAG,KAAK;IACpC;EACF;AACF,CAAC,CAAC;AAIF;AACA,OAAO,MAAM,iBAAiB,GAAG,MAA8B;EAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;EAC1B,OAAO,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,OAAO,MAAM,mBAAmB,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["surfaces/index.ts"],"sourcesContent":["export type { AvatarProps, AvatarSize } from \"./Avatar\";\nexport { Avatar } from \"./Avatar\";\nexport type { DescriptionListItem, DescriptionListProps } from \"./DescriptionList\";\nexport { DescriptionList } from \"./DescriptionList\";\nexport type { LinkCardColor, LinkCardProps } from \"./LinkCard\";\nexport { LinkCard } from \"./LinkCard\";\nexport type { NotFoundStateAction, NotFoundStateProps } from \"./NotFoundState\";\nexport { NotFoundState } from \"./NotFoundState\";\nexport type { NoticeCardProps, NoticeGridProps, NoticeTone } from \"./NoticeCard\";\nexport { NOTICE_CARD_CLASSES, NoticeCard } from \"./NoticeCard\";\nexport type { PaperProps, PaperTag } from \"./Paper\";\nexport { Paper } from \"./Paper\";\nexport type {\n PlaceholderAlign,\n PlaceholderProps,\n PlaceholderState,\n PlaceholderSurface,\n PlaceholderVariant,\n} from \"./Placeholder\";\nexport { default as Placeholder } from \"./Placeholder\";\nexport type { ProgressBarProps, ProgressBarTone } from \"./ProgressBar\";\nexport { ProgressBar } from \"./ProgressBar\";\nexport type { ProgressRingProps, ProgressRingTone } from \"./ProgressRing\";\nexport { ProgressRing } from \"./ProgressRing\";\nexport type { ResourceCardProps, ResourceCardState } from \"./ResourceCard\";\nexport { ResourceCard } from \"./ResourceCard\";\nexport type { StatCellAccent, StatCellProps, StatCellTone } from \"./StatCell\";\nexport { StatCell } from \"./StatCell\";\nexport type {\n StatGridAction,\n StatGridColumns,\n StatGridProps,\n StatGridSize,\n StatGridSurface,\n} from \"./StatGrid\";\nexport { StatGrid } from \"./StatGrid\";\nexport type { StatusBadgeProps, StatusTone } from \"./StatusBadge\";\nexport { StatusBadge } from \"./StatusBadge\";\nexport type { TagProps, TagSize } from \"./Tag\";\nexport { Tag } from \"./Tag\";\n"],"mappings":"AACA,SAAS,MAAM,QAAQ,UAAU;AAEjC,SAAS,eAAe,QAAQ,mBAAmB;AAEnD,SAAS,QAAQ,QAAQ,YAAY;AAErC,SAAS,aAAa,QAAQ,iBAAiB;AAE/C,SAAS,mBAAmB,EAAE,UAAU,QAAQ,cAAc;AAE9D,SAAS,KAAK,QAAQ,SAAS;AAQ/B,SAAS,OAAO,IAAI,WAAW,QAAQ,eAAe;AAEtD,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,QAAQ,QAAQ,YAAY;AAQrC,SAAS,QAAQ,QAAQ,YAAY;AAErC,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,GAAG,QAAQ,OAAO","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/index.ts"],"sourcesContent":["export type { AvatarProps, AvatarRing, AvatarShape, AvatarSize } from \"./Avatar\";\nexport { Avatar } from \"./Avatar\";\nexport type { AvatarStackPerson, AvatarStackProps } from \"./AvatarStack\";\nexport { AvatarStack } from \"./AvatarStack\";\nexport type { DescriptionListItem, DescriptionListProps } from \"./DescriptionList\";\nexport { DescriptionList } from \"./DescriptionList\";\nexport type { LinkCardColor, LinkCardProps } from \"./LinkCard\";\nexport { LinkCard } from \"./LinkCard\";\nexport type { NotFoundStateAction, NotFoundStateProps } from \"./NotFoundState\";\nexport { NotFoundState } from \"./NotFoundState\";\nexport type { NoticeCardProps, NoticeGridProps, NoticeTone } from \"./NoticeCard\";\nexport { NOTICE_CARD_CLASSES, NoticeCard } from \"./NoticeCard\";\nexport type { PaperProps, PaperTag } from \"./Paper\";\nexport { Paper } from \"./Paper\";\nexport type {\n PlaceholderAlign,\n PlaceholderProps,\n PlaceholderState,\n PlaceholderSurface,\n PlaceholderVariant,\n} from \"./Placeholder\";\nexport { default as Placeholder } from \"./Placeholder\";\nexport type { ProgressBarProps, ProgressBarTone } from \"./ProgressBar\";\nexport { ProgressBar } from \"./ProgressBar\";\nexport type { ProgressRingProps, ProgressRingTone } from \"./ProgressRing\";\nexport { ProgressRing } from \"./ProgressRing\";\nexport type { ResourceCardProps, ResourceCardState } from \"./ResourceCard\";\nexport { ResourceCard } from \"./ResourceCard\";\nexport type { StatCellAccent, StatCellProps, StatCellTone } from \"./StatCell\";\nexport { StatCell } from \"./StatCell\";\nexport type {\n StatGridAction,\n StatGridColumns,\n StatGridProps,\n StatGridSize,\n StatGridSurface,\n} from \"./StatGrid\";\nexport { StatGrid } from \"./StatGrid\";\nexport type { StatusBadgeProps, StatusTone } from \"./StatusBadge\";\nexport { StatusBadge } from \"./StatusBadge\";\nexport type { TagProps, TagSize } from \"./Tag\";\nexport { Tag } from \"./Tag\";\n"],"mappings":"AACA,SAAS,MAAM,QAAQ,UAAU;AAEjC,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,eAAe,QAAQ,mBAAmB;AAEnD,SAAS,QAAQ,QAAQ,YAAY;AAErC,SAAS,aAAa,QAAQ,iBAAiB;AAE/C,SAAS,mBAAmB,EAAE,UAAU,QAAQ,cAAc;AAE9D,SAAS,KAAK,QAAQ,SAAS;AAQ/B,SAAS,OAAO,IAAI,WAAW,QAAQ,eAAe;AAEtD,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,QAAQ,QAAQ,YAAY;AAQrC,SAAS,QAAQ,QAAQ,YAAY;AAErC,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,GAAG,QAAQ,OAAO","ignoreList":[]}
|
|
@@ -4,17 +4,27 @@ import { ssr as _$ssr } from "solid-js/web";
|
|
|
4
4
|
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
5
5
|
import { escape as _$escape } from "solid-js/web";
|
|
6
6
|
var _tmpl$ = ["<div", " role=\"group\"", " aria-haspopup=\"menu\"", ">", "</div>"],
|
|
7
|
-
_tmpl$2 = ["<div
|
|
7
|
+
_tmpl$2 = ["<div class=\"k2b-context-menu__title\" aria-hidden=\"true\">", "</div>"],
|
|
8
|
+
_tmpl$3 = ["<div", " class=\"k2b-ui k2b-context-menu\" role=\"menu\"", " style=\"", "\">", "", "</div>"];
|
|
8
9
|
import { createMemo, createSignal, createUniqueId, onCleanup, onMount, Show } from "solid-js";
|
|
9
10
|
import { Portal } from "solid-js/web";
|
|
10
11
|
import { returnFocus, ringOnReturn } from "../internal/focus-return";
|
|
11
12
|
import { useUiMessages } from "../intl/messages";
|
|
12
|
-
import { DropdownItems, dropdownPosition
|
|
13
|
+
import { DropdownItems, dropdownPosition } from "./Dropdown";
|
|
14
|
+
import { focusRowSegment } from "./menu-rows";
|
|
13
15
|
let closeActiveContextMenu;
|
|
14
16
|
const focusableItems = menu => menu ? Array.from(menu.querySelectorAll(["[role='menuitem']:not([aria-disabled='true'])", "[role='menuitemcheckbox']:not([aria-disabled='true'])", "[role='menuitemradio']:not([aria-disabled='true'])"].join(", "))) : [];
|
|
15
17
|
|
|
16
18
|
/** Right-click menu with keyboard invocation, one-open-at-a-time behavior, and viewport clamping. */
|
|
17
19
|
export function ContextMenu(props) {
|
|
20
|
+
return ContextMenuBase(props);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Package-internal, not exported from the package index: `openAt` lets GestureMenu open the menu at a held finger, and
|
|
25
|
+
* `title` names what was pressed above the entries, since the finger covers it.
|
|
26
|
+
*/
|
|
27
|
+
export function ContextMenuBase(props) {
|
|
18
28
|
const messages = useUiMessages();
|
|
19
29
|
const generatedId = `k2b-context-${createUniqueId()}`;
|
|
20
30
|
const menuId = `${generatedId}-menu`;
|
|
@@ -148,6 +158,7 @@ export function ContextMenu(props) {
|
|
|
148
158
|
close();
|
|
149
159
|
}
|
|
150
160
|
};
|
|
161
|
+
props.openAt?.(open);
|
|
151
162
|
onMount(() => {
|
|
152
163
|
onCleanup(() => {
|
|
153
164
|
detachOpenListeners();
|
|
@@ -160,7 +171,14 @@ export function ContextMenu(props) {
|
|
|
160
171
|
},
|
|
161
172
|
children: point => _$createComponent(Portal, {
|
|
162
173
|
get children() {
|
|
163
|
-
return _$ssr(_tmpl$
|
|
174
|
+
return _$ssr(_tmpl$3, _$ssrAttribute("id", _$escape(menuId, true), false), _$ssrAttribute("aria-label", _$escape(props.label ?? messages().contextMenu, true), false), _$ssrStyleProperty("left:", `${_$escape(point().x, true)}px`) + _$ssrStyleProperty(";top:", `${_$escape(point().y, true)}px`), _$escape(_$createComponent(Show, {
|
|
175
|
+
get when() {
|
|
176
|
+
return props.title;
|
|
177
|
+
},
|
|
178
|
+
get children() {
|
|
179
|
+
return _$ssr(_tmpl$2, _$escape(props.title));
|
|
180
|
+
}
|
|
181
|
+
})), _$escape(_$createComponent(DropdownItems, {
|
|
164
182
|
get items() {
|
|
165
183
|
return items();
|
|
166
184
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["actions/ContextMenu.tsx"],"sourcesContent":["import { createMemo, createSignal, createUniqueId, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Portal } from \"solid-js/web\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { type DropdownItem, DropdownItems, type DropdownPosition, dropdownPosition, focusRowSegment } from \"./Dropdown\";\n\nexport type ContextMenuProps = {\n items: readonly DropdownItem[];\n children: JSX.Element;\n class?: string | ((isOpen: boolean) => string);\n /** Tab order of the context-menu host. Descendant-focused composite widgets use -1. */\n tabIndex?: number;\n disabled?: boolean;\n onClose?: () => void;\n onOpen?: () => void;\n id?: string;\n label?: string;\n};\n\nlet closeActiveContextMenu: (() => void) | undefined;\n\nconst focusableItems = (menu: HTMLElement | undefined): HTMLElement[] =>\n menu\n ? Array.from(\n menu.querySelectorAll<HTMLElement>(\n [\n \"[role='menuitem']:not([aria-disabled='true'])\",\n \"[role='menuitemcheckbox']:not([aria-disabled='true'])\",\n \"[role='menuitemradio']:not([aria-disabled='true'])\",\n ].join(\", \"),\n ),\n )\n : [];\n\n/** Right-click menu with keyboard invocation, one-open-at-a-time behavior, and viewport clamping. */\nexport function ContextMenu(props: ContextMenuProps): JSX.Element {\n const messages = useUiMessages();\n const generatedId = `k2b-context-${createUniqueId()}`;\n const menuId = `${generatedId}-menu`;\n const [position, setPosition] = createSignal<{ x: number; y: number }>();\n let host: HTMLDivElement | undefined;\n let menu: HTMLDivElement | undefined;\n let listenersAttached = false;\n let hostRing = true;\n /** The element inside the host that had focus as the menu opened, such as a row or a day of a composite widget. */\n let opener: HTMLElement | undefined;\n let anchor = { x: 0, y: 0 };\n let viewport = { width: 0, height: 0 };\n let resizeObserver: ResizeObserver | undefined;\n\n const isOpen = () => position() !== undefined;\n const hostClass = createMemo(() => (typeof props.class === \"function\" ? props.class(isOpen()) : props.class));\n const items = createMemo<readonly DropdownItem[]>(() => props.items);\n\n const dismiss = (event: PointerEvent) => {\n if (menu?.contains(event.target as Node)) return;\n close();\n };\n const closeOnScroll = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && menu?.contains(target)) return;\n close();\n };\n // A resize event may leave the viewport's size unchanged; headless Chromium\n // was seen to fire one on a fresh page. The clamped menu is still in place.\n const closeOnResize = () => {\n if (window.innerWidth === viewport.width && window.innerHeight === viewport.height) return;\n close();\n };\n const attachOpenListeners = () => {\n if (listenersAttached) return;\n listenersAttached = true;\n document.addEventListener(\"pointerdown\", dismiss);\n document.addEventListener(\"keydown\", keyDown);\n window.addEventListener(\"resize\", closeOnResize);\n window.addEventListener(\"scroll\", closeOnScroll, true);\n };\n const detachOpenListeners = () => {\n if (!listenersAttached) return;\n listenersAttached = false;\n document.removeEventListener(\"pointerdown\", dismiss);\n document.removeEventListener(\"keydown\", keyDown);\n window.removeEventListener(\"resize\", closeOnResize);\n window.removeEventListener(\"scroll\", closeOnScroll, true);\n resizeObserver?.disconnect();\n };\n /** Clamps the rendered menu into the viewport beside the point that opened it. */\n const place = () => {\n if (!isOpen() || !menu?.isConnected) return;\n const point = dropdownPosition(\n new DOMRect(anchor.x, anchor.y, 0, 0),\n menu.getBoundingClientRect(),\n \"bottom-right\" satisfies DropdownPosition,\n { width: window.innerWidth, height: window.innerHeight },\n 0,\n );\n setPosition({ x: point.left, y: point.top });\n };\n const close = () => {\n detachOpenListeners();\n if (!isOpen()) return;\n setPosition();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n props.onClose?.();\n };\n const focusItem = (index: number) => {\n const items = focusableItems(menu);\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.focus();\n };\n const open = (x: number, y: number) => {\n if (props.disabled) return;\n closeActiveContextMenu?.();\n // Focus may sit on a descendant of the host, as in composite widgets; Escape returns it there.\n const focused = document.activeElement;\n opener = focused instanceof HTMLElement && focused !== host && host?.contains(focused) ? focused : undefined;\n hostRing = ringOnReturn(focused);\n anchor = { x, y };\n viewport = { width: window.innerWidth, height: window.innerHeight };\n setPosition({ x, y });\n closeActiveContextMenu = close;\n attachOpenListeners();\n props.onOpen?.();\n // The menu sizes to its entries, so it is measured once rendered and\n // clamped into the viewport before the next paint, and again whenever its\n // entries change its size while it is open.\n queueMicrotask(() => {\n if (!isOpen() || !menu?.isConnected) return;\n place();\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver ??= new ResizeObserver(place);\n resizeObserver.observe(menu);\n }\n focusItem(0);\n });\n };\n const keyDown = (event: KeyboardEvent) => {\n if (!isOpen()) return;\n const items = focusableItems(menu);\n const current = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n focusItem(current + (event.key === \"ArrowDown\" ? 1 : -1));\n } else if (focusRowSegment(items, event.key)) {\n event.preventDefault();\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focusItem(event.key === \"Home\" ? 0 : -1);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n close();\n returnFocus(opener?.isConnected ? opener : host, hostRing);\n } else if (event.key === \"Tab\") {\n close();\n }\n };\n\n onMount(() => {\n onCleanup(() => {\n detachOpenListeners();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n });\n });\n\n return (\n <>\n {/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: the named group owns the context-menu relationship without pretending arbitrary children form one button. */}\n <div\n ref={host}\n id={props.id ?? generatedId}\n class={hostClass()}\n role=\"group\"\n tabIndex={props.disabled ? undefined : (props.tabIndex ?? 0)}\n aria-label={props.label ?? messages().contextMenu}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen()}\n aria-controls={isOpen() ? menuId : undefined}\n aria-disabled={props.disabled ? \"true\" : undefined}\n onContextMenu={(event) => {\n if (props.disabled) return;\n event.preventDefault();\n event.stopPropagation();\n open(event.clientX, event.clientY);\n }}\n onKeyDown={(event) => {\n if (props.disabled || (event.key !== \"ContextMenu\" && !(event.shiftKey && event.key === \"F10\"))) return;\n event.preventDefault();\n // Beside the focused element, such as a row of a composite widget, rather than the corner of the whole host.\n const focused = document.activeElement;\n const rect = (focused instanceof HTMLElement && host?.contains(focused) ? focused : host)?.getBoundingClientRect();\n if (rect) open(rect.left + 12, rect.top + 12);\n }}\n >\n {props.children}\n </div>\n <Show when={position()}>\n {(point) => (\n <Portal>\n <div\n ref={menu}\n id={menuId}\n class=\"k2b-ui k2b-context-menu\"\n role=\"menu\"\n aria-label={props.label ?? messages().contextMenu}\n style={{ left: `${point().x}px`, top: `${point().y}px` }}\n onPointerDown={(event) => event.stopPropagation()}\n >\n <DropdownItems items={items()} close={close} />\n </div>\n </Portal>\n )}\n </Show>\n </>\n );\n}\n\nexport default ContextMenu;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["actions/ContextMenu.tsx"],"sourcesContent":["import { createMemo, createSignal, createUniqueId, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Portal } from \"solid-js/web\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { type DropdownItem, DropdownItems, type DropdownPosition, dropdownPosition } from \"./Dropdown\";\nimport { focusRowSegment } from \"./menu-rows\";\n\nexport type ContextMenuProps = {\n items: readonly DropdownItem[];\n children: JSX.Element;\n class?: string | ((isOpen: boolean) => string);\n /** Tab order of the context-menu host. Descendant-focused composite widgets use -1. */\n tabIndex?: number;\n disabled?: boolean;\n onClose?: () => void;\n onOpen?: () => void;\n id?: string;\n label?: string;\n};\n\nlet closeActiveContextMenu: (() => void) | undefined;\n\nconst focusableItems = (menu: HTMLElement | undefined): HTMLElement[] =>\n menu\n ? Array.from(\n menu.querySelectorAll<HTMLElement>(\n [\n \"[role='menuitem']:not([aria-disabled='true'])\",\n \"[role='menuitemcheckbox']:not([aria-disabled='true'])\",\n \"[role='menuitemradio']:not([aria-disabled='true'])\",\n ].join(\", \"),\n ),\n )\n : [];\n\n/** Right-click menu with keyboard invocation, one-open-at-a-time behavior, and viewport clamping. */\nexport function ContextMenu(props: ContextMenuProps): JSX.Element {\n return ContextMenuBase(props);\n}\n\n/**\n * Package-internal, not exported from the package index: `openAt` lets GestureMenu open the menu at a held finger, and\n * `title` names what was pressed above the entries, since the finger covers it.\n */\nexport function ContextMenuBase(\n props: ContextMenuProps & { openAt?: (open: (x: number, y: number) => void) => void; title?: string },\n): JSX.Element {\n const messages = useUiMessages();\n const generatedId = `k2b-context-${createUniqueId()}`;\n const menuId = `${generatedId}-menu`;\n const [position, setPosition] = createSignal<{ x: number; y: number }>();\n let host: HTMLDivElement | undefined;\n let menu: HTMLDivElement | undefined;\n let listenersAttached = false;\n let hostRing = true;\n /** The element inside the host that had focus as the menu opened, such as a row or a day of a composite widget. */\n let opener: HTMLElement | undefined;\n let anchor = { x: 0, y: 0 };\n let viewport = { width: 0, height: 0 };\n let resizeObserver: ResizeObserver | undefined;\n\n const isOpen = () => position() !== undefined;\n const hostClass = createMemo(() => (typeof props.class === \"function\" ? props.class(isOpen()) : props.class));\n const items = createMemo<readonly DropdownItem[]>(() => props.items);\n\n const dismiss = (event: PointerEvent) => {\n if (menu?.contains(event.target as Node)) return;\n close();\n };\n const closeOnScroll = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && menu?.contains(target)) return;\n close();\n };\n // A resize event may leave the viewport's size unchanged; headless Chromium\n // was seen to fire one on a fresh page. The clamped menu is still in place.\n const closeOnResize = () => {\n if (window.innerWidth === viewport.width && window.innerHeight === viewport.height) return;\n close();\n };\n const attachOpenListeners = () => {\n if (listenersAttached) return;\n listenersAttached = true;\n document.addEventListener(\"pointerdown\", dismiss);\n document.addEventListener(\"keydown\", keyDown);\n window.addEventListener(\"resize\", closeOnResize);\n window.addEventListener(\"scroll\", closeOnScroll, true);\n };\n const detachOpenListeners = () => {\n if (!listenersAttached) return;\n listenersAttached = false;\n document.removeEventListener(\"pointerdown\", dismiss);\n document.removeEventListener(\"keydown\", keyDown);\n window.removeEventListener(\"resize\", closeOnResize);\n window.removeEventListener(\"scroll\", closeOnScroll, true);\n resizeObserver?.disconnect();\n };\n /** Clamps the rendered menu into the viewport beside the point that opened it. */\n const place = () => {\n if (!isOpen() || !menu?.isConnected) return;\n const point = dropdownPosition(\n new DOMRect(anchor.x, anchor.y, 0, 0),\n menu.getBoundingClientRect(),\n \"bottom-right\" satisfies DropdownPosition,\n { width: window.innerWidth, height: window.innerHeight },\n 0,\n );\n setPosition({ x: point.left, y: point.top });\n };\n const close = () => {\n detachOpenListeners();\n if (!isOpen()) return;\n setPosition();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n props.onClose?.();\n };\n const focusItem = (index: number) => {\n const items = focusableItems(menu);\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.focus();\n };\n const open = (x: number, y: number) => {\n if (props.disabled) return;\n closeActiveContextMenu?.();\n // Focus may sit on a descendant of the host, as in composite widgets; Escape returns it there.\n const focused = document.activeElement;\n opener = focused instanceof HTMLElement && focused !== host && host?.contains(focused) ? focused : undefined;\n hostRing = ringOnReturn(focused);\n anchor = { x, y };\n viewport = { width: window.innerWidth, height: window.innerHeight };\n setPosition({ x, y });\n closeActiveContextMenu = close;\n attachOpenListeners();\n props.onOpen?.();\n // The menu sizes to its entries, so it is measured once rendered and\n // clamped into the viewport before the next paint, and again whenever its\n // entries change its size while it is open.\n queueMicrotask(() => {\n if (!isOpen() || !menu?.isConnected) return;\n place();\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver ??= new ResizeObserver(place);\n resizeObserver.observe(menu);\n }\n focusItem(0);\n });\n };\n const keyDown = (event: KeyboardEvent) => {\n if (!isOpen()) return;\n const items = focusableItems(menu);\n const current = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n focusItem(current + (event.key === \"ArrowDown\" ? 1 : -1));\n } else if (focusRowSegment(items, event.key)) {\n event.preventDefault();\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focusItem(event.key === \"Home\" ? 0 : -1);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n close();\n returnFocus(opener?.isConnected ? opener : host, hostRing);\n } else if (event.key === \"Tab\") {\n close();\n }\n };\n\n props.openAt?.(open);\n\n onMount(() => {\n onCleanup(() => {\n detachOpenListeners();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n });\n });\n\n return (\n <>\n {/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: the named group owns the context-menu relationship without pretending arbitrary children form one button. */}\n <div\n ref={host}\n id={props.id ?? generatedId}\n class={hostClass()}\n role=\"group\"\n tabIndex={props.disabled ? undefined : (props.tabIndex ?? 0)}\n aria-label={props.label ?? messages().contextMenu}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen()}\n aria-controls={isOpen() ? menuId : undefined}\n aria-disabled={props.disabled ? \"true\" : undefined}\n onContextMenu={(event) => {\n if (props.disabled) return;\n event.preventDefault();\n event.stopPropagation();\n open(event.clientX, event.clientY);\n }}\n onKeyDown={(event) => {\n if (props.disabled || (event.key !== \"ContextMenu\" && !(event.shiftKey && event.key === \"F10\"))) return;\n event.preventDefault();\n // Beside the focused element, such as a row of a composite widget, rather than the corner of the whole host.\n const focused = document.activeElement;\n const rect = (focused instanceof HTMLElement && host?.contains(focused) ? focused : host)?.getBoundingClientRect();\n if (rect) open(rect.left + 12, rect.top + 12);\n }}\n >\n {props.children}\n </div>\n <Show when={position()}>\n {(point) => (\n <Portal>\n <div\n ref={menu}\n id={menuId}\n class=\"k2b-ui k2b-context-menu\"\n role=\"menu\"\n aria-label={props.label ?? messages().contextMenu}\n style={{ left: `${point().x}px`, top: `${point().y}px` }}\n onPointerDown={(event) => event.stopPropagation()}\n >\n {/* The menu carries the same name for assistive technology. */}\n <Show when={props.title}>\n <div class=\"k2b-context-menu__title\" aria-hidden=\"true\">\n {props.title}\n </div>\n </Show>\n <DropdownItems items={items()} close={close} />\n </div>\n </Portal>\n )}\n </Show>\n </>\n );\n}\n\nexport default ContextMenu;\n"],"mappings":"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","ignoreList":[]}
|