@k2b/ui 0.45.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/dist/browser/actions/Dropdown.js +8 -1
  2. package/dist/browser/actions/Dropdown.js.map +1 -1
  3. package/dist/browser/actions/FilterChip.js +11 -5
  4. package/dist/browser/actions/FilterChip.js.map +1 -1
  5. package/dist/browser/actions/ViewTabs.js +225 -93
  6. package/dist/browser/actions/ViewTabs.js.map +1 -1
  7. package/dist/browser/chat/ChatDecision.js +10 -6
  8. package/dist/browser/chat/ChatDecision.js.map +1 -1
  9. package/dist/browser/content/FileGrid.js +125 -99
  10. package/dist/browser/content/FileGrid.js.map +1 -1
  11. package/dist/browser/content/VirtualFeed.js +26 -21
  12. package/dist/browser/content/VirtualFeed.js.map +1 -1
  13. package/dist/browser/inputs/Combobox.js +14 -6
  14. package/dist/browser/inputs/Combobox.js.map +1 -1
  15. package/dist/browser/inputs/choice.js +36 -9
  16. package/dist/browser/inputs/choice.js.map +1 -1
  17. package/dist/browser/layout/AnchoredPopover.js +2 -1
  18. package/dist/browser/layout/AnchoredPopover.js.map +1 -1
  19. package/dist/browser/layout/AppWorkspace.js +348 -444
  20. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  21. package/dist/browser/layout/AppWorkspaceSidebarItemStatus.js +113 -0
  22. package/dist/browser/layout/AppWorkspaceSidebarItemStatus.js.map +1 -0
  23. package/dist/browser/layout/DetailPanel.js +130 -108
  24. package/dist/browser/layout/DetailPanel.js.map +1 -1
  25. package/dist/browser/layout/DetailSections.js +1123 -0
  26. package/dist/browser/layout/DetailSections.js.map +1 -0
  27. package/dist/browser/layout/DetailsToggle.js +32 -0
  28. package/dist/browser/layout/DetailsToggle.js.map +1 -0
  29. package/dist/browser/layout/Discussion.js +3 -0
  30. package/dist/browser/layout/Discussion.js.map +1 -1
  31. package/dist/browser/layout/MobileShell.js +141 -102
  32. package/dist/browser/layout/MobileShell.js.map +1 -1
  33. package/dist/browser/layout/PageTitle.js +33 -10
  34. package/dist/browser/layout/PageTitle.js.map +1 -1
  35. package/dist/browser/layout/app-workspace-controller.js +12 -0
  36. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  37. package/dist/browser/layout/detail-sections-messages.js +127 -0
  38. package/dist/browser/layout/detail-sections-messages.js.map +1 -0
  39. package/dist/browser/layout/index.js +3 -0
  40. package/dist/browser/layout/index.js.map +1 -1
  41. package/dist/browser/surfaces/Avatar.js +3 -1
  42. package/dist/browser/surfaces/Avatar.js.map +1 -1
  43. package/dist/browser/surfaces/AvatarStack.js +95 -61
  44. package/dist/browser/surfaces/AvatarStack.js.map +1 -1
  45. package/dist/browser/surfaces/ChangeList.js +77 -0
  46. package/dist/browser/surfaces/ChangeList.js.map +1 -0
  47. package/dist/browser/surfaces/index.js +2 -1
  48. package/dist/browser/surfaces/index.js.map +1 -1
  49. package/dist/browser/text-editor/TextEditor.js +19 -8
  50. package/dist/browser/text-editor/TextEditor.js.map +1 -1
  51. package/dist/ssr/actions/Dropdown.js +6 -0
  52. package/dist/ssr/actions/Dropdown.js.map +1 -1
  53. package/dist/ssr/actions/FilterChip.js +1 -1
  54. package/dist/ssr/actions/FilterChip.js.map +1 -1
  55. package/dist/ssr/actions/ViewTabs.js +144 -37
  56. package/dist/ssr/actions/ViewTabs.js.map +1 -1
  57. package/dist/ssr/chat/ChatDecision.js +10 -6
  58. package/dist/ssr/chat/ChatDecision.js.map +1 -1
  59. package/dist/ssr/content/FileGrid.js +36 -22
  60. package/dist/ssr/content/FileGrid.js.map +1 -1
  61. package/dist/ssr/content/VirtualFeed.js +26 -21
  62. package/dist/ssr/content/VirtualFeed.js.map +1 -1
  63. package/dist/ssr/inputs/Combobox.js +6 -3
  64. package/dist/ssr/inputs/Combobox.js.map +1 -1
  65. package/dist/ssr/inputs/choice.js +36 -9
  66. package/dist/ssr/inputs/choice.js.map +1 -1
  67. package/dist/ssr/layout/AnchoredPopover.js +2 -1
  68. package/dist/ssr/layout/AnchoredPopover.js.map +1 -1
  69. package/dist/ssr/layout/AppWorkspace.js +66 -132
  70. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  71. package/dist/ssr/layout/AppWorkspaceSidebarItemStatus.js +76 -0
  72. package/dist/ssr/layout/AppWorkspaceSidebarItemStatus.js.map +1 -0
  73. package/dist/ssr/layout/DetailPanel.js +18 -1
  74. package/dist/ssr/layout/DetailPanel.js.map +1 -1
  75. package/dist/ssr/layout/DetailSections.js +838 -0
  76. package/dist/ssr/layout/DetailSections.js.map +1 -0
  77. package/dist/ssr/layout/DetailsToggle.js +29 -0
  78. package/dist/ssr/layout/DetailsToggle.js.map +1 -0
  79. package/dist/ssr/layout/Discussion.js +3 -0
  80. package/dist/ssr/layout/Discussion.js.map +1 -1
  81. package/dist/ssr/layout/MobileShell.js +60 -29
  82. package/dist/ssr/layout/MobileShell.js.map +1 -1
  83. package/dist/ssr/layout/PageTitle.js +29 -6
  84. package/dist/ssr/layout/PageTitle.js.map +1 -1
  85. package/dist/ssr/layout/app-workspace-controller.js +12 -0
  86. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  87. package/dist/ssr/layout/detail-sections-messages.js +127 -0
  88. package/dist/ssr/layout/detail-sections-messages.js.map +1 -0
  89. package/dist/ssr/layout/index.js +3 -0
  90. package/dist/ssr/layout/index.js.map +1 -1
  91. package/dist/ssr/surfaces/Avatar.js +3 -1
  92. package/dist/ssr/surfaces/Avatar.js.map +1 -1
  93. package/dist/ssr/surfaces/AvatarStack.js +61 -32
  94. package/dist/ssr/surfaces/AvatarStack.js.map +1 -1
  95. package/dist/ssr/surfaces/ChangeList.js +37 -0
  96. package/dist/ssr/surfaces/ChangeList.js.map +1 -0
  97. package/dist/ssr/surfaces/index.js +2 -1
  98. package/dist/ssr/surfaces/index.js.map +1 -1
  99. package/dist/ssr/text-editor/TextEditor.js +19 -8
  100. package/dist/ssr/text-editor/TextEditor.js.map +1 -1
  101. package/dist/styles.css +1 -1
  102. package/dist/types/actions/FilterChip.d.ts +4 -0
  103. package/dist/types/actions/ViewTabs.d.ts +11 -1
  104. package/dist/types/chat/ChatDecision.d.ts +5 -0
  105. package/dist/types/content/FileGrid.d.ts +6 -0
  106. package/dist/types/inputs/Combobox.d.ts +2 -0
  107. package/dist/types/inputs/choice.d.ts +9 -3
  108. package/dist/types/layout/AppWorkspace.d.ts +2 -28
  109. package/dist/types/layout/AppWorkspaceSidebarItemStatus.d.ts +30 -0
  110. package/dist/types/layout/DetailPanel.d.ts +9 -0
  111. package/dist/types/layout/DetailSections.d.ts +186 -0
  112. package/dist/types/layout/DetailsToggle.d.ts +13 -0
  113. package/dist/types/layout/MobileShell.d.ts +12 -0
  114. package/dist/types/layout/PageTitle.d.ts +7 -0
  115. package/dist/types/layout/detail-sections-messages.d.ts +61 -0
  116. package/dist/types/layout/index.d.ts +5 -1
  117. package/dist/types/surfaces/Avatar.d.ts +3 -0
  118. package/dist/types/surfaces/AvatarStack.d.ts +20 -1
  119. package/dist/types/surfaces/ChangeList.d.ts +20 -0
  120. package/dist/types/surfaces/index.d.ts +5 -3
  121. package/package.json +3 -3
