@k2b/ui 0.27.0 → 0.29.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 +35 -4
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/DragAndDrop.js +89 -0
- package/dist/browser/actions/DragAndDrop.js.map +1 -0
- package/dist/browser/actions/Dropdown.js +184 -158
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/GestureMenu.js +95 -139
- 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/drag-and-drop-messages.js +75 -0
- package/dist/browser/actions/drag-and-drop-messages.js.map +1 -0
- package/dist/browser/actions/drag-and-drop.js +692 -0
- package/dist/browser/actions/drag-and-drop.js.map +1 -0
- package/dist/browser/actions/index.js +1 -0
- 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 +714 -410
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/ChatDecision.js +778 -0
- package/dist/browser/chat/ChatDecision.js.map +1 -0
- package/dist/browser/chat/ChatPrimitives.js +34 -28
- package/dist/browser/chat/ChatPrimitives.js.map +1 -1
- package/dist/browser/chat/ChatTimeline.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +25 -1
- package/dist/browser/chat/chat-messages.js.map +1 -1
- package/dist/browser/chat/command-search.js +13 -3
- package/dist/browser/chat/command-search.js.map +1 -1
- package/dist/browser/chat/index.js +8 -1
- 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/chat/types.js.map +1 -1
- package/dist/browser/content/Calendar.js +3 -3
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/Chart.js +60 -86
- 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/FileBrowser.js +2 -2
- package/dist/browser/content/FileBrowser.js.map +1 -1
- package/dist/browser/content/FileTree.js +42 -36
- package/dist/browser/content/FileTree.js.map +1 -1
- package/dist/browser/content/FileTypeIcon.js +72 -0
- package/dist/browser/content/FileTypeIcon.js.map +1 -0
- package/dist/browser/content/FileView.js +2 -2
- package/dist/browser/content/FileView.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/ReferenceChip.js +162 -0
- package/dist/browser/content/ReferenceChip.js.map +1 -0
- package/dist/browser/content/calendar-pointer.js +9 -0
- package/dist/browser/content/calendar-pointer.js.map +1 -1
- package/dist/browser/content/calendar-time-view.js +6 -3
- package/dist/browser/content/calendar-time-view.js.map +1 -1
- 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 +3 -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/AppOverview.js +1 -1
- package/dist/browser/layout/AppOverview.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +644 -445
- package/dist/browser/layout/AppWorkspace.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/PanelDialog.js +88 -86
- package/dist/browser/layout/PanelDialog.js.map +1 -1
- package/dist/browser/layout/ResizeSeparator.js +81 -0
- package/dist/browser/layout/ResizeSeparator.js.map +1 -0
- package/dist/browser/layout/SidebarSwitcher.js +9 -2
- package/dist/browser/layout/SidebarSwitcher.js.map +1 -1
- package/dist/browser/layout/TabBar.js +15 -12
- package/dist/browser/layout/TabBar.js.map +1 -1
- package/dist/browser/layout/TableOfContents.js +10 -2
- package/dist/browser/layout/TableOfContents.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +130 -17
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/detail-panel-messages.js +35 -0
- package/dist/browser/layout/detail-panel-messages.js.map +1 -0
- package/dist/browser/layout/index.js +3 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/resize-separator.js +90 -0
- package/dist/browser/layout/resize-separator.js.map +1 -0
- package/dist/browser/layout/workspace-messages.js +12 -2
- package/dist/browser/layout/workspace-messages.js.map +1 -1
- package/dist/browser/surfaces/Avatar.js +50 -20
- package/dist/browser/surfaces/Avatar.js.map +1 -1
- package/dist/browser/surfaces/AvatarStack.js +406 -0
- package/dist/browser/surfaces/AvatarStack.js.map +1 -0
- package/dist/browser/surfaces/LinkCard.js +1 -1
- package/dist/browser/surfaces/LinkCard.js.map +1 -1
- package/dist/browser/surfaces/Placeholder.js +14 -3
- package/dist/browser/surfaces/Placeholder.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +23 -0
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- 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/browser/widgets/Widget.js +1 -1
- package/dist/browser/widgets/Widget.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +26 -3
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/DragAndDrop.js +63 -0
- package/dist/ssr/actions/DragAndDrop.js.map +1 -0
- package/dist/ssr/actions/Dropdown.js +140 -72
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/GestureMenu.js +76 -107
- 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/drag-and-drop-messages.js +75 -0
- package/dist/ssr/actions/drag-and-drop-messages.js.map +1 -0
- package/dist/ssr/actions/drag-and-drop.js +692 -0
- package/dist/ssr/actions/drag-and-drop.js.map +1 -0
- package/dist/ssr/actions/index.js +1 -0
- 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 +393 -102
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/ChatDecision.js +465 -0
- package/dist/ssr/chat/ChatDecision.js.map +1 -0
- package/dist/ssr/chat/ChatPrimitives.js +2 -2
- package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
- package/dist/ssr/chat/ChatTimeline.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +25 -1
- package/dist/ssr/chat/chat-messages.js.map +1 -1
- package/dist/ssr/chat/command-search.js +13 -3
- package/dist/ssr/chat/command-search.js.map +1 -1
- package/dist/ssr/chat/index.js +8 -1
- 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/chat/types.js.map +1 -1
- package/dist/ssr/content/Calendar.js +3 -3
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/Chart.js +25 -38
- 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/FileBrowser.js +2 -2
- package/dist/ssr/content/FileBrowser.js.map +1 -1
- package/dist/ssr/content/FileTree.js +21 -14
- package/dist/ssr/content/FileTree.js.map +1 -1
- package/dist/ssr/content/FileTypeIcon.js +50 -0
- package/dist/ssr/content/FileTypeIcon.js.map +1 -0
- package/dist/ssr/content/FileView.js +2 -2
- package/dist/ssr/content/FileView.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/ReferenceChip.js +121 -0
- package/dist/ssr/content/ReferenceChip.js.map +1 -0
- package/dist/ssr/content/calendar-pointer.js +9 -0
- package/dist/ssr/content/calendar-pointer.js.map +1 -1
- package/dist/ssr/content/calendar-time-view.js +6 -3
- package/dist/ssr/content/calendar-time-view.js.map +1 -1
- 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 +3 -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/AppOverview.js +1 -1
- package/dist/ssr/layout/AppOverview.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +272 -95
- package/dist/ssr/layout/AppWorkspace.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/PanelDialog.js +7 -6
- package/dist/ssr/layout/PanelDialog.js.map +1 -1
- package/dist/ssr/layout/ResizeSeparator.js +45 -0
- package/dist/ssr/layout/ResizeSeparator.js.map +1 -0
- package/dist/ssr/layout/SidebarSwitcher.js +9 -2
- package/dist/ssr/layout/SidebarSwitcher.js.map +1 -1
- package/dist/ssr/layout/TabBar.js +1 -1
- package/dist/ssr/layout/TabBar.js.map +1 -1
- package/dist/ssr/layout/TableOfContents.js +10 -2
- package/dist/ssr/layout/TableOfContents.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +130 -17
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/detail-panel-messages.js +35 -0
- package/dist/ssr/layout/detail-panel-messages.js.map +1 -0
- package/dist/ssr/layout/index.js +3 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/resize-separator.js +90 -0
- package/dist/ssr/layout/resize-separator.js.map +1 -0
- package/dist/ssr/layout/workspace-messages.js +12 -2
- package/dist/ssr/layout/workspace-messages.js.map +1 -1
- package/dist/ssr/surfaces/Avatar.js +20 -2
- package/dist/ssr/surfaces/Avatar.js.map +1 -1
- package/dist/ssr/surfaces/AvatarStack.js +286 -0
- package/dist/ssr/surfaces/AvatarStack.js.map +1 -0
- package/dist/ssr/surfaces/LinkCard.js +1 -1
- package/dist/ssr/surfaces/LinkCard.js.map +1 -1
- package/dist/ssr/surfaces/Placeholder.js +4 -2
- package/dist/ssr/surfaces/Placeholder.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +23 -0
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- 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/ssr/widgets/Widget.js +1 -1
- package/dist/ssr/widgets/Widget.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/ContextMenu.d.ts +9 -0
- package/dist/types/actions/DragAndDrop.d.ts +29 -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/drag-and-drop-messages.d.ts +35 -0
- package/dist/types/actions/drag-and-drop.d.ts +36 -0
- package/dist/types/actions/index.d.ts +3 -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 +26 -1
- package/dist/types/chat/ChatDecision.d.ts +133 -0
- package/dist/types/chat/ChatPrimitives.d.ts +4 -1
- package/dist/types/chat/ChatTimeline.d.ts +2 -1
- package/dist/types/chat/chat-messages.d.ts +13 -2
- package/dist/types/chat/command-search.d.ts +5 -0
- package/dist/types/chat/index.d.ts +25 -1
- package/dist/types/chat/reaction-people.d.ts +9 -0
- package/dist/types/chat/types.d.ts +54 -1
- package/dist/types/content/Chart.d.ts +11 -5
- package/dist/types/content/FileTypeIcon.d.ts +27 -0
- package/dist/types/content/MessageRow.d.ts +3 -10
- package/dist/types/content/ReactionBar.d.ts +32 -0
- package/dist/types/content/ReferenceChip.d.ts +49 -0
- package/dist/types/content/calendar-pointer.d.ts +6 -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 +5 -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/AppWorkspace.d.ts +5 -3
- package/dist/types/layout/DetailPanel.d.ts +11 -0
- package/dist/types/layout/Discussion.d.ts +8 -0
- package/dist/types/layout/ResizeSeparator.d.ts +9 -0
- package/dist/types/layout/TabBar.d.ts +7 -0
- package/dist/types/layout/TableOfContents.d.ts +2 -0
- package/dist/types/layout/app-workspace-controller.d.ts +2 -0
- package/dist/types/layout/detail-panel-messages.d.ts +15 -0
- package/dist/types/layout/index.d.ts +3 -1
- package/dist/types/layout/resize-separator.d.ts +18 -0
- package/dist/types/layout/workspace-messages.d.ts +5 -0
- package/dist/types/surfaces/Avatar.d.ts +12 -0
- package/dist/types/surfaces/AvatarStack.d.ts +41 -0
- package/dist/types/surfaces/StatCell.d.ts +6 -0
- package/dist/types/surfaces/avatar-messages.d.ts +3 -0
- package/dist/types/surfaces/index.d.ts +3 -1
- package/package.json +7 -2
|
@@ -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":[]}
|
|
@@ -4,7 +4,7 @@ import { insert as _$insert } from "solid-js/web";
|
|
|
4
4
|
import { className as _$className } from "solid-js/web";
|
|
5
5
|
import { effect as _$effect } from "solid-js/web";
|
|
6
6
|
import { getNextElement as _$getNextElement } from "solid-js/web";
|
|
7
|
-
var _tmpl$ = /*#__PURE__*/_$template(`<div class=k2b-link-card__icon><i aria-hidden=true>`),
|
|
7
|
+
var _tmpl$ = /*#__PURE__*/_$template(`<div class="k2b-link-card__icon k2b-icon-tile"><i aria-hidden=true>`),
|
|
8
8
|
_tmpl$2 = /*#__PURE__*/_$template(`<div class=k2b-link-card__copy><span class=k2b-link-card__title></span><p class=k2b-link-card__description>`),
|
|
9
9
|
_tmpl$3 = /*#__PURE__*/_$template(`<span class=k2b-link-card__meta>`),
|
|
10
10
|
_tmpl$4 = /*#__PURE__*/_$template(`<i class="ti ti-chevron-right k2b-link-card__chevron"aria-hidden=true>`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["surfaces/LinkCard.tsx"],"sourcesContent":["import { Link, type LinkNavigateEvent } from \"@k2b/ssr/nav\";\nimport { type JSX, Show } from \"solid-js\";\nimport { Paper } from \"./Paper\";\n\nexport type LinkCardColor = \"blue\" | \"emerald\" | \"violet\" | \"orange\" | \"red\" | \"amber\" | \"zinc\" | \"cyan\" | \"rose\";\n\nexport type LinkCardProps = {\n href: string;\n navigation?: \"document\" | \"enhanced\";\n onNavigate?: (event: LinkNavigateEvent) => void | Promise<void>;\n title: string;\n description: string;\n icon: string;\n /** Glyph color. Omit it to use the host application's accent. */\n color?: LinkCardColor;\n /** One trailing fact, such as a count or a badge. */\n meta?: JSX.Element;\n};\n\nexport function LinkCard(props: LinkCardProps): JSX.Element {\n const content = (\n <>\n <div class=\"k2b-link-card__icon\">\n <i class={`${props.icon} k2b-link-card__glyph`} aria-hidden=\"true\" />\n </div>\n <div class=\"k2b-link-card__copy\">\n <span class=\"k2b-link-card__title\">{props.title}</span>\n <p class=\"k2b-link-card__description\">{props.description}</p>\n </div>\n <Show when={props.meta}>\n <span class=\"k2b-link-card__meta\">{props.meta}</span>\n </Show>\n <i class=\"ti ti-chevron-right k2b-link-card__chevron\" aria-hidden=\"true\" />\n </>\n );\n if (props.navigation === \"enhanced\" && props.onNavigate) {\n return (\n <Link\n href={props.href}\n onNavigate={props.onNavigate}\n class=\"k2b-paper k2b-link-card\"\n data-color={props.color}\n data-interactive=\"true\"\n >\n {content}\n </Link>\n );\n }\n return (\n <Paper as=\"a\" href={props.href} class=\"k2b-link-card\" data-color={props.color} interactive>\n {content}\n </Paper>\n );\n}\n\nexport default LinkCard;\n"],"mappings":";;;;;;;;;;AAAA,SAAS,IAAI,QAAgC,cAAc;AAC3D,SAAmB,IAAI,QAAQ,UAAU;AACzC,SAAS,KAAK,QAAQ,SAAS;AAiB/B,OAAO,SAAS,QAAQ,CAAC,KAAoB,EAAe;EAC1D,MAAM,OAAO;IAAA;MAAA;IAAA,kCAGG,GAAG,KAAK,CAAC,IAAI,uBAAuB;IAAA;EAAA;IAAA;MAAA;MAAA;IAAA,sBAGV,KAAK,CAAC,KAAK;IAAA,sBACR,KAAK,CAAC,WAAW;IAAA;EAAA,wBAEzD,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,KAAK,CAAC,IAAI;IAAA;IAAA;MAAA;MAAA,sBACe,KAAK,CAAC,IAAI;MAAA;IAAA;EAAA,8BAIlD;EACD,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU,IAAI,KAAK,CAAC,UAAU,EAAE;IACvD,yBACG,IAAI;MAAA,IACH,IAAI;QAAA,OAAE,KAAK,CAAC,IAAI;MAAA;MAAA,IAChB,UAAU;QAAA,OAAE,KAAK,CAAC,UAAU;MAAA;MAAA;MAAA;QAAA,OAEhB,KAAK,CAAC,KAAK;MAAA;MAAA;MAAA,UAGtB;IAAO;EAGd;EACA,yBACG,KAAK;IAAC,EAAE;IAAA,IAAK,IAAI;MAAA,OAAE,KAAK,CAAC,IAAI;IAAA;IAAA;IAAA;MAAA,OAAoC,KAAK,CAAC,KAAK;IAAA;IAAE,WAAW;IAAA,UACvF;EAAO;AAGd;AAEA,eAAe,QAAQ","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/LinkCard.tsx"],"sourcesContent":["import { Link, type LinkNavigateEvent } from \"@k2b/ssr/nav\";\nimport { type JSX, Show } from \"solid-js\";\nimport { Paper } from \"./Paper\";\n\nexport type LinkCardColor = \"blue\" | \"emerald\" | \"violet\" | \"orange\" | \"red\" | \"amber\" | \"zinc\" | \"cyan\" | \"rose\";\n\nexport type LinkCardProps = {\n href: string;\n navigation?: \"document\" | \"enhanced\";\n onNavigate?: (event: LinkNavigateEvent) => void | Promise<void>;\n title: string;\n description: string;\n icon: string;\n /** Glyph color. Omit it to use the host application's accent. */\n color?: LinkCardColor;\n /** One trailing fact, such as a count or a badge. */\n meta?: JSX.Element;\n};\n\nexport function LinkCard(props: LinkCardProps): JSX.Element {\n const content = (\n <>\n <div class=\"k2b-link-card__icon k2b-icon-tile\">\n <i class={`${props.icon} k2b-link-card__glyph`} aria-hidden=\"true\" />\n </div>\n <div class=\"k2b-link-card__copy\">\n <span class=\"k2b-link-card__title\">{props.title}</span>\n <p class=\"k2b-link-card__description\">{props.description}</p>\n </div>\n <Show when={props.meta}>\n <span class=\"k2b-link-card__meta\">{props.meta}</span>\n </Show>\n <i class=\"ti ti-chevron-right k2b-link-card__chevron\" aria-hidden=\"true\" />\n </>\n );\n if (props.navigation === \"enhanced\" && props.onNavigate) {\n return (\n <Link\n href={props.href}\n onNavigate={props.onNavigate}\n class=\"k2b-paper k2b-link-card\"\n data-color={props.color}\n data-interactive=\"true\"\n >\n {content}\n </Link>\n );\n }\n return (\n <Paper as=\"a\" href={props.href} class=\"k2b-link-card\" data-color={props.color} interactive>\n {content}\n </Paper>\n );\n}\n\nexport default LinkCard;\n"],"mappings":";;;;;;;;;;AAAA,SAAS,IAAI,QAAgC,cAAc;AAC3D,SAAmB,IAAI,QAAQ,UAAU;AACzC,SAAS,KAAK,QAAQ,SAAS;AAiB/B,OAAO,SAAS,QAAQ,CAAC,KAAoB,EAAe;EAC1D,MAAM,OAAO;IAAA;MAAA;IAAA,kCAGG,GAAG,KAAK,CAAC,IAAI,uBAAuB;IAAA;EAAA;IAAA;MAAA;MAAA;IAAA,sBAGV,KAAK,CAAC,KAAK;IAAA,sBACR,KAAK,CAAC,WAAW;IAAA;EAAA,wBAEzD,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,KAAK,CAAC,IAAI;IAAA;IAAA;MAAA;MAAA,sBACe,KAAK,CAAC,IAAI;MAAA;IAAA;EAAA,8BAIlD;EACD,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU,IAAI,KAAK,CAAC,UAAU,EAAE;IACvD,yBACG,IAAI;MAAA,IACH,IAAI;QAAA,OAAE,KAAK,CAAC,IAAI;MAAA;MAAA,IAChB,UAAU;QAAA,OAAE,KAAK,CAAC,UAAU;MAAA;MAAA;MAAA;QAAA,OAEhB,KAAK,CAAC,KAAK;MAAA;MAAA;MAAA,UAGtB;IAAO;EAGd;EACA,yBACG,KAAK;IAAC,EAAE;IAAA,IAAK,IAAI;MAAA,OAAE,KAAK,CAAC,IAAI;IAAA;IAAA;IAAA;MAAA,OAAoC,KAAK,CAAC,KAAK;IAAA;IAAE,WAAW;IAAA,UACvF;EAAO;AAGd;AAEA,eAAe,QAAQ","ignoreList":[]}
|
|
@@ -8,7 +8,7 @@ import { memo as _$memo } from "solid-js/web";
|
|
|
8
8
|
var _tmpl$ = /*#__PURE__*/_$template(`<p class=k2b-placeholder__title>`),
|
|
9
9
|
_tmpl$2 = /*#__PURE__*/_$template(`<div class=k2b-placeholder__description>`),
|
|
10
10
|
_tmpl$3 = /*#__PURE__*/_$template(`<div class=k2b-placeholder__action>`),
|
|
11
|
-
_tmpl$4 = /*#__PURE__*/_$template(`<span
|
|
11
|
+
_tmpl$4 = /*#__PURE__*/_$template(`<span><i aria-hidden=true>`);
|
|
12
12
|
import { Show } from "solid-js";
|
|
13
13
|
import { Dynamic } from "solid-js/web";
|
|
14
14
|
import { Paper } from "./Paper";
|
|
@@ -53,10 +53,21 @@ export default function Placeholder(props) {
|
|
|
53
53
|
get when() {
|
|
54
54
|
return icon();
|
|
55
55
|
},
|
|
56
|
-
children: iconClass =>
|
|
56
|
+
children: iconClass => // An empty state's icon sits in a soft chip of the app colour; loading and error keep their status
|
|
57
|
+
// colours on the same box, so a state change never resizes it.
|
|
58
|
+
(() => {
|
|
57
59
|
var _el$4 = _$getNextElement(_tmpl$4),
|
|
58
60
|
_el$5 = _el$4.firstChild;
|
|
59
|
-
_$effect(
|
|
61
|
+
_$effect(_p$ => {
|
|
62
|
+
var _v$ = state() === "empty" && variant() !== "inline" ? "k2b-placeholder__icon k2b-icon-tile" : "k2b-placeholder__icon",
|
|
63
|
+
_v$2 = iconClass();
|
|
64
|
+
_v$ !== _p$.e && _$className(_el$4, _p$.e = _v$);
|
|
65
|
+
_v$2 !== _p$.t && _$className(_el$5, _p$.t = _v$2);
|
|
66
|
+
return _p$;
|
|
67
|
+
}, {
|
|
68
|
+
e: undefined,
|
|
69
|
+
t: undefined
|
|
70
|
+
});
|
|
60
71
|
return _el$4;
|
|
61
72
|
})()
|
|
62
73
|
}), _$createComponent(Show, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["surfaces/Placeholder.tsx"],"sourcesContent":["import { type JSX, Show } from \"solid-js\";\nimport { Dynamic } from \"solid-js/web\";\nimport { Paper } from \"./Paper\";\n\nexport type PlaceholderAlign = \"center\" | \"left\";\nexport type PlaceholderSurface = \"none\" | \"paper\";\nexport type PlaceholderState = \"empty\" | \"loading\" | \"error\";\n/** `compact` stacks inside a section, `inline` is one row in a list or sidebar, `panel` fills a work area. */\nexport type PlaceholderVariant = \"compact\" | \"inline\" | \"panel\";\n\nexport type PlaceholderProps = {\n title?: JSX.Element;\n description?: JSX.Element;\n icon?: string;\n action?: JSX.Element;\n align?: PlaceholderAlign;\n surface?: PlaceholderSurface;\n state?: PlaceholderState;\n variant?: PlaceholderVariant;\n class?: string;\n};\n\nexport default function Placeholder(props: PlaceholderProps): JSX.Element {\n const align = () => props.align ?? \"center\";\n const state = () => props.state ?? \"empty\";\n const variant = () => props.variant ?? \"compact\";\n const icon = () => props.icon ?? (state() === \"loading\" ? \"ti ti-loader-2\" : state() === \"error\" ? \"ti ti-alert-circle\" : undefined);\n\n return (\n <Dynamic\n component={props.surface === \"paper\" ? Paper : \"div\"}\n class={`k2b-placeholder ${props.class ?? \"\"}`}\n data-align={align()}\n data-state={state()}\n data-surface={props.surface ?? \"none\"}\n data-variant={variant()}\n role={state() === \"error\" ? \"alert\" : state() === \"loading\" ? \"status\" : undefined}\n aria-live={state() === \"loading\" ? \"polite\" : undefined}\n aria-busy={state() === \"loading\" ? \"true\" : undefined}\n >\n <Show when={icon()}>\n {(iconClass) => (\n <span class
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/Placeholder.tsx"],"sourcesContent":["import { type JSX, Show } from \"solid-js\";\nimport { Dynamic } from \"solid-js/web\";\nimport { Paper } from \"./Paper\";\n\nexport type PlaceholderAlign = \"center\" | \"left\";\nexport type PlaceholderSurface = \"none\" | \"paper\";\nexport type PlaceholderState = \"empty\" | \"loading\" | \"error\";\n/** `compact` stacks inside a section, `inline` is one row in a list or sidebar, `panel` fills a work area. */\nexport type PlaceholderVariant = \"compact\" | \"inline\" | \"panel\";\n\nexport type PlaceholderProps = {\n title?: JSX.Element;\n description?: JSX.Element;\n icon?: string;\n action?: JSX.Element;\n align?: PlaceholderAlign;\n surface?: PlaceholderSurface;\n state?: PlaceholderState;\n variant?: PlaceholderVariant;\n class?: string;\n};\n\nexport default function Placeholder(props: PlaceholderProps): JSX.Element {\n const align = () => props.align ?? \"center\";\n const state = () => props.state ?? \"empty\";\n const variant = () => props.variant ?? \"compact\";\n const icon = () => props.icon ?? (state() === \"loading\" ? \"ti ti-loader-2\" : state() === \"error\" ? \"ti ti-alert-circle\" : undefined);\n\n return (\n <Dynamic\n component={props.surface === \"paper\" ? Paper : \"div\"}\n class={`k2b-placeholder ${props.class ?? \"\"}`}\n data-align={align()}\n data-state={state()}\n data-surface={props.surface ?? \"none\"}\n data-variant={variant()}\n role={state() === \"error\" ? \"alert\" : state() === \"loading\" ? \"status\" : undefined}\n aria-live={state() === \"loading\" ? \"polite\" : undefined}\n aria-busy={state() === \"loading\" ? \"true\" : undefined}\n >\n <Show when={icon()}>\n {(iconClass) => (\n // An empty state's icon sits in a soft chip of the app colour; loading and error keep their status\n // colours on the same box, so a state change never resizes it.\n <span class={state() === \"empty\" && variant() !== \"inline\" ? \"k2b-placeholder__icon k2b-icon-tile\" : \"k2b-placeholder__icon\"}>\n <i class={iconClass()} aria-hidden=\"true\" />\n </span>\n )}\n </Show>\n <Show when={props.title}>\n <p class=\"k2b-placeholder__title\">{props.title}</p>\n </Show>\n <Show when={props.description}>\n <div class=\"k2b-placeholder__description\">{props.description}</div>\n </Show>\n <Show when={props.action}>\n <div class=\"k2b-placeholder__action\">{props.action}</div>\n </Show>\n </Dynamic>\n );\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAmB,IAAI,QAAQ,UAAU;AACzC,SAAS,OAAO,QAAQ,cAAc;AACtC,SAAS,KAAK,QAAQ,SAAS;;AAK/B;;AAeA,eAAe,SAAS,WAAW,CAAC,KAAuB,EAAe;EACxE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,IAAI,QAAQ;EAC3C,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,IAAI,OAAO;EAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,IAAI,SAAS;EAChD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,gBAAgB,GAAG,KAAK,CAAC,CAAC,KAAK,OAAO,GAAG,oBAAoB,GAAG,SAAS,CAAC;EAEpI,yBACG,OAAO;IAAA,IACN,SAAS;MAAA,OAAE,KAAK,CAAC,OAAO,KAAK,OAAO,GAAG,KAAK,GAAG,KAAK;IAAA;IAAA;MAAA,OAC7C,mBAAmB,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE;IAAA;IAAA;MAAA,OACjC,KAAK,CAAC,CAAC;IAAA;IAAA;MAAA,OACP,KAAK,CAAC,CAAC;IAAA;IAAA;MAAA,OACL,KAAK,CAAC,OAAO,IAAI,MAAM;IAAA;IAAA;MAAA,OACvB,OAAO,CAAC,CAAC;IAAA;IAAA,IACvB,IAAI;MAAA,OAAE,kBAAK,CAAC,CAAC,KAAK,OAAO,MAAG,OAAO,GAAG,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS;IAAA;IAAA;MAAA,OACvE,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS;IAAA;IAAA;MAAA,OAC5C,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,MAAM,GAAG,SAAS;IAAA;IAAA;MAAA,0BAEpD,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,IAAI,CAAC,CAAC;QAAA;QAAA,UACd,SAAS,IACT;QACA;QAAA;UAAA;YAAA;UAAA;YAAA,UACa,KAAK,CAAC,CAAC,KAAK,OAAO,IAAI,OAAO,CAAC,CAAC,KAAK,QAAQ,GAAG,qCAAqC,GAAG,uBAAuB;cAAA,OAChH,SAAS,CAAC,CAAC;YAAA;YAAA;YAAA;UAAA;YAAA;YAAA;UAAA;UAAA;QAAA;MAExB,sBAEF,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,KAAK;QAAA;QAAA;UAAA;UAAA,qBACc,KAAK,CAAC,KAAK;UAAA;QAAA;MAAA,sBAE/C,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,WAAW;QAAA;QAAA;UAAA;UAAA,sBACgB,KAAK,CAAC,WAAW;UAAA;QAAA;MAAA,sBAE7D,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,MAAM;QAAA;QAAA;UAAA;UAAA,sBACgB,KAAK,CAAC,MAAM;UAAA;QAAA;MAAA;IAAA;EAAA;AAI1D","ignoreList":[]}
|
|
@@ -17,11 +17,26 @@ var _tmpl$ = /*#__PURE__*/_$template(`<span class=k2b-stat-cell__label>`),
|
|
|
17
17
|
_tmpl$8 = /*#__PURE__*/_$template(`<a class="k2b-stat-cell k2b-stat-cell--link"><i class="ti ti-external-link k2b-stat-cell__link-icon"aria-hidden=true></i><!$><!/>`);
|
|
18
18
|
import { Show } from "solid-js";
|
|
19
19
|
import Chart from "../content/Chart";
|
|
20
|
+
import { useLocale } from "../intl/locale";
|
|
20
21
|
import { useStatGridSize, useStatGridSurface } from "./StatGrid";
|
|
21
22
|
function Body(props) {
|
|
22
23
|
const gridSize = useStatGridSize();
|
|
23
24
|
const size = () => props.size ?? gridSize;
|
|
24
25
|
const accent = () => props.accent;
|
|
26
|
+
const locale = useLocale();
|
|
27
|
+
const defaultTrendTooltip = ({
|
|
28
|
+
datum
|
|
29
|
+
}) => {
|
|
30
|
+
const y = datum.values.find(field => field.key === "y")?.value ?? "";
|
|
31
|
+
return {
|
|
32
|
+
rows: [{
|
|
33
|
+
label: props.label,
|
|
34
|
+
value: typeof y === "number" ? new Intl.NumberFormat(locale(), {
|
|
35
|
+
maximumFractionDigits: 6
|
|
36
|
+
}).format(y) : y
|
|
37
|
+
}]
|
|
38
|
+
};
|
|
39
|
+
};
|
|
25
40
|
return [(() => {
|
|
26
41
|
var _el$ = _$getNextElement(_tmpl$);
|
|
27
42
|
_$insert(_el$, () => props.label);
|
|
@@ -51,6 +66,14 @@ function Body(props) {
|
|
|
51
66
|
get children() {
|
|
52
67
|
return _$createComponent(Chart, {
|
|
53
68
|
kind: "sparkline",
|
|
69
|
+
get labels() {
|
|
70
|
+
return {
|
|
71
|
+
interactiveChart: props.label
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
get tooltip() {
|
|
75
|
+
return props.trendTooltip ?? defaultTrendTooltip;
|
|
76
|
+
},
|
|
54
77
|
"class": "k2b-stat-cell__trend",
|
|
55
78
|
style: {
|
|
56
79
|
height: "32px"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["surfaces/StatCell.tsx"],"sourcesContent":["import { type JSX, Show } from \"solid-js\";\nimport Chart from \"../content/Chart\";\nimport type { AccentColor } from \"../semantics\";\nimport { type StatGridSize, useStatGridSize, useStatGridSurface } from \"./StatGrid\";\n\nexport type StatCellTone = AccentColor;\n\nexport type StatCellAccent = {\n tone: StatCellTone;\n icon: string;\n text?: string;\n};\n\nexport type StatCellProps = {\n label: string;\n value: string | number | JSX.Element;\n sub?: string;\n valueClass?: string;\n accent?: StatCellAccent;\n href?: string;\n title?: string;\n trend?: readonly number[];\n size?: StatGridSize;\n /**\n * Wraps the label, value and support line instead of truncating them. Use it for a cell whose height nothing\n * reserves, such as one figure on its own; cells compared in a row keep one line each.\n */\n wrap?: boolean;\n};\n\nfunction Body(props: StatCellProps): JSX.Element {\n const gridSize = useStatGridSize();\n const size = () => props.size ?? gridSize;\n const accent = () => props.accent;\n return (\n <>\n <span class=\"k2b-stat-cell__label\" data-size={size()}>\n {props.label}\n </span>\n <span class={`k2b-stat-cell__value ${props.valueClass ?? \"\"}`} data-size={size()} title={props.title}>\n {props.value}\n </span>\n <Show when={props.trend && props.trend.length > 1}>\n <Chart\n kind=\"sparkline\"\n class=\"k2b-stat-cell__trend\"\n style={{ height: \"32px\" }}\n data={Array.from(props.trend ?? [])}\n showLast\n showMinMax\n />\n </Show>\n <Show when={props.sub || accent()}>\n <div class=\"k2b-stat-cell__support\">\n <Show when={props.sub}>{(sub) => <span class=\"k2b-stat-cell__sub\">{sub()}</span>}</Show>\n <Show when={accent()}>\n {(value) => (\n <Show\n when={value().text}\n fallback={<i class={`${value().icon} k2b-stat-cell__accent-icon`} data-tone={value().tone} aria-hidden=\"true\" />}\n >\n {(text) => (\n <span class=\"k2b-stat-cell__accent\" data-tone={value().tone}>\n <i class={value().icon} aria-hidden=\"true\" />\n {text()}\n </span>\n )}\n </Show>\n )}\n </Show>\n </div>\n </Show>\n </>\n );\n}\n\nexport function StatCell(props: StatCellProps): JSX.Element {\n const gridSize = useStatGridSize();\n const size = () => props.size ?? gridSize;\n const surface = useStatGridSurface();\n return (\n <Show\n when={props.href}\n fallback={\n <div class=\"k2b-stat-cell\" data-size={size()} data-surface={surface} data-wrap={props.wrap || undefined}>\n <Body {...props} />\n </div>\n }\n >\n {(href) => (\n <a\n href={href()}\n class=\"k2b-stat-cell k2b-stat-cell--link\"\n data-size={size()}\n data-surface={surface}\n data-wrap={props.wrap || undefined}\n >\n <i class=\"ti ti-external-link k2b-stat-cell__link-icon\" aria-hidden=\"true\" />\n <Body {...props} />\n </a>\n )}\n </Show>\n );\n}\n\nexport default StatCell;\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,SAAmB,IAAI,QAAQ,UAAU;AACzC,OAAO,KAAK,MAAM,kBAAkB;AAEpC,SAA4B,eAAe,EAAE,kBAAkB,QAAQ,YAAY;
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/StatCell.tsx"],"sourcesContent":["import { type JSX, Show } from \"solid-js\";\nimport Chart from \"../content/Chart\";\nimport type { ChartTooltipFormatter } from \"../content/chart-inspection-core\";\nimport { useLocale } from \"../intl/locale\";\nimport type { AccentColor } from \"../semantics\";\nimport { type StatGridSize, useStatGridSize, useStatGridSurface } from \"./StatGrid\";\n\nexport type StatCellTone = AccentColor;\n\nexport type StatCellAccent = {\n tone: StatCellTone;\n icon: string;\n text?: string;\n};\n\nexport type StatCellProps = {\n label: string;\n value: string | number | JSX.Element;\n sub?: string;\n valueClass?: string;\n accent?: StatCellAccent;\n href?: string;\n title?: string;\n trend?: readonly number[];\n /**\n * Replaces the default trend tooltip in browser code, for example with a period title or a unit.\n * `selection.datum.index` is the source index into `trend`.\n */\n trendTooltip?: ChartTooltipFormatter;\n size?: StatGridSize;\n /**\n * Wraps the label, value and support line instead of truncating them. Use it for a cell whose height nothing\n * reserves, such as one figure on its own; cells compared in a row keep one line each.\n */\n wrap?: boolean;\n};\n\nfunction Body(props: StatCellProps): JSX.Element {\n const gridSize = useStatGridSize();\n const size = () => props.size ?? gridSize;\n const accent = () => props.accent;\n const locale = useLocale();\n const defaultTrendTooltip: ChartTooltipFormatter = ({ datum }) => {\n const y = datum.values.find((field) => field.key === \"y\")?.value ?? \"\";\n return {\n rows: [\n { label: props.label, value: typeof y === \"number\" ? new Intl.NumberFormat(locale(), { maximumFractionDigits: 6 }).format(y) : y },\n ],\n };\n };\n return (\n <>\n <span class=\"k2b-stat-cell__label\" data-size={size()}>\n {props.label}\n </span>\n <span class={`k2b-stat-cell__value ${props.valueClass ?? \"\"}`} data-size={size()} title={props.title}>\n {props.value}\n </span>\n <Show when={props.trend && props.trend.length > 1}>\n <Chart\n kind=\"sparkline\"\n labels={{ interactiveChart: props.label }}\n tooltip={props.trendTooltip ?? defaultTrendTooltip}\n class=\"k2b-stat-cell__trend\"\n style={{ height: \"32px\" }}\n data={Array.from(props.trend ?? [])}\n showLast\n showMinMax\n />\n </Show>\n <Show when={props.sub || accent()}>\n <div class=\"k2b-stat-cell__support\">\n <Show when={props.sub}>{(sub) => <span class=\"k2b-stat-cell__sub\">{sub()}</span>}</Show>\n <Show when={accent()}>\n {(value) => (\n <Show\n when={value().text}\n fallback={<i class={`${value().icon} k2b-stat-cell__accent-icon`} data-tone={value().tone} aria-hidden=\"true\" />}\n >\n {(text) => (\n <span class=\"k2b-stat-cell__accent\" data-tone={value().tone}>\n <i class={value().icon} aria-hidden=\"true\" />\n {text()}\n </span>\n )}\n </Show>\n )}\n </Show>\n </div>\n </Show>\n </>\n );\n}\n\nexport function StatCell(props: StatCellProps): JSX.Element {\n const gridSize = useStatGridSize();\n const size = () => props.size ?? gridSize;\n const surface = useStatGridSurface();\n return (\n <Show\n when={props.href}\n fallback={\n <div class=\"k2b-stat-cell\" data-size={size()} data-surface={surface} data-wrap={props.wrap || undefined}>\n <Body {...props} />\n </div>\n }\n >\n {(href) => (\n <a\n href={href()}\n class=\"k2b-stat-cell k2b-stat-cell--link\"\n data-size={size()}\n data-surface={surface}\n data-wrap={props.wrap || undefined}\n >\n <i class=\"ti ti-external-link k2b-stat-cell__link-icon\" aria-hidden=\"true\" />\n <Body {...props} />\n </a>\n )}\n </Show>\n );\n}\n\nexport default StatCell;\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":[]}
|