@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 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/ReactionBar.tsx"],"sourcesContent":["import { type Accessor, createEffect, createMemo, createSignal, For, type JSX, on, onCleanup, onMount, Show } from \"solid-js\";\nimport { IconButton } from \"../actions/Button\";\nimport { useChatMessages } from \"../chat/chat-messages\";\nimport { positionTooltipSurface } from \"../feedback/tooltip-position\";\nimport { ScrollArea } from \"../layout/ScrollArea\";\n\nexport type ReactionBarItem = {\n /** Stable identity of the reaction, passed to `onToggle`. */\n key: string;\n emoji: string;\n count: number;\n /** The reader reacted this way; the chip shows pressed. */\n own?: boolean;\n /** Who reacted, for example from `reactionPeople`. Read by screen readers and shown in the names hint. */\n label?: string;\n /** A change of the reader's own reaction is still being saved; the chip carries `aria-busy`. */\n busy?: boolean;\n};\nexport type ReactionBarProps = {\n reactions: readonly ReactionBarItem[];\n /** Called with a reaction's key when the reader presses its chip. Without it, the chips are not controls. */\n onToggle?: (key: string) => void;\n /** Called by \"Add reaction\" with the button to anchor a picker to, such as `EmojiPicker.Popover`. Without it there is no button. */\n onAdd?: (anchor: HTMLElement) => void;\n /** \"default\": 26 px chips (chat, item detail). \"compact\": 24 px chips (cards). */\n density?: \"default\" | \"compact\";\n /** \"scroll\" (default): one line of fixed height that scrolls sideways. \"wrap\": every chip shows, lines wrap. */\n overflow?: \"scroll\" | \"wrap\";\n /** Shows at most this many chips and then \"+n\", n being the number of further emoji. The shown chips do not scroll. */\n max?: number;\n /** Screen-reader text of \"+n\"; defaults to \"{n} more reactions\". */\n moreLabel?: (count: number) => string;\n /** \"always\" (default) or \"progressive\": shown on hover and focus with a mouse or trackpad (k2b-progressive-action, inside the caller's k2b-progressive-row), kept while its picker is open, hidden on touch. Its place stays reserved. */\n add?: \"always\" | \"progressive\";\n class?: string;\n};\n\nconst HOVER_MS = 250;\nconst HOLD_MS = 500;\nconst MOVE_TOLERANCE = 8;\n\nexport function ReactionBar(props: ReactionBarProps): JSX.Element {\n const chatMessages = useChatMessages();\n // A max uses the wrapping layout, so the shown chips, +n, and add button wrap together.\n const overflow = () => (props.max !== undefined ? \"wrap\" : (props.overflow ?? \"scroll\"));\n const shown = createMemo(() => (props.max === undefined ? props.reactions : props.reactions.slice(0, props.max)));\n const keys = createMemo(() => shown().map((reaction) => reaction.key));\n const byKey = createMemo(() => new Map(shown().map((reaction) => [reaction.key, reaction])));\n const more = () => props.reactions.length - shown().length;\n /** The reaction whose names the hint shows; it follows that reaction while the caller updates it. */\n const [hintKey, setHintKey] = createSignal<string>();\n const hinted = () => {\n const key = hintKey();\n const reaction = key === undefined ? undefined : byKey().get(key);\n return reaction?.label?.trim() ? reaction : undefined;\n };\n const hint = () => {\n const reaction = hinted();\n return reaction ? `${reaction.emoji} ${reaction.label}` : \"\";\n };\n const [touch, setTouch] = createSignal(false);\n let root: HTMLDivElement | undefined;\n let surface: HTMLSpanElement | undefined;\n\n onMount(() => {\n if (!root || !surface) return;\n const bar = root;\n const tooltip = surface;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let openChip: HTMLElement | undefined;\n let swallowClick = false;\n let press: { chip: HTMLElement; id: number; x: number; y: number; held: boolean; moved: boolean } | undefined;\n\n const chipOf = (target: EventTarget | null): HTMLElement | undefined => {\n const chip = target instanceof Element ? target.closest<HTMLElement>(\"[data-reaction-key]\") : null;\n return chip && chip.closest(\".k2b-reaction-bar\") === bar ? chip : undefined;\n };\n const clearTimer = () => {\n clearTimeout(timer);\n timer = undefined;\n };\n const close = () => {\n clearTimer();\n openChip = undefined;\n try {\n tooltip.hidePopover();\n } catch {\n /* The surface may already be disconnected. */\n }\n document.removeEventListener(\"pointerdown\", dismiss, true);\n document.removeEventListener(\"keydown\", escape);\n window.removeEventListener(\"scroll\", close, true);\n window.removeEventListener(\"resize\", close);\n };\n const dismiss = () => close();\n const escape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") close();\n };\n /** Opens the names hint over a chip; false when the chip has no names to show. */\n const open = (chip: HTMLElement, fromTouch: boolean): boolean => {\n clearTimer();\n const reaction = byKey().get(chip.dataset.reactionKey ?? \"\");\n if (!reaction?.label?.trim() || !chip.isConnected) return false;\n setHintKey(reaction.key);\n setTouch(fromTouch);\n if (!tooltip.matches(\":popover-open\")) {\n try {\n tooltip.showPopover();\n } catch {\n return false;\n }\n }\n openChip = chip;\n positionTooltipSurface(tooltip, chip, \"top\");\n document.addEventListener(\"pointerdown\", dismiss, true);\n document.addEventListener(\"keydown\", escape);\n window.addEventListener(\"scroll\", close, true);\n window.addEventListener(\"resize\", close);\n return true;\n };\n // An open hint follows its reaction: new names show at once, and it closes when the reaction, its names, or its\n // chip go away.\n createEffect(\n on(hinted, (reaction) => {\n if (!openChip) return;\n if (!reaction || !openChip.isConnected) close();\n else positionTooltipSurface(tooltip, openChip, \"top\");\n }),\n );\n const delayed = (chip: HTMLElement) => {\n if (touch() && openChip) return;\n if (\n !byKey()\n .get(chip.dataset.reactionKey ?? \"\")\n ?.label?.trim()\n ) {\n close();\n return;\n }\n clearTimer();\n if (openChip) open(chip, false);\n else timer = setTimeout(() => open(chip, false), HOVER_MS);\n };\n const enter = (event: PointerEvent) => {\n const chip = chipOf(event.target);\n if (chip && event.target === chip && event.pointerType !== \"touch\") delayed(chip);\n };\n const leave = (event: PointerEvent) => {\n if (event.target !== chipOf(event.target) || (touch() && openChip)) return;\n // Moving directly to another chip keeps an open hint available for its immediate update.\n const next = chipOf(event.relatedTarget);\n if (\n !next ||\n !byKey()\n .get(next.dataset.reactionKey ?? \"\")\n ?.label?.trim()\n )\n close();\n };\n const focusIn = (event: FocusEvent) => {\n const chip = chipOf(event.target);\n if (chip?.matches(\":focus-visible\")) delayed(chip);\n };\n const focusOut = (event: FocusEvent) => {\n if (chipOf(event.target) && !chipOf(event.relatedTarget) && !(touch() && openChip)) close();\n };\n const resetSwallow = () => {\n swallowClick = false;\n document.removeEventListener(\"pointerdown\", resetSwallow, true);\n };\n const endPress = () => {\n clearTimer();\n press = undefined;\n document.removeEventListener(\"pointermove\", move, true);\n document.removeEventListener(\"pointerup\", up, true);\n document.removeEventListener(\"pointercancel\", cancel, true);\n };\n const down = (event: PointerEvent) => {\n resetSwallow();\n close();\n endPress();\n const chip = chipOf(event.target);\n if (!chip || (event.pointerType !== \"touch\" && event.pointerType !== \"pen\")) return;\n press = { chip, id: event.pointerId, x: event.clientX, y: event.clientY, held: false, moved: false };\n timer = setTimeout(() => {\n timer = undefined;\n if (!press || press.moved) return;\n // Only a hold that shows names takes the press; on a chip without names it stays an ordinary press.\n press.held = open(press.chip, true);\n }, HOLD_MS);\n document.addEventListener(\"pointermove\", move, true);\n document.addEventListener(\"pointerup\", up, true);\n document.addEventListener(\"pointercancel\", cancel, true);\n };\n const move = (event: PointerEvent) => {\n if (!press || event.pointerId !== press.id) return;\n if (Math.hypot(event.clientX - press.x, event.clientY - press.y) > MOVE_TOLERANCE) {\n press.moved = true;\n clearTimer();\n }\n };\n const up = (event: PointerEvent) => {\n if (!press || event.pointerId !== press.id) return;\n if (press.held) {\n swallowClick = true;\n // Some browsers send no click after a hold. Never consume the next real tap.\n document.addEventListener(\"pointerdown\", resetSwallow, true);\n } else if (!press.moved && !props.onToggle) open(press.chip, true);\n endPress();\n };\n const cancel = (event: PointerEvent) => {\n if (event.pointerId === press?.id) endPress();\n };\n const touchEnd = (event: TouchEvent) => {\n if (!swallowClick || !event.cancelable) return;\n // A cancelled touchend sends no click, so nothing is left to swallow.\n event.preventDefault();\n resetSwallow();\n };\n // Only the click of the held finger or pen is swallowed; a keyboard's click has no detail and always goes through.\n const click = (event: MouseEvent) => {\n if (!swallowClick || event.detail === 0) return;\n event.preventDefault();\n event.stopPropagation();\n resetSwallow();\n };\n const contextMenu = (event: MouseEvent) => {\n if (chipOf(event.target) && (press || swallowClick || (touch() && openChip))) event.preventDefault();\n };\n\n bar.addEventListener(\"pointerenter\", enter, true);\n bar.addEventListener(\"pointerleave\", leave, true);\n bar.addEventListener(\"focusin\", focusIn);\n bar.addEventListener(\"focusout\", focusOut);\n bar.addEventListener(\"pointerdown\", down);\n bar.addEventListener(\"touchend\", touchEnd, { passive: false });\n bar.addEventListener(\"click\", click, true);\n bar.addEventListener(\"contextmenu\", contextMenu);\n onCleanup(() => {\n close();\n endPress();\n resetSwallow();\n bar.removeEventListener(\"pointerenter\", enter, true);\n bar.removeEventListener(\"pointerleave\", leave, true);\n bar.removeEventListener(\"focusin\", focusIn);\n bar.removeEventListener(\"focusout\", focusOut);\n bar.removeEventListener(\"pointerdown\", down);\n bar.removeEventListener(\"touchend\", touchEnd);\n bar.removeEventListener(\"click\", click, true);\n bar.removeEventListener(\"contextmenu\", contextMenu);\n });\n });\n\n const chip = (key: string, reaction: Accessor<ReactionBarItem>) => {\n const label = (own: boolean) =>\n chatMessages().messageReaction({ emoji: reaction().emoji, count: reaction().count, names: reaction().label, own });\n return (\n <Show\n when={props.onToggle}\n fallback={\n <span\n class=\"k2b-reaction-bar__chip\"\n role=\"img\"\n aria-label={label(Boolean(reaction().own))}\n aria-busy={reaction().busy ? \"true\" : undefined}\n data-own={reaction().own ? \"\" : undefined}\n data-reaction-key={key}\n data-gesture-ignore\n >\n <span aria-hidden=\"true\">{reaction().emoji}</span>\n <span aria-hidden=\"true\">{reaction().count}</span>\n </span>\n }\n >\n {(toggle) => (\n <button\n type=\"button\"\n class=\"k2b-reaction-bar__chip\"\n aria-pressed={reaction().own ? \"true\" : \"false\"}\n aria-label={label(false)}\n aria-busy={reaction().busy ? \"true\" : undefined}\n data-own={reaction().own ? \"\" : undefined}\n data-reaction-key={key}\n onClick={() => toggle()(key)}\n >\n <span aria-hidden=\"true\">{reaction().emoji}</span>\n <span aria-hidden=\"true\">{reaction().count}</span>\n </button>\n )}\n </Show>\n );\n };\n const chips = () => <For each={keys()}>{(key) => <Show when={byKey().get(key)}>{(reaction) => chip(key, reaction)}</Show>}</For>;\n\n return (\n <div\n ref={root}\n class={props.class ? `k2b-reaction-bar ${props.class}` : \"k2b-reaction-bar\"}\n role=\"group\"\n aria-label={chatMessages().messageReactions}\n data-density={props.density ?? \"default\"}\n data-overflow={overflow()}\n data-add={props.onAdd ? (props.add ?? \"always\") : undefined}\n data-empty={props.reactions.length === 0 ? \"\" : undefined}\n >\n <Show when={overflow() === \"scroll\"} fallback={<div class=\"k2b-reaction-bar__list\">{chips()}</div>}>\n <Show when={shown().length > 0}>\n <ScrollArea orientation=\"horizontal\" class=\"k2b-reaction-bar__scroll\" tabindex={props.onToggle ? undefined : 0}>\n {chips()}\n </ScrollArea>\n </Show>\n </Show>\n <Show when={more() > 0}>\n <span class=\"k2b-reaction-bar__more\">\n <span aria-hidden=\"true\">+{more()}</span>\n <span class=\"k2b-sr-only\">{props.moreLabel?.(more()) ?? chatMessages().moreReactions({ count: more() })}</span>\n </span>\n </Show>\n <Show when={props.onAdd}>\n {(add) => (\n <span class={`k2b-reaction-bar__add${props.add === \"progressive\" ? \" k2b-progressive-action\" : \"\"}`}>\n <IconButton\n label={chatMessages().messageAddReaction}\n size=\"xs\"\n class=\"k2b-reaction-bar__add-button\"\n onClick={(event) => add()(event.currentTarget)}\n >\n <i class=\"ti ti-mood-plus\" aria-hidden=\"true\" />\n </IconButton>\n </span>\n )}\n </Show>\n <span\n ref={surface}\n class=\"k2b-tooltip k2b-reaction-bar__hint\"\n popover=\"manual\"\n role=\"tooltip\"\n aria-hidden=\"true\"\n data-touch={touch() ? \"\" : undefined}\n >\n {hint()}\n </span>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { mergeProps as _$mergeProps } from "solid-js/web";
|
|
2
|
+
import { ssrElement as _$ssrElement } from "solid-js/web";
|
|
3
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
4
|
+
import { escape as _$escape } from "solid-js/web";
|
|
5
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
6
|
+
import { memo as _$memo } from "solid-js/web";
|
|
7
|
+
var _tmpl$ = ["<span class=\"k2b-sr-only\">", "</span>"],
|
|
8
|
+
_tmpl$2 = ["<span aria-hidden=\"true\">", "</span>"],
|
|
9
|
+
_tmpl$3 = ["<span class=\"k2b-reference__avatar\" aria-hidden=\"true\">", "</span>"],
|
|
10
|
+
_tmpl$4 = ["<i class=\"", "\" aria-hidden=\"true\"></i>"];
|
|
11
|
+
import { Show } from "solid-js";
|
|
12
|
+
import { Avatar } from "../surfaces/Avatar";
|
|
13
|
+
|
|
14
|
+
/** The visible length of a chip; longer titles are cut in the middle. */
|
|
15
|
+
export const REFERENCE_CHIP_MAX_CHARACTERS = 40;
|
|
16
|
+
const graphemes = text => typeof Intl.Segmenter === "function" ? Array.from(new Intl.Segmenter(undefined, {
|
|
17
|
+
granularity: "grapheme"
|
|
18
|
+
}).segment(text), part => part.segment) : Array.from(text);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Shortens `text` to at most `max` visible characters by cutting its middle, so the start and an ending such as
|
|
22
|
+
* ".pdf" stay readable. Counts user-perceived characters, so an emoji is never split.
|
|
23
|
+
* @example truncateMiddle("Quarterly report for the operations team 2026.pdf", 24) // "Quarterly re…m 2026.pdf"
|
|
24
|
+
*/
|
|
25
|
+
export const truncateMiddle = (text, max = REFERENCE_CHIP_MAX_CHARACTERS) => {
|
|
26
|
+
const characters = graphemes(text);
|
|
27
|
+
if (characters.length <= max) return text;
|
|
28
|
+
if (max < 2) return "…";
|
|
29
|
+
const tail = Math.floor((max - 1) / 2);
|
|
30
|
+
const head = max - 1 - tail;
|
|
31
|
+
return `${characters.slice(0, head).join("").trimEnd()}…${characters.slice(characters.length - tail).join("").trimStart()}`;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** A thing or a place: an icon in its application colour and its title, a link while it exists. */
|
|
35
|
+
|
|
36
|
+
/** A person: avatar and display name. The address belongs in the preview, never in the chip. */
|
|
37
|
+
|
|
38
|
+
/** A date or time the host already formatted for the reader. */
|
|
39
|
+
|
|
40
|
+
const fullText = props => props.kind === "person" ? props.name : props.kind === "time" ? props.label : props.title;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A typed reference inside a sentence: a thing, a place, a person, or a time, in the calm `.k2b-reference` pill.
|
|
44
|
+
* A chip shows at most 40 characters and cuts longer titles in the middle; the full title stays its accessible name
|
|
45
|
+
* and tooltip.
|
|
46
|
+
* @example <ReferenceChip kind="object" title="Maintenance window" icon="ti ti-mail" accent="var(--app-mail)" href="/mail/…" />
|
|
47
|
+
*/
|
|
48
|
+
export function ReferenceChip(props) {
|
|
49
|
+
const full = () => fullText(props);
|
|
50
|
+
const visible = () => truncateMiddle(full());
|
|
51
|
+
const cut = () => visible() !== full();
|
|
52
|
+
const gone = () => props.kind !== "person" && props.kind !== "time" && props.gone === true;
|
|
53
|
+
const href = () => gone() || props.kind === "time" ? undefined : props.href;
|
|
54
|
+
const accent = () => props.kind === "object" || props.kind === "place" ? props.accent : undefined;
|
|
55
|
+
const icon = () => props.kind === "time" ? "ti ti-clock" : props.kind === "object" || props.kind === "place" ? props.icon : undefined;
|
|
56
|
+
const content = () => [_$createComponent(Show, {
|
|
57
|
+
get when() {
|
|
58
|
+
return props.kind === "person" ? props : undefined;
|
|
59
|
+
},
|
|
60
|
+
children: person => _$ssr(_tmpl$3, _$escape(_$createComponent(Avatar, {
|
|
61
|
+
get name() {
|
|
62
|
+
return person().name;
|
|
63
|
+
},
|
|
64
|
+
get src() {
|
|
65
|
+
return person().src;
|
|
66
|
+
},
|
|
67
|
+
size: "xs"
|
|
68
|
+
})))
|
|
69
|
+
}), _$createComponent(Show, {
|
|
70
|
+
get when() {
|
|
71
|
+
return icon();
|
|
72
|
+
},
|
|
73
|
+
children: name => _$ssr(_tmpl$4, `k2b-reference__icon ${_$escape(name(), true)}`)
|
|
74
|
+
}), _$createComponent(Show, {
|
|
75
|
+
get when() {
|
|
76
|
+
return cut();
|
|
77
|
+
},
|
|
78
|
+
get fallback() {
|
|
79
|
+
return full();
|
|
80
|
+
},
|
|
81
|
+
get children() {
|
|
82
|
+
return [_$ssr(_tmpl$, _$escape(full())), _$ssr(_tmpl$2, _$escape(visible()))];
|
|
83
|
+
}
|
|
84
|
+
})];
|
|
85
|
+
const shared = () => ({
|
|
86
|
+
class: `k2b-reference k2b-reference-chip${props.class ? ` ${props.class}` : ""}`,
|
|
87
|
+
"data-kind": props.kind,
|
|
88
|
+
"data-gone": gone() ? "true" : undefined,
|
|
89
|
+
title: cut() ? full() : undefined,
|
|
90
|
+
style: accent() ? {
|
|
91
|
+
"--k2b-reference-icon": accent()
|
|
92
|
+
} : undefined
|
|
93
|
+
});
|
|
94
|
+
return _$createComponent(Show, {
|
|
95
|
+
get when() {
|
|
96
|
+
return href();
|
|
97
|
+
},
|
|
98
|
+
get fallback() {
|
|
99
|
+
return _$createComponent(Show, {
|
|
100
|
+
get when() {
|
|
101
|
+
return props.kind === "time" ? props : undefined;
|
|
102
|
+
},
|
|
103
|
+
get fallback() {
|
|
104
|
+
return _$ssrElement("span", shared(), _$escape(content()), false);
|
|
105
|
+
},
|
|
106
|
+
children: time => _$ssrElement("time", _$mergeProps(shared, {
|
|
107
|
+
get dateTime() {
|
|
108
|
+
return time().dateTime;
|
|
109
|
+
}
|
|
110
|
+
}), _$escape(content()), false)
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
children: link => _$ssrElement("a", _$mergeProps(shared, {
|
|
114
|
+
get href() {
|
|
115
|
+
return link();
|
|
116
|
+
}
|
|
117
|
+
}), _$escape(content()), false)
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
export default ReferenceChip;
|
|
121
|
+
//# sourceMappingURL=ReferenceChip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/ReferenceChip.tsx"],"sourcesContent":["import { type JSX, Show } from \"solid-js\";\nimport { Avatar } from \"../surfaces/Avatar\";\n\n/** The visible length of a chip; longer titles are cut in the middle. */\nexport const REFERENCE_CHIP_MAX_CHARACTERS = 40;\n\nconst graphemes = (text: string): string[] =>\n typeof Intl.Segmenter === \"function\"\n ? Array.from(new Intl.Segmenter(undefined, { granularity: \"grapheme\" }).segment(text), (part) => part.segment)\n : Array.from(text);\n\n/**\n * Shortens `text` to at most `max` visible characters by cutting its middle, so the start and an ending such as\n * \".pdf\" stay readable. Counts user-perceived characters, so an emoji is never split.\n * @example truncateMiddle(\"Quarterly report for the operations team 2026.pdf\", 24) // \"Quarterly re…m 2026.pdf\"\n */\nexport const truncateMiddle = (text: string, max: number = REFERENCE_CHIP_MAX_CHARACTERS): string => {\n const characters = graphemes(text);\n if (characters.length <= max) return text;\n if (max < 2) return \"…\";\n const tail = Math.floor((max - 1) / 2);\n const head = max - 1 - tail;\n return `${characters.slice(0, head).join(\"\").trimEnd()}…${characters\n .slice(characters.length - tail)\n .join(\"\")\n .trimStart()}`;\n};\n\ntype ReferenceChipCommon = {\n class?: string;\n};\n\n/** A thing or a place: an icon in its application colour and its title, a link while it exists. */\nexport type ReferenceChipObjectProps = ReferenceChipCommon & {\n kind: \"object\" | \"place\";\n title: string;\n /** Destination of the chip. Omit it, or set `gone`, when there is nothing to open. */\n href?: string;\n /** Icon class, for example `ti ti-mail`. */\n icon?: string;\n /** Icon colour, usually the owning application's accent. Sets `--k2b-reference-icon`. */\n accent?: string;\n /** The thing no longer exists: struck through and never a link. */\n gone?: boolean;\n};\n\n/** A person: avatar and display name. The address belongs in the preview, never in the chip. */\nexport type ReferenceChipPersonProps = ReferenceChipCommon & {\n kind: \"person\";\n name: string;\n /** Avatar image; initials on a tint from the name otherwise. */\n src?: string | null;\n href?: string;\n};\n\n/** A date or time the host already formatted for the reader. */\nexport type ReferenceChipTimeProps = ReferenceChipCommon & {\n kind: \"time\";\n label: string;\n /** Machine-readable value for `<time datetime>`. */\n dateTime?: string;\n};\n\nexport type ReferenceChipProps = ReferenceChipObjectProps | ReferenceChipPersonProps | ReferenceChipTimeProps;\n\nconst fullText = (props: ReferenceChipProps): string =>\n props.kind === \"person\" ? props.name : props.kind === \"time\" ? props.label : props.title;\n\n/**\n * A typed reference inside a sentence: a thing, a place, a person, or a time, in the calm `.k2b-reference` pill.\n * A chip shows at most 40 characters and cuts longer titles in the middle; the full title stays its accessible name\n * and tooltip.\n * @example <ReferenceChip kind=\"object\" title=\"Maintenance window\" icon=\"ti ti-mail\" accent=\"var(--app-mail)\" href=\"/mail/…\" />\n */\nexport function ReferenceChip(props: ReferenceChipProps): JSX.Element {\n const full = () => fullText(props);\n const visible = () => truncateMiddle(full());\n const cut = () => visible() !== full();\n const gone = () => props.kind !== \"person\" && props.kind !== \"time\" && props.gone === true;\n const href = () => (gone() || props.kind === \"time\" ? undefined : props.href);\n const accent = () => (props.kind === \"object\" || props.kind === \"place\" ? props.accent : undefined);\n const icon = () => (props.kind === \"time\" ? \"ti ti-clock\" : props.kind === \"object\" || props.kind === \"place\" ? props.icon : undefined);\n\n const content = () => (\n <>\n <Show when={props.kind === \"person\" ? props : undefined}>\n {(person) => (\n <span class=\"k2b-reference__avatar\" aria-hidden=\"true\">\n <Avatar name={person().name} src={person().src} size=\"xs\" />\n </span>\n )}\n </Show>\n <Show when={icon()}>{(name) => <i class={`k2b-reference__icon ${name()}`} aria-hidden=\"true\" />}</Show>\n <Show when={cut()} fallback={full()}>\n <span class=\"k2b-sr-only\">{full()}</span>\n <span aria-hidden=\"true\">{visible()}</span>\n </Show>\n </>\n );\n\n const shared = () => ({\n class: `k2b-reference k2b-reference-chip${props.class ? ` ${props.class}` : \"\"}`,\n \"data-kind\": props.kind,\n \"data-gone\": gone() ? \"true\" : undefined,\n title: cut() ? full() : undefined,\n style: accent() ? { \"--k2b-reference-icon\": accent() } : undefined,\n });\n\n return (\n <Show\n when={href()}\n fallback={\n <Show when={props.kind === \"time\" ? props : undefined} fallback={<span {...shared()}>{content()}</span>}>\n {(time) => (\n <time {...shared()} dateTime={time().dateTime}>\n {content()}\n </time>\n )}\n </Show>\n }\n >\n {(link) => (\n <a {...shared()} href={link()}>\n {content()}\n </a>\n )}\n </Show>\n );\n}\n\nexport default ReferenceChip;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -17,6 +17,15 @@ export const calendarAutoScrollSpeed = (clientY, top, bottom, edge = 56, maximum
|
|
|
17
17
|
};
|
|
18
18
|
let cancelActiveSession = null;
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Runs `open` once the browser has handled the pointer release that ends a drag. The browser light-dismisses an
|
|
22
|
+
* `auto` popover that opens while it dispatches that `pointerup`, as the HTML popover rules ask and Chromium 156
|
|
23
|
+
* does, so a popover that a drag opens must open after the release.
|
|
24
|
+
*/
|
|
25
|
+
export const afterPointerRelease = open => {
|
|
26
|
+
window.setTimeout(open, 0);
|
|
27
|
+
};
|
|
28
|
+
|
|
20
29
|
/**
|
|
21
30
|
* Owns one pointer gesture from threshold crossing through commit or cancel.
|
|
22
31
|
* Views provide geometry through `resolve`; this helper owns global cleanup,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["content/calendar-pointer.ts"],"sourcesContent":["import { suppressTextSelection } from \"../internal/text-selection\";\n\nexport const CALENDAR_SNAP_MINUTES = 15;\n\nexport const snapCalendarMinutes = (minutes: number, step = CALENDAR_SNAP_MINUTES): number => Math.round(minutes / step) * step;\n\nexport const calendarDayIndexAtPoint = (clientX: number, startX: number, width: number, days: number): number | null => {\n if (days <= 0 || width <= 0 || clientX < startX || clientX >= startX + width) return null;\n return Math.min(days - 1, Math.floor(((clientX - startX) / width) * days));\n};\n\nexport const calendarMinuteAtPoint = (clientY: number, top: number, height: number, startHour: number, endHour: number): number => {\n const totalMinutes = Math.max(60, (endHour - startHour + 1) * 60);\n const ratio = height > 0 ? Math.min(1, Math.max(0, (clientY - top) / height)) : 0;\n return snapCalendarMinutes(startHour * 60 + ratio * totalMinutes);\n};\n\nexport const calendarAutoScrollSpeed = (clientY: number, top: number, bottom: number, edge = 56, maximum = 18): number => {\n if (clientY < top + edge) return -Math.ceil(maximum * Math.min(1, (top + edge - clientY) / edge));\n if (clientY > bottom - edge) return Math.ceil(maximum * Math.min(1, (clientY - (bottom - edge)) / edge));\n return 0;\n};\n\ntype CalendarPointerSessionOptions<T> = {\n event: PointerEvent;\n resolve: (clientX: number, clientY: number) => T | null;\n onActivate?: () => void;\n onPreview: (value: T) => void;\n onCommit: (value: T) => void;\n onCancel?: () => void;\n /** Called once whenever the session ends, even before activation, after onCommit or onCancel. */\n onEnd?: () => void;\n scrollContainer?: HTMLElement;\n threshold?: number;\n /**\n * The edges scroll only once the pointer has been well inside the container, and only while it is over it, so a drag\n * that comes in from outside, such as from a list below, does not scroll on its way in.\n */\n armAutoScroll?: boolean;\n /** Called on every move once the gesture is active, such as to move a token with the pointer. */\n onMove?: (clientX: number, clientY: number) => void;\n};\n\nlet cancelActiveSession: (() => void) | null = null;\n\n/**\n * Owns one pointer gesture from threshold crossing through commit or cancel.\n * Views provide geometry through `resolve`; this helper owns global cleanup,\n * pointer cancellation, Escape handling, and edge auto-scroll.\n */\nexport const startCalendarPointerSession = <T>(options: CalendarPointerSessionOptions<T>): (() => void) => {\n if (options.event.button !== 0 || !options.event.isPrimary) return () => {};\n\n cancelActiveSession?.();\n\n const pointerId = options.event.pointerId;\n const target = options.event.currentTarget instanceof HTMLElement ? options.event.currentTarget : null;\n const startX = options.event.clientX;\n const startY = options.event.clientY;\n // Leave enough room for normal click jitter before an event becomes a drag.\n const threshold = options.threshold ?? 6;\n let clientX = startX;\n let clientY = startY;\n let active = false;\n let finished = false;\n let latest: T | null = null;\n let scrollFrame = 0;\n let releaseTextSelection: (() => void) | null = null;\n let armed = !options.armAutoScroll;\n\n const preview = () => {\n const value = options.resolve(clientX, clientY);\n if (value === null) return;\n latest = value;\n options.onPreview(value);\n };\n\n const autoScroll = () => {\n scrollFrame = 0;\n if (!active || !options.scrollContainer) return;\n const rect = options.scrollContainer.getBoundingClientRect();\n const inside = clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;\n if (!armed && inside && clientY > rect.top + 56 && clientY < rect.bottom - 56) armed = true;\n const speed = armed && (inside || !options.armAutoScroll) ? calendarAutoScrollSpeed(clientY, rect.top, rect.bottom) : 0;\n if (speed !== 0) {\n const before = options.scrollContainer.scrollTop;\n options.scrollContainer.scrollTop += speed;\n if (options.scrollContainer.scrollTop !== before) preview();\n }\n scrollFrame = requestAnimationFrame(autoScroll);\n };\n\n const cleanup = () => {\n if (scrollFrame) cancelAnimationFrame(scrollFrame);\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", cancel);\n window.removeEventListener(\"blur\", cancel);\n window.removeEventListener(\"keydown\", onKeyDown);\n if (target?.hasPointerCapture?.(pointerId)) target.releasePointerCapture(pointerId);\n releaseTextSelection?.();\n if (cancelActiveSession === cancel) cancelActiveSession = null;\n };\n\n const activate = () => {\n if (active) return;\n active = true;\n releaseTextSelection = suppressTextSelection(pointerId);\n target?.setPointerCapture?.(pointerId);\n options.onActivate?.();\n preview();\n if (options.scrollContainer) scrollFrame = requestAnimationFrame(autoScroll);\n };\n\n function cancel() {\n if (finished) return;\n finished = true;\n cleanup();\n try {\n if (active) options.onCancel?.();\n } finally {\n options.onEnd?.();\n }\n }\n\n function onMove(event: PointerEvent) {\n if (finished || event.pointerId !== pointerId) return;\n clientX = event.clientX;\n clientY = event.clientY;\n if (!active && Math.hypot(clientX - startX, clientY - startY) >= threshold) activate();\n if (!active) return;\n event.preventDefault();\n options.onMove?.(clientX, clientY);\n preview();\n }\n\n function onUp(event: PointerEvent) {\n if (finished || event.pointerId !== pointerId) return;\n finished = true;\n cleanup();\n try {\n if (active && latest !== null) options.onCommit(latest);\n else if (active) options.onCancel?.();\n } finally {\n options.onEnd?.();\n }\n }\n\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n cancel();\n }\n\n window.addEventListener(\"pointermove\", onMove, { passive: false });\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", cancel);\n window.addEventListener(\"blur\", cancel);\n window.addEventListener(\"keydown\", onKeyDown);\n cancelActiveSession = cancel;\n return cancel;\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["content/calendar-pointer.ts"],"sourcesContent":["import { suppressTextSelection } from \"../internal/text-selection\";\n\nexport const CALENDAR_SNAP_MINUTES = 15;\n\nexport const snapCalendarMinutes = (minutes: number, step = CALENDAR_SNAP_MINUTES): number => Math.round(minutes / step) * step;\n\nexport const calendarDayIndexAtPoint = (clientX: number, startX: number, width: number, days: number): number | null => {\n if (days <= 0 || width <= 0 || clientX < startX || clientX >= startX + width) return null;\n return Math.min(days - 1, Math.floor(((clientX - startX) / width) * days));\n};\n\nexport const calendarMinuteAtPoint = (clientY: number, top: number, height: number, startHour: number, endHour: number): number => {\n const totalMinutes = Math.max(60, (endHour - startHour + 1) * 60);\n const ratio = height > 0 ? Math.min(1, Math.max(0, (clientY - top) / height)) : 0;\n return snapCalendarMinutes(startHour * 60 + ratio * totalMinutes);\n};\n\nexport const calendarAutoScrollSpeed = (clientY: number, top: number, bottom: number, edge = 56, maximum = 18): number => {\n if (clientY < top + edge) return -Math.ceil(maximum * Math.min(1, (top + edge - clientY) / edge));\n if (clientY > bottom - edge) return Math.ceil(maximum * Math.min(1, (clientY - (bottom - edge)) / edge));\n return 0;\n};\n\ntype CalendarPointerSessionOptions<T> = {\n event: PointerEvent;\n resolve: (clientX: number, clientY: number) => T | null;\n onActivate?: () => void;\n onPreview: (value: T) => void;\n onCommit: (value: T) => void;\n onCancel?: () => void;\n /** Called once whenever the session ends, even before activation, after onCommit or onCancel. */\n onEnd?: () => void;\n scrollContainer?: HTMLElement;\n threshold?: number;\n /**\n * The edges scroll only once the pointer has been well inside the container, and only while it is over it, so a drag\n * that comes in from outside, such as from a list below, does not scroll on its way in.\n */\n armAutoScroll?: boolean;\n /** Called on every move once the gesture is active, such as to move a token with the pointer. */\n onMove?: (clientX: number, clientY: number) => void;\n};\n\nlet cancelActiveSession: (() => void) | null = null;\n\n/**\n * Runs `open` once the browser has handled the pointer release that ends a drag. The browser light-dismisses an\n * `auto` popover that opens while it dispatches that `pointerup`, as the HTML popover rules ask and Chromium 156\n * does, so a popover that a drag opens must open after the release.\n */\nexport const afterPointerRelease = (open: () => void): void => {\n window.setTimeout(open, 0);\n};\n\n/**\n * Owns one pointer gesture from threshold crossing through commit or cancel.\n * Views provide geometry through `resolve`; this helper owns global cleanup,\n * pointer cancellation, Escape handling, and edge auto-scroll.\n */\nexport const startCalendarPointerSession = <T>(options: CalendarPointerSessionOptions<T>): (() => void) => {\n if (options.event.button !== 0 || !options.event.isPrimary) return () => {};\n\n cancelActiveSession?.();\n\n const pointerId = options.event.pointerId;\n const target = options.event.currentTarget instanceof HTMLElement ? options.event.currentTarget : null;\n const startX = options.event.clientX;\n const startY = options.event.clientY;\n // Leave enough room for normal click jitter before an event becomes a drag.\n const threshold = options.threshold ?? 6;\n let clientX = startX;\n let clientY = startY;\n let active = false;\n let finished = false;\n let latest: T | null = null;\n let scrollFrame = 0;\n let releaseTextSelection: (() => void) | null = null;\n let armed = !options.armAutoScroll;\n\n const preview = () => {\n const value = options.resolve(clientX, clientY);\n if (value === null) return;\n latest = value;\n options.onPreview(value);\n };\n\n const autoScroll = () => {\n scrollFrame = 0;\n if (!active || !options.scrollContainer) return;\n const rect = options.scrollContainer.getBoundingClientRect();\n const inside = clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;\n if (!armed && inside && clientY > rect.top + 56 && clientY < rect.bottom - 56) armed = true;\n const speed = armed && (inside || !options.armAutoScroll) ? calendarAutoScrollSpeed(clientY, rect.top, rect.bottom) : 0;\n if (speed !== 0) {\n const before = options.scrollContainer.scrollTop;\n options.scrollContainer.scrollTop += speed;\n if (options.scrollContainer.scrollTop !== before) preview();\n }\n scrollFrame = requestAnimationFrame(autoScroll);\n };\n\n const cleanup = () => {\n if (scrollFrame) cancelAnimationFrame(scrollFrame);\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", cancel);\n window.removeEventListener(\"blur\", cancel);\n window.removeEventListener(\"keydown\", onKeyDown);\n if (target?.hasPointerCapture?.(pointerId)) target.releasePointerCapture(pointerId);\n releaseTextSelection?.();\n if (cancelActiveSession === cancel) cancelActiveSession = null;\n };\n\n const activate = () => {\n if (active) return;\n active = true;\n releaseTextSelection = suppressTextSelection(pointerId);\n target?.setPointerCapture?.(pointerId);\n options.onActivate?.();\n preview();\n if (options.scrollContainer) scrollFrame = requestAnimationFrame(autoScroll);\n };\n\n function cancel() {\n if (finished) return;\n finished = true;\n cleanup();\n try {\n if (active) options.onCancel?.();\n } finally {\n options.onEnd?.();\n }\n }\n\n function onMove(event: PointerEvent) {\n if (finished || event.pointerId !== pointerId) return;\n clientX = event.clientX;\n clientY = event.clientY;\n if (!active && Math.hypot(clientX - startX, clientY - startY) >= threshold) activate();\n if (!active) return;\n event.preventDefault();\n options.onMove?.(clientX, clientY);\n preview();\n }\n\n function onUp(event: PointerEvent) {\n if (finished || event.pointerId !== pointerId) return;\n finished = true;\n cleanup();\n try {\n if (active && latest !== null) options.onCommit(latest);\n else if (active) options.onCancel?.();\n } finally {\n options.onEnd?.();\n }\n }\n\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n cancel();\n }\n\n window.addEventListener(\"pointermove\", onMove, { passive: false });\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", cancel);\n window.addEventListener(\"blur\", cancel);\n window.addEventListener(\"keydown\", onKeyDown);\n cancelActiveSession = cancel;\n return cancel;\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -27,7 +27,7 @@ import { createEffect, createMemo, createSignal, For, on, onCleanup, onMount, Sh
|
|
|
27
27
|
import { announce } from "../feedback/announce";
|
|
28
28
|
import { addDayKeys, buildDays, clockAt, DAY_MINUTES, dayKeyOf, dayLanes, dayMinuteAt, dayTopTerms, dayYTerms, freeGaps, GAP_LABEL_MINUTES, GAP_LONG_MINUTES, gapProposal, instantInDay, instantsInDay, minuteInDay, readDayGeometry, resizedInDay, snapMinutes, subtractTerms, termsCss, wakeMinutes } from "./calendar-days";
|
|
29
29
|
import { useCalendarMessages } from "./calendar-messages";
|
|
30
|
-
import { startCalendarPointerSession } from "./calendar-pointer";
|
|
30
|
+
import { afterPointerRelease, startCalendarPointerSession } from "./calendar-pointer";
|
|
31
31
|
import { EventChip, eventHref, ownerDateConfig, parseDate, placeCalendarPopover, validDate } from "./calendar-shared";
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -568,9 +568,12 @@ export const createTimeView = props => {
|
|
|
568
568
|
}),
|
|
569
569
|
onCommit: next => {
|
|
570
570
|
const anchor = document.querySelector(".k2b-calendar-ghost[data-live]")?.getBoundingClientRect() ?? body.element;
|
|
571
|
-
endGesture();
|
|
572
571
|
swallowNextClick();
|
|
573
|
-
|
|
572
|
+
// The ghost stays until the quick create replaces it, so the slot never blinks.
|
|
573
|
+
afterPointerRelease(() => {
|
|
574
|
+
endGesture();
|
|
575
|
+
openQuickCreate(key, next.start, next.end, anchor);
|
|
576
|
+
});
|
|
574
577
|
},
|
|
575
578
|
onCancel: endGesture
|
|
576
579
|
});
|