@@ -0,0 +1,1123 @@
1
+ import { template as _$template } from "solid-js/web";
2
+ import { delegateEvents as _$delegateEvents } from "solid-js/web";
3
+ import { mergeProps as _$mergeProps } from "solid-js/web";
4
+ import { use as _$use } from "solid-js/web";
5
+ import { runHydrationEvents as _$runHydrationEvents } from "solid-js/web";
6
+ import { className as _$className } from "solid-js/web";
7
+ import { setStyleProperty as _$setStyleProperty } from "solid-js/web";
8
+ import { memo as _$memo } from "solid-js/web";
9
+ import { setAttribute as _$setAttribute } from "solid-js/web";
10
+ import { effect as _$effect } from "solid-js/web";
11
+ import { getNextElement as _$getNextElement } from "solid-js/web";
12
+ import { getNextMarker as _$getNextMarker } from "solid-js/web";
13
+ import { insert as _$insert } from "solid-js/web";
14
+ import { createComponent as _$createComponent } from "solid-js/web";
15
+ var _tmpl$ = /*#__PURE__*/_$template(`<span class=k2b-detail-presence__face><!$><!/><span class=k2b-detail-presence__dot aria-hidden=true>`),
16
+ _tmpl$2 = /*#__PURE__*/_$template(`<span class=k2b-detail-presence__swatch aria-hidden=true>`),
17
+ _tmpl$3 = /*#__PURE__*/_$template(`<strong>`),
18
+ _tmpl$4 = /*#__PURE__*/_$template(`<i aria-hidden=true>`),
19
+ _tmpl$5 = /*#__PURE__*/_$template(`<button type=button class=k2b-detail-presence__chip><span aria-hidden=true class=k2b-detail-presence__chip-content>`),
20
+ _tmpl$6 = /*#__PURE__*/_$template(`<span class=k2b-detail-presence__chip><span class=k2b-sr-only></span><span aria-hidden=true class=k2b-detail-presence__chip-content>`),
21
+ _tmpl$7 = /*#__PURE__*/_$template(`<div class=k2b-detail-presence__strip><div class=k2b-detail-presence__chips></div><!$><!/>`),
22
+ _tmpl$8 = /*#__PURE__*/_$template(`<p class="k2b-detail-presence__where k2b-truncate-fade">`),
23
+ _tmpl$9 = /*#__PURE__*/_$template(`<div class=k2b-detail-presence>`),
24
+ _tmpl$0 = /*#__PURE__*/_$template(`<div class="k2b-detail-presence__strip k2b-detail-presence__problem"role=status><i class="ti ti-alert-triangle"aria-hidden=true></i><span class=k2b-truncate-fade></span><!$><!/>`),
25
+ _tmpl$1 = /*#__PURE__*/_$template(`<div class=k2b-detail-presence__strip aria-hidden=true><span class=k2b-detail-presence__skeleton></span><span class=k2b-detail-presence__skeleton></span><span class=k2b-detail-presence__skeleton>`),
26
+ _tmpl$10 = /*#__PURE__*/_$template(`<p class=k2b-detail-presence__where><span class=k2b-detail-presence__skeleton-line aria-hidden=true></span><span class=k2b-sr-only role=status>`),
27
+ _tmpl$11 = /*#__PURE__*/_$template(`<i class="ti ti-refresh"aria-hidden=true>`),
28
+ _tmpl$12 = /*#__PURE__*/_$template(`<span class=k2b-detail-presence__more>+<!$><!/>`),
29
+ _tmpl$13 = /*#__PURE__*/_$template(`<span class=k2b-detail-presence__self><!$><!/><!$><!/>`),
30
+ _tmpl$14 = /*#__PURE__*/_$template(`<span class=k2b-detail-presence-slot__more>+<!$><!/>`),
31
+ _tmpl$15 = /*#__PURE__*/_$template(`<span class=k2b-detail-presence-slot aria-hidden=true><!$><!/><!$><!/>`),
32
+ _tmpl$16 = /*#__PURE__*/_$template(`<span class=k2b-sr-only role=status>`),
33
+ _tmpl$17 = /*#__PURE__*/_$template(`<div class=k2b-detail-section-error role=alert><i class="ti ti-alert-circle"aria-hidden=true></i><span></span><!$><!/>`),
34
+ _tmpl$18 = /*#__PURE__*/_$template(`<p class=k2b-detail-section-note>`),
35
+ _tmpl$19 = /*#__PURE__*/_$template(`<div class=k2b-detail-section-rows><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`),
36
+ _tmpl$20 = /*#__PURE__*/_$template(`<span class=k2b-detail-row-skeleton__face>`),
37
+ _tmpl$21 = /*#__PURE__*/_$template(`<span class=k2b-detail-row-skeleton>`),
38
+ _tmpl$22 = /*#__PURE__*/_$template(`<i class="ti ti-settings"aria-hidden=true>`),
39
+ _tmpl$23 = /*#__PURE__*/_$template(`<div class=k2b-detail-section-group><div class=k2b-detail-section-label></div><!$><!/><!$><!/>`),
40
+ _tmpl$24 = /*#__PURE__*/_$template(`<div class=k2b-detail-section-rows aria-busy=true><!$><!/><span class=k2b-sr-only role=status>`),
41
+ _tmpl$25 = /*#__PURE__*/_$template(`<div class=k2b-detail-section-rows><!$><!/><!$><!/><!$><!/><!$><!/>`),
42
+ _tmpl$26 = /*#__PURE__*/_$template(`<div class=k2b-detail-section-rows><!$><!/><!$><!/>`),
43
+ _tmpl$27 = /*#__PURE__*/_$template(`<dl class=k2b-detail-properties>`),
44
+ _tmpl$28 = /*#__PURE__*/_$template(`<span class=k2b-detail-properties__leading>`),
45
+ _tmpl$29 = /*#__PURE__*/_$template(`<div class=k2b-detail-properties__item><dt></dt><dd><!$><!/><!$><!/>`),
46
+ _tmpl$30 = /*#__PURE__*/_$template(`<span class=k2b-detail-properties__value>`),
47
+ _tmpl$31 = /*#__PURE__*/_$template(`<a class="k2b-detail-properties__value k2b-detail-properties__link">`),
48
+ _tmpl$32 = /*#__PURE__*/_$template(`<ul class=k2b-detail-tags>`),
49
+ _tmpl$33 = /*#__PURE__*/_$template(`<li>`),
50
+ _tmpl$34 = /*#__PURE__*/_$template(`<span class=k2b-detail-tag>#<!$><!/>`),
51
+ _tmpl$35 = /*#__PURE__*/_$template(`<a class=k2b-detail-tag>#<!$><!/>`);
52
+ import { children, createMemo, createSignal, For, onCleanup, Show } from "solid-js";
53
+ import { Button } from "../actions/Button";
54
+ import { Avatar } from "../surfaces/Avatar";
55
+ import { AvatarStack } from "../surfaces/AvatarStack";
56
+ import { personColor } from "../surfaces/person-color";
57
+ import DetailPanel from "./DetailPanel";
58
+ import { useDetailPanelMessages } from "./detail-panel-messages";
59
+ import { useDetailSectionMessages } from "./detail-sections-messages";
60
+
61
+ /*
62
+ * Shared sections of an object's detail panel. Each one is a `DetailPanel.Section` with its icon, title, and count, so
63
+ * its content starts on the title's text edge, and each keeps its height while its data changes. Apps pass data; the
64
+ * order of sections is a convention (see the DetailPanel UI context).
65
+ */
66
+
67
+ const listNames = (names, and) => names.length <= 1 ? names[0] ?? "" : `${names.slice(0, -1).join(", ")} ${and} ${names.at(-1)}`;
68
+
69
+ // ── Presence ────────────────────────────────────────────────────────────
70
+
71
+ /** `offline` keeps the last known people, pale and without live dots; `unavailable` offers `onRetry`. */
72
+
73
+ const PresenceFace = props => (() => {
74
+ var _el$ = _$getNextElement(_tmpl$),
75
+ _el$3 = _el$.firstChild,
76
+ [_el$4, _co$] = _$getNextMarker(_el$3.nextSibling),
77
+ _el$2 = _el$4.nextSibling;
78
+ _$insert(_el$, _$createComponent(Avatar, {
79
+ get name() {
80
+ return props.person.name;
81
+ },
82
+ get src() {
83
+ return props.person.src;
84
+ },
85
+ get icon() {
86
+ return props.person.icon;
87
+ },
88
+ get shape() {
89
+ return props.person.shape;
90
+ },
91
+ size: "xs",
92
+ alt: ""
93
+ }), _el$4, _co$);
94
+ _$effect(() => _$setAttribute(_el$, "data-live", props.live ? "true" : undefined));
95
+ return _el$;
96
+ })();
97
+
98
+ /**
99
+ * "Here now": who has the object open, what they do, and where. Always two lines tall in every state, so people
100
+ * coming, going, or moving never shift the panel. Chips that do not fit wrap into a hidden line and count as "+n";
101
+ * "+n" and "You" open the full list, which `AvatarStack` shows beside it or as a sheet on phones.
102
+ */
103
+ export function DetailPresence(props) {
104
+ const t = useDetailSectionMessages();
105
+ const state = () => props.state ?? "live";
106
+ const others = createMemo(() => props.people.filter(person => !person.self));
107
+ const self = createMemo(() => props.people.find(person => person.self));
108
+ const short = person => person.shortName ?? person.name;
109
+ const color = person => person.color ?? personColor(person.name);
110
+ const [hidden, setHidden] = createSignal(0);
111
+ let chips;
112
+
113
+ // Chips that do not fit wrap into the clipped second line; they leave the tab order and count as "+n".
114
+ const fit = () => {
115
+ if (!chips) return;
116
+ const all = Array.from(chips.children).filter(child => child instanceof HTMLElement);
117
+ const top = all[0]?.offsetTop ?? 0;
118
+ let wrapped = 0;
119
+ for (const chip of all) {
120
+ const out = chip.offsetTop > top;
121
+ chip.inert = out;
122
+ if (out) wrapped += 1;
123
+ }
124
+ setHidden(wrapped);
125
+ };
126
+ // The strip mounts again after loading or an outage, so each mounted strip watches itself.
127
+ const watchChips = element => {
128
+ chips = element;
129
+ if (typeof ResizeObserver === "undefined") return;
130
+ const resized = new ResizeObserver(fit);
131
+ resized.observe(element);
132
+ const changed = new MutationObserver(fit);
133
+ changed.observe(element, {
134
+ childList: true
135
+ });
136
+ queueMicrotask(fit);
137
+ onCleanup(() => {
138
+ resized.disconnect();
139
+ changed.disconnect();
140
+ });
141
+ };
142
+ const describe = person => person.activity === "writing" ? t().personWriting({
143
+ name: person.name,
144
+ place: person.place ?? ""
145
+ }) : t().personReading({
146
+ name: person.name
147
+ });
148
+ const listPeople = createMemo(() => props.people.map(person => ({
149
+ id: person.id,
150
+ name: person.self ? t().you : person.name,
151
+ src: person.src,
152
+ icon: person.icon,
153
+ shape: person.shape,
154
+ self: person.self,
155
+ detailIcon: person.self ? undefined : person.activity === "writing" ? "ti ti-pencil" : "ti ti-eye",
156
+ detail: [person.self ? undefined : person.activity === "writing" ? t().writing : t().reading, person.place].filter(Boolean).join(" · "),
157
+ trailing: person.trailing,
158
+ onSelect: person.onSelect
159
+ })));
160
+ const where = () => {
161
+ if (state() === "offline" || others().length === 0) return props.note;
162
+ const writers = others().filter(person => person.activity === "writing");
163
+ const readers = others().filter(person => person.activity !== "writing");
164
+ return [_$createComponent(For, {
165
+ each: writers,
166
+ children: (person, index) => [_$memo(() => index() > 0 ? ", " : ""), (() => {
167
+ var _el$5 = _$getNextElement(_tmpl$2);
168
+ _$effect(_$p => _$setStyleProperty(_el$5, "--k2b-person-color", color(person)));
169
+ return _el$5;
170
+ })(), (() => {
171
+ var _el$6 = _$getNextElement(_tmpl$3);
172
+ _$insert(_el$6, () => short(person));
173
+ return _el$6;
174
+ })(), _$createComponent(Show, {
175
+ get when() {
176
+ return person.place;
177
+ },
178
+ children: place => [" ", _$memo(() => t().writesIn), " ", _$memo(place)]
179
+ })]
180
+ }), _$createComponent(Show, {
181
+ get when() {
182
+ return _$memo(() => writers.length > 0)() && readers.length > 0;
183
+ },
184
+ children: " · "
185
+ }), _$createComponent(Show, {
186
+ get when() {
187
+ return readers.length > 0;
188
+ },
189
+ get children() {
190
+ return t().readingAlong({
191
+ names: listNames(readers.map(short), t().and),
192
+ count: readers.length
193
+ });
194
+ }
195
+ })];
196
+ };
197
+ const chip = person => {
198
+ const content = [_$createComponent(PresenceFace, {
199
+ person: person,
200
+ get live() {
201
+ return state() === "live";
202
+ }
203
+ }), _$memo(() => short(person)), (() => {
204
+ var _el$7 = _$getNextElement(_tmpl$4);
205
+ _$effect(_p$ => {
206
+ var _v$ = person.activity === "writing" ? "ti ti-pencil k2b-detail-presence__activity" : "ti ti-eye k2b-detail-presence__activity",
207
+ _v$2 = person.activity ?? "reading";
208
+ _v$ !== _p$.e && _$className(_el$7, _p$.e = _v$);
209
+ _v$2 !== _p$.t && _$setAttribute(_el$7, "data-activity", _p$.t = _v$2);
210
+ return _p$;
211
+ }, {
212
+ e: undefined,
213
+ t: undefined
214
+ });
215
+ return _el$7;
216
+ })()];
217
+ return _$createComponent(Show, {
218
+ get when() {
219
+ return _$memo(() => !!person.onSelect)() && state() === "live";
220
+ },
221
+ get fallback() {
222
+ return (() => {
223
+ var _el$0 = _$getNextElement(_tmpl$6),
224
+ _el$1 = _el$0.firstChild,
225
+ _el$10 = _el$1.nextSibling;
226
+ _$insert(_el$1, () => describe(person));
227
+ _$insert(_el$10, content);
228
+ _$effect(_p$ => {
229
+ var _v$6 = color(person),
230
+ _v$7 = describe(person);
231
+ _v$6 !== _p$.e && _$setStyleProperty(_el$0, "--k2b-person-color", _p$.e = _v$6);
232
+ _v$7 !== _p$.t && _$setAttribute(_el$0, "title", _p$.t = _v$7);
233
+ return _p$;
234
+ }, {
235
+ e: undefined,
236
+ t: undefined
237
+ });
238
+ return _el$0;
239
+ })();
240
+ },
241
+ get children() {
242
+ var _el$8 = _$getNextElement(_tmpl$5),
243
+ _el$9 = _el$8.firstChild;
244
+ _el$8.$$click = () => person.onSelect?.();
245
+ _$insert(_el$9, content);
246
+ _$effect(_p$ => {
247
+ var _v$3 = color(person),
248
+ _v$4 = describe(person),
249
+ _v$5 = t().jumpTo({
250
+ name: person.name,
251
+ place: person.place ?? ""
252
+ });
253
+ _v$3 !== _p$.e && _$setStyleProperty(_el$8, "--k2b-person-color", _p$.e = _v$3);
254
+ _v$4 !== _p$.t && _$setAttribute(_el$8, "title", _p$.t = _v$4);
255
+ _v$5 !== _p$.a && _$setAttribute(_el$8, "aria-label", _p$.a = _v$5);
256
+ return _p$;
257
+ }, {
258
+ e: undefined,
259
+ t: undefined,
260
+ a: undefined
261
+ });
262
+ _$runHydrationEvents();
263
+ return _el$8;
264
+ }
265
+ });
266
+ };
267
+ const count = () => (state() === "live" || state() === "offline") && others().length > 0 ? others().length : undefined;
268
+ const meta = () => state() === "live" && others().length === 0 ? t().onlyYou : undefined;
269
+ return _$createComponent(DetailPanel.Section, {
270
+ get title() {
271
+ return props.title ?? t().hereNow;
272
+ },
273
+ icon: "ti ti-users",
274
+ get count() {
275
+ return count();
276
+ },
277
+ get meta() {
278
+ return meta();
279
+ },
280
+ get actions() {
281
+ return props.actions;
282
+ },
283
+ get ["class"]() {
284
+ return props.class;
285
+ },
286
+ get children() {
287
+ var _el$11 = _$getNextElement(_tmpl$9);
288
+ _$insert(_el$11, _$createComponent(Show, {
289
+ get when() {
290
+ return _$memo(() => state() !== "loading")() && state() !== "unavailable";
291
+ },
292
+ get fallback() {
293
+ return _$createComponent(Show, {
294
+ get when() {
295
+ return state() === "unavailable";
296
+ },
297
+ get fallback() {
298
+ return [_$getNextElement(_tmpl$1), (() => {
299
+ var _el$24 = _$getNextElement(_tmpl$10),
300
+ _el$25 = _el$24.firstChild,
301
+ _el$26 = _el$25.nextSibling;
302
+ _$insert(_el$26, () => t().presenceLoading);
303
+ return _el$24;
304
+ })()];
305
+ },
306
+ get children() {
307
+ return [(() => {
308
+ var _el$17 = _$getNextElement(_tmpl$0),
309
+ _el$18 = _el$17.firstChild,
310
+ _el$19 = _el$18.nextSibling,
311
+ _el$20 = _el$19.nextSibling,
312
+ [_el$21, _co$3] = _$getNextMarker(_el$20.nextSibling);
313
+ _$insert(_el$19, () => t().presenceUnavailable);
314
+ _$insert(_el$17, _$createComponent(Show, {
315
+ get when() {
316
+ return props.onRetry;
317
+ },
318
+ children: retry => _$createComponent(Button, {
319
+ variant: "text",
320
+ size: "xs",
321
+ "class": "k2b-detail-presence__retry",
322
+ onClick: () => retry()(),
323
+ get children() {
324
+ return [_$getNextElement(_tmpl$11), " ", _$memo(() => t().retry)];
325
+ }
326
+ })
327
+ }), _el$21, _co$3);
328
+ return _el$17;
329
+ })(), (() => {
330
+ var _el$22 = _$getNextElement(_tmpl$8);
331
+ _$insert(_el$22, () => props.note);
332
+ return _el$22;
333
+ })()];
334
+ }
335
+ });
336
+ },
337
+ get children() {
338
+ return [(() => {
339
+ var _el$12 = _$getNextElement(_tmpl$7),
340
+ _el$13 = _el$12.firstChild,
341
+ _el$14 = _el$13.nextSibling,
342
+ [_el$15, _co$2] = _$getNextMarker(_el$14.nextSibling);
343
+ _$use(watchChips, _el$13);
344
+ _$insert(_el$13, _$createComponent(For, {
345
+ get each() {
346
+ return others();
347
+ },
348
+ children: person => chip(person)
349
+ }));
350
+ _$insert(_el$12, _$createComponent(AvatarStack, {
351
+ "class": "k2b-detail-presence__all",
352
+ get people() {
353
+ return listPeople();
354
+ },
355
+ get title() {
356
+ return props.title ?? t().hereNow;
357
+ },
358
+ get label() {
359
+ return t().everyoneHere({
360
+ count: props.people.length
361
+ });
362
+ },
363
+ get hint() {
364
+ return props.listHint;
365
+ },
366
+ get trigger() {
367
+ return [(() => {
368
+ var _el$28 = _$getNextElement(_tmpl$12),
369
+ _el$29 = _el$28.firstChild,
370
+ _el$30 = _el$29.nextSibling,
371
+ [_el$31, _co$4] = _$getNextMarker(_el$30.nextSibling);
372
+ _$insert(_el$28, hidden, _el$31, _co$4);
373
+ _$effect(() => _$setAttribute(_el$28, "data-empty", hidden() === 0 ? "true" : undefined));
374
+ return _el$28;
375
+ })(), _$createComponent(Show, {
376
+ get when() {
377
+ return self();
378
+ },
379
+ children: person => (() => {
380
+ var _el$32 = _$getNextElement(_tmpl$13),
381
+ _el$33 = _el$32.firstChild,
382
+ [_el$34, _co$5] = _$getNextMarker(_el$33.nextSibling),
383
+ _el$35 = _el$34.nextSibling,
384
+ [_el$36, _co$6] = _$getNextMarker(_el$35.nextSibling);
385
+ _$insert(_el$32, _$createComponent(PresenceFace, {
386
+ get person() {
387
+ return person();
388
+ },
389
+ live: false
390
+ }), _el$34, _co$5);
391
+ _$insert(_el$32, () => t().you, _el$36, _co$6);
392
+ return _el$32;
393
+ })()
394
+ })];
395
+ }
396
+ }), _el$15, _co$2);
397
+ return _el$12;
398
+ })(), (() => {
399
+ var _el$16 = _$getNextElement(_tmpl$8);
400
+ _$insert(_el$16, where);
401
+ return _el$16;
402
+ })()];
403
+ }
404
+ }));
405
+ _$effect(_p$ => {
406
+ var _v$8 = state(),
407
+ _v$9 = state() === "loading" ? "true" : undefined;
408
+ _v$8 !== _p$.e && _$setAttribute(_el$11, "data-state", _p$.e = _v$8);
409
+ _v$9 !== _p$.t && _$setAttribute(_el$11, "aria-busy", _p$.t = _v$9);
410
+ return _p$;
411
+ }, {
412
+ e: undefined,
413
+ t: undefined
414
+ });
415
+ return _el$11;
416
+ }
417
+ });
418
+ }
419
+
420
+ /** A fixed slot at the end of a row for the people working there, such as an outline heading. Always the same width. */
421
+ export function DetailPresenceSlot(props) {
422
+ const max = () => Math.max(1, props.max ?? 2);
423
+ return (() => {
424
+ var _el$37 = _$getNextElement(_tmpl$15),
425
+ _el$42 = _el$37.firstChild,
426
+ [_el$43, _co$8] = _$getNextMarker(_el$42.nextSibling),
427
+ _el$44 = _el$43.nextSibling,
428
+ [_el$45, _co$9] = _$getNextMarker(_el$44.nextSibling);
429
+ _$insert(_el$37, _$createComponent(For, {
430
+ get each() {
431
+ return props.people.slice(0, max());
432
+ },
433
+ children: person => _$createComponent(Avatar, {
434
+ get name() {
435
+ return person.name;
436
+ },
437
+ get src() {
438
+ return person.src;
439
+ },
440
+ get icon() {
441
+ return person.icon;
442
+ },
443
+ get shape() {
444
+ return person.shape;
445
+ },
446
+ size: "xs",
447
+ alt: ""
448
+ })
449
+ }), _el$43, _co$8);
450
+ _$insert(_el$37, _$createComponent(Show, {
451
+ get when() {
452
+ return props.people.length > max();
453
+ },
454
+ get children() {
455
+ var _el$38 = _$getNextElement(_tmpl$14),
456
+ _el$39 = _el$38.firstChild,
457
+ _el$40 = _el$39.nextSibling,
458
+ [_el$41, _co$7] = _$getNextMarker(_el$40.nextSibling);
459
+ _$insert(_el$38, () => props.people.length - max(), _el$41, _co$7);
460
+ return _el$38;
461
+ }
462
+ }), _el$45, _co$9);
463
+ return _el$37;
464
+ })();
465
+ }
466
+
467
+ // ── Access ──────────────────────────────────────────────────────────────
468
+
469
+ const ACCESS_ICONS = {
470
+ person: undefined,
471
+ service: undefined,
472
+ group: "ti ti-users-group",
473
+ everyone: "ti ti-users",
474
+ public: "ti ti-world"
475
+ };
476
+
477
+ /**
478
+ * Who has access and with which role, read-only. Closed it names the first entries; open it lists `limit` rows and
479
+ * "Show n more". A list that may load later passes `state="loading"` and keeps its place.
480
+ */
481
+ export function DetailAccess(props) {
482
+ const t = useDetailSectionMessages();
483
+ const panel = useDetailPanelMessages();
484
+ const [all, setAll] = createSignal(false);
485
+ const limit = () => Math.max(1, props.limit ?? 5);
486
+ const state = () => props.state ?? "ready";
487
+ const shown = () => all() ? props.entries : props.entries.slice(0, limit());
488
+ const hiddenCount = () => Math.max(0, props.entries.length - limit());
489
+ const nameOf = entry => entry.self ? t().you : entry.name;
490
+ const summary = () => {
491
+ if (state() === "loading") return t().accessLoading;
492
+ if (state() === "error") return t().accessFailed;
493
+ const names = props.entries.slice(0, 2).map(nameOf);
494
+ return names.length ? t().accessSummary({
495
+ names: names.join(", "),
496
+ more: Math.max(0, props.entries.length - 2)
497
+ }) : undefined;
498
+ };
499
+ const leading = entry => {
500
+ const kind = entry.kind ?? "person";
501
+ return _$createComponent(Avatar, {
502
+ get name() {
503
+ return entry.name;
504
+ },
505
+ get src() {
506
+ return kind === "person" ? entry.src : undefined;
507
+ },
508
+ get icon() {
509
+ return ACCESS_ICONS[kind];
510
+ },
511
+ shape: kind === "person" ? "circle" : "square",
512
+ size: "xs",
513
+ alt: ""
514
+ });
515
+ };
516
+ return _$createComponent(DetailPanel.Section, {
517
+ get title() {
518
+ return props.title ?? t().access;
519
+ },
520
+ icon: "ti ti-lock-access",
521
+ get count() {
522
+ return _$memo(() => state() === "ready")() ? props.entries.length : undefined;
523
+ },
524
+ collapsible: true,
525
+ get summary() {
526
+ return summary();
527
+ },
528
+ get defaultOpen() {
529
+ return props.defaultOpen;
530
+ },
531
+ get open() {
532
+ return props.open;
533
+ },
534
+ get onOpenChange() {
535
+ return props.onOpenChange;
536
+ },
537
+ get ["class"]() {
538
+ return props.class;
539
+ },
540
+ get children() {
541
+ var _el$46 = _$getNextElement(_tmpl$19),
542
+ _el$54 = _el$46.firstChild,
543
+ [_el$55, _co$1] = _$getNextMarker(_el$54.nextSibling),
544
+ _el$56 = _el$55.nextSibling,
545
+ [_el$57, _co$10] = _$getNextMarker(_el$56.nextSibling),
546
+ _el$58 = _el$57.nextSibling,
547
+ [_el$59, _co$11] = _$getNextMarker(_el$58.nextSibling),
548
+ _el$60 = _el$59.nextSibling,
549
+ [_el$61, _co$12] = _$getNextMarker(_el$60.nextSibling),
550
+ _el$62 = _el$61.nextSibling,
551
+ [_el$63, _co$13] = _$getNextMarker(_el$62.nextSibling);
552
+ _$insert(_el$46, _$createComponent(Show, {
553
+ get when() {
554
+ return state() === "loading";
555
+ },
556
+ get children() {
557
+ return [_$createComponent(For, {
558
+ each: [0, 1, 2],
559
+ children: () => _$createComponent(DetailPanel.Row, {
560
+ get leading() {
561
+ return _$getNextElement(_tmpl$20);
562
+ },
563
+ get title() {
564
+ return _$getNextElement(_tmpl$21);
565
+ }
566
+ })
567
+ }), (() => {
568
+ var _el$47 = _$getNextElement(_tmpl$16);
569
+ _$insert(_el$47, () => t().accessLoading);
570
+ return _el$47;
571
+ })()];
572
+ }
573
+ }), _el$55, _co$1);
574
+ _$insert(_el$46, _$createComponent(Show, {
575
+ get when() {
576
+ return state() === "error";
577
+ },
578
+ get children() {
579
+ var _el$48 = _$getNextElement(_tmpl$17),
580
+ _el$49 = _el$48.firstChild,
581
+ _el$50 = _el$49.nextSibling,
582
+ _el$51 = _el$50.nextSibling,
583
+ [_el$52, _co$0] = _$getNextMarker(_el$51.nextSibling);
584
+ _$insert(_el$50, () => t().accessFailed);
585
+ _$insert(_el$48, _$createComponent(Show, {
586
+ get when() {
587
+ return props.onRetry;
588
+ },
589
+ children: retry => _$createComponent(Button, {
590
+ variant: "text",
591
+ size: "xs",
592
+ onClick: () => retry()(),
593
+ get children() {
594
+ return t().retry;
595
+ }
596
+ })
597
+ }), _el$52, _co$0);
598
+ return _el$48;
599
+ }
600
+ }), _el$57, _co$10);
601
+ _$insert(_el$46, _$createComponent(Show, {
602
+ get when() {
603
+ return state() === "ready";
604
+ },
605
+ get children() {
606
+ return [_$createComponent(For, {
607
+ get each() {
608
+ return shown();
609
+ },
610
+ children: entry => _$createComponent(DetailPanel.Row, {
611
+ get leading() {
612
+ return leading(entry);
613
+ },
614
+ get title() {
615
+ return nameOf(entry);
616
+ },
617
+ get description() {
618
+ return entry.detail;
619
+ },
620
+ get trailing() {
621
+ return entry.role;
622
+ }
623
+ })
624
+ }), _$createComponent(Show, {
625
+ get when() {
626
+ return hiddenCount() > 0;
627
+ },
628
+ get children() {
629
+ return _$createComponent(DetailPanel.Action, {
630
+ type: "button",
631
+ get ["aria-expanded"]() {
632
+ return all();
633
+ },
634
+ get leading() {
635
+ return (() => {
636
+ var _el$66 = _$getNextElement(_tmpl$4);
637
+ _$effect(() => _$className(_el$66, all() ? "ti ti-chevron-up" : "ti ti-chevron-down"));
638
+ return _el$66;
639
+ })();
640
+ },
641
+ get title() {
642
+ return _$memo(() => !!all())() ? panel().showLess : panel().showMore({
643
+ count: hiddenCount()
644
+ });
645
+ },
646
+ onClick: () => setAll(!all())
647
+ });
648
+ }
649
+ })];
650
+ }
651
+ }), _el$59, _co$11);
652
+ _$insert(_el$46, _$createComponent(Show, {
653
+ get when() {
654
+ return props.manage;
655
+ },
656
+ children: manage => _$createComponent(Show, {
657
+ get when() {
658
+ return manage().href;
659
+ },
660
+ get fallback() {
661
+ return _$createComponent(DetailPanel.Action, {
662
+ type: "button",
663
+ get leading() {
664
+ return _$getNextElement(_tmpl$22);
665
+ },
666
+ get title() {
667
+ return manage().label;
668
+ },
669
+ onClick: () => manage().onClick?.()
670
+ });
671
+ },
672
+ children: href => _$createComponent(DetailPanel.Action, {
673
+ get href() {
674
+ return href();
675
+ },
676
+ get leading() {
677
+ return _$getNextElement(_tmpl$22);
678
+ },
679
+ get title() {
680
+ return manage().label;
681
+ }
682
+ })
683
+ })
684
+ }), _el$61, _co$12);
685
+ _$insert(_el$46, _$createComponent(Show, {
686
+ get when() {
687
+ return props.note;
688
+ },
689
+ get children() {
690
+ var _el$53 = _$getNextElement(_tmpl$18);
691
+ _$insert(_el$53, () => props.note);
692
+ return _el$53;
693
+ }
694
+ }), _el$63, _co$13);
695
+ _$effect(() => _$setAttribute(_el$46, "aria-busy", state() === "loading" ? "true" : undefined));
696
+ return _el$46;
697
+ }
698
+ });
699
+ }
700
+
701
+ // ── Links ───────────────────────────────────────────────────────────────
702
+
703
+ const LinkRow = props => {
704
+ const item = props.item;
705
+ const menu = item.menuItems ? {
706
+ menuItems: item.menuItems,
707
+ menuLabel: item.menuLabel
708
+ } : {};
709
+ const shared = {
710
+ leading: item.leading ?? (() => {
711
+ var _el$69 = _$getNextElement(_tmpl$4);
712
+ _$effect(() => _$className(_el$69, item.icon ?? "ti ti-file-text"));
713
+ return _el$69;
714
+ })(),
715
+ title: item.title,
716
+ description: item.description,
717
+ trailing: item.trailing,
718
+ ...menu
719
+ };
720
+ return _$createComponent(Show, {
721
+ get when() {
722
+ return _$memo(() => !!!item.disabled)() && item.href;
723
+ },
724
+ get fallback() {
725
+ return _$createComponent(DetailPanel.Action, _$mergeProps({
726
+ type: "button",
727
+ get disabled() {
728
+ return item.disabled;
729
+ },
730
+ onClick: event => item.onClick?.(event)
731
+ }, shared));
732
+ },
733
+ children: href => _$createComponent(DetailPanel.Action, _$mergeProps({
734
+ get href() {
735
+ return href();
736
+ },
737
+ get target() {
738
+ return item.target;
739
+ },
740
+ get rel() {
741
+ return item.rel;
742
+ },
743
+ onClick: event => item.onClick?.(event)
744
+ }, shared))
745
+ });
746
+ };
747
+ const LinkGroup = props => {
748
+ const panel = useDetailPanelMessages();
749
+ const [all, setAll] = createSignal(false);
750
+ const hiddenCount = () => Math.max(0, props.items.length - props.limit);
751
+ return (() => {
752
+ var _el$70 = _$getNextElement(_tmpl$23),
753
+ _el$71 = _el$70.firstChild,
754
+ _el$72 = _el$71.nextSibling,
755
+ [_el$73, _co$14] = _$getNextMarker(_el$72.nextSibling),
756
+ _el$74 = _el$73.nextSibling,
757
+ [_el$75, _co$15] = _$getNextMarker(_el$74.nextSibling);
758
+ _$insert(_el$71, () => props.label);
759
+ _$insert(_el$70, _$createComponent(For, {
760
+ get each() {
761
+ return _$memo(() => !!all())() ? props.items : props.items.slice(0, props.limit);
762
+ },
763
+ children: item => _$createComponent(LinkRow, {
764
+ item: item
765
+ })
766
+ }), _el$73, _co$14);
767
+ _$insert(_el$70, _$createComponent(Show, {
768
+ get when() {
769
+ return hiddenCount() > 0;
770
+ },
771
+ get children() {
772
+ return _$createComponent(DetailPanel.Action, {
773
+ type: "button",
774
+ get ["aria-expanded"]() {
775
+ return all();
776
+ },
777
+ get leading() {
778
+ return (() => {
779
+ var _el$76 = _$getNextElement(_tmpl$4);
780
+ _$effect(() => _$className(_el$76, all() ? "ti ti-chevron-up" : "ti ti-chevron-down"));
781
+ return _el$76;
782
+ })();
783
+ },
784
+ get title() {
785
+ return _$memo(() => !!all())() ? panel().showLess : panel().showMore({
786
+ count: hiddenCount()
787
+ });
788
+ },
789
+ onClick: () => setAll(!all())
790
+ });
791
+ }
792
+ }), _el$75, _co$15);
793
+ return _el$70;
794
+ })();
795
+ };
796
+
797
+ /**
798
+ * "Linked from" and "Links to" in one section. Without links it is one row: the title and "None yet", followed by the
799
+ * `footer` when there is one.
800
+ */
801
+ export function DetailLinks(props) {
802
+ const t = useDetailSectionMessages();
803
+ const limit = () => Math.max(1, props.limit ?? 5);
804
+ const state = () => props.state ?? "ready";
805
+ const total = () => props.incoming.length + props.outgoing.length;
806
+ // Resolve once: the empty state reads it as a condition and as content.
807
+ const footer = children(() => props.footer);
808
+ const summary = () => {
809
+ if (state() === "loading") return t().linksLoading;
810
+ if (state() === "error") return t().linksFailed;
811
+ const names = items => ({
812
+ names: listNames(items.slice(0, 2).map(item => item.title), t().and),
813
+ more: Math.max(0, items.length - 2)
814
+ });
815
+ return props.incoming.length ? t().linkedBySummary(names(props.incoming)) : t().linksToSummary(names(props.outgoing));
816
+ };
817
+ // Loading and failure take the row the next links would take, so the loaded rows above never move.
818
+ const pending = () => [_$createComponent(Show, {
819
+ get when() {
820
+ return state() === "loading";
821
+ },
822
+ get children() {
823
+ var _el$77 = _$getNextElement(_tmpl$24),
824
+ _el$79 = _el$77.firstChild,
825
+ [_el$80, _co$16] = _$getNextMarker(_el$79.nextSibling),
826
+ _el$78 = _el$80.nextSibling;
827
+ _$insert(_el$77, _$createComponent(DetailPanel.Row, {
828
+ get leading() {
829
+ return _$getNextElement(_tmpl$20);
830
+ },
831
+ get title() {
832
+ return _$getNextElement(_tmpl$21);
833
+ }
834
+ }), _el$80, _co$16);
835
+ _$insert(_el$78, () => t().linksLoading);
836
+ return _el$77;
837
+ }
838
+ }), _$createComponent(Show, {
839
+ get when() {
840
+ return state() === "error";
841
+ },
842
+ get children() {
843
+ var _el$81 = _$getNextElement(_tmpl$17),
844
+ _el$82 = _el$81.firstChild,
845
+ _el$83 = _el$82.nextSibling,
846
+ _el$84 = _el$83.nextSibling,
847
+ [_el$85, _co$17] = _$getNextMarker(_el$84.nextSibling);
848
+ _$insert(_el$83, () => t().linksFailed);
849
+ _$insert(_el$81, _$createComponent(Show, {
850
+ get when() {
851
+ return props.onRetry;
852
+ },
853
+ children: retry => _$createComponent(Button, {
854
+ variant: "text",
855
+ size: "xs",
856
+ onClick: () => retry()(),
857
+ get children() {
858
+ return t().retry;
859
+ }
860
+ })
861
+ }), _el$85, _co$17);
862
+ return _el$81;
863
+ }
864
+ })];
865
+ return _$createComponent(Show, {
866
+ get when() {
867
+ return total() > 0;
868
+ },
869
+ get fallback() {
870
+ return _$createComponent(DetailPanel.Section, {
871
+ get title() {
872
+ return props.title ?? t().links;
873
+ },
874
+ icon: "ti ti-arrows-exchange",
875
+ get count() {
876
+ return state() === "ready" ? 0 : undefined;
877
+ },
878
+ get ["class"]() {
879
+ return props.class;
880
+ },
881
+ get children() {
882
+ return _$createComponent(Show, {
883
+ get when() {
884
+ return state() !== "ready" || footer();
885
+ },
886
+ get children() {
887
+ var _el$97 = _$getNextElement(_tmpl$26),
888
+ _el$98 = _el$97.firstChild,
889
+ [_el$99, _co$22] = _$getNextMarker(_el$98.nextSibling),
890
+ _el$100 = _el$99.nextSibling,
891
+ [_el$101, _co$23] = _$getNextMarker(_el$100.nextSibling);
892
+ _$insert(_el$97, pending, _el$99, _co$22);
893
+ _$insert(_el$97, footer, _el$101, _co$23);
894
+ return _el$97;
895
+ }
896
+ });
897
+ }
898
+ });
899
+ },
900
+ get children() {
901
+ return _$createComponent(DetailPanel.Section, {
902
+ get title() {
903
+ return props.title ?? t().links;
904
+ },
905
+ icon: "ti ti-arrows-exchange",
906
+ get count() {
907
+ return _$memo(() => state() === "ready")() ? total() : undefined;
908
+ },
909
+ collapsible: true,
910
+ get defaultOpen() {
911
+ return props.defaultOpen ?? true;
912
+ },
913
+ get summary() {
914
+ return summary();
915
+ },
916
+ get ["class"]() {
917
+ return props.class;
918
+ },
919
+ get children() {
920
+ var _el$88 = _$getNextElement(_tmpl$25),
921
+ _el$89 = _el$88.firstChild,
922
+ [_el$90, _co$18] = _$getNextMarker(_el$89.nextSibling),
923
+ _el$91 = _el$90.nextSibling,
924
+ [_el$92, _co$19] = _$getNextMarker(_el$91.nextSibling),
925
+ _el$93 = _el$92.nextSibling,
926
+ [_el$94, _co$20] = _$getNextMarker(_el$93.nextSibling),
927
+ _el$95 = _el$94.nextSibling,
928
+ [_el$96, _co$21] = _$getNextMarker(_el$95.nextSibling);
929
+ _$insert(_el$88, _$createComponent(Show, {
930
+ get when() {
931
+ return props.incoming.length > 0;
932
+ },
933
+ get children() {
934
+ return _$createComponent(LinkGroup, {
935
+ get label() {
936
+ return t().linkedBy({
937
+ count: props.incoming.length
938
+ });
939
+ },
940
+ get items() {
941
+ return props.incoming;
942
+ },
943
+ get limit() {
944
+ return limit();
945
+ }
946
+ });
947
+ }
948
+ }), _el$90, _co$18);
949
+ _$insert(_el$88, _$createComponent(Show, {
950
+ get when() {
951
+ return props.outgoing.length > 0;
952
+ },
953
+ get children() {
954
+ return _$createComponent(LinkGroup, {
955
+ get label() {
956
+ return t().linksTo({
957
+ count: props.outgoing.length
958
+ });
959
+ },
960
+ get items() {
961
+ return props.outgoing;
962
+ },
963
+ get limit() {
964
+ return limit();
965
+ }
966
+ });
967
+ }
968
+ }), _el$92, _co$19);
969
+ _$insert(_el$88, pending, _el$94, _co$20);
970
+ _$insert(_el$88, footer, _el$96, _co$21);
971
+ return _el$88;
972
+ }
973
+ });
974
+ }
975
+ });
976
+ }
977
+
978
+ // ── Properties ──────────────────────────────────────────────────────────
979
+
980
+ /** Facts about the object as label and value rows, such as created, edited, size, and the way to its history. */
981
+ export function DetailProperties(props) {
982
+ const t = useDetailSectionMessages();
983
+ return _$createComponent(DetailPanel.Section, {
984
+ get title() {
985
+ return props.title ?? t().properties;
986
+ },
987
+ get icon() {
988
+ return props.icon ?? "ti ti-info-square";
989
+ },
990
+ collapsible: true,
991
+ get defaultOpen() {
992
+ return props.defaultOpen;
993
+ },
994
+ get summary() {
995
+ return props.summary;
996
+ },
997
+ get ["class"]() {
998
+ return props.class;
999
+ },
1000
+ get children() {
1001
+ return [(() => {
1002
+ var _el$102 = _$getNextElement(_tmpl$27);
1003
+ _$insert(_el$102, _$createComponent(For, {
1004
+ get each() {
1005
+ return props.items;
1006
+ },
1007
+ children: item => (() => {
1008
+ var _el$103 = _$getNextElement(_tmpl$29),
1009
+ _el$104 = _el$103.firstChild,
1010
+ _el$105 = _el$104.nextSibling,
1011
+ _el$107 = _el$105.firstChild,
1012
+ [_el$108, _co$24] = _$getNextMarker(_el$107.nextSibling),
1013
+ _el$109 = _el$108.nextSibling,
1014
+ [_el$110, _co$25] = _$getNextMarker(_el$109.nextSibling);
1015
+ _$insert(_el$104, () => item.label);
1016
+ _$insert(_el$105, _$createComponent(Show, {
1017
+ get when() {
1018
+ return item.leading;
1019
+ },
1020
+ get children() {
1021
+ var _el$106 = _$getNextElement(_tmpl$28);
1022
+ _$insert(_el$106, () => item.leading);
1023
+ return _el$106;
1024
+ }
1025
+ }), _el$108, _co$24);
1026
+ _$insert(_el$105, _$createComponent(Show, {
1027
+ get when() {
1028
+ return item.href;
1029
+ },
1030
+ get fallback() {
1031
+ return (() => {
1032
+ var _el$111 = _$getNextElement(_tmpl$30);
1033
+ _$insert(_el$111, () => item.value);
1034
+ return _el$111;
1035
+ })();
1036
+ },
1037
+ children: href => (() => {
1038
+ var _el$112 = _$getNextElement(_tmpl$31);
1039
+ _$insert(_el$112, () => item.value);
1040
+ _$effect(() => _$setAttribute(_el$112, "href", href()));
1041
+ return _el$112;
1042
+ })()
1043
+ }), _el$110, _co$25);
1044
+ return _el$103;
1045
+ })()
1046
+ }));
1047
+ return _el$102;
1048
+ })(), _$memo(() => props.children)];
1049
+ }
1050
+ });
1051
+ }
1052
+
1053
+ // ── Tags ────────────────────────────────────────────────────────────────
1054
+
1055
+ /** The object's tags as chips; a chip with `href` leads to everything with that tag. */
1056
+ export function DetailTags(props) {
1057
+ const t = useDetailSectionMessages();
1058
+ return _$createComponent(DetailPanel.Section, {
1059
+ get title() {
1060
+ return props.title ?? t().tags;
1061
+ },
1062
+ icon: "ti ti-hash",
1063
+ get count() {
1064
+ return props.tags.length;
1065
+ },
1066
+ get ["class"]() {
1067
+ return props.class;
1068
+ },
1069
+ get children() {
1070
+ return _$createComponent(Show, {
1071
+ get when() {
1072
+ return props.tags.length > 0;
1073
+ },
1074
+ get fallback() {
1075
+ return _$memo(() => !!props.emptyHint)() ? (() => {
1076
+ var _el$114 = _$getNextElement(_tmpl$18);
1077
+ _$insert(_el$114, () => props.emptyHint);
1078
+ return _el$114;
1079
+ })() : undefined;
1080
+ },
1081
+ get children() {
1082
+ var _el$113 = _$getNextElement(_tmpl$32);
1083
+ _$insert(_el$113, _$createComponent(For, {
1084
+ get each() {
1085
+ return props.tags;
1086
+ },
1087
+ children: tag => (() => {
1088
+ var _el$115 = _$getNextElement(_tmpl$33);
1089
+ _$insert(_el$115, _$createComponent(Show, {
1090
+ get when() {
1091
+ return tag.href;
1092
+ },
1093
+ get fallback() {
1094
+ return (() => {
1095
+ var _el$116 = _$getNextElement(_tmpl$34),
1096
+ _el$117 = _el$116.firstChild,
1097
+ _el$118 = _el$117.nextSibling,
1098
+ [_el$119, _co$26] = _$getNextMarker(_el$118.nextSibling);
1099
+ _$insert(_el$116, () => tag.label, _el$119, _co$26);
1100
+ return _el$116;
1101
+ })();
1102
+ },
1103
+ children: href => (() => {
1104
+ var _el$120 = _$getNextElement(_tmpl$35),
1105
+ _el$121 = _el$120.firstChild,
1106
+ _el$122 = _el$121.nextSibling,
1107
+ [_el$123, _co$27] = _$getNextMarker(_el$122.nextSibling);
1108
+ _$insert(_el$120, () => tag.label, _el$123, _co$27);
1109
+ _$effect(() => _$setAttribute(_el$120, "href", href()));
1110
+ return _el$120;
1111
+ })()
1112
+ }));
1113
+ return _el$115;
1114
+ })()
1115
+ }));
1116
+ return _el$113;
1117
+ }
1118
+ });
1119
+ }
1120
+ });
1121
+ }
1122
+ _$delegateEvents(["click"]);
1123
+ //# sourceMappingURL=DetailSections.js.map