@selectwin/kit 0.1.219 → 0.1.221

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.
@@ -0,0 +1,22 @@
1
+ import { ComponentPropsWithoutRef, ReactNode } from 'react';
2
+ export interface SelectCarouselSlide {
3
+ key: string;
4
+ /** O título do slide ("Entrega no período"): o cabeçalho dele e o nome do ponto que leva até ele. */
5
+ title: string;
6
+ /** A análise em uma frase. */
7
+ text: ReactNode;
8
+ /** Para onde a seta leva: um endereço do app (o `<Link>` do roteador). */
9
+ to?: string;
10
+ /** Ou um endereço de fora. */
11
+ href?: string;
12
+ }
13
+ type SelectCarouselOwnProps = {
14
+ slides: readonly SelectCarouselSlide[];
15
+ /** O nome do carrossel ("Análises do período"); padrão: "Destaques". */
16
+ label?: string;
17
+ /** De quanto em quanto tempo passa sozinho, em ms (padrão 7000). */
18
+ interval?: number;
19
+ };
20
+ export type SelectCarouselProps = SelectCarouselOwnProps & Omit<ComponentPropsWithoutRef<'section'>, keyof SelectCarouselOwnProps>;
21
+ export declare function SelectCarousel({ slides, label, interval, className, ...rest }: SelectCarouselProps): import("react").JSX.Element | null;
22
+ export {};
@@ -0,0 +1,133 @@
1
+ /* empty css */
2
+ import { safeHref as e } from "./internal/safeHref.js";
3
+ import { ArrowUpRightIcon as t, ChevronLeftIcon as n, ChevronRightIcon as r, PauseIcon as i, PlayIcon as a } from "./icons.js";
4
+ import { formatSelectNumber as o, useSelectLocale as s, useSelectMessages as c } from "./SelectLocale.js";
5
+ import { useEffect as l, useRef as u, useState as d } from "react";
6
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
7
+ import { Link as m } from "react-router-dom";
8
+ //#region src/SelectCarousel.tsx
9
+ var h = () => typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
10
+ function g({ slides: g, label: _, interval: v = 7e3, className: y, ...b }) {
11
+ let x = c().carousel, S = s(), C = g.length, [w, T] = d(0), [E, D] = d(!1), [O, k] = d(() => !h()), [A, j] = d(!1), M = u(null), N = Math.min(w, Math.max(0, C - 1)), P = O && !A && C > 1;
12
+ l(() => {
13
+ if (!P) return;
14
+ let e = window.setTimeout(() => {
15
+ D(!1), T((e) => (e + 1) % C);
16
+ }, v);
17
+ return () => window.clearTimeout(e);
18
+ }, [
19
+ P,
20
+ C,
21
+ w,
22
+ v
23
+ ]);
24
+ let F = (e) => {
25
+ D(e < N), T((e % C + C) % C);
26
+ }, I = g[N];
27
+ if (!I) return null;
28
+ let L = e(I.to ?? I.href), R = L === void 0 ? null : I.to == null ? /* @__PURE__ */ f("a", {
29
+ href: L,
30
+ className: "select-carousel__go",
31
+ "aria-label": x.open(I.title),
32
+ children: /* @__PURE__ */ f(t, {})
33
+ }) : /* @__PURE__ */ f(m, {
34
+ to: L,
35
+ className: "select-carousel__go",
36
+ "aria-label": x.open(I.title),
37
+ children: /* @__PURE__ */ f(t, {})
38
+ });
39
+ return /* @__PURE__ */ p("section", {
40
+ ...b,
41
+ className: `select-carousel${y ? " " + y : ""}`,
42
+ "aria-roledescription": x.carousel,
43
+ "aria-label": _ ?? x.label,
44
+ onMouseEnter: () => j(!0),
45
+ onMouseLeave: () => j(!1),
46
+ onFocus: () => j(!0),
47
+ onBlur: (e) => {
48
+ e.currentTarget.contains(e.relatedTarget) || j(!1);
49
+ },
50
+ onKeyDown: (e) => {
51
+ C < 2 || e.key !== "ArrowRight" && e.key !== "ArrowLeft" || (e.preventDefault(), F(N + (e.key === "ArrowRight" ? 1 : -1)));
52
+ },
53
+ onPointerDown: (e) => {
54
+ e.pointerType !== "mouse" && (M.current = e.clientX);
55
+ },
56
+ onPointerUp: (e) => {
57
+ if (M.current === null) return;
58
+ let t = e.clientX - M.current;
59
+ M.current = null, C > 1 && Math.abs(t) > 40 && F(N + (t < 0 ? 1 : -1));
60
+ },
61
+ children: [
62
+ /* @__PURE__ */ f("span", {
63
+ className: "select-carousel__layer",
64
+ "aria-hidden": "true"
65
+ }),
66
+ /* @__PURE__ */ f("span", {
67
+ className: "select-carousel__layer select-carousel__layer--2",
68
+ "aria-hidden": "true"
69
+ }),
70
+ /* @__PURE__ */ p("div", {
71
+ className: "select-carousel__card",
72
+ children: [/* @__PURE__ */ f("div", {
73
+ className: "select-carousel__slides",
74
+ "aria-live": P ? "off" : "polite",
75
+ children: /* @__PURE__ */ p("div", {
76
+ className: `select-carousel__slide${E ? " is-back" : ""}`,
77
+ role: "group",
78
+ "aria-roledescription": x.slide,
79
+ "aria-label": x.position(o(N + 1, S), o(C, S)),
80
+ children: [/* @__PURE__ */ p("span", {
81
+ className: "select-carousel__head",
82
+ children: [/* @__PURE__ */ f("span", { children: I.title }), R]
83
+ }), /* @__PURE__ */ f("span", {
84
+ className: "select-carousel__text",
85
+ children: I.text
86
+ })]
87
+ }, I.key)
88
+ }), C > 1 && /* @__PURE__ */ p("div", {
89
+ className: "select-carousel__nav",
90
+ children: [/* @__PURE__ */ f("span", {
91
+ className: "select-carousel__dots",
92
+ children: g.map((e, t) => /* @__PURE__ */ f("button", {
93
+ type: "button",
94
+ className: "select-carousel__dot",
95
+ "aria-label": `${o(t + 1, S)}: ${e.title}`,
96
+ "aria-current": t === N ? "true" : void 0,
97
+ onClick: () => F(t)
98
+ }, e.key))
99
+ }), /* @__PURE__ */ p("span", {
100
+ className: "select-carousel__ctrl",
101
+ children: [
102
+ /* @__PURE__ */ f("button", {
103
+ type: "button",
104
+ className: "select-carousel__btn",
105
+ "aria-label": x.previous,
106
+ onClick: () => F(N - 1),
107
+ children: /* @__PURE__ */ f(n, {})
108
+ }),
109
+ /* @__PURE__ */ f("button", {
110
+ type: "button",
111
+ className: "select-carousel__btn",
112
+ "aria-label": O ? x.pause : x.play,
113
+ onClick: () => k((e) => !e),
114
+ children: f(O ? i : a, {})
115
+ }),
116
+ /* @__PURE__ */ f("button", {
117
+ type: "button",
118
+ className: "select-carousel__btn",
119
+ "aria-label": x.next,
120
+ onClick: () => F(N + 1),
121
+ children: /* @__PURE__ */ f(r, {})
122
+ })
123
+ ]
124
+ })]
125
+ })]
126
+ })
127
+ ]
128
+ });
129
+ }
130
+ //#endregion
131
+ export { g as SelectCarousel };
132
+
133
+ //# sourceMappingURL=SelectCarousel.js.map
@@ -34,5 +34,19 @@ export interface SelectConversationBubbleProps {
34
34
  avatar?: ReactNode;
35
35
  /** 0.1.184: a hora ao lado do nome, em cima do balão ("Você · 26/10, 08:46"). */
36
36
  time?: ReactNode;
37
+ /** 0.1.221: a mídia dentro do balão, acima do texto (a legenda): o `SelectConversationMedia`. */
38
+ media?: ReactNode;
37
39
  }
