@llui/components 0.4.9 → 0.5.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/components/accordion.d.ts +13 -13
- package/dist/components/accordion.d.ts.map +1 -1
- package/dist/components/accordion.js +9 -9
- package/dist/components/accordion.js.map +1 -1
- package/dist/components/alert-dialog.d.ts +8 -8
- package/dist/components/alert-dialog.d.ts.map +1 -1
- package/dist/components/alert-dialog.js +2 -2
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/angle-slider.d.ts +13 -13
- package/dist/components/angle-slider.d.ts.map +1 -1
- package/dist/components/angle-slider.js +11 -11
- package/dist/components/angle-slider.js.map +1 -1
- package/dist/components/async-list.d.ts +7 -7
- package/dist/components/async-list.d.ts.map +1 -1
- package/dist/components/async-list.js +5 -8
- package/dist/components/async-list.js.map +1 -1
- package/dist/components/avatar.d.ts +9 -9
- package/dist/components/avatar.d.ts.map +1 -1
- package/dist/components/avatar.js +7 -7
- package/dist/components/avatar.js.map +1 -1
- package/dist/components/carousel.d.ts +18 -18
- package/dist/components/carousel.d.ts.map +1 -1
- package/dist/components/carousel.js +12 -12
- package/dist/components/carousel.js.map +1 -1
- package/dist/components/cascade-select.d.ts +12 -12
- package/dist/components/cascade-select.d.ts.map +1 -1
- package/dist/components/cascade-select.js +8 -8
- package/dist/components/cascade-select.js.map +1 -1
- package/dist/components/checkbox.d.ts +14 -14
- package/dist/components/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox.js +12 -12
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/clipboard.d.ts +8 -8
- package/dist/components/clipboard.d.ts.map +1 -1
- package/dist/components/clipboard.js +6 -6
- package/dist/components/clipboard.js.map +1 -1
- package/dist/components/collapsible.d.ts +11 -11
- package/dist/components/collapsible.d.ts.map +1 -1
- package/dist/components/collapsible.js +9 -9
- package/dist/components/collapsible.js.map +1 -1
- package/dist/components/color-picker.d.ts +19 -19
- package/dist/components/color-picker.d.ts.map +1 -1
- package/dist/components/color-picker.js +21 -21
- package/dist/components/color-picker.js.map +1 -1
- package/dist/components/combobox.d.ts +25 -25
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/combobox.js +54 -59
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/context-menu.d.ts +14 -14
- package/dist/components/context-menu.d.ts.map +1 -1
- package/dist/components/context-menu.js +15 -19
- package/dist/components/context-menu.js.map +1 -1
- package/dist/components/date-input.d.ts +13 -13
- package/dist/components/date-input.d.ts.map +1 -1
- package/dist/components/date-input.js +11 -11
- package/dist/components/date-input.js.map +1 -1
- package/dist/components/date-picker.d.ts +11 -11
- package/dist/components/date-picker.d.ts.map +1 -1
- package/dist/components/date-picker.js +7 -7
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/dialog.d.ts +15 -15
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/dialog.js +45 -50
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/drawer.d.ts +13 -13
- package/dist/components/drawer.d.ts.map +1 -1
- package/dist/components/drawer.js +44 -49
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/editable.d.ts +11 -11
- package/dist/components/editable.d.ts.map +1 -1
- package/dist/components/editable.js +9 -9
- package/dist/components/editable.js.map +1 -1
- package/dist/components/file-upload.d.ts +19 -19
- package/dist/components/file-upload.d.ts.map +1 -1
- package/dist/components/file-upload.js +14 -14
- package/dist/components/file-upload.js.map +1 -1
- package/dist/components/floating-panel.d.ts +14 -14
- package/dist/components/floating-panel.d.ts.map +1 -1
- package/dist/components/floating-panel.js +13 -14
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form.d.ts +9 -9
- package/dist/components/form.d.ts.map +1 -1
- package/dist/components/form.js +7 -7
- package/dist/components/form.js.map +1 -1
- package/dist/components/hover-card.d.ts +9 -9
- package/dist/components/hover-card.d.ts.map +1 -1
- package/dist/components/hover-card.js +12 -13
- package/dist/components/hover-card.js.map +1 -1
- package/dist/components/image-cropper.d.ts +8 -8
- package/dist/components/image-cropper.d.ts.map +1 -1
- package/dist/components/image-cropper.js +7 -8
- package/dist/components/image-cropper.js.map +1 -1
- package/dist/components/in-view.d.ts +6 -6
- package/dist/components/in-view.d.ts.map +1 -1
- package/dist/components/in-view.js +2 -2
- package/dist/components/in-view.js.map +1 -1
- package/dist/components/listbox.d.ts +16 -16
- package/dist/components/listbox.d.ts.map +1 -1
- package/dist/components/listbox.js +16 -16
- package/dist/components/listbox.js.map +1 -1
- package/dist/components/marquee.d.ts +8 -8
- package/dist/components/marquee.d.ts.map +1 -1
- package/dist/components/marquee.js +8 -11
- package/dist/components/marquee.js.map +1 -1
- package/dist/components/menu.d.ts +15 -15
- package/dist/components/menu.d.ts.map +1 -1
- package/dist/components/menu.js +16 -17
- package/dist/components/menu.js.map +1 -1
- package/dist/components/navigation-menu.d.ts +12 -12
- package/dist/components/navigation-menu.d.ts.map +1 -1
- package/dist/components/navigation-menu.js +8 -8
- package/dist/components/navigation-menu.js.map +1 -1
- package/dist/components/number-input.d.ts +18 -18
- package/dist/components/number-input.d.ts.map +1 -1
- package/dist/components/number-input.js +16 -20
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/pagination.d.ts +13 -13
- package/dist/components/pagination.d.ts.map +1 -1
- package/dist/components/pagination.js +11 -17
- package/dist/components/pagination.js.map +1 -1
- package/dist/components/password-input.d.ts +11 -11
- package/dist/components/password-input.d.ts.map +1 -1
- package/dist/components/password-input.js +11 -11
- package/dist/components/password-input.js.map +1 -1
- package/dist/components/pin-input.d.ts +9 -9
- package/dist/components/pin-input.d.ts.map +1 -1
- package/dist/components/pin-input.js +9 -9
- package/dist/components/pin-input.js.map +1 -1
- package/dist/components/popover.d.ts +11 -11
- package/dist/components/popover.d.ts.map +1 -1
- package/dist/components/popover.js +61 -60
- package/dist/components/popover.js.map +1 -1
- package/dist/components/presence.d.ts +7 -5
- package/dist/components/presence.d.ts.map +1 -1
- package/dist/components/presence.js +5 -3
- package/dist/components/presence.js.map +1 -1
- package/dist/components/progress.d.ts +14 -14
- package/dist/components/progress.d.ts.map +1 -1
- package/dist/components/progress.js +12 -12
- package/dist/components/progress.js.map +1 -1
- package/dist/components/qr-code.d.ts +7 -7
- package/dist/components/qr-code.d.ts.map +1 -1
- package/dist/components/qr-code.js +7 -7
- package/dist/components/qr-code.js.map +1 -1
- package/dist/components/radio-group.d.ts +15 -15
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js +12 -13
- package/dist/components/radio-group.js.map +1 -1
- package/dist/components/rating-group.d.ts +13 -13
- package/dist/components/rating-group.d.ts.map +1 -1
- package/dist/components/rating-group.js +10 -11
- package/dist/components/rating-group.js.map +1 -1
- package/dist/components/scroll-area.d.ts +10 -10
- package/dist/components/scroll-area.d.ts.map +1 -1
- package/dist/components/scroll-area.js +10 -15
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/select.d.ts +26 -26
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +29 -33
- package/dist/components/select.js.map +1 -1
- package/dist/components/signature-pad.d.ts +12 -12
- package/dist/components/signature-pad.d.ts.map +1 -1
- package/dist/components/signature-pad.js +10 -10
- package/dist/components/signature-pad.js.map +1 -1
- package/dist/components/slider.d.ts +22 -22
- package/dist/components/slider.d.ts.map +1 -1
- package/dist/components/slider.js +17 -17
- package/dist/components/slider.js.map +1 -1
- package/dist/components/sortable.d.ts +11 -11
- package/dist/components/sortable.d.ts.map +1 -1
- package/dist/components/sortable.js +20 -20
- package/dist/components/sortable.js.map +1 -1
- package/dist/components/splitter.d.ts +15 -15
- package/dist/components/splitter.d.ts.map +1 -1
- package/dist/components/splitter.js +15 -15
- package/dist/components/splitter.js.map +1 -1
- package/dist/components/steps.d.ts +14 -14
- package/dist/components/steps.d.ts.map +1 -1
- package/dist/components/steps.js +10 -16
- package/dist/components/steps.js.map +1 -1
- package/dist/components/switch.d.ts +12 -12
- package/dist/components/switch.d.ts.map +1 -1
- package/dist/components/switch.js +10 -10
- package/dist/components/switch.js.map +1 -1
- package/dist/components/tabs.d.ts +15 -15
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +11 -11
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/tags-input.d.ts +14 -14
- package/dist/components/tags-input.d.ts.map +1 -1
- package/dist/components/tags-input.js +10 -10
- package/dist/components/tags-input.js.map +1 -1
- package/dist/components/theme-switch.d.ts +5 -5
- package/dist/components/theme-switch.d.ts.map +1 -1
- package/dist/components/theme-switch.js +3 -3
- package/dist/components/theme-switch.js.map +1 -1
- package/dist/components/time-picker.d.ts +19 -19
- package/dist/components/time-picker.d.ts.map +1 -1
- package/dist/components/time-picker.js +17 -17
- package/dist/components/time-picker.js.map +1 -1
- package/dist/components/timer.d.ts +10 -10
- package/dist/components/timer.d.ts.map +1 -1
- package/dist/components/timer.js +8 -8
- package/dist/components/timer.js.map +1 -1
- package/dist/components/toast.d.ts +8 -8
- package/dist/components/toast.d.ts.map +1 -1
- package/dist/components/toast.js +4 -4
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toc.d.ts +12 -12
- package/dist/components/toc.d.ts.map +1 -1
- package/dist/components/toc.js +8 -8
- package/dist/components/toc.js.map +1 -1
- package/dist/components/toggle-group.d.ts +13 -13
- package/dist/components/toggle-group.d.ts.map +1 -1
- package/dist/components/toggle-group.js +9 -9
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle.d.ts +8 -8
- package/dist/components/toggle.d.ts.map +1 -1
- package/dist/components/toggle.js +6 -6
- package/dist/components/toggle.js.map +1 -1
- package/dist/components/tooltip.d.ts +10 -10
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +13 -14
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/tour.d.ts +7 -7
- package/dist/components/tour.d.ts.map +1 -1
- package/dist/components/tour.js +5 -5
- package/dist/components/tour.js.map +1 -1
- package/dist/components/tree-view.d.ts +19 -19
- package/dist/components/tree-view.d.ts.map +1 -1
- package/dist/components/tree-view.js +23 -23
- package/dist/components/tree-view.js.map +1 -1
- package/dist/patterns/confirm-dialog.d.ts +4 -4
- package/dist/patterns/confirm-dialog.d.ts.map +1 -1
- package/dist/patterns/confirm-dialog.js +7 -9
- package/dist/patterns/confirm-dialog.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/enter-view.d.ts +0 -73
- package/dist/components/enter-view.d.ts.map +0 -1
- package/dist/components/enter-view.js +0 -51
- package/dist/utils/validators.d.ts +0 -34
- package/dist/utils/validators.d.ts.map +0 -1
- package/dist/utils/validators.js +0 -83
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floating-panel.js","sourceRoot":"","sources":["../../src/components/floating-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Floating panel — a draggable + resizable window-like surface, useful\n * for dev tools overlays, pop-out inspectors, preview panels, etc. The\n * state machine tracks position and size; the view layer wires pointer\n * events on the drag handle and resize grips and dispatches the\n * corresponding messages.\n *\n * Coordinates are in pixels relative to the positioning container\n * (typically `position: fixed` relative to the viewport).\n */\n\nexport type ResizeHandle = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw'\n\nexport interface FloatingPanelState {\n position: { x: number; y: number }\n size: { width: number; height: number }\n minSize: { width: number; height: number }\n maxSize: { width: number; height: number } | null\n open: boolean\n minimized: boolean\n maximized: boolean\n dragging: boolean\n resizing: ResizeHandle | null\n /** Snapshot of the pre-maximize geometry (for restore). */\n restoreBounds: { x: number; y: number; width: number; height: number } | null\n disabled: boolean\n}\n\nexport type FloatingPanelMsg =\n /** @intent(\"Open the floating panel\") */\n | { type: 'open' }\n /** @intent(\"Close the floating panel\") */\n | { type: 'close' }\n /** @intent(\"Minimize the panel (collapses to title bar)\") */\n | { type: 'minimize' }\n /** @intent(\"Restore the panel from its minimized state\") */\n | { type: 'restoreFromMinimized' }\n /** @intent(\"Maximize the panel (fills the viewport)\") */\n | { type: 'maximize' }\n /** @intent(\"Restore the panel to its pre-maximize geometry\") */\n | { type: 'restoreFromMaximized' }\n /** @intent(\"Toggle between minimized and normal\") */\n | { type: 'toggleMinimize' }\n /** @intent(\"Toggle between maximized and normal\") */\n | { type: 'toggleMaximize' }\n /** @humanOnly */\n | { type: 'dragStart' }\n /** @humanOnly */\n | { type: 'dragMove'; dx: number; dy: number }\n /** @humanOnly */\n | { type: 'dragEnd' }\n /** @humanOnly */\n | { type: 'resizeStart'; handle: ResizeHandle }\n /** @humanOnly */\n | { type: 'resizeMove'; dx: number; dy: number }\n /** @humanOnly */\n | { type: 'resizeEnd' }\n /** @intent(\"Set the panel's top-left position in pixels\") */\n | { type: 'setPosition'; x: number; y: number }\n /** @intent(\"Set the panel's size in pixels (clamped to min/max)\") */\n | { type: 'setSize'; width: number; height: number }\n\nexport interface FloatingPanelInit {\n position?: { x: number; y: number }\n size?: { width: number; height: number }\n minSize?: { width: number; height: number }\n maxSize?: { width: number; height: number } | null\n open?: boolean\n disabled?: boolean\n}\n\nfunction clamp(v: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, v))\n}\n\nexport function init(opts: FloatingPanelInit = {}): FloatingPanelState {\n return {\n position: opts.position ?? { x: 100, y: 100 },\n size: opts.size ?? { width: 400, height: 300 },\n minSize: opts.minSize ?? { width: 200, height: 150 },\n maxSize: opts.maxSize ?? null,\n open: opts.open ?? true,\n minimized: false,\n maximized: false,\n dragging: false,\n resizing: null,\n restoreBounds: null,\n disabled: opts.disabled ?? false,\n }\n}\n\nfunction clampSize(\n width: number,\n height: number,\n min: FloatingPanelState['minSize'],\n max: FloatingPanelState['maxSize'],\n): { width: number; height: number } {\n const maxW = max?.width ?? Infinity\n const maxH = max?.height ?? Infinity\n return {\n width: clamp(width, min.width, maxW),\n height: clamp(height, min.height, maxH),\n }\n}\n\nfunction applyResize(\n state: FloatingPanelState,\n dx: number,\n dy: number,\n handle: ResizeHandle,\n): FloatingPanelState {\n let { x, y } = state.position\n let { width, height } = state.size\n if (handle.includes('e')) width += dx\n if (handle.includes('w')) {\n width -= dx\n x += dx\n }\n if (handle.includes('s')) height += dy\n if (handle.includes('n')) {\n height -= dy\n y += dy\n }\n const size = clampSize(width, height, state.minSize, state.maxSize)\n // If clamping changed width/height, undo the x/y shift by that delta.\n if (handle.includes('w')) x += width - size.width\n if (handle.includes('n')) y += height - size.height\n return { ...state, position: { x, y }, size }\n}\n\nexport function update(\n state: FloatingPanelState,\n msg: FloatingPanelMsg,\n): [FloatingPanelState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'open':\n return [{ ...state, open: true }, []]\n case 'close':\n return [{ ...state, open: false, dragging: false, resizing: null }, []]\n case 'minimize':\n return [{ ...state, minimized: true, dragging: false, resizing: null }, []]\n case 'restoreFromMinimized':\n return [{ ...state, minimized: false }, []]\n case 'toggleMinimize':\n return [{ ...state, minimized: !state.minimized }, []]\n case 'maximize': {\n if (state.maximized) return [state, []]\n return [\n {\n ...state,\n maximized: true,\n restoreBounds: {\n x: state.position.x,\n y: state.position.y,\n width: state.size.width,\n height: state.size.height,\n },\n },\n [],\n ]\n }\n case 'restoreFromMaximized': {\n if (!state.maximized || !state.restoreBounds) {\n return [{ ...state, maximized: false }, []]\n }\n const b = state.restoreBounds\n return [\n {\n ...state,\n maximized: false,\n position: { x: b.x, y: b.y },\n size: { width: b.width, height: b.height },\n restoreBounds: null,\n },\n [],\n ]\n }\n case 'toggleMaximize':\n return update(state, {\n type: state.maximized ? 'restoreFromMaximized' : 'maximize',\n })\n case 'dragStart':\n if (state.maximized) return [state, []]\n return [{ ...state, dragging: true }, []]\n case 'dragMove':\n if (!state.dragging) return [state, []]\n return [\n {\n ...state,\n position: {\n x: state.position.x + msg.dx,\n y: state.position.y + msg.dy,\n },\n },\n [],\n ]\n case 'dragEnd':\n return [{ ...state, dragging: false }, []]\n case 'resizeStart':\n if (state.maximized) return [state, []]\n return [{ ...state, resizing: msg.handle }, []]\n case 'resizeMove':\n if (state.resizing === null) return [state, []]\n return [applyResize(state, msg.dx, msg.dy, state.resizing), []]\n case 'resizeEnd':\n return [{ ...state, resizing: null }, []]\n case 'setPosition':\n return [{ ...state, position: { x: msg.x, y: msg.y } }, []]\n case 'setSize': {\n const size = clampSize(msg.width, msg.height, state.minSize, state.maxSize)\n return [{ ...state, size }, []]\n }\n }\n}\n\nexport interface FloatingPanelParts<S> {\n root: {\n role: 'dialog'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'floating-panel'\n 'data-part': 'root'\n 'data-dragging': (s: S) => '' | undefined\n 'data-resizing': (s: S) => '' | undefined\n 'data-minimized': (s: S) => '' | undefined\n 'data-maximized': (s: S) => '' | undefined\n hidden: (s: S) => boolean\n style: (s: S) => string\n }\n dragHandle: {\n 'data-scope': 'floating-panel'\n 'data-part': 'drag-handle'\n onPointerDown: (e: PointerEvent) => void\n }\n content: {\n 'data-scope': 'floating-panel'\n 'data-part': 'content'\n hidden: (s: S) => boolean\n }\n minimizeTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'floating-panel'\n 'data-part': 'minimize-trigger'\n onClick: (e: MouseEvent) => void\n }\n maximizeTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'floating-panel'\n 'data-part': 'maximize-trigger'\n onClick: (e: MouseEvent) => void\n }\n closeTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'floating-panel'\n 'data-part': 'close-trigger'\n onClick: (e: MouseEvent) => void\n }\n resizeHandle: (handle: ResizeHandle) => {\n 'data-scope': 'floating-panel'\n 'data-part': 'resize-handle'\n 'data-handle': ResizeHandle\n onPointerDown: (e: PointerEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n label?: string\n minimizeLabel?: string\n maximizeLabel?: string\n closeLabel?: string\n}\n\nexport function connect<S>(\n get: (s: S) => FloatingPanelState,\n send: Send<FloatingPanelMsg>,\n opts: ConnectOptions = {},\n): FloatingPanelParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n return {\n root: {\n role: 'dialog',\n 'aria-label': opts.label ?? ((s: S) => locale(s).floatingPanel.label),\n 'data-scope': 'floating-panel',\n 'data-part': 'root',\n 'data-dragging': (s) => (get(s).dragging ? '' : undefined),\n 'data-resizing': (s) => (get(s).resizing !== null ? '' : undefined),\n 'data-minimized': (s) => (get(s).minimized ? '' : undefined),\n 'data-maximized': (s) => (get(s).maximized ? '' : undefined),\n hidden: (s) => !get(s).open,\n style: (s) => {\n const st = get(s)\n if (st.maximized) return 'position:fixed;inset:0;width:auto;height:auto;'\n return (\n `position:fixed;` +\n `left:${st.position.x}px;top:${st.position.y}px;` +\n `width:${st.size.width}px;height:${st.size.height}px;`\n )\n },\n },\n dragHandle: {\n 'data-scope': 'floating-panel',\n 'data-part': 'drag-handle',\n onPointerDown: tagSend(send, ['dragStart'], () => send({ type: 'dragStart' })),\n },\n content: {\n 'data-scope': 'floating-panel',\n 'data-part': 'content',\n hidden: (s) => get(s).minimized,\n },\n minimizeTrigger: {\n type: 'button',\n 'aria-label': opts.minimizeLabel ?? ((s: S) => locale(s).floatingPanel.minimize),\n 'data-scope': 'floating-panel',\n 'data-part': 'minimize-trigger',\n onClick: tagSend(send, ['toggleMinimize'], () => send({ type: 'toggleMinimize' })),\n },\n maximizeTrigger: {\n type: 'button',\n 'aria-label': opts.maximizeLabel ?? ((s: S) => locale(s).floatingPanel.maximize),\n 'data-scope': 'floating-panel',\n 'data-part': 'maximize-trigger',\n onClick: tagSend(send, ['toggleMaximize'], () => send({ type: 'toggleMaximize' })),\n },\n closeTrigger: {\n type: 'button',\n 'aria-label': opts.closeLabel ?? ((s: S) => locale(s).floatingPanel.close),\n 'data-scope': 'floating-panel',\n 'data-part': 'close-trigger',\n onClick: tagSend(send, ['close'], () => send({ type: 'close' })),\n },\n resizeHandle: (handle: ResizeHandle) => ({\n 'data-scope': 'floating-panel',\n 'data-part': 'resize-handle',\n 'data-handle': handle,\n onPointerDown: tagSend(send, ['resizeStart'], () => send({ type: 'resizeStart', handle })),\n }),\n }\n}\n\nexport const floatingPanel = { init, update, connect }\n"]}
|
|
1
|
+
{"version":3,"file":"floating-panel.js","sourceRoot":"","sources":["../../src/components/floating-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, Signal } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\n\n/**\n * Floating panel — a draggable + resizable window-like surface, useful\n * for dev tools overlays, pop-out inspectors, preview panels, etc. The\n * state machine tracks position and size; the view layer wires pointer\n * events on the drag handle and resize grips and dispatches the\n * corresponding messages.\n *\n * Coordinates are in pixels relative to the positioning container\n * (typically `position: fixed` relative to the viewport).\n */\n\nexport type ResizeHandle = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw'\n\nexport interface FloatingPanelState {\n position: { x: number; y: number }\n size: { width: number; height: number }\n minSize: { width: number; height: number }\n maxSize: { width: number; height: number } | null\n open: boolean\n minimized: boolean\n maximized: boolean\n dragging: boolean\n resizing: ResizeHandle | null\n /** Snapshot of the pre-maximize geometry (for restore). */\n restoreBounds: { x: number; y: number; width: number; height: number } | null\n disabled: boolean\n}\n\nexport type FloatingPanelMsg =\n /** @intent(\"Open the floating panel\") */\n | { type: 'open' }\n /** @intent(\"Close the floating panel\") */\n | { type: 'close' }\n /** @intent(\"Minimize the panel (collapses to title bar)\") */\n | { type: 'minimize' }\n /** @intent(\"Restore the panel from its minimized state\") */\n | { type: 'restoreFromMinimized' }\n /** @intent(\"Maximize the panel (fills the viewport)\") */\n | { type: 'maximize' }\n /** @intent(\"Restore the panel to its pre-maximize geometry\") */\n | { type: 'restoreFromMaximized' }\n /** @intent(\"Toggle between minimized and normal\") */\n | { type: 'toggleMinimize' }\n /** @intent(\"Toggle between maximized and normal\") */\n | { type: 'toggleMaximize' }\n /** @humanOnly */\n | { type: 'dragStart' }\n /** @humanOnly */\n | { type: 'dragMove'; dx: number; dy: number }\n /** @humanOnly */\n | { type: 'dragEnd' }\n /** @humanOnly */\n | { type: 'resizeStart'; handle: ResizeHandle }\n /** @humanOnly */\n | { type: 'resizeMove'; dx: number; dy: number }\n /** @humanOnly */\n | { type: 'resizeEnd' }\n /** @intent(\"Set the panel's top-left position in pixels\") */\n | { type: 'setPosition'; x: number; y: number }\n /** @intent(\"Set the panel's size in pixels (clamped to min/max)\") */\n | { type: 'setSize'; width: number; height: number }\n\nexport interface FloatingPanelInit {\n position?: { x: number; y: number }\n size?: { width: number; height: number }\n minSize?: { width: number; height: number }\n maxSize?: { width: number; height: number } | null\n open?: boolean\n disabled?: boolean\n}\n\nfunction clamp(v: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, v))\n}\n\nexport function init(opts: FloatingPanelInit = {}): FloatingPanelState {\n return {\n position: opts.position ?? { x: 100, y: 100 },\n size: opts.size ?? { width: 400, height: 300 },\n minSize: opts.minSize ?? { width: 200, height: 150 },\n maxSize: opts.maxSize ?? null,\n open: opts.open ?? true,\n minimized: false,\n maximized: false,\n dragging: false,\n resizing: null,\n restoreBounds: null,\n disabled: opts.disabled ?? false,\n }\n}\n\nfunction clampSize(\n width: number,\n height: number,\n min: FloatingPanelState['minSize'],\n max: FloatingPanelState['maxSize'],\n): { width: number; height: number } {\n const maxW = max?.width ?? Infinity\n const maxH = max?.height ?? Infinity\n return {\n width: clamp(width, min.width, maxW),\n height: clamp(height, min.height, maxH),\n }\n}\n\nfunction applyResize(\n state: FloatingPanelState,\n dx: number,\n dy: number,\n handle: ResizeHandle,\n): FloatingPanelState {\n let { x, y } = state.position\n let { width, height } = state.size\n if (handle.includes('e')) width += dx\n if (handle.includes('w')) {\n width -= dx\n x += dx\n }\n if (handle.includes('s')) height += dy\n if (handle.includes('n')) {\n height -= dy\n y += dy\n }\n const size = clampSize(width, height, state.minSize, state.maxSize)\n // If clamping changed width/height, undo the x/y shift by that delta.\n if (handle.includes('w')) x += width - size.width\n if (handle.includes('n')) y += height - size.height\n return { ...state, position: { x, y }, size }\n}\n\nexport function update(\n state: FloatingPanelState,\n msg: FloatingPanelMsg,\n): [FloatingPanelState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'open':\n return [{ ...state, open: true }, []]\n case 'close':\n return [{ ...state, open: false, dragging: false, resizing: null }, []]\n case 'minimize':\n return [{ ...state, minimized: true, dragging: false, resizing: null }, []]\n case 'restoreFromMinimized':\n return [{ ...state, minimized: false }, []]\n case 'toggleMinimize':\n return [{ ...state, minimized: !state.minimized }, []]\n case 'maximize': {\n if (state.maximized) return [state, []]\n return [\n {\n ...state,\n maximized: true,\n restoreBounds: {\n x: state.position.x,\n y: state.position.y,\n width: state.size.width,\n height: state.size.height,\n },\n },\n [],\n ]\n }\n case 'restoreFromMaximized': {\n if (!state.maximized || !state.restoreBounds) {\n return [{ ...state, maximized: false }, []]\n }\n const b = state.restoreBounds\n return [\n {\n ...state,\n maximized: false,\n position: { x: b.x, y: b.y },\n size: { width: b.width, height: b.height },\n restoreBounds: null,\n },\n [],\n ]\n }\n case 'toggleMaximize':\n return update(state, {\n type: state.maximized ? 'restoreFromMaximized' : 'maximize',\n })\n case 'dragStart':\n if (state.maximized) return [state, []]\n return [{ ...state, dragging: true }, []]\n case 'dragMove':\n if (!state.dragging) return [state, []]\n return [\n {\n ...state,\n position: {\n x: state.position.x + msg.dx,\n y: state.position.y + msg.dy,\n },\n },\n [],\n ]\n case 'dragEnd':\n return [{ ...state, dragging: false }, []]\n case 'resizeStart':\n if (state.maximized) return [state, []]\n return [{ ...state, resizing: msg.handle }, []]\n case 'resizeMove':\n if (state.resizing === null) return [state, []]\n return [applyResize(state, msg.dx, msg.dy, state.resizing), []]\n case 'resizeEnd':\n return [{ ...state, resizing: null }, []]\n case 'setPosition':\n return [{ ...state, position: { x: msg.x, y: msg.y } }, []]\n case 'setSize': {\n const size = clampSize(msg.width, msg.height, state.minSize, state.maxSize)\n return [{ ...state, size }, []]\n }\n }\n}\n\nexport interface FloatingPanelParts {\n root: {\n role: 'dialog'\n 'aria-label': string\n 'data-scope': 'floating-panel'\n 'data-part': 'root'\n 'data-dragging': Signal<'' | undefined>\n 'data-resizing': Signal<'' | undefined>\n 'data-minimized': Signal<'' | undefined>\n 'data-maximized': Signal<'' | undefined>\n hidden: Signal<boolean>\n style: Signal<string>\n }\n dragHandle: {\n 'data-scope': 'floating-panel'\n 'data-part': 'drag-handle'\n onPointerDown: (e: PointerEvent) => void\n }\n content: {\n 'data-scope': 'floating-panel'\n 'data-part': 'content'\n hidden: Signal<boolean>\n }\n minimizeTrigger: {\n type: 'button'\n 'aria-label': string\n 'data-scope': 'floating-panel'\n 'data-part': 'minimize-trigger'\n onClick: (e: MouseEvent) => void\n }\n maximizeTrigger: {\n type: 'button'\n 'aria-label': string\n 'data-scope': 'floating-panel'\n 'data-part': 'maximize-trigger'\n onClick: (e: MouseEvent) => void\n }\n closeTrigger: {\n type: 'button'\n 'aria-label': string\n 'data-scope': 'floating-panel'\n 'data-part': 'close-trigger'\n onClick: (e: MouseEvent) => void\n }\n resizeHandle: (handle: ResizeHandle) => {\n 'data-scope': 'floating-panel'\n 'data-part': 'resize-handle'\n 'data-handle': ResizeHandle\n onPointerDown: (e: PointerEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n label?: string\n minimizeLabel?: string\n maximizeLabel?: string\n closeLabel?: string\n}\n\nexport function connect(\n state: Signal<FloatingPanelState>,\n send: Send<FloatingPanelMsg>,\n opts: ConnectOptions = {},\n): FloatingPanelParts {\n const locale = useContext(LocaleContext)\n return {\n root: {\n role: 'dialog',\n 'aria-label': opts.label ?? locale.floatingPanel.label,\n 'data-scope': 'floating-panel',\n 'data-part': 'root',\n 'data-dragging': state.map((st) => (st.dragging ? '' : undefined)),\n 'data-resizing': state.map((st) => (st.resizing !== null ? '' : undefined)),\n 'data-minimized': state.map((st) => (st.minimized ? '' : undefined)),\n 'data-maximized': state.map((st) => (st.maximized ? '' : undefined)),\n hidden: state.map((st) => !st.open),\n style: state.map((st) => {\n if (st.maximized) return 'position:fixed;inset:0;width:auto;height:auto;'\n return (\n `position:fixed;` +\n `left:${st.position.x}px;top:${st.position.y}px;` +\n `width:${st.size.width}px;height:${st.size.height}px;`\n )\n }),\n },\n dragHandle: {\n 'data-scope': 'floating-panel',\n 'data-part': 'drag-handle',\n onPointerDown: tagSend(send, ['dragStart'], () => send({ type: 'dragStart' })),\n },\n content: {\n 'data-scope': 'floating-panel',\n 'data-part': 'content',\n hidden: state.map((st) => st.minimized),\n },\n minimizeTrigger: {\n type: 'button',\n 'aria-label': opts.minimizeLabel ?? locale.floatingPanel.minimize,\n 'data-scope': 'floating-panel',\n 'data-part': 'minimize-trigger',\n onClick: tagSend(send, ['toggleMinimize'], () => send({ type: 'toggleMinimize' })),\n },\n maximizeTrigger: {\n type: 'button',\n 'aria-label': opts.maximizeLabel ?? locale.floatingPanel.maximize,\n 'data-scope': 'floating-panel',\n 'data-part': 'maximize-trigger',\n onClick: tagSend(send, ['toggleMaximize'], () => send({ type: 'toggleMaximize' })),\n },\n closeTrigger: {\n type: 'button',\n 'aria-label': opts.closeLabel ?? locale.floatingPanel.close,\n 'data-scope': 'floating-panel',\n 'data-part': 'close-trigger',\n onClick: tagSend(send, ['close'], () => send({ type: 'close' })),\n },\n resizeHandle: (handle: ResizeHandle) => ({\n 'data-scope': 'floating-panel',\n 'data-part': 'resize-handle',\n 'data-handle': handle,\n onPointerDown: tagSend(send, ['resizeStart'], () => send({ type: 'resizeStart', handle })),\n }),\n }\n}\n\nexport const floatingPanel = { init, update, connect }\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Send } from '@llui/dom';
|
|
1
|
+
import type { Send, Signal } from '@llui/dom';
|
|
2
2
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
3
|
/**
|
|
4
4
|
* Form — submit lifecycle + touched tracking + Standard Schema validation.
|
|
@@ -71,32 +71,32 @@ export type FormMsg =
|
|
|
71
71
|
};
|
|
72
72
|
export declare function init(): FormState;
|
|
73
73
|
export declare function update(state: FormState, msg: FormMsg): [FormState, never[]];
|
|
74
|
-
export interface FormParts
|
|
74
|
+
export interface FormParts {
|
|
75
75
|
root: {
|
|
76
76
|
'data-scope': 'form';
|
|
77
77
|
'data-part': 'root';
|
|
78
|
-
'data-state':
|
|
79
|
-
'aria-busy':
|
|
78
|
+
'data-state': Signal<FormStatus>;
|
|
79
|
+
'aria-busy': Signal<'true' | undefined>;
|
|
80
80
|
};
|
|
81
81
|
field: (name: string) => {
|
|
82
82
|
'data-scope': 'form';
|
|
83
83
|
'data-part': 'field';
|
|
84
|
-
'data-touched':
|
|
85
|
-
touched:
|
|
84
|
+
'data-touched': Signal<'' | undefined>;
|
|
85
|
+
touched: Signal<boolean>;
|
|
86
86
|
onBlur: (e: FocusEvent) => void;
|
|
87
87
|
};
|
|
88
88
|
submit: {
|
|
89
89
|
type: 'submit';
|
|
90
90
|
'data-scope': 'form';
|
|
91
91
|
'data-part': 'submit';
|
|
92
|
-
'data-state':
|
|
93
|
-
disabled:
|
|
92
|
+
'data-state': Signal<FormStatus>;
|
|
93
|
+
disabled: Signal<boolean>;
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
96
|
export interface ConnectOptions {
|
|
97
97
|
id: string;
|
|
98
98
|
}
|
|
99
|
-
export declare function connect
|
|
99
|
+
export declare function connect(state: Signal<FormState>, send: Send<FormMsg>, _opts: ConnectOptions): FormParts;
|
|
100
100
|
export interface ValidateResult<T> {
|
|
101
101
|
isValid: boolean;
|
|
102
102
|
/** Field name → first error message. Field name is derived from the issue's path. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/components/form.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/components/form.ts"],"names":[],"mappings":"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"}
|
package/dist/components/form.js
CHANGED
|
@@ -24,27 +24,27 @@ export function update(state, msg) {
|
|
|
24
24
|
return [init(), []];
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
export function connect(
|
|
27
|
+
export function connect(state, send, _opts) {
|
|
28
28
|
return {
|
|
29
29
|
root: {
|
|
30
30
|
'data-scope': 'form',
|
|
31
31
|
'data-part': 'root',
|
|
32
|
-
'data-state': (s) =>
|
|
33
|
-
'aria-busy': (s) => (
|
|
32
|
+
'data-state': state.map((s) => s.status),
|
|
33
|
+
'aria-busy': state.map((s) => (s.status === 'submitting' ? 'true' : undefined)),
|
|
34
34
|
},
|
|
35
35
|
field: (name) => ({
|
|
36
36
|
'data-scope': 'form',
|
|
37
37
|
'data-part': 'field',
|
|
38
|
-
'data-touched': (s) => (
|
|
39
|
-
touched: (s) => !!
|
|
38
|
+
'data-touched': state.map((s) => (s.touched[name] ? '' : undefined)),
|
|
39
|
+
touched: state.map((s) => !!s.touched[name]),
|
|
40
40
|
onBlur: tagSend(send, ['touch'], () => send({ type: 'touch', field: name })),
|
|
41
41
|
}),
|
|
42
42
|
submit: {
|
|
43
43
|
type: 'submit',
|
|
44
44
|
'data-scope': 'form',
|
|
45
45
|
'data-part': 'submit',
|
|
46
|
-
'data-state': (s) =>
|
|
47
|
-
disabled: (s) =>
|
|
46
|
+
'data-state': state.map((s) => s.status),
|
|
47
|
+
disabled: state.map((s) => s.status === 'submitting'),
|
|
48
48
|
},
|
|
49
49
|
};
|
|
50
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/components/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA8DnC,MAAM,UAAU,IAAI;IAClB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAgB,EAAE,GAAY;IACnD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YAChD,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAC7E,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAA;YACpC,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM;gBAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;YAC7C,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAA;QACpC,CAAC;QACD,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QACpE,KAAK,eAAe;YAClB,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QACnE,KAAK,aAAa;YAChB,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;QACpE,KAAK,OAAO;YACV,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;IACvB,CAAC;AACH,CAAC;AA6BD,MAAM,UAAU,OAAO,CACrB,GAAwB,EACxB,IAAmB,EACnB,KAAqB;IAErB,OAAO;QACL,IAAI,EAAE;YACJ,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,MAAM;YACnB,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM;YAClC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;SAC1E;QACD,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAChB,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,OAAO;YACpB,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9D,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;YACtC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;SAC7E,CAAC;QACF,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,QAAQ;YACrB,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM;YAClC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY;SAChD;KACF,CAAA;AACH,CAAC;AAYD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAI,MAA2B,EAAE,MAAe;IAC5E,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACnD,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,qEAAqE;YACnE,mFAAmF,CACtF,CAAA;IACH,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAClD,CAAC;IAED,MAAM,MAAM,GAAqC,EAAE,CAAA;IACnD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;QACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,GAAG,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAY,CAAA;QACtE,wCAAwC;QACxC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAA;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAA2B,EAC3B,MAAe;IAEf,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAEzD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAClD,CAAC;IAED,MAAM,MAAM,GAAqC,EAAE,CAAA;IACnD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;QACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,GAAG,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAY,CAAA;QACtE,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAA;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;AAC1D,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAA","sourcesContent":["import { tagSend } from '@llui/dom'\nimport type { Send } from '@llui/dom'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\n\n/**\n * Form — submit lifecycle + touched tracking + Standard Schema validation.\n *\n * Values live in the parent component's state; `form` tracks submit status\n * and which fields have been interacted with (blur), so errors are shown\n * only after touch instead of immediately.\n *\n * Bring your own validation library — any Standard Schema-compatible\n * schema works (Zod, Valibot, ArkType, etc.). See https://standardschema.dev.\n *\n * ```ts\n * import { z } from 'zod'\n * import { form, validateSchema } from '@llui/components/form'\n *\n * const schema = z.object({\n * email: z.string().email(),\n * password: z.string().min(8),\n * })\n *\n * type Values = z.infer<typeof schema>\n * type State = { values: Values; form: FormState }\n *\n * update: (state, msg) => {\n * switch (msg.type) {\n * case 'submit': {\n * const result = validateSchema(schema, state.values)\n * if (!result.isValid) {\n * return [{ ...state, form: { ...state.form, touched: { email: true, password: true } } }, []]\n * }\n * return [{ ...state, form: { ...state.form, status: 'submitting' } }, [saveUserEffect]]\n * }\n * }\n * }\n * ```\n */\n\nexport type FormStatus = 'idle' | 'submitting' | 'submitted' | 'error'\n\nexport interface FormState {\n status: FormStatus\n touched: Record<string, boolean>\n submitError: string | null\n}\n\nexport type FormMsg =\n /** @intent(\"Mark a single field as touched (typically on blur)\") */\n | { type: 'touch'; field: string }\n /** @intent(\"Mark every named field as touched (typically on submit attempt)\") */\n | { type: 'touchAll'; fields: string[] }\n /** @intent(\"Begin form submission — validate and dispatch the save effect\") */\n | { type: 'submit' }\n /** @intent(\"Mark the in-flight submission as successful\") */\n | { type: 'submitSuccess' }\n /** @intent(\"Mark the in-flight submission as failed with the given error message\") */\n | { type: 'submitError'; error: string }\n /** @intent(\"Reset the form to its initial state (clears touched flags and submit status)\") */\n | { type: 'reset' }\n\nexport function init(): FormState {\n return { status: 'idle', touched: {}, submitError: null }\n}\n\nexport function update(state: FormState, msg: FormMsg): [FormState, never[]] {\n switch (msg.type) {\n case 'touch':\n if (state.touched[msg.field]) return [state, []]\n return [{ ...state, touched: { ...state.touched, [msg.field]: true } }, []]\n case 'touchAll': {\n const touched = { ...state.touched }\n for (const f of msg.fields) touched[f] = true\n return [{ ...state, touched }, []]\n }\n case 'submit':\n return [{ ...state, status: 'submitting', submitError: null }, []]\n case 'submitSuccess':\n return [{ ...state, status: 'submitted', submitError: null }, []]\n case 'submitError':\n return [{ ...state, status: 'error', submitError: msg.error }, []]\n case 'reset':\n return [init(), []]\n }\n}\n\nexport interface FormParts<S> {\n root: {\n 'data-scope': 'form'\n 'data-part': 'root'\n 'data-state': (s: S) => FormStatus\n 'aria-busy': (s: S) => 'true' | undefined\n }\n field: (name: string) => {\n 'data-scope': 'form'\n 'data-part': 'field'\n 'data-touched': (s: S) => '' | undefined\n touched: (s: S) => boolean\n onBlur: (e: FocusEvent) => void\n }\n submit: {\n type: 'submit'\n 'data-scope': 'form'\n 'data-part': 'submit'\n 'data-state': (s: S) => FormStatus\n disabled: (s: S) => boolean\n }\n}\n\nexport interface ConnectOptions {\n id: string\n}\n\nexport function connect<S>(\n get: (s: S) => FormState,\n send: Send<FormMsg>,\n _opts: ConnectOptions,\n): FormParts<S> {\n return {\n root: {\n 'data-scope': 'form',\n 'data-part': 'root',\n 'data-state': (s) => get(s).status,\n 'aria-busy': (s) => (get(s).status === 'submitting' ? 'true' : undefined),\n },\n field: (name) => ({\n 'data-scope': 'form',\n 'data-part': 'field',\n 'data-touched': (s) => (get(s).touched[name] ? '' : undefined),\n touched: (s) => !!get(s).touched[name],\n onBlur: tagSend(send, ['touch'], () => send({ type: 'touch', field: name })),\n }),\n submit: {\n type: 'submit',\n 'data-scope': 'form',\n 'data-part': 'submit',\n 'data-state': (s) => get(s).status,\n disabled: (s) => get(s).status === 'submitting',\n },\n }\n}\n\n// ── Standard Schema integration ────────────────────────────────\n\nexport interface ValidateResult<T> {\n isValid: boolean\n /** Field name → first error message. Field name is derived from the issue's path. */\n errors: Partial<Record<keyof T, string>>\n /** All issues from the schema validator, unaltered. */\n issues: readonly StandardSchemaV1.Issue[]\n}\n\n/**\n * Run a Standard Schema synchronously against a values object. Throws if\n * the schema returns a Promise — use sync validation only for form submit.\n *\n * Works with any library implementing the Standard Schema spec:\n * Zod (v3.24+), Valibot (v1+), ArkType, etc.\n */\nexport function validateSchema<T>(schema: StandardSchemaV1<T>, values: unknown): ValidateResult<T> {\n const result = schema['~standard'].validate(values)\n if (result instanceof Promise) {\n throw new Error(\n '[@llui/components/form] validateSchema: schema returned a Promise. ' +\n 'Form validation must be synchronous. Use `validateSchemaAsync` for async schemas.',\n )\n }\n\n if (!result.issues) {\n return { isValid: true, errors: {}, issues: [] }\n }\n\n const errors: Partial<Record<keyof T, string>> = {}\n for (const issue of result.issues) {\n const path = issue.path\n if (!path || path.length === 0) continue\n const first = path[0]\n const key = (typeof first === 'object' ? first.key : first) as keyof T\n // Only record the first error per field\n if (errors[key] === undefined) {\n errors[key] = issue.message\n }\n }\n\n return { isValid: false, errors, issues: result.issues }\n}\n\n/**\n * Async variant — returns a Promise. Use when the schema performs async\n * validation (e.g. uniqueness checks against a backend).\n */\nexport async function validateSchemaAsync<T>(\n schema: StandardSchemaV1<T>,\n values: unknown,\n): Promise<ValidateResult<T>> {\n const result = await schema['~standard'].validate(values)\n\n if (!result.issues) {\n return { isValid: true, errors: {}, issues: [] }\n }\n\n const errors: Partial<Record<keyof T, string>> = {}\n for (const issue of result.issues) {\n const path = issue.path\n if (!path || path.length === 0) continue\n const first = path[0]\n const key = (typeof first === 'object' ? first.key : first) as keyof T\n if (errors[key] === undefined) {\n errors[key] = issue.message\n }\n }\n\n return { isValid: false, errors, issues: result.issues }\n}\n\nexport const form = { init, update, connect, validateSchema, validateSchemaAsync }\n"]}
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/components/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA8DnC,MAAM,UAAU,IAAI;IAClB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAgB,EAAE,GAAY;IACnD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YAChD,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAC7E,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAA;YACpC,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM;gBAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;YAC7C,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAA;QACpC,CAAC;QACD,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QACpE,KAAK,eAAe;YAClB,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QACnE,KAAK,aAAa;YAChB,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;QACpE,KAAK,OAAO;YACV,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;IACvB,CAAC;AACH,CAAC;AA6BD,MAAM,UAAU,OAAO,CACrB,KAAwB,EACxB,IAAmB,EACnB,KAAqB;IAErB,OAAO;QACL,IAAI,EAAE;YACJ,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,MAAM;YACnB,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YACxC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;SAChF;QACD,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAChB,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,OAAO;YACpB,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACpE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC5C,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;SAC7E,CAAC;QACF,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,QAAQ;YACrB,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YACxC,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC;SACtD;KACF,CAAA;AACH,CAAC;AAYD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAI,MAA2B,EAAE,MAAe;IAC5E,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACnD,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,qEAAqE;YACnE,mFAAmF,CACtF,CAAA;IACH,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAClD,CAAC;IAED,MAAM,MAAM,GAAqC,EAAE,CAAA;IACnD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;QACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,GAAG,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAY,CAAA;QACtE,wCAAwC;QACxC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAA;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAA2B,EAC3B,MAAe;IAEf,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAEzD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAClD,CAAC;IAED,MAAM,MAAM,GAAqC,EAAE,CAAA;IACnD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;QACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,GAAG,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAY,CAAA;QACtE,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAA;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;AAC1D,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAA","sourcesContent":["import { tagSend } from '@llui/dom'\nimport type { Send, Signal } from '@llui/dom'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\n\n/**\n * Form — submit lifecycle + touched tracking + Standard Schema validation.\n *\n * Values live in the parent component's state; `form` tracks submit status\n * and which fields have been interacted with (blur), so errors are shown\n * only after touch instead of immediately.\n *\n * Bring your own validation library — any Standard Schema-compatible\n * schema works (Zod, Valibot, ArkType, etc.). See https://standardschema.dev.\n *\n * ```ts\n * import { z } from 'zod'\n * import { form, validateSchema } from '@llui/components/form'\n *\n * const schema = z.object({\n * email: z.string().email(),\n * password: z.string().min(8),\n * })\n *\n * type Values = z.infer<typeof schema>\n * type State = { values: Values; form: FormState }\n *\n * update: (state, msg) => {\n * switch (msg.type) {\n * case 'submit': {\n * const result = validateSchema(schema, state.values)\n * if (!result.isValid) {\n * return [{ ...state, form: { ...state.form, touched: { email: true, password: true } } }, []]\n * }\n * return [{ ...state, form: { ...state.form, status: 'submitting' } }, [saveUserEffect]]\n * }\n * }\n * }\n * ```\n */\n\nexport type FormStatus = 'idle' | 'submitting' | 'submitted' | 'error'\n\nexport interface FormState {\n status: FormStatus\n touched: Record<string, boolean>\n submitError: string | null\n}\n\nexport type FormMsg =\n /** @intent(\"Mark a single field as touched (typically on blur)\") */\n | { type: 'touch'; field: string }\n /** @intent(\"Mark every named field as touched (typically on submit attempt)\") */\n | { type: 'touchAll'; fields: string[] }\n /** @intent(\"Begin form submission — validate and dispatch the save effect\") */\n | { type: 'submit' }\n /** @intent(\"Mark the in-flight submission as successful\") */\n | { type: 'submitSuccess' }\n /** @intent(\"Mark the in-flight submission as failed with the given error message\") */\n | { type: 'submitError'; error: string }\n /** @intent(\"Reset the form to its initial state (clears touched flags and submit status)\") */\n | { type: 'reset' }\n\nexport function init(): FormState {\n return { status: 'idle', touched: {}, submitError: null }\n}\n\nexport function update(state: FormState, msg: FormMsg): [FormState, never[]] {\n switch (msg.type) {\n case 'touch':\n if (state.touched[msg.field]) return [state, []]\n return [{ ...state, touched: { ...state.touched, [msg.field]: true } }, []]\n case 'touchAll': {\n const touched = { ...state.touched }\n for (const f of msg.fields) touched[f] = true\n return [{ ...state, touched }, []]\n }\n case 'submit':\n return [{ ...state, status: 'submitting', submitError: null }, []]\n case 'submitSuccess':\n return [{ ...state, status: 'submitted', submitError: null }, []]\n case 'submitError':\n return [{ ...state, status: 'error', submitError: msg.error }, []]\n case 'reset':\n return [init(), []]\n }\n}\n\nexport interface FormParts {\n root: {\n 'data-scope': 'form'\n 'data-part': 'root'\n 'data-state': Signal<FormStatus>\n 'aria-busy': Signal<'true' | undefined>\n }\n field: (name: string) => {\n 'data-scope': 'form'\n 'data-part': 'field'\n 'data-touched': Signal<'' | undefined>\n touched: Signal<boolean>\n onBlur: (e: FocusEvent) => void\n }\n submit: {\n type: 'submit'\n 'data-scope': 'form'\n 'data-part': 'submit'\n 'data-state': Signal<FormStatus>\n disabled: Signal<boolean>\n }\n}\n\nexport interface ConnectOptions {\n id: string\n}\n\nexport function connect(\n state: Signal<FormState>,\n send: Send<FormMsg>,\n _opts: ConnectOptions,\n): FormParts {\n return {\n root: {\n 'data-scope': 'form',\n 'data-part': 'root',\n 'data-state': state.map((s) => s.status),\n 'aria-busy': state.map((s) => (s.status === 'submitting' ? 'true' : undefined)),\n },\n field: (name) => ({\n 'data-scope': 'form',\n 'data-part': 'field',\n 'data-touched': state.map((s) => (s.touched[name] ? '' : undefined)),\n touched: state.map((s) => !!s.touched[name]),\n onBlur: tagSend(send, ['touch'], () => send({ type: 'touch', field: name })),\n }),\n submit: {\n type: 'submit',\n 'data-scope': 'form',\n 'data-part': 'submit',\n 'data-state': state.map((s) => s.status),\n disabled: state.map((s) => s.status === 'submitting'),\n },\n }\n}\n\n// ── Standard Schema integration ────────────────────────────────\n\nexport interface ValidateResult<T> {\n isValid: boolean\n /** Field name → first error message. Field name is derived from the issue's path. */\n errors: Partial<Record<keyof T, string>>\n /** All issues from the schema validator, unaltered. */\n issues: readonly StandardSchemaV1.Issue[]\n}\n\n/**\n * Run a Standard Schema synchronously against a values object. Throws if\n * the schema returns a Promise — use sync validation only for form submit.\n *\n * Works with any library implementing the Standard Schema spec:\n * Zod (v3.24+), Valibot (v1+), ArkType, etc.\n */\nexport function validateSchema<T>(schema: StandardSchemaV1<T>, values: unknown): ValidateResult<T> {\n const result = schema['~standard'].validate(values)\n if (result instanceof Promise) {\n throw new Error(\n '[@llui/components/form] validateSchema: schema returned a Promise. ' +\n 'Form validation must be synchronous. Use `validateSchemaAsync` for async schemas.',\n )\n }\n\n if (!result.issues) {\n return { isValid: true, errors: {}, issues: [] }\n }\n\n const errors: Partial<Record<keyof T, string>> = {}\n for (const issue of result.issues) {\n const path = issue.path\n if (!path || path.length === 0) continue\n const first = path[0]\n const key = (typeof first === 'object' ? first.key : first) as keyof T\n // Only record the first error per field\n if (errors[key] === undefined) {\n errors[key] = issue.message\n }\n }\n\n return { isValid: false, errors, issues: result.issues }\n}\n\n/**\n * Async variant — returns a Promise. Use when the schema performs async\n * validation (e.g. uniqueness checks against a backend).\n */\nexport async function validateSchemaAsync<T>(\n schema: StandardSchemaV1<T>,\n values: unknown,\n): Promise<ValidateResult<T>> {\n const result = await schema['~standard'].validate(values)\n\n if (!result.issues) {\n return { isValid: true, errors: {}, issues: [] }\n }\n\n const errors: Partial<Record<keyof T, string>> = {}\n for (const issue of result.issues) {\n const path = issue.path\n if (!path || path.length === 0) continue\n const first = path[0]\n const key = (typeof first === 'object' ? first.key : first) as keyof T\n if (errors[key] === undefined) {\n errors[key] = issue.message\n }\n }\n\n return { isValid: false, errors, issues: result.issues }\n}\n\nexport const form = { init, update, connect, validateSchema, validateSchemaAsync }\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Send, TransitionOptions } from '@llui/dom';
|
|
1
|
+
import type { Send, Signal, TransitionOptions } from '@llui/dom';
|
|
2
2
|
import { type Placement } from '../utils/floating.js';
|
|
3
3
|
/**
|
|
4
4
|
* Hover card — richer tooltip-like popup triggered by hover or focus.
|
|
@@ -21,12 +21,12 @@ export interface HoverCardInit {
|
|
|
21
21
|
}
|
|
22
22
|
export declare function init(opts?: HoverCardInit): HoverCardState;
|
|
23
23
|
export declare function update(state: HoverCardState, msg: HoverCardMsg): [HoverCardState, never[]];
|
|
24
|
-
export interface HoverCardParts
|
|
24
|
+
export interface HoverCardParts {
|
|
25
25
|
trigger: {
|
|
26
26
|
id: string;
|
|
27
27
|
'aria-haspopup': 'dialog';
|
|
28
28
|
'aria-controls': string;
|
|
29
|
-
'data-state':
|
|
29
|
+
'data-state': Signal<'open' | 'closed'>;
|
|
30
30
|
'data-scope': 'hover-card';
|
|
31
31
|
'data-part': 'trigger';
|
|
32
32
|
onPointerEnter: (e: PointerEvent) => void;
|
|
@@ -42,7 +42,7 @@ export interface HoverCardParts<S> {
|
|
|
42
42
|
content: {
|
|
43
43
|
role: 'dialog';
|
|
44
44
|
id: string;
|
|
45
|
-
'data-state':
|
|
45
|
+
'data-state': Signal<'open' | 'closed'>;
|
|
46
46
|
'data-scope': 'hover-card';
|
|
47
47
|
'data-part': 'content';
|
|
48
48
|
onPointerEnter: (e: PointerEvent) => void;
|
|
@@ -60,11 +60,11 @@ export interface ConnectOptions {
|
|
|
60
60
|
/** ms before hiding after pointer leaves (default: 300). */
|
|
61
61
|
closeDelay?: number;
|
|
62
62
|
}
|
|
63
|
-
export declare function connect
|
|
64
|
-
export interface OverlayOptions
|
|
65
|
-
|
|
63
|
+
export declare function connect(state: Signal<HoverCardState>, send: Send<HoverCardMsg>, opts: ConnectOptions): HoverCardParts;
|
|
64
|
+
export interface OverlayOptions {
|
|
65
|
+
state: Signal<HoverCardState>;
|
|
66
66
|
send: Send<HoverCardMsg>;
|
|
67
|
-
parts: HoverCardParts
|
|
67
|
+
parts: HoverCardParts;
|
|
68
68
|
content: () => Node[];
|
|
69
69
|
placement?: Placement;
|
|
70
70
|
offset?: number;
|
|
@@ -74,7 +74,7 @@ export interface OverlayOptions<S> {
|
|
|
74
74
|
target?: string | HTMLElement;
|
|
75
75
|
arrowSelector?: string;
|
|
76
76
|
}
|
|
77
|
-
export declare function overlay
|
|
77
|
+
export declare function overlay(opts: OverlayOptions): Node;
|
|
78
78
|
export declare const hoverCard: {
|
|
79
79
|
init: typeof init;
|
|
80
80
|
update: typeof update;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover-card.d.ts","sourceRoot":"","sources":["../../src/components/hover-card.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"hover-card.d.ts","sourceRoot":"","sources":["../../src/components/hover-card.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ export function update(state, msg) {
|
|
|
13
13
|
return [{ ...state, open: msg.open }, []];
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
export function connect(
|
|
16
|
+
export function connect(state, send, opts) {
|
|
17
17
|
const base = opts.id;
|
|
18
18
|
const triggerId = `${base}:trigger`;
|
|
19
19
|
const contentId = `${base}:content`;
|
|
@@ -50,7 +50,7 @@ export function connect(get, send, opts) {
|
|
|
50
50
|
id: triggerId,
|
|
51
51
|
'aria-haspopup': 'dialog',
|
|
52
52
|
'aria-controls': contentId,
|
|
53
|
-
'data-state': (s) => (
|
|
53
|
+
'data-state': state.map((s) => (s.open ? 'open' : 'closed')),
|
|
54
54
|
'data-scope': 'hover-card',
|
|
55
55
|
'data-part': 'trigger',
|
|
56
56
|
onPointerEnter: scheduleOpen,
|
|
@@ -66,7 +66,7 @@ export function connect(get, send, opts) {
|
|
|
66
66
|
content: {
|
|
67
67
|
role: 'dialog',
|
|
68
68
|
id: contentId,
|
|
69
|
-
'data-state': (s) => (
|
|
69
|
+
'data-state': state.map((s) => (s.open ? 'open' : 'closed')),
|
|
70
70
|
'data-scope': 'hover-card',
|
|
71
71
|
'data-part': 'content',
|
|
72
72
|
onPointerEnter: () => {
|
|
@@ -84,7 +84,7 @@ export function connect(get, send, opts) {
|
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
export function overlay(opts) {
|
|
87
|
-
const
|
|
87
|
+
const rawTarget = opts.target ?? 'body';
|
|
88
88
|
const placement = opts.placement ?? 'bottom';
|
|
89
89
|
const offset = opts.offset ?? 8;
|
|
90
90
|
const flip = opts.flip !== false;
|
|
@@ -92,11 +92,12 @@ export function overlay(opts) {
|
|
|
92
92
|
const parts = opts.parts;
|
|
93
93
|
const contentId = parts.content.id;
|
|
94
94
|
const triggerId = parts.trigger.id;
|
|
95
|
-
return show({
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
return show(opts.state.map((s) => s.open), () => {
|
|
96
|
+
const targetEl = typeof rawTarget === 'string'
|
|
97
|
+
? (document.querySelector(rawTarget) ?? document.body)
|
|
98
|
+
: rawTarget;
|
|
99
|
+
return [
|
|
100
|
+
portal(() => {
|
|
100
101
|
onMount(() => {
|
|
101
102
|
const contentEl = document.getElementById(contentId);
|
|
102
103
|
const triggerEl = document.getElementById(triggerId);
|
|
@@ -118,10 +119,8 @@ export function overlay(opts) {
|
|
|
118
119
|
});
|
|
119
120
|
});
|
|
120
121
|
return [div(parts.positioner, opts.content())];
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
enter: opts.transition?.enter,
|
|
124
|
-
leave: opts.transition?.leave,
|
|
122
|
+
}, targetEl),
|
|
123
|
+
];
|
|
125
124
|
});
|
|
126
125
|
}
|
|
127
126
|
export const hoverCard = { init, update, connect, overlay };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover-card.js","sourceRoot":"","sources":["../../src/components/hover-card.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, TransitionOptions } from '@llui/dom'\nimport { show, portal, onMount, div } from '@llui/dom'\nimport { attachFloating, type Placement } from '../utils/floating.js'\n\n/**\n * Hover card — richer tooltip-like popup triggered by hover or focus.\n * Unlike tooltip, it uses `role=\"dialog\"` (not `role=\"tooltip\"`) and\n * allows interactive content. Content can be hovered without closing.\n */\n\nexport interface HoverCardState {\n open: boolean\n}\n\nexport type HoverCardMsg = { type: 'show' } | { type: 'hide' } | { type: 'setOpen'; open: boolean }\n\nexport interface HoverCardInit {\n open?: boolean\n}\n\nexport function init(opts: HoverCardInit = {}): HoverCardState {\n return { open: opts.open ?? false }\n}\n\nexport function update(state: HoverCardState, msg: HoverCardMsg): [HoverCardState, never[]] {\n switch (msg.type) {\n case 'show':\n return [{ ...state, open: true }, []]\n case 'hide':\n return [{ ...state, open: false }, []]\n case 'setOpen':\n return [{ ...state, open: msg.open }, []]\n }\n}\n\nexport interface HoverCardParts<S> {\n trigger: {\n id: string\n 'aria-haspopup': 'dialog'\n 'aria-controls': string\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'hover-card'\n 'data-part': 'trigger'\n onPointerEnter: (e: PointerEvent) => void\n onPointerLeave: (e: PointerEvent) => void\n onFocus: (e: FocusEvent) => void\n onBlur: (e: FocusEvent) => void\n }\n positioner: {\n 'data-scope': 'hover-card'\n 'data-part': 'positioner'\n style: string\n }\n content: {\n role: 'dialog'\n id: string\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'hover-card'\n 'data-part': 'content'\n onPointerEnter: (e: PointerEvent) => void\n onPointerLeave: (e: PointerEvent) => void\n }\n arrow: {\n 'data-scope': 'hover-card'\n 'data-part': 'arrow'\n }\n}\n\nexport interface ConnectOptions {\n id: string\n /** ms before showing on hover (default: 700). */\n openDelay?: number\n /** ms before hiding after pointer leaves (default: 300). */\n closeDelay?: number\n}\n\nexport function connect<S>(\n get: (s: S) => HoverCardState,\n send: Send<HoverCardMsg>,\n opts: ConnectOptions,\n): HoverCardParts<S> {\n const base = opts.id\n const triggerId = `${base}:trigger`\n const contentId = `${base}:content`\n const openDelay = opts.openDelay ?? 700\n const closeDelay = opts.closeDelay ?? 300\n\n let openTimer: ReturnType<typeof setTimeout> | null = null\n let closeTimer: ReturnType<typeof setTimeout> | null = null\n\n const clearTimers = (): void => {\n if (openTimer) {\n clearTimeout(openTimer)\n openTimer = null\n }\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n }\n\n const scheduleOpen = (): void => {\n clearTimers()\n openTimer = setTimeout(() => {\n openTimer = null\n send({ type: 'show' })\n }, openDelay)\n }\n\n const scheduleClose = (): void => {\n clearTimers()\n closeTimer = setTimeout(() => {\n closeTimer = null\n send({ type: 'hide' })\n }, closeDelay)\n }\n\n return {\n trigger: {\n id: triggerId,\n 'aria-haspopup': 'dialog',\n 'aria-controls': contentId,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'hover-card',\n 'data-part': 'trigger',\n onPointerEnter: scheduleOpen,\n onPointerLeave: scheduleClose,\n onFocus: scheduleOpen,\n onBlur: scheduleClose,\n },\n positioner: {\n 'data-scope': 'hover-card',\n 'data-part': 'positioner',\n style: 'position:absolute;top:0;left:0;',\n },\n content: {\n role: 'dialog',\n id: contentId,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'hover-card',\n 'data-part': 'content',\n onPointerEnter: () => {\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n },\n onPointerLeave: scheduleClose,\n },\n arrow: {\n 'data-scope': 'hover-card',\n 'data-part': 'arrow',\n },\n }\n}\n\nexport interface OverlayOptions<S> {\n get: (s: S) => HoverCardState\n send: Send<HoverCardMsg>\n parts: HoverCardParts<S>\n content: () => Node[]\n placement?: Placement\n offset?: number\n flip?: boolean\n shift?: boolean\n transition?: TransitionOptions\n target?: string | HTMLElement\n arrowSelector?: string\n}\n\nexport function overlay<S>(opts: OverlayOptions<S>): Node[] {\n const target = opts.target ?? 'body'\n const placement = opts.placement ?? 'bottom'\n const offset = opts.offset ?? 8\n const flip = opts.flip !== false\n const shift = opts.shift !== false\n const parts = opts.parts\n const contentId = parts.content.id\n const triggerId = parts.trigger.id\n\n return show<S, HoverCardMsg>({\n when: (s) => opts.get(s).open,\n render: () =>\n portal({\n target,\n render: () => {\n onMount(() => {\n const contentEl = document.getElementById(contentId)\n const triggerEl = document.getElementById(triggerId)\n if (!contentEl || !triggerEl) return\n const positioner = contentEl.closest('[data-part=\"positioner\"]') as HTMLElement | null\n const floatingEl = positioner ?? contentEl\n const arrow = opts.arrowSelector\n ? (contentEl.querySelector(opts.arrowSelector) as HTMLElement | null)\n : null\n return attachFloating({\n anchor: triggerEl,\n floating: floatingEl,\n placement,\n offset,\n flip,\n shift,\n arrow: arrow ?? undefined,\n })\n })\n return [div(parts.positioner, opts.content())]\n },\n }),\n enter: opts.transition?.enter,\n leave: opts.transition?.leave,\n })\n}\n\nexport const hoverCard = { init, update, connect, overlay }\n"]}
|
|
1
|
+
{"version":3,"file":"hover-card.js","sourceRoot":"","sources":["../../src/components/hover-card.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, Signal, TransitionOptions } from '@llui/dom'\nimport { show, portal, onMount, div } from '@llui/dom'\nimport { attachFloating, type Placement } from '../utils/floating.js'\n\n/**\n * Hover card — richer tooltip-like popup triggered by hover or focus.\n * Unlike tooltip, it uses `role=\"dialog\"` (not `role=\"tooltip\"`) and\n * allows interactive content. Content can be hovered without closing.\n */\n\nexport interface HoverCardState {\n open: boolean\n}\n\nexport type HoverCardMsg = { type: 'show' } | { type: 'hide' } | { type: 'setOpen'; open: boolean }\n\nexport interface HoverCardInit {\n open?: boolean\n}\n\nexport function init(opts: HoverCardInit = {}): HoverCardState {\n return { open: opts.open ?? false }\n}\n\nexport function update(state: HoverCardState, msg: HoverCardMsg): [HoverCardState, never[]] {\n switch (msg.type) {\n case 'show':\n return [{ ...state, open: true }, []]\n case 'hide':\n return [{ ...state, open: false }, []]\n case 'setOpen':\n return [{ ...state, open: msg.open }, []]\n }\n}\n\nexport interface HoverCardParts {\n trigger: {\n id: string\n 'aria-haspopup': 'dialog'\n 'aria-controls': string\n 'data-state': Signal<'open' | 'closed'>\n 'data-scope': 'hover-card'\n 'data-part': 'trigger'\n onPointerEnter: (e: PointerEvent) => void\n onPointerLeave: (e: PointerEvent) => void\n onFocus: (e: FocusEvent) => void\n onBlur: (e: FocusEvent) => void\n }\n positioner: {\n 'data-scope': 'hover-card'\n 'data-part': 'positioner'\n style: string\n }\n content: {\n role: 'dialog'\n id: string\n 'data-state': Signal<'open' | 'closed'>\n 'data-scope': 'hover-card'\n 'data-part': 'content'\n onPointerEnter: (e: PointerEvent) => void\n onPointerLeave: (e: PointerEvent) => void\n }\n arrow: {\n 'data-scope': 'hover-card'\n 'data-part': 'arrow'\n }\n}\n\nexport interface ConnectOptions {\n id: string\n /** ms before showing on hover (default: 700). */\n openDelay?: number\n /** ms before hiding after pointer leaves (default: 300). */\n closeDelay?: number\n}\n\nexport function connect(\n state: Signal<HoverCardState>,\n send: Send<HoverCardMsg>,\n opts: ConnectOptions,\n): HoverCardParts {\n const base = opts.id\n const triggerId = `${base}:trigger`\n const contentId = `${base}:content`\n const openDelay = opts.openDelay ?? 700\n const closeDelay = opts.closeDelay ?? 300\n\n let openTimer: ReturnType<typeof setTimeout> | null = null\n let closeTimer: ReturnType<typeof setTimeout> | null = null\n\n const clearTimers = (): void => {\n if (openTimer) {\n clearTimeout(openTimer)\n openTimer = null\n }\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n }\n\n const scheduleOpen = (): void => {\n clearTimers()\n openTimer = setTimeout(() => {\n openTimer = null\n send({ type: 'show' })\n }, openDelay)\n }\n\n const scheduleClose = (): void => {\n clearTimers()\n closeTimer = setTimeout(() => {\n closeTimer = null\n send({ type: 'hide' })\n }, closeDelay)\n }\n\n return {\n trigger: {\n id: triggerId,\n 'aria-haspopup': 'dialog',\n 'aria-controls': contentId,\n 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),\n 'data-scope': 'hover-card',\n 'data-part': 'trigger',\n onPointerEnter: scheduleOpen,\n onPointerLeave: scheduleClose,\n onFocus: scheduleOpen,\n onBlur: scheduleClose,\n },\n positioner: {\n 'data-scope': 'hover-card',\n 'data-part': 'positioner',\n style: 'position:absolute;top:0;left:0;',\n },\n content: {\n role: 'dialog',\n id: contentId,\n 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),\n 'data-scope': 'hover-card',\n 'data-part': 'content',\n onPointerEnter: () => {\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n },\n onPointerLeave: scheduleClose,\n },\n arrow: {\n 'data-scope': 'hover-card',\n 'data-part': 'arrow',\n },\n }\n}\n\nexport interface OverlayOptions {\n state: Signal<HoverCardState>\n send: Send<HoverCardMsg>\n parts: HoverCardParts\n content: () => Node[]\n placement?: Placement\n offset?: number\n flip?: boolean\n shift?: boolean\n transition?: TransitionOptions\n target?: string | HTMLElement\n arrowSelector?: string\n}\n\nexport function overlay(opts: OverlayOptions): Node {\n const rawTarget = opts.target ?? 'body'\n const placement = opts.placement ?? 'bottom'\n const offset = opts.offset ?? 8\n const flip = opts.flip !== false\n const shift = opts.shift !== false\n const parts = opts.parts\n const contentId = parts.content.id\n const triggerId = parts.trigger.id\n\n return show(\n opts.state.map((s) => s.open),\n () => {\n const targetEl =\n typeof rawTarget === 'string'\n ? (document.querySelector(rawTarget) ?? document.body)\n : rawTarget\n return [\n portal(() => {\n onMount(() => {\n const contentEl = document.getElementById(contentId)\n const triggerEl = document.getElementById(triggerId)\n if (!contentEl || !triggerEl) return\n const positioner = contentEl.closest('[data-part=\"positioner\"]') as HTMLElement | null\n const floatingEl = positioner ?? contentEl\n const arrow = opts.arrowSelector\n ? (contentEl.querySelector(opts.arrowSelector) as HTMLElement | null)\n : null\n return attachFloating({\n anchor: triggerEl,\n floating: floatingEl,\n placement,\n offset,\n flip,\n shift,\n arrow: arrow ?? undefined,\n })\n })\n return [div(parts.positioner, opts.content())]\n }, targetEl),\n ]\n },\n )\n}\n\nexport const hoverCard = { init, update, connect, overlay }\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Send } from '@llui/dom';
|
|
1
|
+
import type { Send, Signal } from '@llui/dom';
|
|
2
2
|
/**
|
|
3
3
|
* Image cropper — select a rectangular crop region over an image,
|
|
4
4
|
* optionally constrained to an aspect ratio. The machine tracks the
|
|
@@ -104,13 +104,13 @@ export declare function centerFill(image: {
|
|
|
104
104
|
}, aspectRatio: number | null): CropRect;
|
|
105
105
|
export declare function init(opts?: ImageCropperInit): ImageCropperState;
|
|
106
106
|
export declare function update(state: ImageCropperState, msg: ImageCropperMsg): [ImageCropperState, never[]];
|
|
107
|
-
export interface ImageCropperParts
|
|
107
|
+
export interface ImageCropperParts {
|
|
108
108
|
root: {
|
|
109
109
|
'data-scope': 'image-cropper';
|
|
110
110
|
'data-part': 'root';
|
|
111
|
-
'data-dragging':
|
|
112
|
-
'data-resizing':
|
|
113
|
-
'data-disabled':
|
|
111
|
+
'data-dragging': Signal<'' | undefined>;
|
|
112
|
+
'data-resizing': Signal<'' | undefined>;
|
|
113
|
+
'data-disabled': Signal<'' | undefined>;
|
|
114
114
|
};
|
|
115
115
|
image: {
|
|
116
116
|
'data-scope': 'image-cropper';
|
|
@@ -121,7 +121,7 @@ export interface ImageCropperParts<S> {
|
|
|
121
121
|
cropBox: {
|
|
122
122
|
'data-scope': 'image-cropper';
|
|
123
123
|
'data-part': 'crop-box';
|
|
124
|
-
style:
|
|
124
|
+
style: Signal<string>;
|
|
125
125
|
onPointerDown: (e: PointerEvent) => void;
|
|
126
126
|
};
|
|
127
127
|
resizeHandle: (handle: ResizeHandle) => {
|
|
@@ -132,7 +132,7 @@ export interface ImageCropperParts<S> {
|
|
|
132
132
|
};
|
|
133
133
|
resetTrigger: {
|
|
134
134
|
type: 'button';
|
|
135
|
-
'aria-label': string
|
|
135
|
+
'aria-label': string;
|
|
136
136
|
'data-scope': 'image-cropper';
|
|
137
137
|
'data-part': 'reset-trigger';
|
|
138
138
|
onClick: (e: MouseEvent) => void;
|
|
@@ -141,7 +141,7 @@ export interface ImageCropperParts<S> {
|
|
|
141
141
|
export interface ConnectOptions {
|
|
142
142
|
resetLabel?: string;
|
|
143
143
|
}
|
|
144
|
-
export declare function connect
|
|
144
|
+
export declare function connect(state: Signal<ImageCropperState>, send: Send<ImageCropperMsg>, opts?: ConnectOptions): ImageCropperParts;
|
|
145
145
|
export declare const imageCropper: {
|
|
146
146
|
init: typeof init;
|
|
147
147
|
update: typeof update;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-cropper.d.ts","sourceRoot":"","sources":["../../src/components/image-cropper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"image-cropper.d.ts","sourceRoot":"","sources":["../../src/components/image-cropper.ts"],"names":[],"mappings":"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"}
|
|
@@ -158,15 +158,15 @@ export function update(state, msg) {
|
|
|
158
158
|
return [{ ...state, crop: centerFill(state.image, state.aspectRatio) }, []];
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
export function connect(
|
|
161
|
+
export function connect(state, send, opts = {}) {
|
|
162
162
|
const locale = useContext(LocaleContext);
|
|
163
163
|
return {
|
|
164
164
|
root: {
|
|
165
165
|
'data-scope': 'image-cropper',
|
|
166
166
|
'data-part': 'root',
|
|
167
|
-
'data-dragging': (
|
|
168
|
-
'data-resizing': (
|
|
169
|
-
'data-disabled': (
|
|
167
|
+
'data-dragging': state.map((st) => (st.dragging ? '' : undefined)),
|
|
168
|
+
'data-resizing': state.map((st) => (st.resizing !== null ? '' : undefined)),
|
|
169
|
+
'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),
|
|
170
170
|
},
|
|
171
171
|
image: {
|
|
172
172
|
'data-scope': 'image-cropper',
|
|
@@ -180,8 +180,7 @@ export function connect(get, send, opts = {}) {
|
|
|
180
180
|
cropBox: {
|
|
181
181
|
'data-scope': 'image-cropper',
|
|
182
182
|
'data-part': 'crop-box',
|
|
183
|
-
style: (
|
|
184
|
-
const st = get(s);
|
|
183
|
+
style: state.map((st) => {
|
|
185
184
|
if (st.image.width === 0 || st.image.height === 0)
|
|
186
185
|
return 'display:none;';
|
|
187
186
|
// Express as percentages so the crop box scales with the rendered image.
|
|
@@ -190,7 +189,7 @@ export function connect(get, send, opts = {}) {
|
|
|
190
189
|
const wp = (st.crop.width / st.image.width) * 100;
|
|
191
190
|
const hp = (st.crop.height / st.image.height) * 100;
|
|
192
191
|
return `left:${xp}%;top:${yp}%;width:${wp}%;height:${hp}%;`;
|
|
193
|
-
},
|
|
192
|
+
}),
|
|
194
193
|
onPointerDown: tagSend(send, ['dragStart'], () => send({ type: 'dragStart' })),
|
|
195
194
|
},
|
|
196
195
|
resizeHandle: (handle) => ({
|
|
@@ -201,7 +200,7 @@ export function connect(get, send, opts = {}) {
|
|
|
201
200
|
}),
|
|
202
201
|
resetTrigger: {
|
|
203
202
|
type: 'button',
|
|
204
|
-
'aria-label': opts.resetLabel ??
|
|
203
|
+
'aria-label': opts.resetLabel ?? locale.imageCropper.reset,
|
|
205
204
|
'data-scope': 'image-cropper',
|
|
206
205
|
'data-part': 'reset-trigger',
|
|
207
206
|
onClick: tagSend(send, ['reset'], () => send({ type: 'reset' })),
|