@k2b/ui 0.9.1 → 0.11.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/dist/browser/actions/Button.js +15 -7
- package/dist/browser/actions/Button.js.map +1 -1
- package/dist/browser/actions/ContextMenu.js +55 -15
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/Dropdown.js +39 -15
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/FilterChip.js +1 -7
- package/dist/browser/actions/FilterChip.js.map +1 -1
- package/dist/browser/actions/SplitButton.js +0 -3
- package/dist/browser/actions/SplitButton.js.map +1 -1
- package/dist/browser/chat/ChatComposer.js +78 -91
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/ChatContextPopup.js +47 -21
- package/dist/browser/chat/ChatContextPopup.js.map +1 -1
- package/dist/browser/chat/ChatPrimitives.js +221 -232
- package/dist/browser/chat/ChatPrimitives.js.map +1 -1
- package/dist/browser/chat/index.js +3 -2
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/content/Chart.js +99 -106
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/ChartExplorer.js +3 -6
- package/dist/browser/content/ChartExplorer.js.map +1 -1
- package/dist/browser/content/FileBrowser.js +1 -1
- package/dist/browser/content/FileBrowser.js.map +1 -1
- package/dist/browser/content/FileTree.js +1 -1
- package/dist/browser/content/FileTree.js.map +1 -1
- package/dist/browser/content/FileView.js +304 -287
- package/dist/browser/content/FileView.js.map +1 -1
- package/dist/browser/content/Lightbox.js +18 -0
- package/dist/browser/content/Lightbox.js.map +1 -1
- package/dist/browser/content/PdfPreview.js +68 -43
- package/dist/browser/content/PdfPreview.js.map +1 -1
- package/dist/browser/content/ZoomPanViewport.js +51 -52
- package/dist/browser/content/ZoomPanViewport.js.map +1 -1
- package/dist/browser/feedback/HoverPreview.js +391 -0
- package/dist/browser/feedback/HoverPreview.js.map +1 -0
- package/dist/browser/feedback/Tooltip.js +50 -8
- package/dist/browser/feedback/Tooltip.js.map +1 -1
- package/dist/browser/feedback/dialog-core.js +21 -3
- package/dist/browser/feedback/dialog-core.js.map +1 -1
- package/dist/browser/feedback/index.js +1 -0
- package/dist/browser/feedback/index.js.map +1 -1
- package/dist/browser/inputs/AutocompleteEditor.js +5 -4
- package/dist/browser/inputs/AutocompleteEditor.js.map +1 -1
- package/dist/browser/inputs/DatePicker.js +10 -0
- package/dist/browser/inputs/DatePicker.js.map +1 -1
- package/dist/browser/inputs/FileInputs.js +46 -36
- package/dist/browser/inputs/FileInputs.js.map +1 -1
- package/dist/browser/inputs/SelectChip.js +2 -1
- package/dist/browser/inputs/SelectChip.js.map +1 -1
- package/dist/browser/inputs/choice.js +5 -1
- package/dist/browser/inputs/choice.js.map +1 -1
- package/dist/browser/inputs/markdown/MarkdownEditor.js +173 -173
- package/dist/browser/inputs/markdown/MarkdownEditor.js.map +1 -1
- package/dist/browser/inputs/markdown/Toolbar.js +31 -34
- package/dist/browser/inputs/markdown/Toolbar.js.map +1 -1
- package/dist/browser/internal/focus-return.js +61 -0
- package/dist/browser/internal/focus-return.js.map +1 -0
- package/dist/browser/layout/AppOverview.js +1 -1
- package/dist/browser/layout/AppOverview.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +105 -77
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/DetailPanel.js +16 -15
- package/dist/browser/layout/DetailPanel.js.map +1 -1
- package/dist/browser/layout/FloatingWindow.js +3 -1
- package/dist/browser/layout/FloatingWindow.js.map +1 -1
- package/dist/browser/layout/PanelDialog.js +10 -9
- package/dist/browser/layout/PanelDialog.js.map +1 -1
- package/dist/browser/layout/Panes.js +82 -81
- package/dist/browser/layout/Panes.js.map +1 -1
- package/dist/browser/layout/SidebarItemPreview.js +48 -136
- package/dist/browser/layout/SidebarItemPreview.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +35 -4
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/surfaces/ProgressBar.js.map +1 -1
- package/dist/browser/surfaces/ProgressRing.js +72 -0
- package/dist/browser/surfaces/ProgressRing.js.map +1 -0
- package/dist/browser/surfaces/index.js +1 -0
- package/dist/browser/surfaces/index.js.map +1 -1
- package/dist/ssr/actions/Button.js +15 -7
- package/dist/ssr/actions/Button.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +55 -15
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +31 -12
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/FilterChip.js +1 -7
- package/dist/ssr/actions/FilterChip.js.map +1 -1
- package/dist/ssr/actions/SplitButton.js +0 -3
- package/dist/ssr/actions/SplitButton.js.map +1 -1
- package/dist/ssr/chat/ChatComposer.js +61 -10
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/ChatContextPopup.js +19 -5
- package/dist/ssr/chat/ChatContextPopup.js.map +1 -1
- package/dist/ssr/chat/ChatPrimitives.js +104 -74
- package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
- package/dist/ssr/chat/index.js +3 -2
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/content/Chart.js +22 -11
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/ChartExplorer.js +3 -6
- package/dist/ssr/content/ChartExplorer.js.map +1 -1
- package/dist/ssr/content/FileBrowser.js +1 -1
- package/dist/ssr/content/FileBrowser.js.map +1 -1
- package/dist/ssr/content/FileTree.js +1 -1
- package/dist/ssr/content/FileTree.js.map +1 -1
- package/dist/ssr/content/FileView.js +105 -33
- package/dist/ssr/content/FileView.js.map +1 -1
- package/dist/ssr/content/Lightbox.js +17 -0
- package/dist/ssr/content/Lightbox.js.map +1 -1
- package/dist/ssr/content/PdfPreview.js +44 -14
- package/dist/ssr/content/PdfPreview.js.map +1 -1
- package/dist/ssr/content/ZoomPanViewport.js +11 -3
- package/dist/ssr/content/ZoomPanViewport.js.map +1 -1
- package/dist/ssr/feedback/HoverPreview.js +360 -0
- package/dist/ssr/feedback/HoverPreview.js.map +1 -0
- package/dist/ssr/feedback/Tooltip.js +50 -8
- package/dist/ssr/feedback/Tooltip.js.map +1 -1
- package/dist/ssr/feedback/dialog-core.js +21 -3
- package/dist/ssr/feedback/dialog-core.js.map +1 -1
- package/dist/ssr/feedback/index.js +1 -0
- package/dist/ssr/feedback/index.js.map +1 -1
- package/dist/ssr/inputs/AutocompleteEditor.js +5 -4
- package/dist/ssr/inputs/AutocompleteEditor.js.map +1 -1
- package/dist/ssr/inputs/DatePicker.js +5 -0
- package/dist/ssr/inputs/DatePicker.js.map +1 -1
- package/dist/ssr/inputs/FileInputs.js +29 -11
- package/dist/ssr/inputs/FileInputs.js.map +1 -1
- package/dist/ssr/inputs/SelectChip.js +2 -1
- package/dist/ssr/inputs/SelectChip.js.map +1 -1
- package/dist/ssr/inputs/choice.js +5 -1
- package/dist/ssr/inputs/choice.js.map +1 -1
- package/dist/ssr/inputs/markdown/MarkdownEditor.js +46 -10
- package/dist/ssr/inputs/markdown/MarkdownEditor.js.map +1 -1
- package/dist/ssr/inputs/markdown/Toolbar.js +30 -2
- package/dist/ssr/inputs/markdown/Toolbar.js.map +1 -1
- package/dist/ssr/internal/focus-return.js +61 -0
- package/dist/ssr/internal/focus-return.js.map +1 -0
- package/dist/ssr/layout/AppOverview.js +1 -1
- package/dist/ssr/layout/AppOverview.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +84 -66
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/DetailPanel.js +16 -15
- package/dist/ssr/layout/DetailPanel.js.map +1 -1
- package/dist/ssr/layout/FloatingWindow.js +3 -1
- package/dist/ssr/layout/FloatingWindow.js.map +1 -1
- package/dist/ssr/layout/PanelDialog.js +10 -9
- package/dist/ssr/layout/PanelDialog.js.map +1 -1
- package/dist/ssr/layout/Panes.js +39 -8
- package/dist/ssr/layout/Panes.js.map +1 -1
- package/dist/ssr/layout/SidebarItemPreview.js +36 -108
- package/dist/ssr/layout/SidebarItemPreview.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +35 -4
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/surfaces/ProgressBar.js.map +1 -1
- package/dist/ssr/surfaces/ProgressRing.js +31 -0
- package/dist/ssr/surfaces/ProgressRing.js.map +1 -0
- package/dist/ssr/surfaces/index.js +1 -0
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/Button.d.ts +5 -0
- package/dist/types/actions/Dropdown.d.ts +5 -1
- package/dist/types/actions/SplitButton.d.ts +1 -0
- package/dist/types/chat/ChatContextPopup.d.ts +8 -0
- package/dist/types/chat/index.d.ts +3 -2
- package/dist/types/feedback/HoverPreview.d.ts +83 -0
- package/dist/types/feedback/Tooltip.d.ts +6 -0
- package/dist/types/feedback/index.d.ts +2 -0
- package/dist/types/feedback/prompts.d.ts +9 -6
- package/dist/types/inputs/SelectChip.d.ts +1 -0
- package/dist/types/inputs/completion/overlay.d.ts +3 -1
- package/dist/types/internal/focus-return.d.ts +20 -0
- package/dist/types/intl/Format.d.ts +16 -8
- package/dist/types/layout/AppWorkspace.d.ts +14 -0
- package/dist/types/layout/BottomSheet.d.ts +6 -1
- package/dist/types/layout/SidebarItemPreview.d.ts +1 -1
- package/dist/types/layout/app-workspace-controller.d.ts +5 -0
- package/dist/types/surfaces/ProgressBar.d.ts +1 -1
- package/dist/types/surfaces/ProgressRing.d.ts +13 -0
- package/dist/types/surfaces/index.d.ts +2 -0
- package/package.json +3 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createEffect, createSignal, onCleanup } from "solid-js";
|
|
2
|
+
import { returnFocus, ringOnReturn } from "../internal/focus-return";
|
|
2
3
|
export const filterChoiceOptions = (options, query) => {
|
|
3
4
|
const normalized = query.trim().toLocaleLowerCase();
|
|
4
5
|
if (!normalized) return options;
|
|
@@ -129,6 +130,7 @@ export function createChoicePopover(disabled) {
|
|
|
129
130
|
const [open, setOpen] = createSignal(false);
|
|
130
131
|
const [trigger, setTrigger] = createSignal();
|
|
131
132
|
const [popover, setPopover] = createSignal();
|
|
133
|
+
let triggerRing = true;
|
|
132
134
|
const place = () => {
|
|
133
135
|
const triggerElement = trigger();
|
|
134
136
|
const popoverElement = popover();
|
|
@@ -137,15 +139,17 @@ export function createChoicePopover(disabled) {
|
|
|
137
139
|
const show = () => {
|
|
138
140
|
const popoverElement = popover();
|
|
139
141
|
if (disabled() || !popoverElement || popoverIsOpen(popoverElement)) return;
|
|
142
|
+
triggerRing = ringOnReturn(trigger());
|
|
140
143
|
popoverElement.showPopover();
|
|
141
144
|
setOpen(true);
|
|
142
145
|
queueMicrotask(place);
|
|
143
146
|
};
|
|
144
147
|
const hide = (restoreFocus = false) => {
|
|
145
148
|
const popoverElement = popover();
|
|
149
|
+
// Before hiding, so the popover does not return focus on its own.
|
|
150
|
+
if (restoreFocus) returnFocus(trigger(), triggerRing);
|
|
146
151
|
if (popoverIsOpen(popoverElement)) popoverElement?.hidePopover();
|
|
147
152
|
setOpen(false);
|
|
148
|
-
if (restoreFocus) queueMicrotask(() => trigger()?.focus());
|
|
149
153
|
};
|
|
150
154
|
createEffect(() => {
|
|
151
155
|
const popoverElement = popover();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/choice.ts"],"sourcesContent":["import { createEffect, createSignal, onCleanup, type Setter } from \"solid-js\";\n\nexport type ChoiceOption<T extends string = string> = {\n value: T;\n label: string;\n description?: string;\n icon?: string;\n color?: string;\n disabled?: boolean;\n /** Optional overlapping groups used by choice controls that expose group filtering. */\n groups?: readonly string[];\n};\n\nexport type ChoiceOptionsLoader<T extends string = string> = (query: string, signal: AbortSignal) => Promise<readonly ChoiceOption<T>[]>;\n\nexport const filterChoiceOptions = <T extends string>(options: readonly ChoiceOption<T>[], query: string): readonly ChoiceOption<T>[] => {\n const normalized = query.trim().toLocaleLowerCase();\n if (!normalized) return options;\n return options.filter((option) =>\n [option.label, option.description, option.value].some((part) => part?.toLocaleLowerCase().includes(normalized)),\n );\n};\n\nexport const nextEnabledChoiceIndex = <T extends string>(\n options: readonly ChoiceOption<T>[],\n current: number,\n direction: 1 | -1,\n): number => {\n if (options.length === 0 || options.every((option) => option.disabled)) return -1;\n\n let index = current;\n for (let visited = 0; visited < options.length; visited += 1) {\n index = (index + direction + options.length) % options.length;\n if (!options[index]?.disabled) return index;\n }\n return -1;\n};\n\n/**\n * Counts the leading pills that fit into `available` pixels and measures the\n * whole row. When not all of them fit, the rest collapse into a summary pill\n * of width `more`; the first pill always stays and truncates when even it does\n * not fit. Without a measured width (no layout yet) every pill stays. Half a\n * pixel of slack absorbs layout rounding, so a row given exactly its own\n * `rowWidth` always fits.\n */\nexport const fitChoicePills = (\n available: number,\n widths: readonly number[],\n gap: number,\n more: number,\n): { visible: number; rowWidth: number } => {\n const rowWidth = widths.reduce((sum, width) => sum + width, 0) + gap * Math.max(0, widths.length - 1);\n if (available <= 0 || rowWidth <= available + 0.5) return { visible: widths.length, rowWidth };\n let used = more;\n let visible = 0;\n for (const width of widths) {\n used += gap + width;\n if (used > available) break;\n visible += 1;\n }\n return { visible: Math.max(1, visible), rowWidth };\n};\n\nconst errorMessage = (error: unknown): string => (error instanceof Error ? error.message : \"Failed to load options\");\n\nexport function createChoiceLoader<T extends string>(\n loader: () => ChoiceOptionsLoader<T> | undefined,\n debounceMs: () => number,\n): {\n options: () => readonly ChoiceOption<T>[];\n loading: () => boolean;\n error: () => string | undefined;\n load: (query: string, immediate?: boolean) => void;\n retry: () => void;\n cancel: () => void;\n} {\n const [options, setOptions] = createSignal<readonly ChoiceOption<T>[]>([]);\n const [loading, setLoading] = createSignal(false);\n const [error, setError] = createSignal<string>();\n let controller: AbortController | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let request = 0;\n let lastQuery = \"\";\n\n const cancel = () => {\n if (timer) clearTimeout(timer);\n timer = undefined;\n controller?.abort();\n controller = undefined;\n };\n\n const run = async (query: string) => {\n const loadOptions = loader();\n if (!loadOptions) return;\n\n controller?.abort();\n controller = new AbortController();\n const currentController = controller;\n const currentRequest = ++request;\n setLoading(true);\n setError(undefined);\n\n try {\n const next = await loadOptions(query, currentController.signal);\n if (currentRequest === request && !currentController.signal.aborted) setOptions(next);\n } catch (reason) {\n if (currentRequest === request && !currentController.signal.aborted) {\n setOptions([]);\n setError(errorMessage(reason));\n }\n } finally {\n if (currentRequest === request) setLoading(false);\n }\n };\n\n const load = (query: string, immediate = false) => {\n lastQuery = query;\n if (timer) clearTimeout(timer);\n timer = undefined;\n if (immediate || debounceMs() <= 0) {\n void run(query);\n return;\n }\n timer = setTimeout(() => {\n timer = undefined;\n void run(query);\n }, debounceMs());\n };\n\n onCleanup(cancel);\n return { options, loading, error, load, retry: () => load(lastQuery, true), cancel };\n}\n\nconst popoverIsOpen = (popover: HTMLElement | undefined): boolean => {\n if (!popover) return false;\n try {\n return popover.matches(\":popover-open\");\n } catch {\n return false;\n }\n};\n\nexport const placeChoicePopover = (trigger: HTMLElement, popover: HTMLElement): void => {\n const margin = 8;\n const gap = 4;\n const triggerRect = trigger.getBoundingClientRect();\n // Cloud sizes its dropdowns to the trigger exactly (`dialog.style.width =\n // rect.width`). Keep that so a narrow toolbar select does not open a wide\n // panel that no longer lines up with the control it belongs to.\n const width = Math.min(triggerRect.width, window.innerWidth - margin * 2);\n popover.style.width = `${width}px`;\n\n const popoverRect = popover.getBoundingClientRect();\n const left = Math.max(margin, Math.min(triggerRect.left, window.innerWidth - width - margin));\n const roomBelow = window.innerHeight - triggerRect.bottom - gap - margin;\n const roomAbove = triggerRect.top - gap - margin;\n const opensAbove = popoverRect.height > roomBelow && roomAbove > roomBelow;\n const top = opensAbove\n ? Math.max(margin, triggerRect.top - popoverRect.height - gap)\n : Math.min(triggerRect.bottom + gap, window.innerHeight - popoverRect.height - margin);\n\n popover.style.left = `${left}px`;\n popover.style.top = `${Math.max(margin, top)}px`;\n};\n\nexport function createChoicePopover(disabled: () => boolean): {\n open: () => boolean;\n setTrigger: Setter<HTMLElement | undefined>;\n setPopover: Setter<HTMLElement | undefined>;\n show: () => void;\n hide: (restoreFocus?: boolean) => void;\n toggle: () => void;\n trigger: () => HTMLElement | undefined;\n} {\n const [open, setOpen] = createSignal(false);\n const [trigger, setTrigger] = createSignal<HTMLElement>();\n const [popover, setPopover] = createSignal<HTMLElement>();\n\n const place = () => {\n const triggerElement = trigger();\n const popoverElement = popover();\n if (triggerElement && popoverElement && open()) placeChoicePopover(triggerElement, popoverElement);\n };\n\n const show = () => {\n const popoverElement = popover();\n if (disabled() || !popoverElement || popoverIsOpen(popoverElement)) return;\n popoverElement.showPopover();\n setOpen(true);\n queueMicrotask(place);\n };\n\n const hide = (restoreFocus = false) => {\n const popoverElement = popover();\n if (popoverIsOpen(popoverElement)) popoverElement?.hidePopover();\n setOpen(false);\n if (restoreFocus) queueMicrotask(() => trigger()?.focus());\n };\n\n createEffect(() => {\n const popoverElement = popover();\n if (!popoverElement) return;\n const syncOpenState = () => setOpen(popoverIsOpen(popoverElement));\n const containWheel = (event: WheelEvent) => {\n if (event.ctrlKey) return;\n event.preventDefault();\n\n const target = event.target instanceof Element ? event.target : undefined;\n const groups = target?.closest<HTMLElement>(\".k2b-choice-groups\");\n const horizontalDelta = event.shiftKey && event.deltaX === 0 ? event.deltaY : event.deltaX;\n if (groups && (event.shiftKey || Math.abs(event.deltaX) > Math.abs(event.deltaY)) && groups.scrollWidth > groups.clientWidth) {\n const unit = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? groups.clientWidth : 1;\n groups.scrollLeft += horizontalDelta * unit;\n return;\n }\n\n const options = popoverElement.querySelector<HTMLElement>(\".k2b-choice-options\");\n if (!options || options.scrollHeight <= options.clientHeight) return;\n const unit = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? options.clientHeight : 1;\n options.scrollTop += event.deltaY * unit;\n };\n popoverElement.addEventListener(\"toggle\", syncOpenState);\n popoverElement.addEventListener(\"wheel\", containWheel, { passive: false });\n onCleanup(() => {\n popoverElement.removeEventListener(\"toggle\", syncOpenState);\n popoverElement.removeEventListener(\"wheel\", containWheel);\n });\n });\n\n createEffect(() => {\n if (!open()) return;\n\n const dismiss = (event: PointerEvent) => {\n const target = event.target;\n if (!(target instanceof Node) || trigger()?.contains(target) || popover()?.contains(target)) return;\n hide();\n };\n const reposition = () => place();\n\n // Async option lists arrive after the popover is already open, so the first\n // placement measures an empty panel. Re-place whenever the panel resizes,\n // otherwise a dropdown that grows past the viewport bottom stays clipped.\n const popoverElement = popover();\n const observer = popoverElement && typeof ResizeObserver !== \"undefined\" ? new ResizeObserver(reposition) : undefined;\n if (popoverElement) observer?.observe(popoverElement);\n\n document.addEventListener(\"pointerdown\", dismiss, true);\n window.addEventListener(\"resize\", reposition);\n window.addEventListener(\"scroll\", reposition, true);\n onCleanup(() => {\n observer?.disconnect();\n document.removeEventListener(\"pointerdown\", dismiss, true);\n window.removeEventListener(\"resize\", reposition);\n window.removeEventListener(\"scroll\", reposition, true);\n });\n });\n\n onCleanup(() => hide());\n return {\n open,\n setTrigger,\n setPopover,\n show,\n hide,\n toggle: () => (open() ? hide() : show()),\n trigger,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/choice.ts"],"sourcesContent":["import { createEffect, createSignal, onCleanup, type Setter } from \"solid-js\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\n\nexport type ChoiceOption<T extends string = string> = {\n value: T;\n label: string;\n description?: string;\n icon?: string;\n color?: string;\n disabled?: boolean;\n /** Optional overlapping groups used by choice controls that expose group filtering. */\n groups?: readonly string[];\n};\n\nexport type ChoiceOptionsLoader<T extends string = string> = (query: string, signal: AbortSignal) => Promise<readonly ChoiceOption<T>[]>;\n\nexport const filterChoiceOptions = <T extends string>(options: readonly ChoiceOption<T>[], query: string): readonly ChoiceOption<T>[] => {\n const normalized = query.trim().toLocaleLowerCase();\n if (!normalized) return options;\n return options.filter((option) =>\n [option.label, option.description, option.value].some((part) => part?.toLocaleLowerCase().includes(normalized)),\n );\n};\n\nexport const nextEnabledChoiceIndex = <T extends string>(\n options: readonly ChoiceOption<T>[],\n current: number,\n direction: 1 | -1,\n): number => {\n if (options.length === 0 || options.every((option) => option.disabled)) return -1;\n\n let index = current;\n for (let visited = 0; visited < options.length; visited += 1) {\n index = (index + direction + options.length) % options.length;\n if (!options[index]?.disabled) return index;\n }\n return -1;\n};\n\n/**\n * Counts the leading pills that fit into `available` pixels and measures the\n * whole row. When not all of them fit, the rest collapse into a summary pill\n * of width `more`; the first pill always stays and truncates when even it does\n * not fit. Without a measured width (no layout yet) every pill stays. Half a\n * pixel of slack absorbs layout rounding, so a row given exactly its own\n * `rowWidth` always fits.\n */\nexport const fitChoicePills = (\n available: number,\n widths: readonly number[],\n gap: number,\n more: number,\n): { visible: number; rowWidth: number } => {\n const rowWidth = widths.reduce((sum, width) => sum + width, 0) + gap * Math.max(0, widths.length - 1);\n if (available <= 0 || rowWidth <= available + 0.5) return { visible: widths.length, rowWidth };\n let used = more;\n let visible = 0;\n for (const width of widths) {\n used += gap + width;\n if (used > available) break;\n visible += 1;\n }\n return { visible: Math.max(1, visible), rowWidth };\n};\n\nconst errorMessage = (error: unknown): string => (error instanceof Error ? error.message : \"Failed to load options\");\n\nexport function createChoiceLoader<T extends string>(\n loader: () => ChoiceOptionsLoader<T> | undefined,\n debounceMs: () => number,\n): {\n options: () => readonly ChoiceOption<T>[];\n loading: () => boolean;\n error: () => string | undefined;\n load: (query: string, immediate?: boolean) => void;\n retry: () => void;\n cancel: () => void;\n} {\n const [options, setOptions] = createSignal<readonly ChoiceOption<T>[]>([]);\n const [loading, setLoading] = createSignal(false);\n const [error, setError] = createSignal<string>();\n let controller: AbortController | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let request = 0;\n let lastQuery = \"\";\n\n const cancel = () => {\n if (timer) clearTimeout(timer);\n timer = undefined;\n controller?.abort();\n controller = undefined;\n };\n\n const run = async (query: string) => {\n const loadOptions = loader();\n if (!loadOptions) return;\n\n controller?.abort();\n controller = new AbortController();\n const currentController = controller;\n const currentRequest = ++request;\n setLoading(true);\n setError(undefined);\n\n try {\n const next = await loadOptions(query, currentController.signal);\n if (currentRequest === request && !currentController.signal.aborted) setOptions(next);\n } catch (reason) {\n if (currentRequest === request && !currentController.signal.aborted) {\n setOptions([]);\n setError(errorMessage(reason));\n }\n } finally {\n if (currentRequest === request) setLoading(false);\n }\n };\n\n const load = (query: string, immediate = false) => {\n lastQuery = query;\n if (timer) clearTimeout(timer);\n timer = undefined;\n if (immediate || debounceMs() <= 0) {\n void run(query);\n return;\n }\n timer = setTimeout(() => {\n timer = undefined;\n void run(query);\n }, debounceMs());\n };\n\n onCleanup(cancel);\n return { options, loading, error, load, retry: () => load(lastQuery, true), cancel };\n}\n\nconst popoverIsOpen = (popover: HTMLElement | undefined): boolean => {\n if (!popover) return false;\n try {\n return popover.matches(\":popover-open\");\n } catch {\n return false;\n }\n};\n\nexport const placeChoicePopover = (trigger: HTMLElement, popover: HTMLElement): void => {\n const margin = 8;\n const gap = 4;\n const triggerRect = trigger.getBoundingClientRect();\n // Cloud sizes its dropdowns to the trigger exactly (`dialog.style.width =\n // rect.width`). Keep that so a narrow toolbar select does not open a wide\n // panel that no longer lines up with the control it belongs to.\n const width = Math.min(triggerRect.width, window.innerWidth - margin * 2);\n popover.style.width = `${width}px`;\n\n const popoverRect = popover.getBoundingClientRect();\n const left = Math.max(margin, Math.min(triggerRect.left, window.innerWidth - width - margin));\n const roomBelow = window.innerHeight - triggerRect.bottom - gap - margin;\n const roomAbove = triggerRect.top - gap - margin;\n const opensAbove = popoverRect.height > roomBelow && roomAbove > roomBelow;\n const top = opensAbove\n ? Math.max(margin, triggerRect.top - popoverRect.height - gap)\n : Math.min(triggerRect.bottom + gap, window.innerHeight - popoverRect.height - margin);\n\n popover.style.left = `${left}px`;\n popover.style.top = `${Math.max(margin, top)}px`;\n};\n\nexport function createChoicePopover(disabled: () => boolean): {\n open: () => boolean;\n setTrigger: Setter<HTMLElement | undefined>;\n setPopover: Setter<HTMLElement | undefined>;\n show: () => void;\n hide: (restoreFocus?: boolean) => void;\n toggle: () => void;\n trigger: () => HTMLElement | undefined;\n} {\n const [open, setOpen] = createSignal(false);\n const [trigger, setTrigger] = createSignal<HTMLElement>();\n const [popover, setPopover] = createSignal<HTMLElement>();\n let triggerRing = true;\n\n const place = () => {\n const triggerElement = trigger();\n const popoverElement = popover();\n if (triggerElement && popoverElement && open()) placeChoicePopover(triggerElement, popoverElement);\n };\n\n const show = () => {\n const popoverElement = popover();\n if (disabled() || !popoverElement || popoverIsOpen(popoverElement)) return;\n triggerRing = ringOnReturn(trigger());\n popoverElement.showPopover();\n setOpen(true);\n queueMicrotask(place);\n };\n\n const hide = (restoreFocus = false) => {\n const popoverElement = popover();\n // Before hiding, so the popover does not return focus on its own.\n if (restoreFocus) returnFocus(trigger(), triggerRing);\n if (popoverIsOpen(popoverElement)) popoverElement?.hidePopover();\n setOpen(false);\n };\n\n createEffect(() => {\n const popoverElement = popover();\n if (!popoverElement) return;\n const syncOpenState = () => setOpen(popoverIsOpen(popoverElement));\n const containWheel = (event: WheelEvent) => {\n if (event.ctrlKey) return;\n event.preventDefault();\n\n const target = event.target instanceof Element ? event.target : undefined;\n const groups = target?.closest<HTMLElement>(\".k2b-choice-groups\");\n const horizontalDelta = event.shiftKey && event.deltaX === 0 ? event.deltaY : event.deltaX;\n if (groups && (event.shiftKey || Math.abs(event.deltaX) > Math.abs(event.deltaY)) && groups.scrollWidth > groups.clientWidth) {\n const unit = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? groups.clientWidth : 1;\n groups.scrollLeft += horizontalDelta * unit;\n return;\n }\n\n const options = popoverElement.querySelector<HTMLElement>(\".k2b-choice-options\");\n if (!options || options.scrollHeight <= options.clientHeight) return;\n const unit = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? options.clientHeight : 1;\n options.scrollTop += event.deltaY * unit;\n };\n popoverElement.addEventListener(\"toggle\", syncOpenState);\n popoverElement.addEventListener(\"wheel\", containWheel, { passive: false });\n onCleanup(() => {\n popoverElement.removeEventListener(\"toggle\", syncOpenState);\n popoverElement.removeEventListener(\"wheel\", containWheel);\n });\n });\n\n createEffect(() => {\n if (!open()) return;\n\n const dismiss = (event: PointerEvent) => {\n const target = event.target;\n if (!(target instanceof Node) || trigger()?.contains(target) || popover()?.contains(target)) return;\n hide();\n };\n const reposition = () => place();\n\n // Async option lists arrive after the popover is already open, so the first\n // placement measures an empty panel. Re-place whenever the panel resizes,\n // otherwise a dropdown that grows past the viewport bottom stays clipped.\n const popoverElement = popover();\n const observer = popoverElement && typeof ResizeObserver !== \"undefined\" ? new ResizeObserver(reposition) : undefined;\n if (popoverElement) observer?.observe(popoverElement);\n\n document.addEventListener(\"pointerdown\", dismiss, true);\n window.addEventListener(\"resize\", reposition);\n window.addEventListener(\"scroll\", reposition, true);\n onCleanup(() => {\n observer?.disconnect();\n document.removeEventListener(\"pointerdown\", dismiss, true);\n window.removeEventListener(\"resize\", reposition);\n window.removeEventListener(\"scroll\", reposition, true);\n });\n });\n\n onCleanup(() => hide());\n return {\n open,\n setTrigger,\n setPopover,\n show,\n hide,\n toggle: () => (open() ? hide() : show()),\n trigger,\n };\n}\n"],"mappings":"AAAA,SAAS,YAAY,EAAE,YAAY,EAAE,SAAS,QAAqB,UAAU;AAC7E,SAAS,WAAW,EAAE,YAAY,QAAQ,0BAA0B;AAepE,OAAO,MAAM,mBAAmB,GAAG,CAAmB,OAAmC,EAAE,KAAa,KAAiC;EACvI,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;EACnD,IAAI,CAAC,UAAU,EAAE,OAAO,OAAO;EAC/B,OAAO,OAAO,CAAC,MAAM,CAAE,MAAM,IAC3B,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAE,IAAI,IAAK,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAChH,CAAC;AACH,CAAC;AAED,OAAO,MAAM,sBAAsB,GAAG,CACpC,OAAmC,EACnC,OAAe,EACf,SAAiB,KACN;EACX,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAE,MAAM,IAAK,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;EAEjF,IAAI,KAAK,GAAG,OAAO;EACnB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,EAAE;IAC5D,KAAK,GAAG,CAAC,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM;IAC7D,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,OAAO,KAAK;EAC7C;EACA,OAAO,CAAC,CAAC;AACX,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAM,cAAc,GAAG,CAC5B,SAAiB,EACjB,MAAyB,EACzB,GAAW,EACX,IAAY,KAC8B;EAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;EACrG,IAAI,SAAS,IAAI,CAAC,IAAI,QAAQ,IAAI,SAAS,GAAG,GAAG,EAAE,OAAO;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM;IAAE;EAAS,CAAC;EAC9F,IAAI,IAAI,GAAG,IAAI;EACf,IAAI,OAAO,GAAG,CAAC;EACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;IAC1B,IAAI,IAAI,GAAG,GAAG,KAAK;IACnB,IAAI,IAAI,GAAG,SAAS,EAAE;IACtB,OAAO,IAAI,CAAC;EACd;EACA,OAAO;IAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC;IAAE;EAAS,CAAC;AACpD,CAAC;AAED,MAAM,YAAY,GAAI,KAAc,IAAc,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,wBAAyB;AAEpH,OAAO,SAAS,kBAAkB,CAChC,MAAgD,EAChD,UAAwB,EAQxB;EACA,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAA6B,EAAE,CAAC;EAC1E,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC;EACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAS,CAAC;EAChD,IAAI,UAAuC;EAC3C,IAAI,KAAgD;EACpD,IAAI,OAAO,GAAG,CAAC;EACf,IAAI,SAAS,GAAG,EAAE;EAElB,MAAM,MAAM,GAAG,MAAM;IACnB,IAAI,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC9B,KAAK,GAAG,SAAS;IACjB,UAAU,EAAE,KAAK,CAAC,CAAC;IACnB,UAAU,GAAG,SAAS;EACxB,CAAC;EAED,MAAM,GAAG,GAAG,MAAO,KAAa,IAAK;IACnC,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC;IAC5B,IAAI,CAAC,WAAW,EAAE;IAElB,UAAU,EAAE,KAAK,CAAC,CAAC;IACnB,UAAU,GAAG,IAAI,eAAe,CAAC,CAAC;IAClC,MAAM,iBAAiB,GAAG,UAAU;IACpC,MAAM,cAAc,GAAG,EAAE,OAAO;IAChC,UAAU,CAAC,IAAI,CAAC;IAChB,QAAQ,CAAC,SAAS,CAAC;IAEnB,IAAI;MACF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,CAAC;MAC/D,IAAI,cAAc,KAAK,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC;IACvF,CAAC,CAAC,OAAO,MAAM,EAAE;MACf,IAAI,cAAc,KAAK,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,EAAE;QACnE,UAAU,CAAC,EAAE,CAAC;QACd,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;MAChC;IACF,CAAC,SAAS;MACR,IAAI,cAAc,KAAK,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC;IACnD;EACF,CAAC;EAED,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,SAAS,GAAG,KAAK,KAAK;IACjD,SAAS,GAAG,KAAK;IACjB,IAAI,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC9B,KAAK,GAAG,SAAS;IACjB,IAAI,SAAS,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE;MAClC,KAAK,GAAG,CAAC,KAAK,CAAC;MACf;IACF;IACA,KAAK,GAAG,UAAU,CAAC,MAAM;MACvB,KAAK,GAAG,SAAS;MACjB,KAAK,GAAG,CAAC,KAAK,CAAC;IACjB,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;EAClB,CAAC;EAED,SAAS,CAAC,MAAM,CAAC;EACjB,OAAO;IAAE,OAAO;IAAE,OAAO;IAAE,KAAK;IAAE,IAAI;IAAE,KAAK,EAAE,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;IAAE;EAAO,CAAC;AACtF;AAEA,MAAM,aAAa,GAAI,OAAgC,IAAc;EACnE,IAAI,CAAC,OAAO,EAAE,OAAO,KAAK;EAC1B,IAAI;IACF,OAAO,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC;EACzC,CAAC,CAAC,MAAM;IACN,OAAO,KAAK;EACd;AACF,CAAC;AAED,OAAO,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAE,OAAoB,KAAW;EACtF,MAAM,MAAM,GAAG,CAAC;EAChB,MAAM,GAAG,GAAG,CAAC;EACb,MAAM,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;EACnD;EACA;EACA;EACA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,CAAC,CAAC;EACzE,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,KAAK,IAAI;EAElC,MAAM,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;EACnD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;EAC7F,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG,GAAG,MAAM;EACxE,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,GAAG,GAAG,GAAG,MAAM;EAChD,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,GAAG,SAAS,IAAI,SAAS,GAAG,SAAS;EAC1E,MAAM,GAAG,GAAG,UAAU,GAClB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG,CAAC,GAC5D,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;EAExF,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI;EAChC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;AAClD,CAAC;AAED,OAAO,SAAS,mBAAmB,CAAC,QAAuB,EAQzD;EACA,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC;EAC3C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAc,CAAC;EACzD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAc,CAAC;EACzD,IAAI,WAAW,GAAG,IAAI;EAEtB,MAAM,KAAK,GAAG,MAAM;IAClB,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC,IAAI,cAAc,IAAI,cAAc,IAAI,IAAI,CAAC,CAAC,EAAE,kBAAkB,CAAC,cAAc,EAAE,cAAc,CAAC;EACpG,CAAC;EAED,MAAM,IAAI,GAAG,MAAM;IACjB,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC,IAAI,QAAQ,CAAC,CAAC,IAAI,CAAC,cAAc,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE;IACpE,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,cAAc,CAAC,WAAW,CAAC,CAAC;IAC5B,OAAO,CAAC,IAAI,CAAC;IACb,cAAc,CAAC,KAAK,CAAC;EACvB,CAAC;EAED,MAAM,IAAI,GAAG,CAAC,YAAY,GAAG,KAAK,KAAK;IACrC,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC;IACA,IAAI,YAAY,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,WAAW,CAAC;IACrD,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;IAChE,OAAO,CAAC,KAAK,CAAC;EAChB,CAAC;EAED,YAAY,CAAC,MAAM;IACjB,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,cAAc,EAAE;IACrB,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IAClE,MAAM,YAAY,GAAI,KAAiB,IAAK;MAC1C,IAAI,KAAK,CAAC,OAAO,EAAE;MACnB,KAAK,CAAC,cAAc,CAAC,CAAC;MAEtB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,YAAY,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS;MACzE,MAAM,MAAM,GAAG,MAAM,EAAE,OAAO,CAAc,oBAAoB,CAAC;MACjE,MAAM,eAAe,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM;MAC1F,IAAI,MAAM,KAAK,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,EAAE;QAC5H,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,KAAK,CAAC,GAAG,MAAM,CAAC,WAAW,GAAG,CAAC;QACxF,MAAM,CAAC,UAAU,IAAI,eAAe,GAAG,IAAI;QAC3C;MACF;MAEA,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,CAAc,qBAAqB,CAAC;MAChF,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,YAAY,EAAE;MAC9D,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,KAAK,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG,CAAC;MAC1F,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;IAC1C,CAAC;IACD,cAAc,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC;IACxD,cAAc,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE;MAAE,OAAO,EAAE;IAAM,CAAC,CAAC;IAC1E,SAAS,CAAC,MAAM;MACd,cAAc,CAAC,mBAAmB,CAAC,QAAQ,EAAE,aAAa,CAAC;MAC3D,cAAc,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC;IAC3D,CAAC,CAAC;EACJ,CAAC,CAAC;EAEF,YAAY,CAAC,MAAM;IACjB,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE;IAEb,MAAM,OAAO,GAAI,KAAmB,IAAK;MACvC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;MAC3B,IAAI,EAAE,MAAM,YAAY,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE;MAC7F,IAAI,CAAC,CAAC;IACR,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,CAAC;;IAEhC;IACA;IACA;IACA,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,cAAc,IAAI,OAAO,cAAc,KAAK,WAAW,GAAG,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,SAAS;IACrH,IAAI,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC;IAErD,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;IACvD,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC7C,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC;IACnD,SAAS,CAAC,MAAM;MACd,QAAQ,EAAE,UAAU,CAAC,CAAC;MACtB,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;MAC1D,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,UAAU,CAAC;MAChD,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC;IACxD,CAAC,CAAC;EACJ,CAAC,CAAC;EAEF,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;EACvB,OAAO;IACL,IAAI;IACJ,UAAU;IACV,UAAU;IACV,IAAI;IACJ,IAAI;IACJ,MAAM,EAAE,MAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAE;IACxC;EACF,CAAC;AACH","ignoreList":[]}
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { ssrElement as _$ssrElement } from "solid-js/web";
|
|
2
2
|
import { mergeProps as _$mergeProps } from "solid-js/web";
|
|
3
|
-
import { memo as _$memo } from "solid-js/web";
|
|
4
3
|
import { ssrStyleProperty as _$ssrStyleProperty } from "solid-js/web";
|
|
4
|
+
import { escape as _$escape } from "solid-js/web";
|
|
5
5
|
import { createComponent as _$createComponent } from "solid-js/web";
|
|
6
6
|
import { ssr as _$ssr } from "solid-js/web";
|
|
7
7
|
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
8
|
-
import {
|
|
9
|
-
var _tmpl$ = ["<
|
|
8
|
+
import { memo as _$memo } from "solid-js/web";
|
|
9
|
+
var _tmpl$ = ["<i", " aria-hidden=\"true\"></i>"],
|
|
10
10
|
_tmpl$2 = ["<div class=\"k2b-markdown-editor__placeholder\" aria-hidden=\"true\">", "</div>"],
|
|
11
11
|
_tmpl$3 = ["<div class=\"k2b-markdown-editor__stats\" aria-hidden=\"true\"", "><span>", " ", "</span><span>", " ", "</span><span>", " ", "</span></div>"],
|
|
12
12
|
_tmpl$4 = "<div class=\"k2b-autocomplete__status\" role=\"status\"><i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\"></i>Loading suggestions</div>",
|
|
13
13
|
_tmpl$5 = ["<div popover=\"manual\" class=\"k2b-autocomplete__options\" role=\"presentation\"", "><div", " class=\"k2b-autocomplete__listbox\" role=\"listbox\"", ">", "", "", "</div></div>"],
|
|
14
14
|
_tmpl$6 = ["<div class=\"k2b-markdown-editor\" role=\"group\"", " style=\"", "\">", "<div class=\"k2b-markdown-editor__surface\">", "<div class=\"k2b-markdown-editor__preview\" aria-hidden=\"true\"></div>", "</div>", "", "</div>"],
|
|
15
|
-
_tmpl$7 =
|
|
15
|
+
_tmpl$7 = "<i class=\"ti ti-x\" aria-hidden=\"true\"></i>",
|
|
16
16
|
_tmpl$8 = ["<div class=\"k2b-autocomplete__status\" data-error=\"true\" role=\"alert\"><i class=\"ti ti-alert-circle\" aria-hidden=\"true\"></i><span>", "</span><button type=\"button\">", "</button></div>"],
|
|
17
17
|
_tmpl$9 = ["<div", " class=\"k2b-autocomplete__option\" role=\"option\"", "><span>", "</span>", "</div>"],
|
|
18
18
|
_tmpl$0 = ["<small>", "</small>"];
|
|
19
19
|
import { highlight } from "@k2b/stdlib";
|
|
20
20
|
import { createEffect, createMemo, createSignal, createUniqueId, For, onCleanup, onMount, Show, untrack } from "solid-js";
|
|
21
|
+
import { Tooltip } from "../../feedback/Tooltip";
|
|
21
22
|
import { createFieldMeta, Field, fieldControlAria } from "../../internal/field";
|
|
22
23
|
import { useUiMessages } from "../../intl/messages";
|
|
23
24
|
import { abbreviations as abbreviationsCompletion, buildSuggestContext, collectKnownLabels, createCompletionBehaviorState, detectQuery, displayLabel, renderWithOverlay, resolveSuggestions } from "../completion";
|
|
@@ -142,10 +143,6 @@ export function MarkdownEditor(props) {
|
|
|
142
143
|
const maxHeight = 260;
|
|
143
144
|
const spaceBelow = window.innerHeight - rect.bottom;
|
|
144
145
|
const openAbove = spaceBelow < maxHeight && rect.top > spaceBelow;
|
|
145
|
-
const width = Math.min(280, window.innerWidth - 16);
|
|
146
|
-
const left = Math.min(rect.left, window.innerWidth - width - 8);
|
|
147
|
-
dropdown.style.setProperty("left", `${Math.max(8, left)}px`, "important");
|
|
148
|
-
dropdown.style.setProperty("width", `${width}px`, "important");
|
|
149
146
|
if (openAbove) {
|
|
150
147
|
dropdown.style.setProperty("top", "auto", "important");
|
|
151
148
|
dropdown.style.setProperty("bottom", `${window.innerHeight - rect.top + 4}px`, "important");
|
|
@@ -154,6 +151,11 @@ export function MarkdownEditor(props) {
|
|
|
154
151
|
dropdown.style.setProperty("bottom", "auto", "important");
|
|
155
152
|
}
|
|
156
153
|
if (!dropdown.matches(":popover-open")) dropdown.showPopover();
|
|
154
|
+
// The list sizes to its suggestions in CSS; measured once shown, it is
|
|
155
|
+
// clamped into the viewport before the next paint.
|
|
156
|
+
const width = dropdown.getBoundingClientRect().width;
|
|
157
|
+
const left = Math.min(rect.left, window.innerWidth - width - 8);
|
|
158
|
+
dropdown.style.setProperty("left", `${Math.max(8, left)}px`, "important");
|
|
157
159
|
};
|
|
158
160
|
const isAbortError = error => error instanceof DOMException ? error.name === "AbortError" : Boolean(error && typeof error === "object" && "name" in error && error.name === "AbortError");
|
|
159
161
|
const applySuggestionList = (context, suggestions) => {
|
|
@@ -394,7 +396,25 @@ export function MarkdownEditor(props) {
|
|
|
394
396
|
return props.onSave;
|
|
395
397
|
},
|
|
396
398
|
get children() {
|
|
397
|
-
return _$
|
|
399
|
+
return _$createComponent(Tooltip.Trigger, {
|
|
400
|
+
type: "button",
|
|
401
|
+
"class": "k2b-markdown-editor__tool",
|
|
402
|
+
get content() {
|
|
403
|
+
return messages().saveShortcut;
|
|
404
|
+
},
|
|
405
|
+
get ["aria-label"]() {
|
|
406
|
+
return messages().save;
|
|
407
|
+
},
|
|
408
|
+
tabIndex: -1,
|
|
409
|
+
get disabled() {
|
|
410
|
+
return props.disabled || props.saveDisabled || props.saving;
|
|
411
|
+
},
|
|
412
|
+
onMouseDown: event => event.preventDefault(),
|
|
413
|
+
onClick: () => props.onSave?.(),
|
|
414
|
+
get children() {
|
|
415
|
+
return _$ssr(_tmpl$, _$ssrAttribute("class", props.saving ? "ti ti-loader-2 k2b-spin" : props.saved ? "ti ti-check" : "ti ti-device-floppy", false));
|
|
416
|
+
}
|
|
417
|
+
});
|
|
398
418
|
}
|
|
399
419
|
});
|
|
400
420
|
return _$createComponent(Field, {
|
|
@@ -438,7 +458,23 @@ export function MarkdownEditor(props) {
|
|
|
438
458
|
return props.onClose;
|
|
439
459
|
},
|
|
440
460
|
get children() {
|
|
441
|
-
return _$
|
|
461
|
+
return _$createComponent(Tooltip.Trigger, {
|
|
462
|
+
type: "button",
|
|
463
|
+
"class": "k2b-markdown-editor__tool",
|
|
464
|
+
get content() {
|
|
465
|
+
return messages().close;
|
|
466
|
+
},
|
|
467
|
+
get ["aria-label"]() {
|
|
468
|
+
return messages().close;
|
|
469
|
+
},
|
|
470
|
+
get tabIndex() {
|
|
471
|
+
return props.disabled ? 0 : -1;
|
|
472
|
+
},
|
|
473
|
+
onClick: () => props.onClose?.(),
|
|
474
|
+
get children() {
|
|
475
|
+
return _$ssr(_tmpl$7);
|
|
476
|
+
}
|
|
477
|
+
});
|
|
442
478
|
}
|
|
443
479
|
})];
|
|
444
480
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/markdown/MarkdownEditor.tsx"],"sourcesContent":["import { highlight } from \"@k2b/stdlib\";\nimport { createEffect, createMemo, createSignal, createUniqueId, For, type JSX, onCleanup, onMount, Show, untrack } from \"solid-js\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../../internal/field\";\nimport { useUiMessages } from \"../../intl/messages\";\nimport {\n abbreviations as abbreviationsCompletion,\n buildSuggestContext,\n type Completion,\n collectKnownLabels,\n createCompletionBehaviorState,\n detectQuery,\n displayLabel,\n type QueryContext,\n renderWithOverlay,\n resolveSuggestions,\n type Suggestion,\n} from \"../completion\";\nimport type { ValueFieldProps } from \"../field-contract\";\nimport { resolveMaybeAccessor } from \"../field-contract\";\nimport { computeActiveFormats } from \"./active-formats\";\nimport { handleListContinuation, handleShortcut, handleSmartPaste } from \"./behaviors\";\nimport { isInCodeZone } from \"./code-zone\";\nimport Toolbar from \"./Toolbar\";\n\nexport type MarkdownEditorProps = ValueFieldProps<string> & {\n onSubmit?: () => void;\n placeholder?: string;\n lines?: number;\n noToolbar?: boolean;\n spellcheck?: boolean;\n name?: string;\n maxLength?: number;\n textareaRef?: (element: HTMLTextAreaElement) => void;\n abbreviations?: Record<string, string>;\n completions?: readonly Completion[];\n showStats?: boolean;\n variant?: \"default\" | \"paper\" | \"embedded\";\n fill?: boolean;\n /** Groups save and close at the end of the toolbar. The caller owns navigation and unsaved-change confirmation. */\n onClose?: () => void;\n onSave?: () => void;\n saveDisabled?: boolean;\n saving?: boolean;\n /** Shows a successful-save check. The caller clears it after a brief delay or the next edit. */\n saved?: boolean;\n toolbarTrailing?: JSX.Element;\n};\n\ntype CompletionState = {\n context: QueryContext;\n suggestions: readonly Suggestion[];\n selectedIndex: number;\n};\n\nexport function MarkdownEditor(props: MarkdownEditorProps): JSX.Element {\n const messages = useUiMessages();\n const meta = createFieldMeta(props.id);\n let textarea: HTMLTextAreaElement | undefined;\n let preview: HTMLDivElement | undefined;\n let dropdown: HTMLDivElement | undefined;\n let completionAbort: AbortController | null = null;\n let completionTimer: ReturnType<typeof setTimeout> | null = null;\n let overlayFrame: number | undefined;\n let overlayInitialized = false;\n let renderPendingOverlay: (() => void) | undefined;\n const completionBehavior = createCompletionBehaviorState();\n\n const [textareaSignal, setTextareaSignal] = createSignal<HTMLTextAreaElement | null>(null);\n const [activeFormats, setActiveFormats] = createSignal<Set<string>>(new Set());\n const [composing, setComposing] = createSignal(false);\n const [localValue, setLocalValue] = createSignal(resolveMaybeAccessor(props.value) ?? \"\");\n const error = () => resolveMaybeAccessor(props.error);\n const [state, setState] = createSignal<CompletionState | null>(null);\n const [loading, setLoading] = createSignal(false);\n const [completionError, setCompletionError] = createSignal<string | null>(null);\n const [dropdownOpen, setDropdownOpen] = createSignal(false);\n const completionId = createUniqueId();\n const listboxId = `${meta.controlId}-${completionId}-suggestions`;\n const optionId = (index: number): string => `${listboxId}-${index}`;\n const activeSuggestion = (): Suggestion | null => {\n const current = state();\n return current?.suggestions[current.selectedIndex] ?? null;\n };\n\n const mergedCompletions = createMemo<readonly Completion[] | undefined>(() => {\n const merged: Completion[] = [];\n if (props.abbreviations && Object.keys(props.abbreviations).length > 0) {\n merged.push(abbreviationsCompletion(props.abbreviations));\n }\n if (props.completions) merged.push(...props.completions);\n return merged.length > 0 ? merged : undefined;\n });\n const knownLabels = createMemo(() => collectKnownLabels(mergedCompletions()));\n\n createEffect(() => {\n const incoming = resolveMaybeAccessor(props.value);\n if (incoming !== undefined && incoming !== null && incoming !== untrack(localValue)) {\n setLocalValue(incoming);\n }\n });\n\n createEffect(() => {\n const target = localValue();\n if (!composing() && textarea && textarea.value !== target) {\n textarea.value = target;\n }\n });\n\n createEffect(() => {\n if (!preview) return;\n const value = localValue();\n const labels = knownLabels();\n const current = state();\n const active = activeSuggestion();\n const ghost =\n current && active\n ? {\n at: current.context.end,\n text: active.text.slice(current.context.text.length),\n }\n : undefined;\n const anchor = current && !ghost ? { at: current.context.end } : undefined;\n renderPendingOverlay = () => {\n if (!preview) return;\n preview.innerHTML = renderWithOverlay(value, (text) => highlight.markdown(text, { knownLabels: labels }), { ghost, anchor });\n if (textarea) {\n preview.scrollTop = textarea.scrollTop;\n preview.scrollLeft = textarea.scrollLeft;\n }\n if (dropdown?.matches(\":popover-open\")) positionDropdown();\n };\n if (!overlayInitialized) {\n overlayInitialized = true;\n renderPendingOverlay();\n renderPendingOverlay = undefined;\n return;\n }\n if (overlayFrame !== undefined) return;\n overlayFrame = requestAnimationFrame(() => {\n overlayFrame = undefined;\n const render = renderPendingOverlay;\n renderPendingOverlay = undefined;\n render?.();\n });\n });\n\n const updateActiveFormats = (): void => {\n if (textarea) setActiveFormats(computeActiveFormats(textarea));\n };\n\n const closeDropdown = (): void => {\n if (dropdown?.matches(\":popover-open\")) dropdown.hidePopover();\n setDropdownOpen(false);\n };\n\n const clearCompletion = (): void => {\n completionAbort?.abort();\n completionAbort = null;\n if (completionTimer) clearTimeout(completionTimer);\n completionTimer = null;\n setState(null);\n setLoading(false);\n setCompletionError(null);\n closeDropdown();\n };\n\n const positionDropdown = (): void => {\n if (!dropdown?.isConnected || !preview?.isConnected || !textarea?.isConnected) {\n return;\n }\n const anchor = preview.querySelector<HTMLElement>(\"[data-completion-anchor]\");\n const rect = anchor?.getBoundingClientRect() ?? textarea.getBoundingClientRect();\n const maxHeight = 260;\n const spaceBelow = window.innerHeight - rect.bottom;\n const openAbove = spaceBelow < maxHeight && rect.top > spaceBelow;\n const width = Math.min(280, window.innerWidth - 16);\n const left = Math.min(rect.left, window.innerWidth - width - 8);\n dropdown.style.setProperty(\"left\", `${Math.max(8, left)}px`, \"important\");\n dropdown.style.setProperty(\"width\", `${width}px`, \"important\");\n if (openAbove) {\n dropdown.style.setProperty(\"top\", \"auto\", \"important\");\n dropdown.style.setProperty(\"bottom\", `${window.innerHeight - rect.top + 4}px`, \"important\");\n } else {\n dropdown.style.setProperty(\"top\", `${rect.bottom + 4}px`, \"important\");\n dropdown.style.setProperty(\"bottom\", \"auto\", \"important\");\n }\n if (!dropdown.matches(\":popover-open\")) dropdown.showPopover();\n };\n\n const isAbortError = (error: unknown): boolean =>\n error instanceof DOMException\n ? error.name === \"AbortError\"\n : Boolean(error && typeof error === \"object\" && \"name\" in error && (error as { name: string }).name === \"AbortError\");\n\n const applySuggestionList = (context: QueryContext, suggestions: readonly Suggestion[]): void => {\n const value = localValue();\n const normalized = context.text.toLowerCase();\n const usable = suggestions.filter((suggestion) => {\n if (suggestion.textEdit) {\n const { start, end, text } = suggestion.textEdit;\n return (\n Number.isInteger(start) &&\n Number.isInteger(end) &&\n start >= 0 &&\n end >= start &&\n end <= value.length &&\n value.slice(start, end) !== text\n );\n }\n return suggestion.text.toLowerCase().startsWith(normalized) && suggestion.text.length > context.text.length;\n });\n if (usable.length === 0) {\n setState(null);\n closeDropdown();\n return;\n }\n const previous = activeSuggestion()?.text;\n const retained = previous ? usable.findIndex((suggestion) => suggestion.text === previous) : -1;\n setState({\n context,\n suggestions: usable,\n selectedIndex: retained >= 0 ? retained : 0,\n });\n if (context.completion.dropdown) {\n setDropdownOpen(true);\n queueMicrotask(positionDropdown);\n } else {\n closeDropdown();\n }\n };\n\n const runAsyncCompletion = async (context: QueryContext, promise: Promise<readonly Suggestion[]>, signal: AbortSignal): Promise<void> => {\n try {\n const suggestions = await promise;\n if (signal.aborted) return;\n setLoading(false);\n applySuggestionList(context, suggestions);\n } catch (error) {\n if (signal.aborted || isAbortError(error)) return;\n setLoading(false);\n setState(null);\n setCompletionError(error instanceof Error ? error.message : \"Suggestions could not be loaded\");\n setDropdownOpen(true);\n queueMicrotask(positionDropdown);\n }\n };\n\n const startCompletionResolution = (context: QueryContext, signal: AbortSignal): void => {\n if (signal.aborted || !textarea) return;\n setLoading(true);\n setCompletionError(null);\n setDropdownOpen(true);\n queueMicrotask(positionDropdown);\n try {\n const result = resolveSuggestions(context.completion, context.query, buildSuggestContext(textarea, context), signal);\n if (result.kind === \"sync\") {\n setLoading(false);\n applySuggestionList(context, result.data);\n } else {\n void runAsyncCompletion(context, result.promise, signal);\n }\n } catch (error) {\n if (signal.aborted || isAbortError(error)) return;\n setLoading(false);\n setState(null);\n setCompletionError(error instanceof Error ? error.message : \"Suggestions could not be loaded\");\n queueMicrotask(positionDropdown);\n }\n };\n\n const recomputeCompletion = (): void => {\n if (!textarea) return;\n const context = detectQuery(textarea, mergedCompletions(), {\n isExcluded: isInCodeZone,\n });\n if (!context) {\n clearCompletion();\n return;\n }\n completionAbort?.abort();\n if (completionTimer) clearTimeout(completionTimer);\n completionTimer = null;\n completionAbort = new AbortController();\n const current = state();\n if (\n current &&\n (current.context.start !== context.start ||\n current.context.end !== context.end ||\n current.context.text !== context.text ||\n current.context.completion !== context.completion)\n ) {\n setState(null);\n closeDropdown();\n }\n setCompletionError(null);\n const delay = Math.max(0, context.completion.debounceMs ?? 0);\n if (delay === 0) {\n startCompletionResolution(context, completionAbort.signal);\n } else {\n setLoading(false);\n if (!state()) closeDropdown();\n const signal = completionAbort.signal;\n completionTimer = setTimeout(() => {\n completionTimer = null;\n startCompletionResolution(context, signal);\n }, delay);\n }\n };\n\n const retryCompletion = (): void => {\n if (!textarea) return;\n const context = detectQuery(textarea, mergedCompletions(), {\n isExcluded: isInCodeZone,\n });\n if (!context) return clearCompletion();\n completionAbort?.abort();\n if (completionTimer) clearTimeout(completionTimer);\n completionTimer = null;\n completionAbort = new AbortController();\n startCompletionResolution(context, completionAbort.signal);\n };\n\n const activateSuggestion = (index = state()?.selectedIndex ?? -1): boolean => {\n const current = state();\n const active = current?.suggestions[index];\n if (!textarea || !current || !active) return false;\n if (!active.textEdit && active.text === current.context.text) {\n closeDropdown();\n setState(null);\n return false;\n }\n const applied = completionBehavior.applySuggestion(textarea, current.context, active);\n closeDropdown();\n setState(null);\n return applied;\n };\n\n const moveSelection = (direction: 1 | -1): void => {\n const current = state();\n if (!current || current.suggestions.length === 0) return;\n setState({\n ...current,\n selectedIndex: (current.selectedIndex + direction + current.suggestions.length) % current.suggestions.length,\n });\n };\n\n const stats = createMemo(() => {\n const value = localValue();\n return {\n lines: value.length === 0 ? 0 : value.split(\"\\n\").length,\n words: value.match(/\\S+/g)?.length ?? 0,\n chars: value.length,\n };\n });\n\n onMount(() => {\n if (textarea) setTextareaSignal(textarea);\n updateActiveFormats();\n const selectionChange = (): void => {\n if (document.activeElement === textarea) {\n updateActiveFormats();\n recomputeCompletion();\n }\n };\n // Reposition an OPEN popover only. Calling `positionDropdown` blindly\n // would `showPopover()` a dropdown that is deliberately closed (a\n // ghost-only completion keeps state without a dropdown).\n const reposition = (): void => {\n if (dropdown?.matches(\":popover-open\")) positionDropdown();\n };\n document.addEventListener(\"selectionchange\", selectionChange);\n window.addEventListener(\"resize\", reposition);\n onCleanup(() => {\n document.removeEventListener(\"selectionchange\", selectionChange);\n window.removeEventListener(\"resize\", reposition);\n if (dropdown?.matches(\":popover-open\")) dropdown.hidePopover();\n completionAbort?.abort();\n if (completionTimer) clearTimeout(completionTimer);\n if (overlayFrame !== undefined) cancelAnimationFrame(overlayFrame);\n overlayFrame = undefined;\n renderPendingOverlay = undefined;\n completionBehavior.reset();\n });\n });\n\n const onInput = (event: InputEvent & { currentTarget: HTMLTextAreaElement }): void => {\n if (\n completionBehavior.tryExpand(event.currentTarget, mergedCompletions(), {\n isExcluded: isInCodeZone,\n })\n ) {\n return;\n }\n setLocalValue(event.currentTarget.value);\n props.onValueChange?.(event.currentTarget.value);\n updateActiveFormats();\n recomputeCompletion();\n };\n\n const onKeyDown = (event: KeyboardEvent): void => {\n if (!textarea || event.isComposing) return;\n if (\n event.key === \"Backspace\" &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.altKey &&\n !event.shiftKey &&\n completionBehavior.tryRestore(textarea)\n ) {\n event.preventDefault();\n return;\n }\n const current = state();\n const dropdownCompletion = current?.context.completion.dropdown === true;\n if (current && dropdownCompletion && (event.key === \"ArrowDown\" || event.key === \"ArrowUp\")) {\n event.preventDefault();\n moveSelection(event.key === \"ArrowDown\" ? 1 : -1);\n return;\n }\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.altKey &&\n current &&\n dropdownCompletion &&\n dropdownOpen()\n ) {\n event.preventDefault();\n activateSuggestion();\n return;\n }\n if (event.key === \"Tab\" && !event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey && current) {\n event.preventDefault();\n activateSuggestion();\n return;\n }\n if (event.key === \"Escape\") {\n if (current) {\n event.preventDefault();\n closeDropdown();\n setState(null);\n return;\n }\n if ((mergedCompletions()?.length ?? 0) > 0) {\n event.preventDefault();\n textarea.blur();\n return;\n }\n }\n if (event.key === \"Enter\" && (event.metaKey || event.ctrlKey) && props.onSubmit) {\n event.preventDefault();\n props.onSubmit();\n return;\n }\n if (handleShortcut(event, textarea)) {\n event.preventDefault();\n return;\n }\n if (event.key === \"Enter\" && !event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey && handleListContinuation(textarea)) {\n event.preventDefault();\n }\n };\n\n const saveControls = (): JSX.Element => (\n <>\n <Show when={props.onSave}>\n <button\n type=\"button\"\n class=\"k2b-markdown-editor__tool\"\n title={messages().saveShortcut}\n aria-label={messages().save}\n tabIndex={-1}\n disabled={props.disabled || props.saveDisabled || props.saving}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => props.onSave?.()}\n >\n <i class={props.saving ? \"ti ti-loader-2 k2b-spin\" : props.saved ? \"ti ti-check\" : \"ti ti-device-floppy\"} aria-hidden=\"true\" />\n </button>\n </Show>\n </>\n );\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={props.error}\n fill={props.fill}\n meta={meta}\n required={props.required}\n disabled={props.disabled}\n >\n <div\n class=\"k2b-markdown-editor\"\n role=\"group\"\n aria-labelledby={props.label ? meta.labelId : undefined}\n aria-label={!props.label ? props[\"aria-label\"] : undefined}\n data-disabled={props.disabled ? \"true\" : undefined}\n data-invalid={error() ? \"true\" : undefined}\n data-variant={props.variant === \"default\" ? undefined : props.variant}\n data-fill={props.fill ? \"true\" : undefined}\n style={{\n \"--k2b-editor-lines\": String(props.lines ?? 6),\n }}\n onKeyDown={(event) => {\n if (props.onSave && (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"s\") {\n event.preventDefault();\n if (!props.disabled && !props.saveDisabled && !props.saving) props.onSave();\n }\n }}\n >\n <Show when={!props.noToolbar}>\n <Toolbar\n textarea={textareaSignal}\n activeFormats={activeFormats}\n disabled={props.disabled}\n trailing={\n <>\n {props.toolbarTrailing}\n {saveControls()}\n <Show when={props.onClose}>\n <button\n type=\"button\"\n class=\"k2b-markdown-editor__tool\"\n title={messages().close}\n aria-label={messages().close}\n tabIndex={props.disabled ? 0 : -1}\n onClick={() => props.onClose?.()}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </Show>\n </>\n }\n />\n </Show>\n <div class=\"k2b-markdown-editor__surface\">\n <Show when={!localValue() && props.placeholder}>\n <div class=\"k2b-markdown-editor__placeholder\" aria-hidden=\"true\">\n {props.placeholder}\n </div>\n </Show>\n <div ref={preview} class=\"k2b-markdown-editor__preview\" aria-hidden=\"true\" />\n <textarea\n ref={(element) => {\n textarea = element;\n props.textareaRef?.(element);\n }}\n id={meta.controlId}\n name={props.name}\n class=\"k2b-markdown-editor__input\"\n onInput={onInput}\n onChange={(event) => props.onValueCommit?.(event.currentTarget.value)}\n onKeyDown={onKeyDown}\n onPaste={(event) => {\n if (textarea && handleSmartPaste(event, textarea)) {\n event.preventDefault();\n }\n }}\n onScroll={(event) => {\n if (preview) {\n preview.scrollTop = event.currentTarget.scrollTop;\n preview.scrollLeft = event.currentTarget.scrollLeft;\n }\n }}\n onCompositionStart={() => setComposing(true)}\n onCompositionEnd={() => setComposing(false)}\n onBlur={(event) => {\n const next = event.relatedTarget as HTMLElement | null;\n if (next && dropdown?.contains(next)) return;\n completionBehavior.reset();\n clearCompletion();\n }}\n disabled={props.disabled}\n required={props.required}\n spellcheck={props.spellcheck ?? true}\n maxLength={props.maxLength}\n {...fieldControlAria(meta, props)}\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-controls={dropdownOpen() ? listboxId : undefined}\n aria-activedescendant={dropdownOpen() && state() ? optionId(state()!.selectedIndex) : undefined}\n />\n </div>\n <Show when={(props.showStats ?? true) && !props.disabled}>\n <div class=\"k2b-markdown-editor__stats\" aria-hidden=\"true\" data-empty={stats().chars === 0 ? \"true\" : undefined}>\n <span>\n {stats().lines} {stats().lines === 1 ? \"line\" : \"lines\"}\n </span>\n <span>\n {stats().words} {stats().words === 1 ? \"word\" : \"words\"}\n </span>\n <span>\n {stats().chars} {stats().chars === 1 ? \"char\" : \"chars\"}\n </span>\n </div>\n </Show>\n <Show when={state() || loading() || completionError()}>\n <div\n ref={dropdown}\n popover=\"manual\"\n class=\"k2b-autocomplete__options\"\n role=\"presentation\"\n aria-label={messages().completionSuggestions}\n >\n <div id={listboxId} class=\"k2b-autocomplete__listbox\" role=\"listbox\" aria-label={messages().suggestions}>\n <Show when={loading()}>\n <div class=\"k2b-autocomplete__status\" role=\"status\">\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n Loading suggestions\n </div>\n </Show>\n <Show when={completionError()}>\n {(message) => (\n <div class=\"k2b-autocomplete__status\" data-error=\"true\" role=\"alert\">\n <i class=\"ti ti-alert-circle\" aria-hidden=\"true\" />\n <span>{message()}</span>\n <button type=\"button\" onMouseDown={(event) => event.preventDefault()} onClick={retryCompletion}>\n {messages().retry}\n </button>\n </div>\n )}\n </Show>\n <For each={state()?.suggestions ?? []}>\n {(suggestion, index) => (\n // biome-ignore lint/a11y/useKeyWithClickEvents: the owning textarea handles keyboard activation through aria-activedescendant.\n <div\n id={optionId(index())}\n class=\"k2b-autocomplete__option\"\n role=\"option\"\n aria-selected={index() === state()?.selectedIndex}\n onMouseEnter={() => {\n const current = state();\n if (current) {\n setState({ ...current, selectedIndex: index() });\n }\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n }}\n onClick={() => {\n activateSuggestion(index());\n textarea?.focus();\n }}\n >\n <span>{displayLabel(suggestion, state()!.context.completion)}</span>\n <Show when={suggestion.hint}>{(hint) => <small>{hint()}</small>}</Show>\n </div>\n )}\n </For>\n </div>\n </div>\n </Show>\n </div>\n </Field>\n );\n}\n\nexport type { Completion, SuggestContext, Suggestion } from \"../completion\";\nexport { abbreviations } from \"../completion\";\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/markdown/MarkdownEditor.tsx"],"sourcesContent":["import { highlight } from \"@k2b/stdlib\";\nimport { createEffect, createMemo, createSignal, createUniqueId, For, type JSX, onCleanup, onMount, Show, untrack } from \"solid-js\";\nimport { Tooltip } from \"../../feedback/Tooltip\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../../internal/field\";\nimport { useUiMessages } from \"../../intl/messages\";\nimport {\n abbreviations as abbreviationsCompletion,\n buildSuggestContext,\n type Completion,\n collectKnownLabels,\n createCompletionBehaviorState,\n detectQuery,\n displayLabel,\n type QueryContext,\n renderWithOverlay,\n resolveSuggestions,\n type Suggestion,\n} from \"../completion\";\nimport type { ValueFieldProps } from \"../field-contract\";\nimport { resolveMaybeAccessor } from \"../field-contract\";\nimport { computeActiveFormats } from \"./active-formats\";\nimport { handleListContinuation, handleShortcut, handleSmartPaste } from \"./behaviors\";\nimport { isInCodeZone } from \"./code-zone\";\nimport Toolbar from \"./Toolbar\";\n\nexport type MarkdownEditorProps = ValueFieldProps<string> & {\n onSubmit?: () => void;\n placeholder?: string;\n lines?: number;\n noToolbar?: boolean;\n spellcheck?: boolean;\n name?: string;\n maxLength?: number;\n textareaRef?: (element: HTMLTextAreaElement) => void;\n abbreviations?: Record<string, string>;\n completions?: readonly Completion[];\n showStats?: boolean;\n variant?: \"default\" | \"paper\" | \"embedded\";\n fill?: boolean;\n /** Groups save and close at the end of the toolbar. The caller owns navigation and unsaved-change confirmation. */\n onClose?: () => void;\n onSave?: () => void;\n saveDisabled?: boolean;\n saving?: boolean;\n /** Shows a successful-save check. The caller clears it after a brief delay or the next edit. */\n saved?: boolean;\n toolbarTrailing?: JSX.Element;\n};\n\ntype CompletionState = {\n context: QueryContext;\n suggestions: readonly Suggestion[];\n selectedIndex: number;\n};\n\nexport function MarkdownEditor(props: MarkdownEditorProps): JSX.Element {\n const messages = useUiMessages();\n const meta = createFieldMeta(props.id);\n let textarea: HTMLTextAreaElement | undefined;\n let preview: HTMLDivElement | undefined;\n let dropdown: HTMLDivElement | undefined;\n let completionAbort: AbortController | null = null;\n let completionTimer: ReturnType<typeof setTimeout> | null = null;\n let overlayFrame: number | undefined;\n let overlayInitialized = false;\n let renderPendingOverlay: (() => void) | undefined;\n const completionBehavior = createCompletionBehaviorState();\n\n const [textareaSignal, setTextareaSignal] = createSignal<HTMLTextAreaElement | null>(null);\n const [activeFormats, setActiveFormats] = createSignal<Set<string>>(new Set());\n const [composing, setComposing] = createSignal(false);\n const [localValue, setLocalValue] = createSignal(resolveMaybeAccessor(props.value) ?? \"\");\n const error = () => resolveMaybeAccessor(props.error);\n const [state, setState] = createSignal<CompletionState | null>(null);\n const [loading, setLoading] = createSignal(false);\n const [completionError, setCompletionError] = createSignal<string | null>(null);\n const [dropdownOpen, setDropdownOpen] = createSignal(false);\n const completionId = createUniqueId();\n const listboxId = `${meta.controlId}-${completionId}-suggestions`;\n const optionId = (index: number): string => `${listboxId}-${index}`;\n const activeSuggestion = (): Suggestion | null => {\n const current = state();\n return current?.suggestions[current.selectedIndex] ?? null;\n };\n\n const mergedCompletions = createMemo<readonly Completion[] | undefined>(() => {\n const merged: Completion[] = [];\n if (props.abbreviations && Object.keys(props.abbreviations).length > 0) {\n merged.push(abbreviationsCompletion(props.abbreviations));\n }\n if (props.completions) merged.push(...props.completions);\n return merged.length > 0 ? merged : undefined;\n });\n const knownLabels = createMemo(() => collectKnownLabels(mergedCompletions()));\n\n createEffect(() => {\n const incoming = resolveMaybeAccessor(props.value);\n if (incoming !== undefined && incoming !== null && incoming !== untrack(localValue)) {\n setLocalValue(incoming);\n }\n });\n\n createEffect(() => {\n const target = localValue();\n if (!composing() && textarea && textarea.value !== target) {\n textarea.value = target;\n }\n });\n\n createEffect(() => {\n if (!preview) return;\n const value = localValue();\n const labels = knownLabels();\n const current = state();\n const active = activeSuggestion();\n const ghost =\n current && active\n ? {\n at: current.context.end,\n text: active.text.slice(current.context.text.length),\n }\n : undefined;\n const anchor = current && !ghost ? { at: current.context.end } : undefined;\n renderPendingOverlay = () => {\n if (!preview) return;\n preview.innerHTML = renderWithOverlay(value, (text) => highlight.markdown(text, { knownLabels: labels }), { ghost, anchor });\n if (textarea) {\n preview.scrollTop = textarea.scrollTop;\n preview.scrollLeft = textarea.scrollLeft;\n }\n if (dropdown?.matches(\":popover-open\")) positionDropdown();\n };\n if (!overlayInitialized) {\n overlayInitialized = true;\n renderPendingOverlay();\n renderPendingOverlay = undefined;\n return;\n }\n if (overlayFrame !== undefined) return;\n overlayFrame = requestAnimationFrame(() => {\n overlayFrame = undefined;\n const render = renderPendingOverlay;\n renderPendingOverlay = undefined;\n render?.();\n });\n });\n\n const updateActiveFormats = (): void => {\n if (textarea) setActiveFormats(computeActiveFormats(textarea));\n };\n\n const closeDropdown = (): void => {\n if (dropdown?.matches(\":popover-open\")) dropdown.hidePopover();\n setDropdownOpen(false);\n };\n\n const clearCompletion = (): void => {\n completionAbort?.abort();\n completionAbort = null;\n if (completionTimer) clearTimeout(completionTimer);\n completionTimer = null;\n setState(null);\n setLoading(false);\n setCompletionError(null);\n closeDropdown();\n };\n\n const positionDropdown = (): void => {\n if (!dropdown?.isConnected || !preview?.isConnected || !textarea?.isConnected) {\n return;\n }\n const anchor = preview.querySelector<HTMLElement>(\"[data-completion-anchor]\");\n const rect = anchor?.getBoundingClientRect() ?? textarea.getBoundingClientRect();\n const maxHeight = 260;\n const spaceBelow = window.innerHeight - rect.bottom;\n const openAbove = spaceBelow < maxHeight && rect.top > spaceBelow;\n if (openAbove) {\n dropdown.style.setProperty(\"top\", \"auto\", \"important\");\n dropdown.style.setProperty(\"bottom\", `${window.innerHeight - rect.top + 4}px`, \"important\");\n } else {\n dropdown.style.setProperty(\"top\", `${rect.bottom + 4}px`, \"important\");\n dropdown.style.setProperty(\"bottom\", \"auto\", \"important\");\n }\n if (!dropdown.matches(\":popover-open\")) dropdown.showPopover();\n // The list sizes to its suggestions in CSS; measured once shown, it is\n // clamped into the viewport before the next paint.\n const width = dropdown.getBoundingClientRect().width;\n const left = Math.min(rect.left, window.innerWidth - width - 8);\n dropdown.style.setProperty(\"left\", `${Math.max(8, left)}px`, \"important\");\n };\n\n const isAbortError = (error: unknown): boolean =>\n error instanceof DOMException\n ? error.name === \"AbortError\"\n : Boolean(error && typeof error === \"object\" && \"name\" in error && (error as { name: string }).name === \"AbortError\");\n\n const applySuggestionList = (context: QueryContext, suggestions: readonly Suggestion[]): void => {\n const value = localValue();\n const normalized = context.text.toLowerCase();\n const usable = suggestions.filter((suggestion) => {\n if (suggestion.textEdit) {\n const { start, end, text } = suggestion.textEdit;\n return (\n Number.isInteger(start) &&\n Number.isInteger(end) &&\n start >= 0 &&\n end >= start &&\n end <= value.length &&\n value.slice(start, end) !== text\n );\n }\n return suggestion.text.toLowerCase().startsWith(normalized) && suggestion.text.length > context.text.length;\n });\n if (usable.length === 0) {\n setState(null);\n closeDropdown();\n return;\n }\n const previous = activeSuggestion()?.text;\n const retained = previous ? usable.findIndex((suggestion) => suggestion.text === previous) : -1;\n setState({\n context,\n suggestions: usable,\n selectedIndex: retained >= 0 ? retained : 0,\n });\n if (context.completion.dropdown) {\n setDropdownOpen(true);\n queueMicrotask(positionDropdown);\n } else {\n closeDropdown();\n }\n };\n\n const runAsyncCompletion = async (context: QueryContext, promise: Promise<readonly Suggestion[]>, signal: AbortSignal): Promise<void> => {\n try {\n const suggestions = await promise;\n if (signal.aborted) return;\n setLoading(false);\n applySuggestionList(context, suggestions);\n } catch (error) {\n if (signal.aborted || isAbortError(error)) return;\n setLoading(false);\n setState(null);\n setCompletionError(error instanceof Error ? error.message : \"Suggestions could not be loaded\");\n setDropdownOpen(true);\n queueMicrotask(positionDropdown);\n }\n };\n\n const startCompletionResolution = (context: QueryContext, signal: AbortSignal): void => {\n if (signal.aborted || !textarea) return;\n setLoading(true);\n setCompletionError(null);\n setDropdownOpen(true);\n queueMicrotask(positionDropdown);\n try {\n const result = resolveSuggestions(context.completion, context.query, buildSuggestContext(textarea, context), signal);\n if (result.kind === \"sync\") {\n setLoading(false);\n applySuggestionList(context, result.data);\n } else {\n void runAsyncCompletion(context, result.promise, signal);\n }\n } catch (error) {\n if (signal.aborted || isAbortError(error)) return;\n setLoading(false);\n setState(null);\n setCompletionError(error instanceof Error ? error.message : \"Suggestions could not be loaded\");\n queueMicrotask(positionDropdown);\n }\n };\n\n const recomputeCompletion = (): void => {\n if (!textarea) return;\n const context = detectQuery(textarea, mergedCompletions(), {\n isExcluded: isInCodeZone,\n });\n if (!context) {\n clearCompletion();\n return;\n }\n completionAbort?.abort();\n if (completionTimer) clearTimeout(completionTimer);\n completionTimer = null;\n completionAbort = new AbortController();\n const current = state();\n if (\n current &&\n (current.context.start !== context.start ||\n current.context.end !== context.end ||\n current.context.text !== context.text ||\n current.context.completion !== context.completion)\n ) {\n setState(null);\n closeDropdown();\n }\n setCompletionError(null);\n const delay = Math.max(0, context.completion.debounceMs ?? 0);\n if (delay === 0) {\n startCompletionResolution(context, completionAbort.signal);\n } else {\n setLoading(false);\n if (!state()) closeDropdown();\n const signal = completionAbort.signal;\n completionTimer = setTimeout(() => {\n completionTimer = null;\n startCompletionResolution(context, signal);\n }, delay);\n }\n };\n\n const retryCompletion = (): void => {\n if (!textarea) return;\n const context = detectQuery(textarea, mergedCompletions(), {\n isExcluded: isInCodeZone,\n });\n if (!context) return clearCompletion();\n completionAbort?.abort();\n if (completionTimer) clearTimeout(completionTimer);\n completionTimer = null;\n completionAbort = new AbortController();\n startCompletionResolution(context, completionAbort.signal);\n };\n\n const activateSuggestion = (index = state()?.selectedIndex ?? -1): boolean => {\n const current = state();\n const active = current?.suggestions[index];\n if (!textarea || !current || !active) return false;\n if (!active.textEdit && active.text === current.context.text) {\n closeDropdown();\n setState(null);\n return false;\n }\n const applied = completionBehavior.applySuggestion(textarea, current.context, active);\n closeDropdown();\n setState(null);\n return applied;\n };\n\n const moveSelection = (direction: 1 | -1): void => {\n const current = state();\n if (!current || current.suggestions.length === 0) return;\n setState({\n ...current,\n selectedIndex: (current.selectedIndex + direction + current.suggestions.length) % current.suggestions.length,\n });\n };\n\n const stats = createMemo(() => {\n const value = localValue();\n return {\n lines: value.length === 0 ? 0 : value.split(\"\\n\").length,\n words: value.match(/\\S+/g)?.length ?? 0,\n chars: value.length,\n };\n });\n\n onMount(() => {\n if (textarea) setTextareaSignal(textarea);\n updateActiveFormats();\n const selectionChange = (): void => {\n if (document.activeElement === textarea) {\n updateActiveFormats();\n recomputeCompletion();\n }\n };\n // Reposition an OPEN popover only. Calling `positionDropdown` blindly\n // would `showPopover()` a dropdown that is deliberately closed (a\n // ghost-only completion keeps state without a dropdown).\n const reposition = (): void => {\n if (dropdown?.matches(\":popover-open\")) positionDropdown();\n };\n document.addEventListener(\"selectionchange\", selectionChange);\n window.addEventListener(\"resize\", reposition);\n onCleanup(() => {\n document.removeEventListener(\"selectionchange\", selectionChange);\n window.removeEventListener(\"resize\", reposition);\n if (dropdown?.matches(\":popover-open\")) dropdown.hidePopover();\n completionAbort?.abort();\n if (completionTimer) clearTimeout(completionTimer);\n if (overlayFrame !== undefined) cancelAnimationFrame(overlayFrame);\n overlayFrame = undefined;\n renderPendingOverlay = undefined;\n completionBehavior.reset();\n });\n });\n\n const onInput = (event: InputEvent & { currentTarget: HTMLTextAreaElement }): void => {\n if (\n completionBehavior.tryExpand(event.currentTarget, mergedCompletions(), {\n isExcluded: isInCodeZone,\n })\n ) {\n return;\n }\n setLocalValue(event.currentTarget.value);\n props.onValueChange?.(event.currentTarget.value);\n updateActiveFormats();\n recomputeCompletion();\n };\n\n const onKeyDown = (event: KeyboardEvent): void => {\n if (!textarea || event.isComposing) return;\n if (\n event.key === \"Backspace\" &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.altKey &&\n !event.shiftKey &&\n completionBehavior.tryRestore(textarea)\n ) {\n event.preventDefault();\n return;\n }\n const current = state();\n const dropdownCompletion = current?.context.completion.dropdown === true;\n if (current && dropdownCompletion && (event.key === \"ArrowDown\" || event.key === \"ArrowUp\")) {\n event.preventDefault();\n moveSelection(event.key === \"ArrowDown\" ? 1 : -1);\n return;\n }\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.altKey &&\n current &&\n dropdownCompletion &&\n dropdownOpen()\n ) {\n event.preventDefault();\n activateSuggestion();\n return;\n }\n if (event.key === \"Tab\" && !event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey && current) {\n event.preventDefault();\n activateSuggestion();\n return;\n }\n if (event.key === \"Escape\") {\n if (current) {\n event.preventDefault();\n closeDropdown();\n setState(null);\n return;\n }\n if ((mergedCompletions()?.length ?? 0) > 0) {\n event.preventDefault();\n textarea.blur();\n return;\n }\n }\n if (event.key === \"Enter\" && (event.metaKey || event.ctrlKey) && props.onSubmit) {\n event.preventDefault();\n props.onSubmit();\n return;\n }\n if (handleShortcut(event, textarea)) {\n event.preventDefault();\n return;\n }\n if (event.key === \"Enter\" && !event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey && handleListContinuation(textarea)) {\n event.preventDefault();\n }\n };\n\n const saveControls = (): JSX.Element => (\n <>\n <Show when={props.onSave}>\n <Tooltip.Trigger\n type=\"button\"\n class=\"k2b-markdown-editor__tool\"\n content={messages().saveShortcut}\n aria-label={messages().save}\n tabIndex={-1}\n disabled={props.disabled || props.saveDisabled || props.saving}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => props.onSave?.()}\n >\n <i class={props.saving ? \"ti ti-loader-2 k2b-spin\" : props.saved ? \"ti ti-check\" : \"ti ti-device-floppy\"} aria-hidden=\"true\" />\n </Tooltip.Trigger>\n </Show>\n </>\n );\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={props.error}\n fill={props.fill}\n meta={meta}\n required={props.required}\n disabled={props.disabled}\n >\n <div\n class=\"k2b-markdown-editor\"\n role=\"group\"\n aria-labelledby={props.label ? meta.labelId : undefined}\n aria-label={!props.label ? props[\"aria-label\"] : undefined}\n data-disabled={props.disabled ? \"true\" : undefined}\n data-invalid={error() ? \"true\" : undefined}\n data-variant={props.variant === \"default\" ? undefined : props.variant}\n data-fill={props.fill ? \"true\" : undefined}\n style={{\n \"--k2b-editor-lines\": String(props.lines ?? 6),\n }}\n onKeyDown={(event) => {\n if (props.onSave && (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"s\") {\n event.preventDefault();\n if (!props.disabled && !props.saveDisabled && !props.saving) props.onSave();\n }\n }}\n >\n <Show when={!props.noToolbar}>\n <Toolbar\n textarea={textareaSignal}\n activeFormats={activeFormats}\n disabled={props.disabled}\n trailing={\n <>\n {props.toolbarTrailing}\n {saveControls()}\n <Show when={props.onClose}>\n <Tooltip.Trigger\n type=\"button\"\n class=\"k2b-markdown-editor__tool\"\n content={messages().close}\n aria-label={messages().close}\n tabIndex={props.disabled ? 0 : -1}\n onClick={() => props.onClose?.()}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </Tooltip.Trigger>\n </Show>\n </>\n }\n />\n </Show>\n <div class=\"k2b-markdown-editor__surface\">\n <Show when={!localValue() && props.placeholder}>\n <div class=\"k2b-markdown-editor__placeholder\" aria-hidden=\"true\">\n {props.placeholder}\n </div>\n </Show>\n <div ref={preview} class=\"k2b-markdown-editor__preview\" aria-hidden=\"true\" />\n <textarea\n ref={(element) => {\n textarea = element;\n props.textareaRef?.(element);\n }}\n id={meta.controlId}\n name={props.name}\n class=\"k2b-markdown-editor__input\"\n onInput={onInput}\n onChange={(event) => props.onValueCommit?.(event.currentTarget.value)}\n onKeyDown={onKeyDown}\n onPaste={(event) => {\n if (textarea && handleSmartPaste(event, textarea)) {\n event.preventDefault();\n }\n }}\n onScroll={(event) => {\n if (preview) {\n preview.scrollTop = event.currentTarget.scrollTop;\n preview.scrollLeft = event.currentTarget.scrollLeft;\n }\n }}\n onCompositionStart={() => setComposing(true)}\n onCompositionEnd={() => setComposing(false)}\n onBlur={(event) => {\n const next = event.relatedTarget as HTMLElement | null;\n if (next && dropdown?.contains(next)) return;\n completionBehavior.reset();\n clearCompletion();\n }}\n disabled={props.disabled}\n required={props.required}\n spellcheck={props.spellcheck ?? true}\n maxLength={props.maxLength}\n {...fieldControlAria(meta, props)}\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-controls={dropdownOpen() ? listboxId : undefined}\n aria-activedescendant={dropdownOpen() && state() ? optionId(state()!.selectedIndex) : undefined}\n />\n </div>\n <Show when={(props.showStats ?? true) && !props.disabled}>\n <div class=\"k2b-markdown-editor__stats\" aria-hidden=\"true\" data-empty={stats().chars === 0 ? \"true\" : undefined}>\n <span>\n {stats().lines} {stats().lines === 1 ? \"line\" : \"lines\"}\n </span>\n <span>\n {stats().words} {stats().words === 1 ? \"word\" : \"words\"}\n </span>\n <span>\n {stats().chars} {stats().chars === 1 ? \"char\" : \"chars\"}\n </span>\n </div>\n </Show>\n <Show when={state() || loading() || completionError()}>\n <div\n ref={dropdown}\n popover=\"manual\"\n class=\"k2b-autocomplete__options\"\n role=\"presentation\"\n aria-label={messages().completionSuggestions}\n >\n <div id={listboxId} class=\"k2b-autocomplete__listbox\" role=\"listbox\" aria-label={messages().suggestions}>\n <Show when={loading()}>\n <div class=\"k2b-autocomplete__status\" role=\"status\">\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n Loading suggestions\n </div>\n </Show>\n <Show when={completionError()}>\n {(message) => (\n <div class=\"k2b-autocomplete__status\" data-error=\"true\" role=\"alert\">\n <i class=\"ti ti-alert-circle\" aria-hidden=\"true\" />\n <span>{message()}</span>\n <button type=\"button\" onMouseDown={(event) => event.preventDefault()} onClick={retryCompletion}>\n {messages().retry}\n </button>\n </div>\n )}\n </Show>\n <For each={state()?.suggestions ?? []}>\n {(suggestion, index) => (\n // biome-ignore lint/a11y/useKeyWithClickEvents: the owning textarea handles keyboard activation through aria-activedescendant.\n <div\n id={optionId(index())}\n class=\"k2b-autocomplete__option\"\n role=\"option\"\n aria-selected={index() === state()?.selectedIndex}\n onMouseEnter={() => {\n const current = state();\n if (current) {\n setState({ ...current, selectedIndex: index() });\n }\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n }}\n onClick={() => {\n activateSuggestion(index());\n textarea?.focus();\n }}\n >\n <span>{displayLabel(suggestion, state()!.context.completion)}</span>\n <Show when={suggestion.hint}>{(hint) => <small>{hint()}</small>}</Show>\n </div>\n )}\n </For>\n </div>\n </div>\n </Show>\n </div>\n </Field>\n );\n}\n\nexport type { Completion, SuggestContext, Suggestion } from \"../completion\";\nexport { abbreviations } from \"../completion\";\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { memo as _$memo } from "solid-js/web";
|
|
1
2
|
import { ssr as _$ssr } from "solid-js/web";
|
|
2
3
|
import { createComponent as _$createComponent } from "solid-js/web";
|
|
3
4
|
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
@@ -5,8 +6,9 @@ import { escape as _$escape } from "solid-js/web";
|
|
|
5
6
|
var _tmpl$ = ["<span class=\"k2b-markdown-editor__trailing\">", "</span>"],
|
|
6
7
|
_tmpl$2 = ["<div class=\"k2b-markdown-editor__toolbar\" role=\"toolbar\"", ">", "", "</div>"],
|
|
7
8
|
_tmpl$3 = "<span class=\"k2b-markdown-editor__separator\" aria-hidden=\"true\"></span>",
|
|
8
|
-
_tmpl$4 = ["<
|
|
9
|
+
_tmpl$4 = ["<i", " aria-hidden=\"true\"></i>"];
|
|
9
10
|
import { For, Show } from "solid-js";
|
|
11
|
+
import { Tooltip } from "../../feedback/Tooltip";
|
|
10
12
|
import { useUiMessages } from "../../intl/messages";
|
|
11
13
|
import { insertLink, toggleBold, toggleBulletList, toggleCode, toggleHeading, toggleItalic, toggleNumberedList, toggleQuote } from "./actions";
|
|
12
14
|
const TOOLS = [{
|
|
@@ -102,7 +104,33 @@ export default function Toolbar(props) {
|
|
|
102
104
|
};
|
|
103
105
|
return _$ssr(_tmpl$2, _$ssrAttribute("aria-label", _$escape(messages().markdownFormatting, true), false), _$escape(_$createComponent(For, {
|
|
104
106
|
each: TOOLS,
|
|
105
|
-
children: (tool, index) => tool.kind === "separator" ? _$ssr(_tmpl$3) : _$
|
|
107
|
+
children: (tool, index) => tool.kind === "separator" ? _$ssr(_tmpl$3) : _$createComponent(Tooltip.Trigger, {
|
|
108
|
+
type: "button",
|
|
109
|
+
"class": "k2b-markdown-editor__tool",
|
|
110
|
+
get content() {
|
|
111
|
+
return title(tool.id, tool.title);
|
|
112
|
+
},
|
|
113
|
+
get ["aria-label"]() {
|
|
114
|
+
return title(tool.id, tool.title);
|
|
115
|
+
},
|
|
116
|
+
get ["aria-pressed"]() {
|
|
117
|
+
return props.activeFormats?.().has(tool.id) ? "true" : undefined;
|
|
118
|
+
},
|
|
119
|
+
get disabled() {
|
|
120
|
+
return props.disabled;
|
|
121
|
+
},
|
|
122
|
+
get tabIndex() {
|
|
123
|
+
return index() === 0 ? 0 : -1;
|
|
124
|
+
},
|
|
125
|
+
onMouseDown: event => event.preventDefault(),
|
|
126
|
+
onClick: () => {
|
|
127
|
+
const textarea = props.textarea();
|
|
128
|
+
if (textarea) tool.run(textarea);
|
|
129
|
+
},
|
|
130
|
+
get children() {
|
|
131
|
+
return _$ssr(_tmpl$4, _$ssrAttribute("class", _$escape(tool.icon, true), false));
|
|
132
|
+
}
|
|
133
|
+
})
|
|
106
134
|
})), _$escape(_$createComponent(Show, {
|
|
107
135
|
get when() {
|
|
108
136
|
return props.trailing;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/markdown/Toolbar.tsx"],"sourcesContent":["import { For, type JSX, Show } from \"solid-js\";\nimport { useUiMessages } from \"../../intl/messages\";\nimport {\n insertLink,\n toggleBold,\n toggleBulletList,\n toggleCode,\n toggleHeading,\n toggleItalic,\n toggleNumberedList,\n toggleQuote,\n} from \"./actions\";\n\ntype ToolbarProps = {\n textarea: () => HTMLTextAreaElement | null;\n activeFormats?: () => Set<string>;\n disabled?: boolean;\n trailing?: JSX.Element;\n};\n\ntype Tool =\n | {\n kind: \"button\";\n id: string;\n icon: string;\n title: string;\n run: (textarea: HTMLTextAreaElement) => void;\n }\n | { kind: \"separator\" };\n\nconst TOOLS: readonly Tool[] = [\n { kind: \"button\", id: \"bold\", icon: \"ti ti-bold\", title: \"Bold (Ctrl/Cmd+B)\", run: toggleBold },\n { kind: \"button\", id: \"italic\", icon: \"ti ti-italic\", title: \"Italic (Ctrl/Cmd+I)\", run: toggleItalic },\n { kind: \"button\", id: \"code\", icon: \"ti ti-code\", title: \"Inline code (Ctrl/Cmd+E)\", run: toggleCode },\n { kind: \"button\", id: \"link\", icon: \"ti ti-link\", title: \"Link (Ctrl/Cmd+K)\", run: insertLink },\n { kind: \"separator\" },\n { kind: \"button\", id: \"h1\", icon: \"ti ti-h-1\", title: \"Heading 1 (Ctrl/Cmd+Shift+1)\", run: (textarea) => toggleHeading(textarea, 1) },\n { kind: \"button\", id: \"h2\", icon: \"ti ti-h-2\", title: \"Heading 2 (Ctrl/Cmd+Shift+2)\", run: (textarea) => toggleHeading(textarea, 2) },\n { kind: \"button\", id: \"h3\", icon: \"ti ti-h-3\", title: \"Heading 3 (Ctrl/Cmd+Shift+3)\", run: (textarea) => toggleHeading(textarea, 3) },\n { kind: \"separator\" },\n { kind: \"button\", id: \"bullet\", icon: \"ti ti-list\", title: \"Bullet list (Ctrl/Cmd+Shift+8)\", run: toggleBulletList },\n { kind: \"button\", id: \"ordered\", icon: \"ti ti-list-numbers\", title: \"Numbered list (Ctrl/Cmd+Shift+7)\", run: toggleNumberedList },\n { kind: \"button\", id: \"quote\", icon: \"ti ti-quote\", title: \"Quote\", run: toggleQuote },\n];\n\nexport default function Toolbar(props: ToolbarProps): JSX.Element {\n const messages = useUiMessages();\n const title = (id: string, fallback: string): string =>\n ({\n bold: messages().boldShortcut,\n italic: messages().italicShortcut,\n code: messages().inlineCodeShortcut,\n link: messages().linkShortcut,\n h1: messages().heading1Shortcut,\n h2: messages().heading2Shortcut,\n h3: messages().heading3Shortcut,\n bullet: messages().bulletListShortcut,\n ordered: messages().numberedListShortcut,\n quote: messages().quote,\n })[id] ?? fallback;\n let toolbar!: HTMLDivElement;\n const moveFocus = (event: KeyboardEvent): void => {\n if (![\"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"].includes(event.key)) return;\n const buttons = Array.from(toolbar.querySelectorAll<HTMLButtonElement>(\".k2b-markdown-editor__tool:not(:disabled)\"));\n if (buttons.length === 0) return;\n const current = Math.max(\n 0,\n buttons.findIndex((button) => button === document.activeElement),\n );\n const next =\n event.key === \"Home\"\n ? 0\n : event.key === \"End\"\n ? buttons.length - 1\n : event.key === \"ArrowLeft\"\n ? (current - 1 + buttons.length) % buttons.length\n : (current + 1) % buttons.length;\n event.preventDefault();\n for (const button of buttons) button.tabIndex = -1;\n buttons[next]!.tabIndex = 0;\n buttons[next]!.focus();\n };\n\n return (\n <div ref={toolbar} class=\"k2b-markdown-editor__toolbar\" role=\"toolbar\" aria-label={messages().markdownFormatting} onKeyDown={moveFocus}>\n <For each={TOOLS}>\n {(tool, index) =>\n tool.kind === \"separator\" ? (\n <span class=\"k2b-markdown-editor__separator\" aria-hidden=\"true\" />\n ) : (\n <
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/markdown/Toolbar.tsx"],"sourcesContent":["import { For, type JSX, Show } from \"solid-js\";\nimport { Tooltip } from \"../../feedback/Tooltip\";\nimport { useUiMessages } from \"../../intl/messages\";\nimport {\n insertLink,\n toggleBold,\n toggleBulletList,\n toggleCode,\n toggleHeading,\n toggleItalic,\n toggleNumberedList,\n toggleQuote,\n} from \"./actions\";\n\ntype ToolbarProps = {\n textarea: () => HTMLTextAreaElement | null;\n activeFormats?: () => Set<string>;\n disabled?: boolean;\n trailing?: JSX.Element;\n};\n\ntype Tool =\n | {\n kind: \"button\";\n id: string;\n icon: string;\n title: string;\n run: (textarea: HTMLTextAreaElement) => void;\n }\n | { kind: \"separator\" };\n\nconst TOOLS: readonly Tool[] = [\n { kind: \"button\", id: \"bold\", icon: \"ti ti-bold\", title: \"Bold (Ctrl/Cmd+B)\", run: toggleBold },\n { kind: \"button\", id: \"italic\", icon: \"ti ti-italic\", title: \"Italic (Ctrl/Cmd+I)\", run: toggleItalic },\n { kind: \"button\", id: \"code\", icon: \"ti ti-code\", title: \"Inline code (Ctrl/Cmd+E)\", run: toggleCode },\n { kind: \"button\", id: \"link\", icon: \"ti ti-link\", title: \"Link (Ctrl/Cmd+K)\", run: insertLink },\n { kind: \"separator\" },\n { kind: \"button\", id: \"h1\", icon: \"ti ti-h-1\", title: \"Heading 1 (Ctrl/Cmd+Shift+1)\", run: (textarea) => toggleHeading(textarea, 1) },\n { kind: \"button\", id: \"h2\", icon: \"ti ti-h-2\", title: \"Heading 2 (Ctrl/Cmd+Shift+2)\", run: (textarea) => toggleHeading(textarea, 2) },\n { kind: \"button\", id: \"h3\", icon: \"ti ti-h-3\", title: \"Heading 3 (Ctrl/Cmd+Shift+3)\", run: (textarea) => toggleHeading(textarea, 3) },\n { kind: \"separator\" },\n { kind: \"button\", id: \"bullet\", icon: \"ti ti-list\", title: \"Bullet list (Ctrl/Cmd+Shift+8)\", run: toggleBulletList },\n { kind: \"button\", id: \"ordered\", icon: \"ti ti-list-numbers\", title: \"Numbered list (Ctrl/Cmd+Shift+7)\", run: toggleNumberedList },\n { kind: \"button\", id: \"quote\", icon: \"ti ti-quote\", title: \"Quote\", run: toggleQuote },\n];\n\nexport default function Toolbar(props: ToolbarProps): JSX.Element {\n const messages = useUiMessages();\n const title = (id: string, fallback: string): string =>\n ({\n bold: messages().boldShortcut,\n italic: messages().italicShortcut,\n code: messages().inlineCodeShortcut,\n link: messages().linkShortcut,\n h1: messages().heading1Shortcut,\n h2: messages().heading2Shortcut,\n h3: messages().heading3Shortcut,\n bullet: messages().bulletListShortcut,\n ordered: messages().numberedListShortcut,\n quote: messages().quote,\n })[id] ?? fallback;\n let toolbar!: HTMLDivElement;\n const moveFocus = (event: KeyboardEvent): void => {\n if (![\"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"].includes(event.key)) return;\n const buttons = Array.from(toolbar.querySelectorAll<HTMLButtonElement>(\".k2b-markdown-editor__tool:not(:disabled)\"));\n if (buttons.length === 0) return;\n const current = Math.max(\n 0,\n buttons.findIndex((button) => button === document.activeElement),\n );\n const next =\n event.key === \"Home\"\n ? 0\n : event.key === \"End\"\n ? buttons.length - 1\n : event.key === \"ArrowLeft\"\n ? (current - 1 + buttons.length) % buttons.length\n : (current + 1) % buttons.length;\n event.preventDefault();\n for (const button of buttons) button.tabIndex = -1;\n buttons[next]!.tabIndex = 0;\n buttons[next]!.focus();\n };\n\n return (\n <div ref={toolbar} class=\"k2b-markdown-editor__toolbar\" role=\"toolbar\" aria-label={messages().markdownFormatting} onKeyDown={moveFocus}>\n <For each={TOOLS}>\n {(tool, index) =>\n tool.kind === \"separator\" ? (\n <span class=\"k2b-markdown-editor__separator\" aria-hidden=\"true\" />\n ) : (\n <Tooltip.Trigger\n type=\"button\"\n class=\"k2b-markdown-editor__tool\"\n content={title(tool.id, tool.title)}\n aria-label={title(tool.id, tool.title)}\n aria-pressed={props.activeFormats?.().has(tool.id) ? \"true\" : undefined}\n disabled={props.disabled}\n tabIndex={index() === 0 ? 0 : -1}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n const textarea = props.textarea();\n if (textarea) tool.run(textarea);\n }}\n >\n <i class={tool.icon} aria-hidden=\"true\" />\n </Tooltip.Trigger>\n )\n }\n </For>\n <Show when={props.trailing}>\n <span class=\"k2b-markdown-editor__trailing\">{props.trailing}</span>\n </Show>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,GAAG,EAAY,IAAI,QAAQ,UAAU;AAC9C,SAAS,OAAO,QAAQ,wBAAwB;AAChD,SAAS,aAAa,QAAQ,qBAAqB;AACnD,SACE,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,WAAW,QACN,WAAW;AAmBlB,MAAM,KAAsB,GAAG,CAC7B;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,MAAM;EAAE,IAAI,EAAE,YAAY;EAAE,KAAK,EAAE,mBAAmB;EAAE,GAAG,EAAE;AAAW,CAAC,EAC/F;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,QAAQ;EAAE,IAAI,EAAE,cAAc;EAAE,KAAK,EAAE,qBAAqB;EAAE,GAAG,EAAE;AAAa,CAAC,EACvG;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,MAAM;EAAE,IAAI,EAAE,YAAY;EAAE,KAAK,EAAE,0BAA0B;EAAE,GAAG,EAAE;AAAW,CAAC,EACtG;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,MAAM;EAAE,IAAI,EAAE,YAAY;EAAE,KAAK,EAAE,mBAAmB;EAAE,GAAG,EAAE;AAAW,CAAC,EAC/F;EAAE,IAAI,EAAE;AAAY,CAAC,EACrB;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,IAAI;EAAE,IAAI,EAAE,WAAW;EAAE,KAAK,EAAE,8BAA8B;EAAE,GAAG,EAAG,QAAQ,IAAK,aAAa,CAAC,QAAQ,EAAE,CAAC;AAAE,CAAC,EACrI;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,IAAI;EAAE,IAAI,EAAE,WAAW;EAAE,KAAK,EAAE,8BAA8B;EAAE,GAAG,EAAG,QAAQ,IAAK,aAAa,CAAC,QAAQ,EAAE,CAAC;AAAE,CAAC,EACrI;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,IAAI;EAAE,IAAI,EAAE,WAAW;EAAE,KAAK,EAAE,8BAA8B;EAAE,GAAG,EAAG,QAAQ,IAAK,aAAa,CAAC,QAAQ,EAAE,CAAC;AAAE,CAAC,EACrI;EAAE,IAAI,EAAE;AAAY,CAAC,EACrB;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,QAAQ;EAAE,IAAI,EAAE,YAAY;EAAE,KAAK,EAAE,gCAAgC;EAAE,GAAG,EAAE;AAAiB,CAAC,EACpH;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,SAAS;EAAE,IAAI,EAAE,oBAAoB;EAAE,KAAK,EAAE,kCAAkC;EAAE,GAAG,EAAE;AAAmB,CAAC,EACjI;EAAE,IAAI,EAAE,QAAQ;EAAE,EAAE,EAAE,OAAO;EAAE,IAAI,EAAE,aAAa;EAAE,KAAK,EAAE,OAAO;EAAE,GAAG,EAAE;AAAY,CAAC,CACvF;AAED,eAAe,SAAS,OAAO,CAAC,KAAmB,EAAe;EAChE,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,QAAgB,KACzC,CAAC;IACC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY;IAC7B,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,cAAc;IACjC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,kBAAkB;IACnC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY;IAC7B,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,gBAAgB;IAC/B,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,gBAAgB;IAC/B,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,gBAAgB;IAC/B,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,kBAAkB;IACrC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,oBAAoB;IACxC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;EACpB,CAAC,EAAE,EAAE,CAAC,IAAI,QAAQ;EACpB,IAAI,OAAwB;EAC5B,MAAM,SAAS,GAAI,KAAoB,IAAW;IAChD,IAAI,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACrE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAoB,2CAA2C,CAAC,CAAC;IACpH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;IAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CACtB,CAAC,EACD,OAAO,CAAC,SAAS,CAAE,MAAM,IAAK,MAAM,KAAK,QAAQ,CAAC,aAAa,CACjE,CAAC;IACD,MAAM,IAAI,GACR,KAAK,CAAC,GAAG,KAAK,MAAM,GAChB,CAAC,GACD,KAAK,CAAC,GAAG,KAAK,KAAK,GACjB,OAAO,CAAC,MAAM,GAAG,CAAC,GAClB,KAAK,CAAC,GAAG,KAAK,WAAW,GACvB,CAAC,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,GAC/C,CAAC,OAAO,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM;IACxC,KAAK,CAAC,cAAc,CAAC,CAAC;IACtB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAE,QAAQ,GAAG,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,CAAE,KAAK,CAAC,CAAC;EACxB,CAAC;EAED,4DACqF,QAAQ,CAAC,CAAC,CAAC,kBAAkB,4CAC7G,GAAG;IAAC,IAAI,EAAE,KAAK;IAAA,UACb,CAAC,IAAI,EAAE,KAAK,KACX,IAAI,CAAC,IAAI,KAAK,WAAW,sCAGtB,OAAO,CAAC,OAAO;MACd,IAAI;MAAA;MAAA,IAEJ,OAAO;QAAA,OAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC;MAAA;MAAA;QAAA,OACvB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC;MAAA;MAAA;QAAA,OACxB,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,SAAS;MAAA;MAAA,IACvE,QAAQ;QAAA,OAAE,KAAK,CAAC,QAAQ;MAAA;MAAA,IACxB,QAAQ;QAAA,OAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;MAAA;MAChC,WAAW,EAAG,KAAK,IAAK,KAAK,CAAC,cAAc,CAAC,CAAC;MAC9C,OAAO,EAAE,MAAM;QACb,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;MAClC,CAAC;MAAA;QAAA,uDAES,IAAI,CAAC,IAAI;MAAA;IAAA;EAEtB,gCAGJ,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,KAAK,CAAC,QAAQ;IAAA;IAAA;MAAA,8BACqB,KAAK,CAAC,QAAQ;IAAA;EAAA;AAInE","ignoreList":[]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overlays return focus to the control that opened them, and the ring comes
|
|
3
|
+
* back only for a keyboard user: a pointer user gets focus back silently, a
|
|
4
|
+
* keyboard user keeps seeing where they are.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const showsFocusRing = element => element?.matches(":focus-visible") ?? false;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Keys that do not make someone a keyboard user: modifiers come with pointer
|
|
11
|
+
* gestures, and pointer users close overlays with Escape too.
|
|
12
|
+
*/
|
|
13
|
+
const passiveKeys = new Set(["Alt", "AltGraph", "CapsLock", "Control", "Escape", "Meta", "Shift"]);
|
|
14
|
+
let lastInput;
|
|
15
|
+
|
|
16
|
+
// Tracked from the start, so the first overlay on a page knows the last input
|
|
17
|
+
// as well. The trigger's ring cannot tell it: Chromium and Firefox do not light
|
|
18
|
+
// the ring of an element that got focus back silently when a key is pressed on it.
|
|
19
|
+
if (typeof window !== "undefined") {
|
|
20
|
+
window.addEventListener("keydown", event => {
|
|
21
|
+
if (!passiveKeys.has(event.key)) lastInput = "keyboard";
|
|
22
|
+
}, true);
|
|
23
|
+
window.addEventListener("pointerdown", () => lastInput = "pointer", true);
|
|
24
|
+
}
|
|
25
|
+
const keyboardLast = () => lastInput === "keyboard";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Read as an overlay opens, while its trigger still holds focus: whether the
|
|
29
|
+
* keyboard opened it. The trigger's ring answers before the first input.
|
|
30
|
+
*/
|
|
31
|
+
export const ringOnReturn = trigger => keyboardLast() || showsFocusRing(trigger);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Moves focus back to `trigger`. It shows a ring when the keyboard opened the
|
|
35
|
+
* overlay (`openedByKeyboard`, what `ringOnReturn` reported as it opened) or
|
|
36
|
+
* worked it since, so a pointer open closed with Escape alone returns silently.
|
|
37
|
+
* Engines without the option focus as before.
|
|
38
|
+
*
|
|
39
|
+
* Call it before the overlay hides: a native popover or dialog that closes
|
|
40
|
+
* with focus inside restores it on its own, with a ring of the browser's choosing.
|
|
41
|
+
*/
|
|
42
|
+
export const returnFocus = (trigger, openedByKeyboard) => {
|
|
43
|
+
if (!trigger) return;
|
|
44
|
+
// Text fields always show where typing goes, so the browser decides.
|
|
45
|
+
if (trigger.matches("input, textarea, [contenteditable]:not([contenteditable='false'])")) {
|
|
46
|
+
trigger.focus();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const ring = openedByKeyboard || keyboardLast();
|
|
50
|
+
// The key that closed an overlay can light the ring of a trigger that kept
|
|
51
|
+
// focus, and focusing the focused element changes nothing.
|
|
52
|
+
if (trigger === document.activeElement) {
|
|
53
|
+
if (showsFocusRing(trigger) === ring) return;
|
|
54
|
+
trigger.blur();
|
|
55
|
+
}
|
|
56
|
+
const options = {
|
|
57
|
+
focusVisible: ring
|
|
58
|
+
};
|
|
59
|
+
trigger.focus(options);
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=focus-return.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["internal/focus-return.ts"],"sourcesContent":["/**\n * Overlays return focus to the control that opened them, and the ring comes\n * back only for a keyboard user: a pointer user gets focus back silently, a\n * keyboard user keeps seeing where they are.\n */\n\nconst showsFocusRing = (element: Element | null | undefined): boolean => element?.matches(\":focus-visible\") ?? false;\n\n/**\n * Keys that do not make someone a keyboard user: modifiers come with pointer\n * gestures, and pointer users close overlays with Escape too.\n */\nconst passiveKeys = new Set([\"Alt\", \"AltGraph\", \"CapsLock\", \"Control\", \"Escape\", \"Meta\", \"Shift\"]);\nlet lastInput: \"keyboard\" | \"pointer\" | undefined;\n\n// Tracked from the start, so the first overlay on a page knows the last input\n// as well. The trigger's ring cannot tell it: Chromium and Firefox do not light\n// the ring of an element that got focus back silently when a key is pressed on it.\nif (typeof window !== \"undefined\") {\n window.addEventListener(\n \"keydown\",\n (event) => {\n if (!passiveKeys.has(event.key)) lastInput = \"keyboard\";\n },\n true,\n );\n window.addEventListener(\"pointerdown\", () => (lastInput = \"pointer\"), true);\n}\n\nconst keyboardLast = (): boolean => lastInput === \"keyboard\";\n\n/**\n * Read as an overlay opens, while its trigger still holds focus: whether the\n * keyboard opened it. The trigger's ring answers before the first input.\n */\nexport const ringOnReturn = (trigger: Element | null | undefined): boolean => keyboardLast() || showsFocusRing(trigger);\n\n/**\n * Moves focus back to `trigger`. It shows a ring when the keyboard opened the\n * overlay (`openedByKeyboard`, what `ringOnReturn` reported as it opened) or\n * worked it since, so a pointer open closed with Escape alone returns silently.\n * Engines without the option focus as before.\n *\n * Call it before the overlay hides: a native popover or dialog that closes\n * with focus inside restores it on its own, with a ring of the browser's choosing.\n */\nexport const returnFocus = (trigger: HTMLElement | null | undefined, openedByKeyboard: boolean): void => {\n if (!trigger) return;\n // Text fields always show where typing goes, so the browser decides.\n if (trigger.matches(\"input, textarea, [contenteditable]:not([contenteditable='false'])\")) {\n trigger.focus();\n return;\n }\n const ring = openedByKeyboard || keyboardLast();\n // The key that closed an overlay can light the ring of a trigger that kept\n // focus, and focusing the focused element changes nothing.\n if (trigger === document.activeElement) {\n if (showsFocusRing(trigger) === ring) return;\n trigger.blur();\n }\n const options: FocusOptions & { focusVisible?: boolean } = { focusVisible: ring };\n trigger.focus(options);\n};\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA,MAAM,cAAc,GAAI,OAAmC,IAAc,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,IAAI,KAAK;;AAEpH;AACA;AACA;AACA;AACA,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAClG,IAAI,SAA6C;;AAEjD;AACA;AACA;AACA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;EACjC,MAAM,CAAC,gBAAgB,CACrB,SAAS,EACR,KAAK,IAAK;IACT,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,SAAS,GAAG,UAAU;EACzD,CAAC,EACD,IACF,CAAC;EACD,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,MAAO,SAAS,GAAG,SAAU,EAAE,IAAI,CAAC;AAC7E;AAEA,MAAM,YAAY,GAAG,MAAe,SAAS,KAAK,UAAU;;AAE5D;AACA;AACA;AACA;AACA,OAAO,MAAM,YAAY,GAAI,OAAmC,IAAc,YAAY,CAAC,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC;;AAEvH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAM,WAAW,GAAG,CAAC,OAAuC,EAAE,gBAAyB,KAAW;EACvG,IAAI,CAAC,OAAO,EAAE;EACd;EACA,IAAI,OAAO,CAAC,OAAO,CAAC,mEAAmE,CAAC,EAAE;IACxF,OAAO,CAAC,KAAK,CAAC,CAAC;IACf;EACF;EACA,MAAM,IAAI,GAAG,gBAAgB,IAAI,YAAY,CAAC,CAAC;EAC/C;EACA;EACA,IAAI,OAAO,KAAK,QAAQ,CAAC,aAAa,EAAE;IACtC,IAAI,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;IACtC,OAAO,CAAC,IAAI,CAAC,CAAC;EAChB;EACA,MAAM,OAAkD,GAAG;IAAE,YAAY,EAAE;EAAK,CAAC;EACjF,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;AACxB,CAAC","ignoreList":[]}
|