38
- export declare function SelectConversationBubble({ direction, author, label, attachment, meta, metaTone, children, avatar, time }: SelectConversationBubbleProps): import("react").JSX.Element;
40
+ export declare function SelectConversationBubble({ direction, author, label, attachment, meta, metaTone, children, avatar, time, media }: SelectConversationBubbleProps): import("react").JSX.Element;
41
+ /**
42
+ * 0.1.221: a mídia de uma mensagem, dentro do balão — a foto, a figurinha (sem fundo, menor), o vídeo e o áudio (com os
43
+ * controles do navegador). Nada é baixado antes de aparecer (`loading="lazy"`, `preload="none"`). Quando o arquivo não
44
+ * abre (o link da mídia expirou), `onError` avisa quem usa, que troca pela nota.
45
+ */
46
+ export declare function SelectConversationMedia({ kind, src, alt, onError, }: {
47
+ kind: 'image' | 'sticker' | 'video' | 'audio';
48
+ src: string;
49
+ /** O que a imagem mostra (a legenda, ou "Imagem"). */
50
+ alt?: string;
51
+ onError?: () => void;
52
+ }): import("react").JSX.Element;
@@ -22,7 +22,14 @@ function l({ children: r, "aria-label": a }) {
22
22
  if (!l.current) return;
23
23
  let e = c(o.current);
24
24
  e && (e.scrollTop = e.scrollHeight);
25
- }), /* @__PURE__ */ i("div", {
25
+ }), e(() => {
26
+ let e = o.current, t = c(e);
27
+ if (!e || !t || typeof ResizeObserver > "u") return;
28
+ let n = new ResizeObserver(() => {
29
+ l.current && (t.scrollTop = t.scrollHeight);
30
+ });
31
+ return n.observe(e), () => n.disconnect();
32
+ }, []), /* @__PURE__ */ i("div", {
26
33
  ref: o,
27
34
  className: "select-convo",
28
35
  role: "log",
@@ -48,8 +55,8 @@ function d({ children: e, time: t }) {
48
55
  }) : null]
