@selectwin/kit 0.1.203 → 0.1.204

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.
@@ -1,10 +1,21 @@
1
- import { ReactNode, ComponentPropsWithoutRef } from 'react';
1
+ import { ComponentPropsWithoutRef, ReactNode } from 'react';
2
2
  export interface SelectAction {
3
3
  content: string;
4
4
  onAction?: () => void;
5
5
  icon?: ReactNode;
6
6
  destructive?: boolean;
7
7
  disabled?: boolean;
8
+ /** 0.1.204: um endereço do app: o item é o `<Link>` do roteador (react-router-dom). */
9
+ to?: string;
10
+ /** 0.1.204: um endereço fora do app ou um arquivo: o item é um `<a>`. */
11
+ href?: string;
12
+ /**
13
+ * 0.1.204: abre em outra aba, com a seta de "abre fora". Por padrão, sim para o `href` absoluto (`https:`, `mailto:`,
14
+ * `tel:`), como no SelectMenuLink.
15
+ */
16
+ external?: boolean;
17
+ /** 0.1.204: baixa o arquivo em vez de abrir: o nome dele, ou `true` para o nome que o servidor der. */
18
+ download?: boolean | string;
8
19
  }
9
20
  export interface SelectActionSection {
10
21
  title?: string;
@@ -15,8 +26,13 @@ type SelectActionListOwnProps = {
15
26
  sections?: SelectActionSection[];
16
27
  /** Fired after any item's action (e.g. to close the surrounding popover). */
17
28
  onAction?: () => void;
29
+ /**
30
+ * 0.1.204: o menu fecha sem uma ação: o Tab sai dele. O popover em volta devolve o foco ao botão que o abriu, e o Tab
31
+ * segue dali, como pede o padrão do menu.
32
+ */
33
+ onClose?: () => void;
18
34
  autoFocus?: boolean;
19
35
  };
20
36
  export type SelectActionListProps = SelectActionListOwnProps & Omit<ComponentPropsWithoutRef<'div'>, keyof SelectActionListOwnProps>;
21
- export declare function SelectActionList({ items, sections, onAction, autoFocus, className, ...rest }: SelectActionListProps): import("react").JSX.Element;
37
+ export declare function SelectActionList({ items, sections, onAction, onClose, autoFocus, className, onKeyDown: onKeyDownProp, ...rest }: SelectActionListProps): import("react").JSX.Element;
22
38
  export {};
@@ -1,55 +1,94 @@
1
- import { useEffect as e, useRef as t } from "react";
2
- import { jsx as n, jsxs as r } from "react/jsx-runtime";
1
+ import { safeHref as e } from "./internal/safeHref.js";
2
+ import { ExternalLinkIcon as t } from "./icons.js";
3
+ import { useEffect as n, useRef as r } from "react";
4
+ import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
5
+ import { Link as s } from "react-router-dom";
3
6
  //#region src/SelectActionList.tsx
4
- function i({ items: i, sections: a, onAction: o, autoFocus: s = !0, className: c, ...l }) {
5
- let u = t(null), d = a ?? (i ? [{ items: i }] : []);
6
- e(() => {
7
+ var c = "[role=\"menuitem\"]:not(:disabled)";
8
+ function l({ action: n, onDone: r }) {
9
+ let c = `select-menu__item${n.destructive ? " select-menu__item--critical" : ""}`, l = () => {
7
10
  var e;
8
- s && ((e = u.current) == null || (e = e.querySelector("[role=\"menuitem\"]:not(:disabled)")) == null || e.focus({ preventScroll: !0 }));
9
- }, [s]);
10
- let f = (e) => {
11
- let t = u.current;
11
+ (e = n.onAction) == null || e.call(n), r == null || r();
12
+ }, u = /* @__PURE__ */ o(i, { children: [n.icon && /* @__PURE__ */ a("span", {
13
+ className: "select-menu__icon",
14
+ children: n.icon
15
+ }), /* @__PURE__ */ a("span", {
16
+ className: "select-menu__label",
17
+ children: n.content
18
+ })] }), d = n.to ?? n.href, f = e(d);
19
+ if (d !== void 0 && f !== void 0 && !n.disabled) {
20
+ let e = n.external ?? (n.to === void 0 && /^(https?:|mailto:|tel:)/i.test(f)), r = {
21
+ role: "menuitem",
22
+ tabIndex: -1,
23
+ className: c,
24
+ onClick: l,
25
+ target: e ? "_blank" : void 0,
26
+ rel: e ? "noreferrer" : void 0,
27
+ download: n.download === !0 ? "" : n.download || void 0
28
+ }, i = e ? /* @__PURE__ */ a("span", {
29
+ className: "select-menu__trailing",
30
+ children: /* @__PURE__ */ a(t, {})
31
+ }) : null;
32
+ return n.to === void 0 ? /* @__PURE__ */ o("a", {
33
+ href: f,
34
+ ...r,
35
+ children: [u, i]
36
+ }) : /* @__PURE__ */ o(s, {
37
+ to: f,
38
+ ...r,
39
+ children: [u, i]
40
+ });
41
+ }
42
+ return /* @__PURE__ */ a("button", {
43
+ type: "button",
44
+ role: "menuitem",
45
+ tabIndex: -1,
46
+ disabled: n.disabled || d !== void 0,
47
+ className: c,
48
+ onClick: l,
49
+ children: u
50
+ });
51
+ }
52
+ function u({ items: e, sections: t, onAction: i, onClose: s, autoFocus: u = !0, className: d, onKeyDown: f, ...p }) {
53
+ let m = r(null), h = t ?? (e ? [{ items: e }] : []);
54
+ n(() => {
55
+ var e;
56
+ u && ((e = m.current) == null || (e = e.querySelector(c)) == null || e.focus({ preventScroll: !0 }));
57
+ }, [u]);
58
+ let g = (e) => {
59
+ if (f == null || f(e), e.defaultPrevented) return;
60
+ let t = m.current;
12
61
  if (!t) return;
13
- let n = Array.from(t.querySelectorAll("[role=\"menuitem\"]:not(:disabled)"));
62
+ if (e.key === "Tab") {
63
+ s == null || s();
64
+ return;
65
+ }
66
+ let n = Array.from(t.querySelectorAll(c));
14
67
  if (n.length === 0) return;
15
- let r = n.indexOf(document.activeElement);
16
- e.key === "ArrowDown" ? (e.preventDefault(), (n[(r + 1) % n.length] ?? n[0]).focus()) : e.key === "ArrowUp" ? (e.preventDefault(), (n[(r - 1 + n.length) % n.length] ?? n[0]).focus()) : e.key === "Home" ? (e.preventDefault(), n[0].focus()) : e.key === "End" && (e.preventDefault(), n[n.length - 1].focus());
68
+ let r = document.activeElement, i = r ? n.indexOf(r) : -1;
69
+ e.key === " " && r instanceof HTMLAnchorElement && i !== -1 ? (e.preventDefault(), r.click()) : e.key === "ArrowDown" ? (e.preventDefault(), (n[(i + 1) % n.length] ?? n[0]).focus()) : e.key === "ArrowUp" ? (e.preventDefault(), (n[(i - 1 + n.length) % n.length] ?? n[0]).focus()) : e.key === "Home" ? (e.preventDefault(), n[0].focus()) : e.key === "End" && (e.preventDefault(), n[n.length - 1].focus());
17
70
  };
18
- return /* @__PURE__ */ n("div", {
19
- ...l,
20
- className: `select-actionlist${c ? " " + c : ""}`,
71
+ return /* @__PURE__ */ a("div", {
72
+ ...p,
73
+ className: `select-actionlist${d ? " " + d : ""}`,
21
74
  role: "menu",
22
- ref: u,
23
- onKeyDown: f,
24
- children: d.map((e, t) => /* @__PURE__ */ r("div", {
75
+ ref: m,
76
+ onKeyDown: g,
77
+ children: h.map((e, t) => /* @__PURE__ */ o("div", {
25
78
  className: "select-actionlist__section",
26
79
  role: "group",
27
80
  "aria-label": e.title,
28
- children: [e.title && /* @__PURE__ */ n("div", {
81
+ children: [e.title && /* @__PURE__ */ a("div", {
29
82
  className: "select-actionlist__title",
30
83
  children: e.title
31
- }), e.items.map((e, t) => /* @__PURE__ */ r("button", {
32
- type: "button",
33
- role: "menuitem",
34
- tabIndex: -1,
35
- disabled: e.disabled,
36
- className: `select-menu__item${e.destructive ? " select-menu__item--critical" : ""}`,
37
- onClick: () => {
38
- var t;
39
- (t = e.onAction) == null || t.call(e), o == null || o();
40
- },
41
- children: [e.icon && /* @__PURE__ */ n("span", {
42
- className: "select-menu__icon",
43
- children: e.icon
44
- }), /* @__PURE__ */ n("span", {
45
- className: "select-menu__label",
46
- children: e.content
47
- })]
84
+ }), e.items.map((e, t) => /* @__PURE__ */ a(l, {
85
+ action: e,
86
+ onDone: i
48
87
  }, t))]
49
88
  }, t))
50
89
  });
51
90
  }
52
91
  //#endregion
53
- export { i as SelectActionList };
92
+ export { u as SelectActionList };
54
93
 
55
94
  //# sourceMappingURL=SelectActionList.js.map
@@ -1,6 +1,8 @@
1
- import { SelectAction } from './SelectActionList';
2
- export declare function SelectActionMenu({ items, label: labelProp, disabled, }: {
3
- items: SelectAction[];
1
+ import { SelectAction, SelectActionSection } from './SelectActionList';
2
+ export declare function SelectActionMenu({ items, sections, label: labelProp, disabled, }: {
3
+ items?: SelectAction[];
4
+ /** 0.1.204: os grupos, separados por um traço (no lugar de `items`). */
5
+ sections?: SelectActionSection[];
4
6
  label?: string;
5
7
  disabled?: boolean;
6
8
  }): import("react").JSX.Element;
@@ -3,31 +3,38 @@ import { ChevronDownIcon as t } from "./icons.js";
3
3
  import { useSelectMessages as n } from "./SelectLocale.js";
4
4
  import { SelectPopover as r } from "./SelectPopover.js";
5
5
  import { SelectActionList as i } from "./SelectActionList.js";
6
- import { useState as a } from "react";
7
- import { jsx as o } from "react/jsx-runtime";
6
+ import { useId as a, useState as o } from "react";
7
+ import { jsx as s } from "react/jsx-runtime";
8
8
  //#region src/SelectActionMenu.tsx
9
- function s({ items: s, label: c, disabled: l }) {
10
- let u = n().common.actions, d = c ?? u, [f, p] = a(!1);
11
- return /* @__PURE__ */ o(r, {
12
- active: f,
13
- onClose: () => p(!1),
9
+ function c({ items: c, sections: l, label: u, disabled: d }) {
10
+ let f = n().common.actions, p = u ?? f, [m, h] = o(!1), g = a(), _ = () => h(!1);
11
+ return /* @__PURE__ */ s(r, {
12
+ active: m,
13
+ onClose: _,
14
14
  placement: "bottom-end",
15
- activator: /* @__PURE__ */ o(e, {
15
+ activator: /* @__PURE__ */ s(e, {
16
16
  variant: "secondary",
17
17
  size: "sm",
18
18
  inline: !0,
19
- trailingIcon: /* @__PURE__ */ o(t, {}),
20
- disabled: l,
21
- onClick: () => p((e) => !e),
22
- children: d
19
+ trailingIcon: /* @__PURE__ */ s(t, {}),
20
+ disabled: d,
21
+ "aria-haspopup": "menu",
22
+ "aria-expanded": m,
23
+ "aria-controls": m ? g : void 0,
24
+ onClick: () => h((e) => !e),
25
+ children: p
23
26
  }),
24
- children: /* @__PURE__ */ o(i, {
25
- items: s,
26
- onAction: () => p(!1)
27
+ children: /* @__PURE__ */ s(i, {
28
+ id: g,
29
+ "aria-label": p,
30
+ items: c,
31
+ sections: l,
32
+ onAction: _,
33
+ onClose: _
27
34
  })
28
35
  });
29
36
  }
30
37
  //#endregion
31
- export { s as SelectActionMenu };
38
+ export { c as SelectActionMenu };
32
39
 
33
40
  //# sourceMappingURL=SelectActionMenu.js.map
@@ -7,95 +7,98 @@ import { useCallback as s, useEffect as c, useLayoutEffect as l, useRef as u, us
7
7
  import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
8
8
  import { createPortal as h } from "react-dom";
9
9
  //#region src/SelectPopover.tsx
10
- var g = [];
11
- function _({ active: _, onClose: v, activator: y, children: b, placement: x = "bottom-start", gap: S = 6, role: C, trapFocus: w = !1, matchWidth: T = !1, theme: E }) {
12
- let D = u(null), O = u(null), k = u(null), [A, j] = d(null), [M, N] = d("light"), [P] = d(() => ({})), F = a(), I = s(() => {
10
+ var g = [], _ = "button:not(:disabled), [href], input:not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex=\"-1\"])";
11
+ function v({ active: v, onClose: y, activator: b, children: x, placement: S = "bottom-start", gap: C = 6, role: w, trapFocus: T = !1, matchWidth: E = !1, theme: D }) {
12
+ let O = u(null), k = u(null), A = u(null), [j, M] = d(null), [N, P] = d("light"), [F] = d(() => ({})), I = a(), L = s(() => {
13
13
  var t;
14
- let n = ((t = D.current) == null ? void 0 : t.firstElementChild) ?? D.current, r = O.current;
14
+ let n = ((t = O.current) == null ? void 0 : t.firstElementChild) ?? O.current, r = k.current;
15
15
  if (!n || !r) return;
16
16
  let i = n.getBoundingClientRect(), a = e(i, {
17
17
  width: r.offsetWidth,
18
18
  height: r.offsetHeight
19
- }, x, S);
20
- j({
19
+ }, S, C);
20
+ M({
21
21
  top: a.top,
22
22
  left: a.left,
23
- minWidth: T ? i.width : void 0
23
+ minWidth: E ? i.width : void 0
24
24
  });
25
25
  }, [
26
- x,
27
26
  S,
28
- T
27
+ C,
28
+ E
29
29
  ]);
30
30
  return l(() => {
31
- if (!_) {
32
- j(null);
31
+ if (!v) {
32
+ M(null);
33
33
  return;
34
34
  }
35
- N(o(D.current)), I();
36
- }, [_, I]), c(() => {
37
- if (_) return k.current = document.activeElement, () => {
35
+ P(o(O.current)), L();
36
+ }, [v, L]), l(() => {
37
+ var e, t;
38
+ if (!v) return;
39
+ let n = document.activeElement, r = !n || n === document.body || !!((e = k.current) != null && e.contains(n));
40
+ return A.current = r ? ((t = O.current) == null ? void 0 : t.querySelector(_)) ?? n : n, () => {
38
41
  var e, t;
39
- return (e = k.current) == null || (t = e.focus) == null ? void 0 : t.call(e, { preventScroll: !0 });
42
+ return (e = A.current) == null || (t = e.focus) == null ? void 0 : t.call(e, { preventScroll: !0 });
40
43
  };
41
- }, [_]), c(() => {
42
- if (!_) return;
43
- let e = O.current;
44
+ }, [v]), c(() => {
45
+ if (!v) return;
46
+ let e = k.current;
44
47
  if (e) return g.push(e), () => {
45
48
  let t = g.lastIndexOf(e);
46
49
  t !== -1 && g.splice(t, 1);
47
50
  };
48
- }, [_]), c(() => {
49
- if (!_) return;
50
- let e = () => I();
51
+ }, [v]), c(() => {
52
+ if (!v) return;
53
+ let e = () => L();
51
54
  return window.addEventListener("scroll", e, !0), window.addEventListener("resize", e), () => {
52
55
  window.removeEventListener("scroll", e, !0), window.removeEventListener("resize", e);
53
56
  };
54
- }, [_, I]), c(() => {
55
- if (!_) return;
56
- let e = i(P, F), t = (e) => {
57
+ }, [v, L]), c(() => {
58
+ if (!v) return;
59
+ let e = i(F, I), t = (e) => {
57
60
  var t, n;
58
61
  let r = e.target;
59
- (t = O.current) != null && t.contains(r) || (n = D.current) != null && n.contains(r) || g.length && g[g.length - 1] !== O.current || v();
62
+ (t = k.current) != null && t.contains(r) || (n = O.current) != null && n.contains(r) || g.length && g[g.length - 1] !== k.current || y();
60
63
  }, n = (e) => {
61
- e.key === "Escape" && r(P) && (e.stopPropagation(), v());
64
+ e.key === "Escape" && r(F) && (e.stopPropagation(), y());
62
65
  };
63
66
  return document.addEventListener("mousedown", t, !0), document.addEventListener("keydown", n), () => {
64
67
  e(), document.removeEventListener("mousedown", t, !0), document.removeEventListener("keydown", n);
65
68
  };
66
69
  }, [
67
- _,
68
70
  v,
69
- P,
70
- F
71
- ]), t(_ && w, O), /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", {
71
+ y,
72
+ F,
73
+ I
74
+ ]), t(v && T, k), /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", {
72
75
  className: "select-pop__trigger",
73
- ref: D,
74
- children: y
75
- }), _ && h(/* @__PURE__ */ p("div", {
76
76
  ref: O,
77
+ children: b
78
+ }), v && h(/* @__PURE__ */ p("div", {
79
+ ref: k,
77
80
  className: "select select-pop__panel",
78
- "data-theme": E ?? M,
79
- role: C,
81
+ "data-theme": D ?? N,
82
+ role: w,
80
83
  tabIndex: -1,
81
- style: A ? {
84
+ style: j ? {
82
85
  position: "fixed",
83
- top: A.top,
84
- left: A.left,
85
- minWidth: A.minWidth
86
+ top: j.top,
87
+ left: j.left,
88
+ minWidth: j.minWidth
86
89
  } : {
87
90
  position: "fixed",
88
91
  top: 0,
89
92
  left: 0,
90
- visibility: "hidden"
93
+ opacity: 0
91
94
  },
92
95
  children: /* @__PURE__ */ p(n, {
93
- value: P,
94
- children: b
96
+ value: F,
97
+ children: x
95
98
  })
96
99
  }), document.body)] });
97
100
  }
98
101
  //#endregion
99
- export { _ as SelectPopover };
102
+ export { v as SelectPopover };
100
103
 
101
104
  //# sourceMappingURL=SelectPopover.js.map
@@ -1,12 +1,9 @@
1
- import { ReactNode } from 'react';
2
- export interface SelectRowAction {
3
- content: string;
4
- onAction?: () => void;
5
- icon?: ReactNode;
6
- destructive?: boolean;
7
- disabled?: boolean;
8
- }
9
- export declare function SelectRowActions({ actions, label: labelProp }: {
10
- actions: SelectRowAction[];
1
+ import { SelectAction, SelectActionSection } from './SelectActionList';
2
+ /** O item do menu da linha: o mesmo do SelectActionList (0.1.204: também o link). */
3
+ export type SelectRowAction = SelectAction;
4
+ export declare function SelectRowActions({ actions, sections, label: labelProp, }: {
5
+ actions?: SelectRowAction[];
6
+ /** 0.1.204: os grupos, separados por um traço (no lugar de `actions`). */
7
+ sections?: SelectActionSection[];
11
8
  label?: string;
12
9
  }): import("react").JSX.Element;
@@ -3,30 +3,37 @@ import { useSelectMessages as t } from "./SelectLocale.js";
3
3
  import { SelectPopover as n } from "./SelectPopover.js";
4
4
  import { SelectActionList as r } from "./SelectActionList.js";
5
5
  import { SelectIconButton as i } from "./SelectIconButton.js";
6
- import { useState as a } from "react";
7
- import { jsx as o } from "react/jsx-runtime";
6
+ import { useId as a, useState as o } from "react";
7
+ import { jsx as s } from "react/jsx-runtime";
8
8
  //#region src/SelectRowActions.tsx
9
- function s({ actions: s, label: c }) {
10
- let l = t().common.actions, u = c ?? l, [d, f] = a(!1);
11
- return /* @__PURE__ */ o(n, {
12
- active: d,
13
- onClose: () => f(!1),
9
+ function c({ actions: c, sections: l, label: u }) {
10
+ let d = t().common.actions, f = u ?? d, [p, m] = o(!1), h = a(), g = () => m(!1);
11
+ return /* @__PURE__ */ s(n, {
12
+ active: p,
13
+ onClose: g,
14
14
  placement: "bottom-end",
15
- activator: /* @__PURE__ */ o(i, {
16
- icon: /* @__PURE__ */ o(e, {}),
17
- label: u,
15
+ activator: /* @__PURE__ */ s(i, {
16
+ icon: /* @__PURE__ */ s(e, {}),
17
+ label: f,
18
18
  size: "sm",
19
19
  variant: "outline",
20
- active: d,
21
- onClick: () => f((e) => !e)
20
+ className: p ? "is-active" : void 0,
21
+ "aria-haspopup": "menu",
22
+ "aria-expanded": p,
23
+ "aria-controls": p ? h : void 0,
24
+ onClick: () => m((e) => !e)
22
25
  }),
23
- children: /* @__PURE__ */ o(r, {
24
- items: s,
25
- onAction: () => f(!1)
26
+ children: /* @__PURE__ */ s(r, {
27
+ id: h,
28
+ "aria-label": f,
29
+ items: c,
30
+ sections: l,
31
+ onAction: g,
32
+ onClose: g
26
33
  })
27
34
  });
28
35
  }
29
36
  //#endregion
30
- export { s as SelectRowActions };
37
+ export { c as SelectRowActions };
31
38
 
32
39
  //# sourceMappingURL=SelectRowActions.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selectwin/kit",
3
- "version": "0.1.203",
3
+ "version": "0.1.204",
4
4
  "description": "Selectwin design-system kit — primitivos React, charts SVG e tokens (theme-aware, sem dependência de biblioteca de chart).",
5
5
  "type": "module",
6
6
  "repository": {