@smwb/ui-solid 0.9.0 → 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.
Files changed (60) hide show
  1. package/README.md +16 -0
  2. package/dist/assets/styles/less/components/floatingWindow/floatingWindow.entry.css +1 -0
  3. package/dist/assets/styles/less/components/treeView/treeView.entry.css +1 -1
  4. package/dist/components/layout/floatingWindow/floatingWindow.d.ts +92 -0
  5. package/dist/components/layout/floatingWindow/floatingWindow.js +417 -0
  6. package/dist/components/layout/floatingWindow/floatingWindow.js.map +1 -0
  7. package/dist/components/layout/floatingWindow/index.d.ts +2 -0
  8. package/dist/connects/rt/index.d.ts +2 -0
  9. package/dist/connects/rt/table/index.d.ts +2 -0
  10. package/dist/connects/rt/table/table.d.ts +48 -0
  11. package/dist/headless/components/layout/floatingWindow/floatingWindow.js +416 -0
  12. package/dist/headless/components/layout/floatingWindow/floatingWindow.js.map +1 -0
  13. package/dist/headless/index.js +314 -308
  14. package/dist/headless/index.js.map +1 -1
  15. package/dist/headless/primitives/createHoverPopover.js +80 -0
  16. package/dist/headless/primitives/createHoverPopover.js.map +1 -0
  17. package/dist/headless/primitives/createRovingTabIndex.js +25 -0
  18. package/dist/headless/primitives/createRovingTabIndex.js.map +1 -0
  19. package/dist/headless/source/components/layout/floatingWindow/floatingWindow.jsx +403 -0
  20. package/dist/headless/source/components/layout/floatingWindow/floatingWindow.jsx.map +1 -0
  21. package/dist/headless/source/components/layout/floatingWindow/index.js +6 -0
  22. package/dist/headless/source/components/layout/floatingWindow/index.js.map +7 -0
  23. package/dist/headless/source/connects/rt/index.js +5 -0
  24. package/dist/headless/source/connects/rt/index.js.map +7 -0
  25. package/dist/headless/source/connects/rt/table/index.js +6 -0
  26. package/dist/headless/source/connects/rt/table/index.js.map +7 -0
  27. package/dist/headless/source/connects/rt/table/table.jsx +183 -0
  28. package/dist/headless/source/connects/rt/table/table.jsx.map +1 -0
  29. package/dist/headless/source/index.js +6 -0
  30. package/dist/headless/source/index.js.map +2 -2
  31. package/dist/headless/source/primitives/createHoverPopover.js +126 -0
  32. package/dist/headless/source/primitives/createHoverPopover.js.map +7 -0
  33. package/dist/headless/source/primitives/createRovingTabIndex.js +45 -0
  34. package/dist/headless/source/primitives/createRovingTabIndex.js.map +7 -0
  35. package/dist/index.d.ts +6 -0
  36. package/dist/index.js +314 -308
  37. package/dist/index.js.map +1 -1
  38. package/dist/primitives/createHoverPopover.d.ts +73 -0
  39. package/dist/primitives/createHoverPopover.js +80 -0
  40. package/dist/primitives/createHoverPopover.js.map +1 -0
  41. package/dist/primitives/createRovingTabIndex.d.ts +26 -0
  42. package/dist/primitives/createRovingTabIndex.js +25 -0
  43. package/dist/primitives/createRovingTabIndex.js.map +1 -0
  44. package/dist/source/components/layout/floatingWindow/floatingWindow.jsx +404 -0
  45. package/dist/source/components/layout/floatingWindow/floatingWindow.jsx.map +1 -0
  46. package/dist/source/components/layout/floatingWindow/index.js +6 -0
  47. package/dist/source/components/layout/floatingWindow/index.js.map +7 -0
  48. package/dist/source/connects/rt/index.js +5 -0
  49. package/dist/source/connects/rt/index.js.map +7 -0
  50. package/dist/source/connects/rt/table/index.js +6 -0
  51. package/dist/source/connects/rt/table/index.js.map +7 -0
  52. package/dist/source/connects/rt/table/table.jsx +183 -0
  53. package/dist/source/connects/rt/table/table.jsx.map +1 -0
  54. package/dist/source/index.js +6 -0
  55. package/dist/source/index.js.map +2 -2
  56. package/dist/source/primitives/createHoverPopover.js +126 -0
  57. package/dist/source/primitives/createHoverPopover.js.map +7 -0
  58. package/dist/source/primitives/createRovingTabIndex.js +45 -0
  59. package/dist/source/primitives/createRovingTabIndex.js.map +7 -0
  60. package/package.json +25 -6
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,73 @@
1
+ import { type Accessor, type JSX } from "solid-js";
2
+ import type { Middleware } from "@floating-ui/dom";
3
+ import { type Placement } from "../utils/floating";
4
+ export interface CreateHoverPopoverOptions {
5
+ /** Placement of the popover relative to its anchor. Default `"bottom-start"`. */
6
+ placement?: Placement;
7
+ /** Offset (px) applied on both axes between the anchor and the popover. Default `4`. */
8
+ offsetPx?: number;
9
+ /** Delay (ms) before opening after pointer enter. Default `0`. */
10
+ openDelay?: number;
11
+ /** Delay (ms) before closing after pointer leave. Default `0`. */
12
+ closeDelay?: number;
13
+ /** Extra floating-ui middleware appended after the smwb defaults. */
14
+ middleware?: Middleware[];
15
+ }
16
+ /** A pointer position in viewport (client) coordinates. */
17
+ export interface HoverPopoverPoint {
18
+ x: number;
19
+ y: number;
20
+ }
21
+ export interface HoverPopoverReferenceProps {
22
+ onPointerEnter: (event: PointerEvent) => void;
23
+ onPointerMove: (event: PointerEvent) => void;
24
+ onPointerLeave: (event: PointerEvent) => void;
25
+ }
26
+ export interface HoverPopoverFloatingProps {
27
+ ref: (node: HTMLElement) => void;
28
+ style: JSX.CSSProperties;
29
+ onPointerEnter: () => void;
30
+ onPointerLeave: () => void;
31
+ }
32
+ export interface HoverPopoverState {
33
+ /** Whether the popover is currently open. */
34
+ open: Accessor<boolean>;
35
+ /**
36
+ * Pointer handlers for the trigger element(s). Spread on a single anchor, or on EVERY
37
+ * row of a list/table to share one popover across many triggers. By default the popover
38
+ * is anchored to the cursor position frozen when it opens. Pass your own handlers to
39
+ * compose them (e.g. to mark which row is active).
40
+ */
41
+ getReferenceProps: (userHandlers?: Partial<HoverPopoverReferenceProps>) => HoverPopoverReferenceProps;
42
+ /** Props for the single floating element; keeps it open while it is hovered. */
43
+ getFloatingProps: (userProps?: {
44
+ style?: JSX.CSSProperties;
45
+ }) => HoverPopoverFloatingProps;
46
+ /** Anchor the popover to a real element instead of the cursor (`null` clears it). */
47
+ setAnchorEl: (element: Element | null) => void;
48
+ /** Anchor the popover to an explicit point, e.g. an external cursor source. */
49
+ setVirtualAnchor: (point: HoverPopoverPoint) => void;
50
+ /** Open immediately, ignoring `openDelay`. */
51
+ openNow: () => void;
52
+ /** Open after `openDelay`. */
53
+ scheduleOpen: () => void;
54
+ /** Close after `closeDelay`. */
55
+ scheduleClose: () => void;
56
+ /** Close immediately. */
57
+ close: () => void;
58
+ }
59
+ /**
60
+ * Headless hover-popover positioning — the Solid twin of ui-react's `useHoverPopover`.
61
+ *
62
+ * Wraps {@link createFloating} with the smwb placement / offset / flip / shift conventions
63
+ * but imposes NO DOM structure: spread `getReferenceProps()` on any trigger (including a
64
+ * `<tr>`, which the wrapper-based `<Tooltip>` cannot do) and `getFloatingProps()` on a
65
+ * single floating element you render yourself.
66
+ *
67
+ * The default anchor is the cursor point frozen when the popover opens (a floating-ui
68
+ * virtual element), so ONE instance can serve a whole table/list — call
69
+ * `getReferenceProps()` on every row and render one shared popover instead of mounting one
70
+ * floating engine per row. Use `setAnchorEl` to anchor to a real element instead.
71
+ */
72
+ export declare function createHoverPopover(options?: CreateHoverPopoverOptions): HoverPopoverState;
73
+ export default createHoverPopover;
@@ -0,0 +1,80 @@
1
+ import { createSignal as F, createMemo as y, onCleanup as D, createEffect as x } from "solid-js";
2
+ import { offset as v, flip as L, shift as w } from "@floating-ui/dom";
3
+ import { resolvePlacement as M } from "../utils/floating.js";
4
+ import { createFloating as R } from "./createFloating.js";
5
+ const _ = "bottom-start", C = 4, S = 8, X = ({ x: t, y: l }) => ({ x: t, y: l, top: l, left: t, right: t, bottom: l, width: 0, height: 0 });
6
+ function G(t = {}) {
7
+ const l = t.offsetPx ?? C, P = t.openDelay ?? 0, g = t.closeDelay ?? 0, [h, n] = F(!1);
8
+ let f = { x: 0, y: 0 }, u = { x: 0, y: 0 }, c = null, s = null, i = null;
9
+ const d = y(() => M(t.placement ?? _)), a = R({
10
+ placement: () => d().placement,
11
+ middleware: () => [
12
+ v({ mainAxis: l, crossAxis: l }),
13
+ d().autoMiddleware ?? L(),
14
+ w({ padding: S }),
15
+ ...t.middleware ?? []
16
+ ]
17
+ }), T = { getBoundingClientRect: () => X(u) }, r = () => {
18
+ s !== null && (clearTimeout(s), s = null), i !== null && (clearTimeout(i), i = null);
19
+ };
20
+ D(r), x(() => {
21
+ h() && (a.setReference(c ?? T), a.update());
22
+ });
23
+ const m = () => {
24
+ c === null && (u = f);
25
+ }, A = () => {
26
+ r(), m(), n(!0);
27
+ }, E = () => {
28
+ if (r(), P <= 0) {
29
+ m(), n(!0);
30
+ return;
31
+ }
32
+ s = setTimeout(() => {
33
+ m(), n(!0);
34
+ }, P);
35
+ }, p = () => {
36
+ if (r(), g <= 0) {
37
+ n(!1);
38
+ return;
39
+ }
40
+ i = setTimeout(() => n(!1), g);
41
+ };
42
+ return {
43
+ open: h,
44
+ getReferenceProps: (o) => ({
45
+ onPointerEnter: (e) => {
46
+ o?.onPointerEnter?.(e), f = { x: e.clientX, y: e.clientY }, E();
47
+ },
48
+ onPointerMove: (e) => {
49
+ o?.onPointerMove?.(e), f = { x: e.clientX, y: e.clientY };
50
+ },
51
+ onPointerLeave: (e) => {
52
+ o?.onPointerLeave?.(e), p();
53
+ }
54
+ }),
55
+ getFloatingProps: (o) => ({
56
+ ref: (e) => a.setFloating(e),
57
+ style: { ...a.floatingStyles(), ...o?.style ?? {} },
58
+ onPointerEnter: () => {
59
+ r(), n(!0);
60
+ },
61
+ onPointerLeave: p
62
+ }),
63
+ setAnchorEl: (o) => {
64
+ c = o;
65
+ },
66
+ setVirtualAnchor: (o) => {
67
+ c = null, u = o;
68
+ },
69
+ openNow: A,
70
+ scheduleOpen: E,
71
+ scheduleClose: p,
72
+ close: () => {
73
+ r(), n(!1);
74
+ }
75
+ };
76
+ }
77
+ export {
78
+ G as createHoverPopover
79
+ };
80
+ //# sourceMappingURL=createHoverPopover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createHoverPopover.js","sources":["../../src/primitives/createHoverPopover.ts"],"sourcesContent":["import { type Accessor, type JSX, createEffect, createMemo, createSignal, onCleanup } from \"solid-js\";\nimport { flip, offset, shift } from \"@floating-ui/dom\";\nimport type { Middleware, VirtualElement } from \"@floating-ui/dom\";\nimport { type Placement, resolvePlacement } from \"../utils/floating\";\nimport { createFloating } from \"./createFloating\";\n\nexport interface CreateHoverPopoverOptions {\n /** Placement of the popover relative to its anchor. Default `\"bottom-start\"`. */\n placement?: Placement;\n /** Offset (px) applied on both axes between the anchor and the popover. Default `4`. */\n offsetPx?: number;\n /** Delay (ms) before opening after pointer enter. Default `0`. */\n openDelay?: number;\n /** Delay (ms) before closing after pointer leave. Default `0`. */\n closeDelay?: number;\n /** Extra floating-ui middleware appended after the smwb defaults. */\n middleware?: Middleware[];\n}\n\n/** A pointer position in viewport (client) coordinates. */\nexport interface HoverPopoverPoint {\n x: number;\n y: number;\n}\n\nexport interface HoverPopoverReferenceProps {\n onPointerEnter: (event: PointerEvent) => void;\n onPointerMove: (event: PointerEvent) => void;\n onPointerLeave: (event: PointerEvent) => void;\n}\n\nexport interface HoverPopoverFloatingProps {\n ref: (node: HTMLElement) => void;\n style: JSX.CSSProperties;\n onPointerEnter: () => void;\n onPointerLeave: () => void;\n}\n\nexport interface HoverPopoverState {\n /** Whether the popover is currently open. */\n open: Accessor<boolean>;\n /**\n * Pointer handlers for the trigger element(s). Spread on a single anchor, or on EVERY\n * row of a list/table to share one popover across many triggers. By default the popover\n * is anchored to the cursor position frozen when it opens. Pass your own handlers to\n * compose them (e.g. to mark which row is active).\n */\n getReferenceProps: (userHandlers?: Partial<HoverPopoverReferenceProps>) => HoverPopoverReferenceProps;\n /** Props for the single floating element; keeps it open while it is hovered. */\n getFloatingProps: (userProps?: { style?: JSX.CSSProperties }) => HoverPopoverFloatingProps;\n /** Anchor the popover to a real element instead of the cursor (`null` clears it). */\n setAnchorEl: (element: Element | null) => void;\n /** Anchor the popover to an explicit point, e.g. an external cursor source. */\n setVirtualAnchor: (point: HoverPopoverPoint) => void;\n /** Open immediately, ignoring `openDelay`. */\n openNow: () => void;\n /** Open after `openDelay`. */\n scheduleOpen: () => void;\n /** Close after `closeDelay`. */\n scheduleClose: () => void;\n /** Close immediately. */\n close: () => void;\n}\n\nconst DEFAULT_PLACEMENT: Placement = \"bottom-start\";\nconst DEFAULT_OFFSET_PX = 4;\nconst SHIFT_PADDING_PX = 8;\n\nconst rectFromPoint = ({ x, y }: HoverPopoverPoint): DOMRect =>\n ({ x, y, top: y, left: x, right: x, bottom: y, width: 0, height: 0 }) as DOMRect;\n\n/**\n * Headless hover-popover positioning — the Solid twin of ui-react's `useHoverPopover`.\n *\n * Wraps {@link createFloating} with the smwb placement / offset / flip / shift conventions\n * but imposes NO DOM structure: spread `getReferenceProps()` on any trigger (including a\n * `<tr>`, which the wrapper-based `<Tooltip>` cannot do) and `getFloatingProps()` on a\n * single floating element you render yourself.\n *\n * The default anchor is the cursor point frozen when the popover opens (a floating-ui\n * virtual element), so ONE instance can serve a whole table/list — call\n * `getReferenceProps()` on every row and render one shared popover instead of mounting one\n * floating engine per row. Use `setAnchorEl` to anchor to a real element instead.\n */\nexport function createHoverPopover(options: CreateHoverPopoverOptions = {}): HoverPopoverState {\n const offsetPx = options.offsetPx ?? DEFAULT_OFFSET_PX;\n const openDelay = options.openDelay ?? 0;\n const closeDelay = options.closeDelay ?? 0;\n\n const [open, setOpen] = createSignal(false);\n\n let cursor: HoverPopoverPoint = { x: 0, y: 0 };\n let anchor: HoverPopoverPoint = { x: 0, y: 0 };\n let anchorEl: Element | null = null;\n let openTimer: ReturnType<typeof setTimeout> | null = null;\n let closeTimer: ReturnType<typeof setTimeout> | null = null;\n\n const resolved = createMemo(() => resolvePlacement(options.placement ?? DEFAULT_PLACEMENT));\n\n const floating = createFloating({\n placement: () => resolved().placement,\n middleware: () => [\n offset({ mainAxis: offsetPx, crossAxis: offsetPx }),\n resolved().autoMiddleware ?? flip(),\n shift({ padding: SHIFT_PADDING_PX }),\n ...(options.middleware ?? []),\n ],\n });\n\n // The virtual reference reads `anchor` LAZILY, so freezing the cursor is just a field\n // write — no need to rebuild the reference on every pointer move.\n const virtualReference: VirtualElement = { getBoundingClientRect: () => rectFromPoint(anchor) };\n\n const clearTimers = (): void => {\n if (openTimer !== null) {\n clearTimeout(openTimer);\n openTimer = null;\n }\n if (closeTimer !== null) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n };\n\n onCleanup(clearTimers);\n\n // Apply the active anchor (element or frozen cursor) whenever the popover opens;\n // createFloating's autoUpdate keeps it positioned while the floating element is mounted.\n createEffect(() => {\n if (!open()) return;\n floating.setReference(anchorEl ?? virtualReference);\n floating.update();\n });\n\n const freezeAnchor = (): void => {\n if (anchorEl === null) anchor = cursor;\n };\n\n const openNow = (): void => {\n clearTimers();\n freezeAnchor();\n setOpen(true);\n };\n\n const scheduleOpen = (): void => {\n clearTimers();\n if (openDelay <= 0) {\n freezeAnchor();\n setOpen(true);\n return;\n }\n openTimer = setTimeout(() => {\n freezeAnchor();\n setOpen(true);\n }, openDelay);\n };\n\n const scheduleClose = (): void => {\n clearTimers();\n if (closeDelay <= 0) {\n setOpen(false);\n return;\n }\n closeTimer = setTimeout(() => setOpen(false), closeDelay);\n };\n\n const close = (): void => {\n clearTimers();\n setOpen(false);\n };\n\n const setVirtualAnchor = (point: HoverPopoverPoint): void => {\n anchorEl = null;\n anchor = point;\n };\n\n const setAnchorEl = (element: Element | null): void => {\n anchorEl = element;\n };\n\n const getReferenceProps = (userHandlers?: Partial<HoverPopoverReferenceProps>): HoverPopoverReferenceProps => ({\n onPointerEnter: (event) => {\n userHandlers?.onPointerEnter?.(event);\n cursor = { x: event.clientX, y: event.clientY };\n scheduleOpen();\n },\n onPointerMove: (event) => {\n userHandlers?.onPointerMove?.(event);\n cursor = { x: event.clientX, y: event.clientY };\n },\n onPointerLeave: (event) => {\n userHandlers?.onPointerLeave?.(event);\n scheduleClose();\n },\n });\n\n const getFloatingProps = (userProps?: { style?: JSX.CSSProperties }): HoverPopoverFloatingProps => ({\n ref: (node) => floating.setFloating(node),\n style: { ...floating.floatingStyles(), ...(userProps?.style ?? {}) },\n onPointerEnter: () => {\n clearTimers();\n setOpen(true);\n },\n onPointerLeave: scheduleClose,\n });\n\n return {\n open,\n getReferenceProps,\n getFloatingProps,\n setAnchorEl,\n setVirtualAnchor,\n openNow,\n scheduleOpen,\n scheduleClose,\n close,\n };\n}\n\nexport default createHoverPopover;\n"],"names":["DEFAULT_PLACEMENT","DEFAULT_OFFSET_PX","SHIFT_PADDING_PX","rectFromPoint","x","y","createHoverPopover","options","offsetPx","openDelay","closeDelay","open","setOpen","createSignal","cursor","anchor","anchorEl","openTimer","closeTimer","resolved","createMemo","resolvePlacement","floating","createFloating","offset","flip","shift","virtualReference","clearTimers","onCleanup","createEffect","freezeAnchor","openNow","scheduleOpen","scheduleClose","userHandlers","event","userProps","node","element","point"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { JSX } from "solid-js";
2
+ export interface CreateRovingTabIndexOptions {
3
+ /** Number of focusable items. */
4
+ count: number | (() => number);
5
+ /** Current active index. */
6
+ activeIndex: number | (() => number);
7
+ /** Called with the next index when navigation keys are pressed. */
8
+ onMove: (nextIndex: number) => void;
9
+ /** Arrow-key axis. */
10
+ orientation?: "horizontal" | "vertical" | "both";
11
+ /** Wrap around the ends (default true). */
12
+ loop?: boolean;
13
+ /** Optional predicate to skip disabled items. */
14
+ isDisabled?: (index: number) => boolean;
15
+ }
16
+ /**
17
+ * Keyboard navigation for composite widgets (tabs, menus, trees, pagination) — the Solid
18
+ * twin of ui-react's `useRovingTabIndex`. Returns an `onKeyDown` handler implementing
19
+ * Arrow/Home/End with optional looping and disabled-skipping. The consumer owns focus and
20
+ * activation.
21
+ *
22
+ * `count`/`activeIndex` accept an accessor so the handler — attached once — always reads
23
+ * the live value instead of the one captured when it was created.
24
+ */
25
+ export declare function createRovingTabIndex(options: CreateRovingTabIndexOptions): JSX.EventHandler<HTMLElement, KeyboardEvent>;
26
+ export default createRovingTabIndex;
@@ -0,0 +1,25 @@
1
+ const h = (o) => typeof o == "function" ? o() : o;
2
+ function w(o) {
3
+ return (e) => {
4
+ const r = h(o.count);
5
+ if (r === 0) return;
6
+ const a = h(o.activeIndex), i = o.orientation ?? "horizontal", d = o.loop ?? !0, l = i === "horizontal" || i === "both", s = i === "vertical" || i === "both", f = l && e.key === "ArrowRight" || s && e.key === "ArrowDown", y = l && e.key === "ArrowLeft" || s && e.key === "ArrowUp";
7
+ let t = null;
8
+ if (f ? t = a + 1 : y ? t = a - 1 : e.key === "Home" ? t = 0 : e.key === "End" && (t = r - 1), t === null) return;
9
+ const u = (n) => d ? (n + r) % r : Math.max(0, Math.min(r - 1, n));
10
+ t = u(t);
11
+ const c = o.isDisabled;
12
+ if (c) {
13
+ let n = 0;
14
+ const k = f || e.key === "Home" ? 1 : -1;
15
+ for (; c(t) && n < r; )
16
+ t = u(t + k), n += 1;
17
+ if (c(t)) return;
18
+ }
19
+ e.preventDefault(), o.onMove(t);
20
+ };
21
+ }
22
+ export {
23
+ w as createRovingTabIndex
24
+ };
25
+ //# sourceMappingURL=createRovingTabIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createRovingTabIndex.js","sources":["../../src/primitives/createRovingTabIndex.ts"],"sourcesContent":["import type { JSX } from \"solid-js\";\n\nexport interface CreateRovingTabIndexOptions {\n /** Number of focusable items. */\n count: number | (() => number);\n /** Current active index. */\n activeIndex: number | (() => number);\n /** Called with the next index when navigation keys are pressed. */\n onMove: (nextIndex: number) => void;\n /** Arrow-key axis. */\n orientation?: \"horizontal\" | \"vertical\" | \"both\";\n /** Wrap around the ends (default true). */\n loop?: boolean;\n /** Optional predicate to skip disabled items. */\n isDisabled?: (index: number) => boolean;\n}\n\nconst read = (value: number | (() => number)): number => (typeof value === \"function\" ? value() : value);\n\n/**\n * Keyboard navigation for composite widgets (tabs, menus, trees, pagination) — the Solid\n * twin of ui-react's `useRovingTabIndex`. Returns an `onKeyDown` handler implementing\n * Arrow/Home/End with optional looping and disabled-skipping. The consumer owns focus and\n * activation.\n *\n * `count`/`activeIndex` accept an accessor so the handler — attached once — always reads\n * the live value instead of the one captured when it was created.\n */\nexport function createRovingTabIndex(\n options: CreateRovingTabIndexOptions,\n): JSX.EventHandler<HTMLElement, KeyboardEvent> {\n return (event) => {\n const count = read(options.count);\n if (count === 0) return;\n\n const activeIndex = read(options.activeIndex);\n const orientation = options.orientation ?? \"horizontal\";\n const loop = options.loop ?? true;\n const horiz = orientation === \"horizontal\" || orientation === \"both\";\n const vert = orientation === \"vertical\" || orientation === \"both\";\n const next = (horiz && event.key === \"ArrowRight\") || (vert && event.key === \"ArrowDown\");\n const prev = (horiz && event.key === \"ArrowLeft\") || (vert && event.key === \"ArrowUp\");\n\n let target: number | null = null;\n if (next) {\n target = activeIndex + 1;\n } else if (prev) {\n target = activeIndex - 1;\n } else if (event.key === \"Home\") {\n target = 0;\n } else if (event.key === \"End\") {\n target = count - 1;\n }\n if (target === null) return;\n\n const clamp = (i: number): number => (loop ? (i + count) % count : Math.max(0, Math.min(count - 1, i)));\n target = clamp(target);\n\n const isDisabled = options.isDisabled;\n if (isDisabled) {\n let guard = 0;\n const step = next || event.key === \"Home\" ? 1 : -1;\n while (isDisabled(target) && guard < count) {\n target = clamp(target + step);\n guard += 1;\n }\n if (isDisabled(target)) return;\n }\n\n event.preventDefault();\n options.onMove(target);\n };\n}\n\nexport default createRovingTabIndex;\n"],"names":["read","value","createRovingTabIndex","options","event","count","activeIndex","orientation","loop","horiz","vert","next","prev","target","clamp","i","isDisabled","guard","step"],"mappings":"AAiBA,MAAMA,IAAO,CAACC,MAA4C,OAAOA,KAAU,aAAaA,MAAUA;AAW3F,SAASC,EACdC,GAC8C;AAC9C,SAAO,CAACC,MAAU;AAChB,UAAMC,IAAQL,EAAKG,EAAQ,KAAK;AAChC,QAAIE,MAAU,EAAG;AAEjB,UAAMC,IAAcN,EAAKG,EAAQ,WAAW,GACtCI,IAAcJ,EAAQ,eAAe,cACrCK,IAAOL,EAAQ,QAAQ,IACvBM,IAAQF,MAAgB,gBAAgBA,MAAgB,QACxDG,IAAOH,MAAgB,cAAcA,MAAgB,QACrDI,IAAQF,KAASL,EAAM,QAAQ,gBAAkBM,KAAQN,EAAM,QAAQ,aACvEQ,IAAQH,KAASL,EAAM,QAAQ,eAAiBM,KAAQN,EAAM,QAAQ;AAE5E,QAAIS,IAAwB;AAU5B,QATIF,IACFE,IAASP,IAAc,IACdM,IACTC,IAASP,IAAc,IACdF,EAAM,QAAQ,SACvBS,IAAS,IACAT,EAAM,QAAQ,UACvBS,IAASR,IAAQ,IAEfQ,MAAW,KAAM;AAErB,UAAMC,IAAQ,CAACC,MAAuBP,KAAQO,IAAIV,KAASA,IAAQ,KAAK,IAAI,GAAG,KAAK,IAAIA,IAAQ,GAAGU,CAAC,CAAC;AACrG,IAAAF,IAASC,EAAMD,CAAM;AAErB,UAAMG,IAAab,EAAQ;AAC3B,QAAIa,GAAY;AACd,UAAIC,IAAQ;AACZ,YAAMC,IAAOP,KAAQP,EAAM,QAAQ,SAAS,IAAI;AAChD,aAAOY,EAAWH,CAAM,KAAKI,IAAQZ;AACnC,QAAAQ,IAASC,EAAMD,IAASK,CAAI,GAC5BD,KAAS;AAEX,UAAID,EAAWH,CAAM,EAAG;AAAA,IAC1B;AAEA,IAAAT,EAAM,eAAA,GACND,EAAQ,OAAOU,CAAM;AAAA,EACvB;AACF;"}
@@ -0,0 +1,404 @@
1
+ import "@smwb/ui-styles/less/components/floatingWindow/floatingWindow.entry.less";
2
+ import {
3
+ For,
4
+ Show,
5
+ createEffect,
6
+ createMemo,
7
+ createSignal,
8
+ mergeProps,
9
+ onCleanup,
10
+ splitProps
11
+ } from "solid-js";
12
+ import { Portal, isServer } from "solid-js/web";
13
+ import cn from "clsx";
14
+ import { Icon } from "../../base/icon";
15
+ import { createCssTransition } from "../../../primitives/createCssTransition";
16
+ import { createControllableState } from "../../../primitives/createControllableState";
17
+ import { createId } from "../../../primitives/createId";
18
+ import { mergeRefs } from "../../../primitives/mergeRefs";
19
+ const RESIZE_DIRS = {
20
+ n: { dx: 0, dy: 1, dw: 0, dh: -1 },
21
+ s: { dx: 0, dy: 0, dw: 0, dh: 1 },
22
+ e: { dx: 0, dy: 0, dw: 1, dh: 0 },
23
+ w: { dx: 1, dy: 0, dw: -1, dh: 0 },
24
+ ne: { dx: 0, dy: 1, dw: 1, dh: -1 },
25
+ nw: { dx: 1, dy: 1, dw: -1, dh: -1 },
26
+ se: { dx: 0, dy: 0, dw: 1, dh: 1 },
27
+ sw: { dx: 1, dy: 0, dw: -1, dh: 1 }
28
+ };
29
+ const RESIZE_ORDER = ["n", "s", "e", "w", "ne", "nw", "se", "sw"];
30
+ const viewportOf = () => typeof window === "undefined" ? { width: 0, height: 0 } : { width: window.innerWidth, height: window.innerHeight };
31
+ function FloatingWindow(props) {
32
+ const merged = mergeProps(
33
+ {
34
+ minWidth: 200,
35
+ minHeight: 120,
36
+ keepVisible: 56,
37
+ moveStep: 24,
38
+ resizeStep: 24,
39
+ collapsible: true,
40
+ movable: true,
41
+ resizable: true,
42
+ closeOnEsc: false,
43
+ defaultPosition: { x: 24, y: 24 },
44
+ defaultSize: { width: 360, height: 420 },
45
+ defaultCollapsed: false,
46
+ moveHandleAriaLabel: "Move window",
47
+ resizeHandleAriaLabel: "Resize window",
48
+ closeAriaLabel: "Close window",
49
+ collapseAriaLabel: "Collapse window",
50
+ expandAriaLabel: "Expand window"
51
+ },
52
+ props
53
+ );
54
+ const [local, rest] = splitProps(merged, [
55
+ "open",
56
+ "title",
57
+ "headerActions",
58
+ "position",
59
+ "defaultPosition",
60
+ "onPositionChange",
61
+ "onMoveEnd",
62
+ "size",
63
+ "defaultSize",
64
+ "onResize",
65
+ "onResizeEnd",
66
+ "minWidth",
67
+ "minHeight",
68
+ "maxWidth",
69
+ "maxHeight",
70
+ "keepVisible",
71
+ "moveStep",
72
+ "resizeStep",
73
+ "zIndex",
74
+ "onActivate",
75
+ "collapsed",
76
+ "defaultCollapsed",
77
+ "onCollapsedChange",
78
+ "collapsible",
79
+ "movable",
80
+ "resizable",
81
+ "closeOnEsc",
82
+ "onClose",
83
+ "moveHandleAriaLabel",
84
+ "resizeHandleAriaLabel",
85
+ "closeAriaLabel",
86
+ "collapseAriaLabel",
87
+ "expandAriaLabel",
88
+ "class",
89
+ "style",
90
+ "children",
91
+ "ref"
92
+ ]);
93
+ let rootEl;
94
+ const titleId = createId(void 0, "smwb-floating-window-title");
95
+ const transition = createCssTransition({
96
+ in: () => local.open,
97
+ timeout: { enter: 120, exit: 120 },
98
+ classNames: { enterDone: "smwb-floating-window_entered" },
99
+ appear: true
100
+ });
101
+ const [position, setPosition] = createControllableState({
102
+ value: () => local.position,
103
+ defaultValue: local.defaultPosition,
104
+ onChange: (next) => local.onPositionChange?.(next)
105
+ });
106
+ const [size, setSize] = createControllableState({
107
+ value: () => local.size,
108
+ defaultValue: local.defaultSize,
109
+ onChange: (next) => local.onResize?.(next)
110
+ });
111
+ const [collapsed, setCollapsed] = createControllableState({
112
+ value: () => local.collapsed,
113
+ defaultValue: local.defaultCollapsed,
114
+ onChange: (next) => local.onCollapsedChange?.(next)
115
+ });
116
+ const clampRect = (rect2, vp) => {
117
+ const maxW = local.maxWidth ?? vp.width;
118
+ const maxH = local.maxHeight ?? vp.height;
119
+ const width = Math.max(local.minWidth, Math.min(maxW, rect2.width));
120
+ const height = Math.max(local.minHeight, Math.min(maxH, rect2.height));
121
+ const keep = Math.min(local.keepVisible, width);
122
+ const x = Math.max(keep - width, Math.min(vp.width - keep, rect2.x));
123
+ const y = Math.max(0, Math.min(Math.max(0, vp.height - keep), rect2.y));
124
+ return { x, y, width, height };
125
+ };
126
+ const fitRect = (rect2, vp) => {
127
+ const clamped = clampRect(rect2, vp);
128
+ return {
129
+ ...clamped,
130
+ x: Math.max(0, Math.min(clamped.x, vp.width - clamped.width)),
131
+ y: Math.max(0, Math.min(clamped.y, vp.height - clamped.height))
132
+ };
133
+ };
134
+ const [placed, setPlaced] = createSignal(false);
135
+ const rect = createMemo(() => {
136
+ const current = { x: position().x, y: position().y, width: size().width, height: size().height };
137
+ return placed() ? clampRect(current, viewportOf()) : fitRect(current, viewportOf());
138
+ });
139
+ const commitRect = (next, gesture = true) => {
140
+ if (gesture) setPlaced(true);
141
+ const clamped = clampRect(next, viewportOf());
142
+ const pos = position();
143
+ const dim = size();
144
+ if (clamped.x !== pos.x || clamped.y !== pos.y) setPosition({ x: clamped.x, y: clamped.y });
145
+ if (clamped.width !== dim.width || clamped.height !== dim.height) {
146
+ setSize({ width: clamped.width, height: clamped.height });
147
+ }
148
+ };
149
+ createEffect(() => {
150
+ if (!local.open) setPlaced(false);
151
+ });
152
+ createEffect(() => {
153
+ if (isServer || !local.open) return;
154
+ const onViewportResize = () => commitRect(rect(), false);
155
+ window.addEventListener("resize", onViewportResize);
156
+ onCleanup(() => window.removeEventListener("resize", onViewportResize));
157
+ });
158
+ createEffect(() => {
159
+ if (isServer || !local.open || !local.closeOnEsc || !local.onClose) return;
160
+ const onKeyDown = (event) => {
161
+ if (event.key !== "Escape") return;
162
+ if (!rootEl || !rootEl.contains(document.activeElement)) return;
163
+ local.onClose?.();
164
+ };
165
+ document.addEventListener("keydown", onKeyDown);
166
+ onCleanup(() => document.removeEventListener("keydown", onKeyDown));
167
+ });
168
+ const activate = () => {
169
+ local.onActivate?.();
170
+ if (rootEl && !rootEl.contains(document.activeElement)) rootEl.focus({ preventScroll: true });
171
+ };
172
+ let move = null;
173
+ const onMoveHandlePointerDown = (event) => {
174
+ if (!local.movable) return;
175
+ if (event.target?.closest("button,[data-no-drag]")) return;
176
+ event.preventDefault();
177
+ const current = rect();
178
+ move = { px: event.clientX, py: event.clientY, x: current.x, y: current.y };
179
+ try {
180
+ event.currentTarget.setPointerCapture?.(event.pointerId);
181
+ } catch {
182
+ }
183
+ };
184
+ const onMoveHandlePointerMove = (event) => {
185
+ if (!move) return;
186
+ const current = rect();
187
+ commitRect({
188
+ ...current,
189
+ x: move.x + event.clientX - move.px,
190
+ y: move.y + event.clientY - move.py
191
+ });
192
+ };
193
+ const endMove = (event) => {
194
+ if (move) {
195
+ move = null;
196
+ const current = rect();
197
+ local.onMoveEnd?.({ x: current.x, y: current.y });
198
+ }
199
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId)) {
200
+ event.currentTarget.releasePointerCapture?.(event.pointerId);
201
+ }
202
+ };
203
+ let resize = null;
204
+ const onResizePointerDown = (dir, event) => {
205
+ event.preventDefault();
206
+ event.stopPropagation();
207
+ resize = { dir, px: event.clientX, py: event.clientY, rect: rect() };
208
+ activate();
209
+ try {
210
+ event.currentTarget.setPointerCapture?.(event.pointerId);
211
+ } catch {
212
+ }
213
+ };
214
+ const onResizePointerMove = (event) => {
215
+ if (!resize) return;
216
+ const sign = RESIZE_DIRS[resize.dir];
217
+ const dx = event.clientX - resize.px;
218
+ const dy = event.clientY - resize.py;
219
+ const start = resize.rect;
220
+ const vp = viewportOf();
221
+ const maxW = local.maxWidth ?? vp.width;
222
+ const maxH = local.maxHeight ?? vp.height;
223
+ const width = Math.min(maxW, Math.max(local.minWidth, start.width + sign.dw * dx));
224
+ const height = Math.min(maxH, Math.max(local.minHeight, start.height + sign.dh * dy));
225
+ commitRect({
226
+ x: sign.dx ? start.x + start.width - width : start.x,
227
+ y: sign.dy ? start.y + start.height - height : start.y,
228
+ width,
229
+ height
230
+ });
231
+ };
232
+ const endResize = (event) => {
233
+ if (resize) {
234
+ resize = null;
235
+ const current = rect();
236
+ local.onResizeEnd?.({ width: current.width, height: current.height });
237
+ }
238
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId)) {
239
+ event.currentTarget.releasePointerCapture?.(event.pointerId);
240
+ }
241
+ };
242
+ const endKeyboardGesture = (resized) => {
243
+ const current = rect();
244
+ if (resized) local.onResizeEnd?.({ width: current.width, height: current.height });
245
+ else local.onMoveEnd?.({ x: current.x, y: current.y });
246
+ };
247
+ const onMoveHandleKeyDown = (event) => {
248
+ const current = rect();
249
+ const step = event.shiftKey ? local.resizeStep : local.moveStep;
250
+ const delta = {
251
+ ArrowLeft: [-step, 0],
252
+ ArrowRight: [step, 0],
253
+ ArrowUp: [0, -step],
254
+ ArrowDown: [0, step]
255
+ };
256
+ const d = delta[event.key];
257
+ if (!d) return;
258
+ event.preventDefault();
259
+ if (event.shiftKey) {
260
+ commitRect({ ...current, width: current.width + d[0], height: current.height + d[1] });
261
+ } else {
262
+ commitRect({ ...current, x: current.x + d[0], y: current.y + d[1] });
263
+ }
264
+ endKeyboardGesture(event.shiftKey);
265
+ };
266
+ const onResizeHandleKeyDown = (event) => {
267
+ const current = rect();
268
+ const vp = viewportOf();
269
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
270
+ event.preventDefault();
271
+ const dir = event.key === "ArrowRight" ? 1 : -1;
272
+ commitRect({ ...current, width: current.width + dir * local.resizeStep });
273
+ } else if (event.key === "ArrowUp" || event.key === "ArrowDown") {
274
+ event.preventDefault();
275
+ const dir = event.key === "ArrowDown" ? 1 : -1;
276
+ commitRect({ ...current, height: current.height + dir * local.resizeStep });
277
+ } else if (event.key === "Home") {
278
+ event.preventDefault();
279
+ commitRect({ ...current, width: local.minWidth, height: local.minHeight });
280
+ } else if (event.key === "End") {
281
+ event.preventDefault();
282
+ commitRect({ ...current, width: local.maxWidth ?? vp.width, height: local.maxHeight ?? vp.height });
283
+ } else {
284
+ return;
285
+ }
286
+ endKeyboardGesture(true);
287
+ };
288
+ const toggleCollapsed = () => setCollapsed((prev) => !prev);
289
+ return <Show when={transition.mounted()}>
290
+ <Portal mount={isServer ? void 0 : document.body}>
291
+ <div
292
+ {...rest}
293
+ ref={mergeRefs(local.ref, (el) => rootEl = el)}
294
+ data-testid="floating-window"
295
+ role="dialog"
296
+ tabindex={-1}
297
+ aria-labelledby={local.title ? titleId : void 0}
298
+ class={cn("smwb-floating-window", local.class, transition.classes(), {
299
+ "smwb-collapsed": collapsed()
300
+ })}
301
+ style={{
302
+ left: `${rect().x}px`,
303
+ top: `${rect().y}px`,
304
+ width: `${rect().width}px`,
305
+ ...collapsed() ? {} : { height: `${rect().height}px` },
306
+ ...local.zIndex === void 0 ? {} : { "z-index": local.zIndex },
307
+ ...typeof local.style === "object" && local.style ? local.style : {}
308
+ }}
309
+ on:pointerdown={activate}
310
+ >
311
+ <div
312
+ class="smwb-floating-window__header"
313
+ data-testid="floating-window-header"
314
+ onPointerDown={onMoveHandlePointerDown}
315
+ onPointerMove={onMoveHandlePointerMove}
316
+ onPointerUp={endMove}
317
+ onPointerCancel={endMove}
318
+ >
319
+ {
320
+ /* The move affordance is the grip, not the header: the header also hosts the
321
+ collapse/close buttons and any consumer `headerActions`, and nesting those
322
+ inside a role="button" is an a11y violation. Pointer drag still works
323
+ anywhere on the header; only the keyboard affordance lives here. */
324
+ }
325
+ <span
326
+ class="smwb-floating-window__grip"
327
+ data-testid="floating-window-move"
328
+ role="button"
329
+ tabindex={0}
330
+ aria-label={local.moveHandleAriaLabel}
331
+ onKeyDown={onMoveHandleKeyDown}
332
+ >
333
+ <Icon name="drag_indicator" />
334
+ </span>
335
+ <Show when={local.title}>
336
+ <span class="smwb-floating-window__title" id={titleId}>
337
+ {local.title}
338
+ </span>
339
+ </Show>
340
+ <div class="smwb-floating-window__actions" data-no-drag>
341
+ {local.headerActions}
342
+ <Show when={local.collapsible}>
343
+ <button
344
+ type="button"
345
+ class="smwb-floating-window__action"
346
+ data-testid="floating-window-collapse"
347
+ aria-label={collapsed() ? local.expandAriaLabel : local.collapseAriaLabel}
348
+ aria-expanded={!collapsed()}
349
+ onClick={toggleCollapsed}
350
+ >
351
+ <Icon name={collapsed() ? "open_in_full" : "close_fullscreen"} />
352
+ </button>
353
+ </Show>
354
+ <Show when={local.onClose}>
355
+ <button
356
+ type="button"
357
+ class="smwb-floating-window__action"
358
+ data-testid="floating-window-close"
359
+ aria-label={local.closeAriaLabel}
360
+ onClick={() => local.onClose?.()}
361
+ >
362
+ <Icon name="close" />
363
+ </button>
364
+ </Show>
365
+ </div>
366
+ </div>
367
+
368
+ <Show when={!collapsed()}>
369
+ <div class="smwb-floating-window__body" data-testid="floating-window-body">
370
+ {local.children}
371
+ </div>
372
+ </Show>
373
+
374
+ <Show when={local.resizable && !collapsed()}>
375
+ <For each={RESIZE_ORDER}>
376
+ {(dir) => <div
377
+ class={cn("smwb-floating-window__resize", `smwb-floating-window__resize_${dir}`)}
378
+ data-testid={`floating-window-resize-${dir}`}
379
+ {...dir === "se" ? {
380
+ role: "separator",
381
+ tabindex: 0,
382
+ "aria-label": local.resizeHandleAriaLabel,
383
+ "aria-valuemin": local.minWidth,
384
+ "aria-valuemax": Math.round(local.maxWidth ?? viewportOf().width),
385
+ "aria-valuenow": Math.round(rect().width),
386
+ onKeyDown: onResizeHandleKeyDown
387
+ } : { "aria-hidden": true, tabindex: -1 }}
388
+ onPointerDown={(event) => onResizePointerDown(dir, event)}
389
+ onPointerMove={onResizePointerMove}
390
+ onPointerUp={endResize}
391
+ onPointerCancel={endResize}
392
+ />}
393
+ </For>
394
+ </Show>
395
+ </div>
396
+ </Portal>
397
+ </Show>;
398
+ }
399
+ var floatingWindow_default = FloatingWindow;
400
+ export {
401
+ FloatingWindow,
402
+ floatingWindow_default as default
403
+ };
404
+ //# sourceMappingURL=floatingWindow.jsx.map