49
56
  });
50
57
  }
51
- function f({ direction: e, author: t, label: n, attachment: s, meta: c, metaTone: l, children: u, avatar: d, time: f }) {
52
- let p = u != null && u !== "", m = /* @__PURE__ */ a(r, { children: [
58
+ function f({ direction: e, author: t, label: n, attachment: s, meta: c, metaTone: l, children: u, avatar: d, time: f, media: p }) {
59
+ let m = u != null && u !== "", h = /* @__PURE__ */ a(r, { children: [
53
60
  t || f ? /* @__PURE__ */ a("span", {
54
61
  className: "select-convo__author",
55
62
  children: [t, f ? /* @__PURE__ */ i("span", {
@@ -57,15 +64,22 @@ function f({ direction: e, author: t, label: n, attachment: s, meta: c, metaTone
57
64
  children: f
58
65
  }) : null]
59
66
  }) : null,
60
- p || n ? /* @__PURE__ */ a("div", {
67
+ m || n || p != null ? /* @__PURE__ */ a("div", {
61
68
  className: "select-convo__bubble",
62
- children: [n ? /* @__PURE__ */ i("span", {
63
- className: "select-convo__label",
64
- children: n
65
- }) : null, p ? /* @__PURE__ */ i("div", {
66
- className: "select-convo__text",
67
- children: u
68
- }) : null]
69
+ children: [
70
+ n ? /* @__PURE__ */ i("span", {
71
+ className: "select-convo__label",
72
+ children: n
73
+ }) : null,
74
+ p == null ? null : /* @__PURE__ */ i("div", {
75
+ className: "select-convo__media",
76
+ children: p
77
+ }),
78
+ m ? /* @__PURE__ */ i("div", {
79
+ className: "select-convo__text",
80
+ children: u
81
+ }) : null
82
+ ]
69
83
  }) : null,
70
84
  s ? /* @__PURE__ */ i("div", {
71
85
  className: "select-convo__attachment",
@@ -84,14 +98,35 @@ function f({ direction: e, author: t, label: n, attachment: s, meta: c, metaTone
84
98
  children: d
85
99
  }), /* @__PURE__ */ i("div", {
86
100
  className: "select-convo__stack",
87
- children: m
101
+ children: h
88
102
  })]
89
103
  }) : /* @__PURE__ */ i("div", {
90
104
  className: o("select-convo__msg", `select-convo__msg--${e}`),
91
- children: m
105
+ children: h
106
+ });
107
+ }
108
+ function p({ kind: e, src: t, alt: n, onError: r }) {
109
+ return e === "audio" ? /* @__PURE__ */ i("audio", {
110
+ className: "select-convo__audio",
111
+ controls: !0,
112
+ preload: "none",
113
+ src: t,
114
+ onError: r
115
+ }) : e === "video" ? /* @__PURE__ */ i("video", {
116
+ className: "select-convo__video",
117
+ controls: !0,
118
+ preload: "none",
119
+ src: t,
120
+ onError: r
121
+ }) : /* @__PURE__ */ i("img", {
122
+ className: `select-convo__image${e === "sticker" ? " select-convo__image--sticker" : ""}`,
123
+ src: t,
124
+ alt: n ?? "",
125
+ loading: "lazy",
126
+ onError: r
92
127
  });
93
128
  }
94
129
  //#endregion
95
- export { l as SelectConversation, f as SelectConversationBubble, u as SelectConversationDay, d as SelectConversationEvent };
130
+ export { l as SelectConversation, f as SelectConversationBubble, u as SelectConversationDay, d as SelectConversationEvent, p as SelectConversationMedia };
96
131
 
97
132
  //# sourceMappingURL=SelectConversation.js.map
@@ -84,6 +84,42 @@ export interface SelectKitMessages {
84
84
  sideNav: {
85
85
  pending: (hint: string) => string;
86
86
  };
87
+ /** 0.1.221: a caixa de entrada (SelectInbox, a lista, o leitor, o compositor e o anexo), que só falava português. */
88
+ inbox: {
89
+ list: string;
90
+ reader: string;
91
+ aside: string;
92
+ unread: string;
93
+ unreadCount: (n: number) => string;
94
+ messages: (n: number) => string;
95
+ flagged: string;
96
+ attachments: (n: number) => string;
97
+ back: string;
98
+ tools: string;
99
+ close: string;
100
+ drop: string;
101
+ open: string;
102
+ minimize: string;
103
+ message: string;
104
+ attachmentLoading: string;
105
+ attachmentReady: string;
106
+ attachmentFailed: string;
107
+ attachmentOpen: (name: string) => string;
108
+ attachmentBusy: (name: string) => string;
109
+ attachmentGet: (name: string) => string;
110
+ };
111
+ /** 0.1.220: o SelectCarousel — o nome, o papel, a posição e os botões. */
112
+ carousel: {
113
+ label: string;
114
+ carousel: string;
115
+ slide: string;
116
+ position: (at: string, count: string) => string;
117
+ previous: string;
118
+ next: string;
119
+ pause: string;
120
+ play: string;
121
+ open: (title: string) => string;
122
+ };
87
123
  /** 0.1.201: o SelectFeeBreakdown — os rótulos de sempre e a legenda da barra. */
88
124
  fees: {
89
125
  gross: string;
@@ -87,6 +87,40 @@ var r = {
87
87
  progress: (e, t) => `${e} de ${t}`
88
88
  },
89
89
  sideNav: { pending: (e) => `${e} (com pendências)` },
90
+ inbox: {
91
+ list: "Conversas",
92
+ reader: "Conversa aberta",
93
+ aside: "Sobre a conversa",
94
+ unread: "Não lida",
95
+ unreadCount: (e) => e === 1 ? "1 não lida" : `${e} não lidas`,
96
+ messages: (e) => `${e} mensagens`,
97
+ flagged: "Com estrela",
98
+ attachments: (e) => e === 1 ? "1 anexo" : `${e} anexos`,
99
+ back: "Voltar para a lista",
100
+ tools: "Organizar a conversa",
101
+ close: "Fechar e descartar",
102
+ drop: "Solte para anexar",
103
+ open: "Abrir a janela",
104
+ minimize: "Minimizar",
105
+ message: "Mensagem",
106
+ attachmentLoading: "Gerando o link…",
107
+ attachmentReady: "Abrir",
108
+ attachmentFailed: "Não deu para pegar · tentar de novo",
109
+ attachmentOpen: (e) => `Abrir ${e} em outra aba`,
110
+ attachmentBusy: (e) => `${e}: gerando o link`,
111
+ attachmentGet: (e) => `Pegar o anexo ${e}`
112
+ },
113
+ carousel: {
114
+ label: "Destaques",
115
+ carousel: "carrossel",
116
+ slide: "slide",
117
+ position: (e, t) => `${e} de ${t}`,
118
+ previous: "Anterior",
119
+ next: "Próximo",
120
+ pause: "Parar de passar sozinho",
121
+ play: "Passar sozinho",
122
+ open: (e) => `Ver: ${e}`
123
+ },
90
124
  fees: {
91
125
  gross: "Valor bruto",
92
126
  net: "Valor líquido",
@@ -180,6 +214,40 @@ var r = {
180
214
  progress: (e, t) => `${e} of ${t}`
181
215
  },
182
216
  sideNav: { pending: (e) => `${e} (pending)` },
217
+ inbox: {
218
+ list: "Conversations",
219
+ reader: "Open conversation",
220
+ aside: "About the conversation",
221
+ unread: "Unread",
222
+ unreadCount: (e) => e === 1 ? "1 unread" : `${e} unread`,
223
+ messages: (e) => `${e} messages`,
224
+ flagged: "Starred",
225
+ attachments: (e) => e === 1 ? "1 attachment" : `${e} attachments`,
226
+ back: "Back to the list",
227
+ tools: "Organize the conversation",
228
+ close: "Close and discard",
229
+ drop: "Drop to attach",
230
+ open: "Open the window",
231
+ minimize: "Minimize",
232
+ message: "Message",
233
+ attachmentLoading: "Getting the link…",
234
+ attachmentReady: "Open",
235
+ attachmentFailed: "Couldn't get it · try again",
236
+ attachmentOpen: (e) => `Open ${e} in a new tab`,
237
+ attachmentBusy: (e) => `${e}: getting the link`,
238
+ attachmentGet: (e) => `Get the attachment ${e}`
239
+ },
240
+ carousel: {
241
+ label: "Highlights",
242
+ carousel: "carousel",
243
+ slide: "slide",
244
+ position: (e, t) => `${e} of ${t}`,
245
+ previous: "Previous",
246
+ next: "Next",
247
+ pause: "Stop rotating",
248
+ play: "Rotate automatically",
249
+ open: (e) => `Open: ${e}`
250
+ },
183
251
  fees: {
184
252
  gross: "Gross amount",
185
253
  net: "Net amount",
@@ -24,10 +24,18 @@ export interface SelectInboxProps {
24
24
  aside?: ReactNode;
25
25
  /** O nome da coluna lateral para o leitor de tela. */
26
26
  asideLabel?: string;
27
+ /** 0.1.221: os nomes da lista e do leitor para o leitor de tela (padrão: "Conversas", "Conversa aberta"). */
28
+ listLabel?: string;
29
+ readerLabel?: string;
30
+ /**
31
+ * 0.1.221: a caixa DENTRO de uma página (o WhatsApp da SWMX, abaixo do cabeçalho), e não na tela inteira: a borda e o
32
+ * canto do cartão. A altura continua sendo a de quem a contém.
33
+ */
34
+ framed?: boolean;
27
35
  'aria-label'?: string;
28
36
  }
29
37
  /** A caixa de entrada em tela cheia: preenche a altura do pai e cada coluna rola por dentro. */
30
- export declare function SelectInbox({ toolbar, banner, list, reader, readerOpen, children, fullBody, aside, asideLabel, 'aria-label': ariaLabel }: SelectInboxProps): import("react").JSX.Element;
38
+ export declare function SelectInbox({ toolbar, banner, list, reader, readerOpen, children, fullBody, aside, asideLabel, listLabel, readerLabel, framed, 'aria-label': ariaLabel, }: SelectInboxProps): import("react").JSX.Element;
31
39
  /** A faixa de aviso sob a barra, de ponta a ponta (ex.: "a senha da sua caixa deixou de valer"). */
32
40
  export declare function SelectInboxBanner({ tone, children, action }: {
33
41
  tone?: 'warning' | 'critical' | 'info';
@@ -35,7 +43,8 @@ export declare function SelectInboxBanner({ tone, children, action }: {
35
43
  action?: ReactNode;
36
44
  }): import("react").JSX.Element;
37
45
  export interface SelectInboxToolbarProps {
38
- title: ReactNode;
46
+ /** O título da caixa (o h1 da tela cheia). 0.1.221: opcional — numa página, o título é o do cabeçalho dela. */
47
+ title?: ReactNode;
39
48
  /** Sob o título: a caixa e a sincronia (`SelectMailboxStatus`). */
40
49
  status?: ReactNode;
41
50
  /** As pastas e a busca. */
@@ -90,9 +99,14 @@ export interface SelectMailListItemProps {
90
99
  unread?: boolean;
91
100
  /** 0.1.161: alguma mensagem da conversa tem estrela — a estrela cheia ao lado da hora. */
92
101
  flagged?: boolean;
102
+ /**
103
+ * 0.1.221: quantas mensagens não lidas (o WhatsApp conta, o e-mail não): o número no lugar do ponto, e a linha em
104
+ * destaque como a `unread`.
105
+ */
106
+ unreadCount?: number;
93
107
  onClick: () => void;
94
108
  }
95
- export declare function SelectMailListItem({ from, avatar, subject, snippet, date, count, attachments, active, unread, flagged, onClick }: SelectMailListItemProps): import("react").JSX.Element;
109
+ export declare function SelectMailListItem({ from, avatar, subject, snippet, date, count, attachments, active, unread: unreadProp, flagged, unreadCount, onClick, }: SelectMailListItemProps): import("react").JSX.Element;
96
110
  /** As linhas fantasmas enquanto a caixa chega. */
97
111
  export declare function SelectMailListSkeleton({ rows }: {
98
112
  rows?: number;
@@ -226,13 +240,19 @@ export declare function SelectMailComposerInput({ value, onChange, placeholder,
226
240
  maxLength?: number;
227
241
  }): import("react").JSX.Element;
228
242
  /** O corpo: texto, sem moldura, que cresce até um teto e rola. */
229
- export declare function SelectMailComposerBody({ value, onChange, placeholder, rows, 'aria-label': ariaLabel, maxLength, }: {
243
+ export declare function SelectMailComposerBody({ value, onChange, placeholder, rows, 'aria-label': ariaLabel, maxLength, onEnter, id, }: {
230
244
  value: string;
231
245
  onChange: (value: string) => void;
232
246
  placeholder?: string;
233
247
  rows?: number;
234
248
  'aria-label'?: string;
235
249
  maxLength?: number;
250
+ /**
251
+ * 0.1.221: o Enter envia (a conversa de mensagens curtas, o WhatsApp) e o Shift+Enter quebra a linha. Durante a
252
+ * composição de um acento ou de um ideograma, o Enter é da composição.
253
+ */
254
+ onEnter?: () => void;
255
+ id?: string;
236
256
  }): import("react").JSX.Element;
237
257
  /** O clipe do rodapé (0.1.149): abre o seletor de arquivos do sistema. Escolher o mesmo arquivo de novo também vale. */
238
258
  export declare function SelectMailAttachButton({ onFiles, accept, multiple, disabled, label, }: {