tempest-react-sdk 0.29.1 → 0.31.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 (85) hide show
  1. package/dist/components/Chat/Chat.cjs +2 -0
  2. package/dist/components/Chat/Chat.cjs.map +1 -0
  3. package/dist/components/Chat/Chat.js +126 -0
  4. package/dist/components/Chat/Chat.js.map +1 -0
  5. package/dist/components/Chat/Chat.module.cjs +2 -0
  6. package/dist/components/Chat/Chat.module.cjs.map +1 -0
  7. package/dist/components/Chat/Chat.module.js +32 -0
  8. package/dist/components/Chat/Chat.module.js.map +1 -0
  9. package/dist/components/Chat/ChatComposer.cjs +2 -0
  10. package/dist/components/Chat/ChatComposer.cjs.map +1 -0
  11. package/dist/components/Chat/ChatComposer.js +67 -0
  12. package/dist/components/Chat/ChatComposer.js.map +1 -0
  13. package/dist/components/Chat/chat-groups.cjs +2 -0
  14. package/dist/components/Chat/chat-groups.cjs.map +1 -0
  15. package/dist/components/Chat/chat-groups.js +89 -0
  16. package/dist/components/Chat/chat-groups.js.map +1 -0
  17. package/dist/components/FilterBar/FilterBar.cjs +2 -0
  18. package/dist/components/FilterBar/FilterBar.cjs.map +1 -0
  19. package/dist/components/FilterBar/FilterBar.js +238 -0
  20. package/dist/components/FilterBar/FilterBar.js.map +1 -0
  21. package/dist/components/FilterBar/FilterBar.module.cjs +2 -0
  22. package/dist/components/FilterBar/FilterBar.module.cjs.map +1 -0
  23. package/dist/components/FilterBar/FilterBar.module.js +20 -0
  24. package/dist/components/FilterBar/FilterBar.module.js.map +1 -0
  25. package/dist/components/FilterBar/filter-model.cjs +2 -0
  26. package/dist/components/FilterBar/filter-model.cjs.map +1 -0
  27. package/dist/components/FilterBar/filter-model.js +167 -0
  28. package/dist/components/FilterBar/filter-model.js.map +1 -0
  29. package/dist/components/Markdown/Markdown.cjs +2 -0
  30. package/dist/components/Markdown/Markdown.cjs.map +1 -0
  31. package/dist/components/Markdown/Markdown.js +124 -0
  32. package/dist/components/Markdown/Markdown.js.map +1 -0
  33. package/dist/components/Markdown/Markdown.module.cjs +2 -0
  34. package/dist/components/Markdown/Markdown.module.cjs.map +1 -0
  35. package/dist/components/Markdown/Markdown.module.js +23 -0
  36. package/dist/components/Markdown/Markdown.module.js.map +1 -0
  37. package/dist/components/Markdown/markdown-parse.cjs +7 -0
  38. package/dist/components/Markdown/markdown-parse.cjs.map +1 -0
  39. package/dist/components/Markdown/markdown-parse.js +269 -0
  40. package/dist/components/Markdown/markdown-parse.js.map +1 -0
  41. package/dist/components/Markdown/markdown-url.cjs +2 -0
  42. package/dist/components/Markdown/markdown-url.cjs.map +1 -0
  43. package/dist/components/Markdown/markdown-url.js +28 -0
  44. package/dist/components/Markdown/markdown-url.js.map +1 -0
  45. package/dist/components/Masonry/Masonry.cjs +2 -0
  46. package/dist/components/Masonry/Masonry.cjs.map +1 -0
  47. package/dist/components/Masonry/Masonry.js +70 -0
  48. package/dist/components/Masonry/Masonry.js.map +1 -0
  49. package/dist/components/Masonry/Masonry.module.cjs +2 -0
  50. package/dist/components/Masonry/Masonry.module.cjs.map +1 -0
  51. package/dist/components/Masonry/Masonry.module.js +10 -0
  52. package/dist/components/Masonry/Masonry.module.js.map +1 -0
  53. package/dist/components/Masonry/masonry-layout.cjs +2 -0
  54. package/dist/components/Masonry/masonry-layout.cjs.map +1 -0
  55. package/dist/components/Masonry/masonry-layout.js +20 -0
  56. package/dist/components/Masonry/masonry-layout.js.map +1 -0
  57. package/dist/components/Tour/Tour.cjs +2 -0
  58. package/dist/components/Tour/Tour.cjs.map +1 -0
  59. package/dist/components/Tour/Tour.js +186 -0
  60. package/dist/components/Tour/Tour.js.map +1 -0
  61. package/dist/components/Tour/Tour.module.cjs +2 -0
  62. package/dist/components/Tour/Tour.module.cjs.map +1 -0
  63. package/dist/components/Tour/Tour.module.js +21 -0
  64. package/dist/components/Tour/Tour.module.js.map +1 -0
  65. package/dist/components/Tour/tour-position.cjs +2 -0
  66. package/dist/components/Tour/tour-position.cjs.map +1 -0
  67. package/dist/components/Tour/tour-position.js +105 -0
  68. package/dist/components/Tour/tour-position.js.map +1 -0
  69. package/dist/components/Transfer/Transfer.cjs +2 -0
  70. package/dist/components/Transfer/Transfer.cjs.map +1 -0
  71. package/dist/components/Transfer/Transfer.js +163 -0
  72. package/dist/components/Transfer/Transfer.js.map +1 -0
  73. package/dist/components/Transfer/Transfer.module.cjs +2 -0
  74. package/dist/components/Transfer/Transfer.module.cjs.map +1 -0
  75. package/dist/components/Transfer/Transfer.module.js +19 -0
  76. package/dist/components/Transfer/Transfer.module.js.map +1 -0
  77. package/dist/components/Transfer/transfer-state.cjs +2 -0
  78. package/dist/components/Transfer/transfer-state.cjs.map +1 -0
  79. package/dist/components/Transfer/transfer-state.js +59 -0
  80. package/dist/components/Transfer/transfer-state.js.map +1 -0
  81. package/dist/styles.css +1 -1
  82. package/dist/tempest-react-sdk.cjs +1 -1
  83. package/dist/tempest-react-sdk.d.ts +674 -0
  84. package/dist/tempest-react-sdk.js +117 -105
  85. package/package.json +1 -1
@@ -359,6 +359,27 @@ export declare interface ApplyThemeOptions {
359
359
  target?: Document | ShadowRoot | HTMLElement;
360
360
  }
361
361
 
362
+ /**
363
+ * Apply a move and return the next value.
364
+ *
365
+ * Disabled rows are dropped here rather than at the call site, so no caller can
366
+ * move one by pressing the bulk button — the check has to live where the
367
+ * decision is made, not in each of the four places that trigger one.
368
+ *
369
+ * @param params.value - Current target ids.
370
+ * @param params.moving - Ids being moved.
371
+ * @param params.to - Destination pane.
372
+ * @param params.items - The catalogue, to look disabled rows up.
373
+ * @param params.order - Ids in catalogue order, so the result stays stable.
374
+ * @returns The next value, in catalogue order.
375
+ */
376
+ export declare function applyTransferMove({ value, moving, to, items, }: {
377
+ value: readonly string[];
378
+ moving: readonly string[];
379
+ to: TransferSide;
380
+ items: readonly TransferItem[];
381
+ }): string[];
382
+
362
383
  /**
363
384
  * Compose the Tempest app-wide providers in one place: error boundary →
364
385
  * TanStack Query → theme → i18n. Query and theme are on by default; i18n and
@@ -1095,6 +1116,177 @@ export declare const CEPInput: ForwardRefExoticComponent<Omit<InputProps, "value
1095
1116
  /** A `var(--tempest-chart-…)` reference, so the value follows the active theme. */
1096
1117
  export declare type ChartColorToken = string;
1097
1118
 
1119
+ /**
1120
+ * A message thread: grouped by author and by day, own messages on one side, with
1121
+ * delivery state, a typing indicator and an optional composer.
1122
+ *
1123
+ * Presentational and controlled, like the rest of the SDK: it takes a list and
1124
+ * emits intent (`onSend`, `onRetry`). Where messages come from — REST, the SDK's
1125
+ * `createWebSocket`, an SSE stream — and how an optimistic insert is done stay with
1126
+ * the app, because those differ per backend and a component that assumed one would
1127
+ * be wrong for most.
1128
+ *
1129
+ * It works as a comment thread too: that is the same component with
1130
+ * `currentUserId` set and no `typing`.
1131
+ *
1132
+ * @example
1133
+ * <Chat
1134
+ * messages={messages}
1135
+ * currentUserId={me.id}
1136
+ * typing={typingNames}
1137
+ * onSend={(text) => send({ text })}
1138
+ * onRetry={(message) => resend(message.id)}
1139
+ * />
1140
+ */
1141
+ export declare function Chat({ messages, currentUserId, onSend, onRetry, typing, renderAvatar, header, emptyState, groupWindowMs, locale, now, placeholder, composerActions, composerDisabled, onSendError, className, ...rest }: ChatProps): JSX.Element;
1142
+
1143
+ /**
1144
+ * The message field of a thread: a textarea that grows with its content, sends on
1145
+ * `Enter` and keeps `Shift+Enter` for a newline.
1146
+ *
1147
+ * Uncontrolled on purpose. A chat draft changes on every keystroke, and lifting
1148
+ * that into app state re-renders the whole thread per character — the one place
1149
+ * where "controlled by default" costs something visible. Apps that need the draft
1150
+ * (a persisted composer, a slash-command menu) read it from `onChange` or drive it
1151
+ * through the ref.
1152
+ *
1153
+ * @example
1154
+ * <ChatComposer onSend={(text) => api.post("/messages", { body: { text } })} />
1155
+ */
1156
+ export declare const ChatComposer: ForwardRefExoticComponent<ChatComposerProps & RefAttributes<ChatComposerHandle>>;
1157
+
1158
+ /** Imperative handle, so a thread can focus the field after retrying a message. */
1159
+ export declare interface ChatComposerHandle {
1160
+ focus: () => void;
1161
+ /** Replace the draft — used to put a failed message back in the field. */
1162
+ setValue: (text: string) => void;
1163
+ }
1164
+
1165
+ export declare interface ChatComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, OverriddenDomProps_3> {
1166
+ /** Called with the trimmed text. The field clears only when this does not throw. */
1167
+ onSend: (text: string) => void | Promise<void>;
1168
+ /** Locale for the placeholder and the send label. Default `"pt-BR"`. */
1169
+ locale?: "pt-BR" | "en";
1170
+ /** Rendered to the left of the send button — an attach button, an emoji picker. */
1171
+ actions?: ReactNode;
1172
+ /** Largest height the field grows to, in lines. Default 6. */
1173
+ maxRows?: number;
1174
+ /** Send label. Defaults to the locale string. */
1175
+ sendLabel?: string;
1176
+ /**
1177
+ * Called when `onSend` rejects. The draft is kept either way.
1178
+ *
1179
+ * Without it the rejection is swallowed after the draft is preserved, because
1180
+ * the alternative is worse: re-throwing out of a DOM event handler surfaces as
1181
+ * an unhandled promise rejection — console noise for the developer, a hit in
1182
+ * whatever crash reporter the app runs, and nothing the user can act on. The
1183
+ * visible signal is the text still sitting in the field; wire this to a toast
1184
+ * to say why.
1185
+ */
1186
+ onError?: (error: unknown) => void;
1187
+ }
1188
+
1189
+ /** A date heading between runs. */
1190
+ export declare interface ChatDay {
1191
+ kind: "day";
1192
+ key: string;
1193
+ /** Midnight of that local day, epoch ms — the label is formatted by the view. */
1194
+ date: number;
1195
+ }
1196
+
1197
+ /** One entry in a thread. */
1198
+ export declare interface ChatMessage {
1199
+ /** Stable identity. Used as the React key and by `onRetry`. */
1200
+ id: string;
1201
+ /** What was said. A node, so an app can render a link, an image or a quote. */
1202
+ body: ReactNode;
1203
+ /** Who said it. Compared against `currentUserId` to decide sides. */
1204
+ authorId: string;
1205
+ /** Display name. Falls back to `authorId` in the header of a run. */
1206
+ authorName?: string;
1207
+ /** Epoch milliseconds. */
1208
+ sentAt: number;
1209
+ /**
1210
+ * Delivery state of an outgoing message.
1211
+ *
1212
+ * `"failed"` is the one that matters: without it an app has to invent its own
1213
+ * way to say "this never left", and the user re-types a message that is
1214
+ * sitting right there.
1215
+ */
1216
+ status?: "sending" | "sent" | "read" | "failed";
1217
+ /** Anything the app wants to carry through to its own renderers. */
1218
+ data?: Record<string, unknown>;
1219
+ }
1220
+
1221
+ export declare interface ChatProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_2> {
1222
+ /** The thread, **oldest first**. Never reordered by the component. */
1223
+ messages: readonly ChatMessage[];
1224
+ /** Author id treated as "own" — decides side, colour and status ticks. */
1225
+ currentUserId?: string;
1226
+ /** Renders the composer when given. Receives the trimmed text. */
1227
+ onSend?: (text: string) => void | Promise<void>;
1228
+ /** Enables the retry control on a `"failed"` message. */
1229
+ onRetry?: (message: ChatMessage) => void;
1230
+ /** Names currently typing. One, two or a count is phrased for you. */
1231
+ typing?: readonly string[];
1232
+ /** Avatar for the first message of a run — an `<Avatar>`, an `<Icon>`. */
1233
+ renderAvatar?: (message: ChatMessage) => ReactNode;
1234
+ /** Rendered above the thread, inside the panel. */
1235
+ header?: ReactNode;
1236
+ /** Shown when there are no messages. */
1237
+ emptyState?: ReactNode;
1238
+ /** Gap that still keeps consecutive messages in one run. Default 5 min. */
1239
+ groupWindowMs?: number;
1240
+ /** Locale for labels. Default `"pt-BR"`. */
1241
+ locale?: "pt-BR" | "en";
1242
+ /** Reference instant for "Hoje"/"Ontem". Default: now, at render time. */
1243
+ now?: number;
1244
+ /** Placeholder for the composer. */
1245
+ placeholder?: string;
1246
+ /** Extra controls inside the composer, before the send button. */
1247
+ composerActions?: ReactNode;
1248
+ /** Disable the composer — no permission, thread archived, offline. */
1249
+ composerDisabled?: boolean;
1250
+ /** Called when `onSend` rejects. The draft stays in the field either way. */
1251
+ onSendError?: (error: unknown) => void;
1252
+ }
1253
+
1254
+ /** A run of consecutive messages from one author, under one day. */
1255
+ export declare interface ChatRun {
1256
+ kind: "run";
1257
+ /** `${authorId}-${first message id}` — stable across re-renders. */
1258
+ key: string;
1259
+ authorId: string;
1260
+ authorName?: string;
1261
+ /** Whether this run belongs to the current user. */
1262
+ own: boolean;
1263
+ messages: ChatMessage[];
1264
+ }
1265
+
1266
+ export declare type ChatSection = ChatDay | ChatRun;
1267
+
1268
+ /** Labels the thread needs, per locale. */
1269
+ declare interface ChatStrings {
1270
+ thread: string;
1271
+ today: string;
1272
+ yesterday: string;
1273
+ you: string;
1274
+ typingOne: (name: string) => string;
1275
+ typingTwo: (a: string, b: string) => string;
1276
+ typingMany: (n: number) => string;
1277
+ sending: string;
1278
+ sent: string;
1279
+ read: string;
1280
+ failed: string;
1281
+ retry: string;
1282
+ empty: string;
1283
+ placeholder: string;
1284
+ send: string;
1285
+ }
1286
+
1287
+ /** Locale strings for the thread. */
1288
+ export declare function chatStrings(locale: "pt-BR" | "en"): ChatStrings;
1289
+
1098
1290
  /**
1099
1291
  * Accessible checkbox. Supports a tri-state via `indeterminate` and pairs the
1100
1292
  * input with a label/description column for forms.
@@ -2526,6 +2718,17 @@ export declare interface DateRangePickerProps extends Omit<HTMLAttributes<HTMLDi
2526
2718
  weekStartsOn?: WeekStart_2;
2527
2719
  }
2528
2720
 
2721
+ /**
2722
+ * Label for a date heading: `"Hoje"`, `"Ontem"`, or the formatted date.
2723
+ *
2724
+ * @param date - Local midnight of the day being labelled.
2725
+ * @param params.now - Reference instant, so tests and SSR-free renders are stable.
2726
+ */
2727
+ export declare function dayLabel(date: number, { locale, now }?: {
2728
+ locale?: "pt-BR" | "en";
2729
+ now?: number;
2730
+ }): string;
2731
+
2529
2732
  /** The visible time window of a day, in minutes from midnight. */
2530
2733
  export declare interface DayWindow {
2531
2734
  startMinute: number;
@@ -2622,6 +2825,15 @@ export declare const DEFAULT_MODE_DURATION_FACTORS: Record<TravelMode, number>;
2622
2825
  */
2623
2826
  export declare function defineRoutes(routes: TempestRouteObject[]): TempestRouteObject[];
2624
2827
 
2828
+ /**
2829
+ * One filter, in words: `"Status é Pago"`.
2830
+ *
2831
+ * Used for the chip and for the screen-reader announcement, from the same source —
2832
+ * a chip that reads `status=eq:paid` to a sighted user and something else to a
2833
+ * screen reader would be two different truths.
2834
+ */
2835
+ export declare function describeFilter(filter: Filter, fields: readonly FilterField[], locale?: "pt-BR" | "en"): string;
2836
+
2625
2837
  /**
2626
2838
  * Renders a semantic `<dl>` of term/description pairs with minimal
2627
2839
  * token-based key/value styling.
@@ -3074,8 +3286,104 @@ export declare interface FileUploadProps {
3074
3286
  className?: string;
3075
3287
  }
3076
3288
 
3289
+ /** One applied filter. */
3290
+ export declare interface Filter {
3291
+ field: string;
3292
+ operator: FilterOperator;
3293
+ /** `between` carries a pair; `in` carries a list; `empty`/`notEmpty` carry nothing. */
3294
+ value?: string | readonly string[];
3295
+ }
3296
+
3297
+ /**
3298
+ * A row of applied filters, and a small editor to add another.
3299
+ *
3300
+ * Filters are combined with **AND**, flat — no nested `(a OR b) AND c` groups. That
3301
+ * is the shape of nearly every admin list ("status is paid, created after March,
3302
+ * text contains nota"), and it is what serializes into a URL somebody can send to a
3303
+ * colleague. Nested groups need a tree UI with per-node operators and a different
3304
+ * serialization; a component trying to be both is clumsy at the common case.
3305
+ *
3306
+ * Controlled, like the rest of the SDK: it holds the half-typed draft in the editor
3307
+ * and nothing else. The applied set is the app's, which is what lets it come from —
3308
+ * and go back into — the URL.
3309
+ *
3310
+ * @example
3311
+ * const [filters, setFilters] = useState<Filter[]>(() =>
3312
+ * filtersFromSearchParams(new URLSearchParams(location.search), FIELDS),
3313
+ * );
3314
+ *
3315
+ * <FilterBar fields={FIELDS} value={filters} onChange={setFilters} />
3316
+ */
3317
+ export declare function FilterBar({ fields, value, onChange, locale, actions, className, ...rest }: FilterBarProps): JSX.Element;
3318
+
3319
+ export declare interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_7> {
3320
+ /** Fields the user may filter by. */
3321
+ fields: readonly FilterField[];
3322
+ /** Applied filters. Controlled. */
3323
+ value: readonly Filter[];
3324
+ /** Next filter set. Combined with AND. */
3325
+ onChange: (filters: Filter[]) => void;
3326
+ /** Locale for the labels. Default `"pt-BR"`. */
3327
+ locale?: "pt-BR" | "en";
3328
+ /** Rendered at the end of the bar — a "save this view" button, a counter. */
3329
+ actions?: ReactNode;
3330
+ }
3331
+
3332
+ /** One filterable field. */
3333
+ export declare interface FilterField {
3334
+ /** Key sent to the backend. */
3335
+ name: string;
3336
+ /** What the user sees. */
3337
+ label: string;
3338
+ type: FilterFieldType;
3339
+ /** Choices for `select`. */
3340
+ options?: ReadonlyArray<{
3341
+ value: string;
3342
+ label: string;
3343
+ }>;
3344
+ /** Restrict or reorder the operators offered. Defaults per type. */
3345
+ operators?: readonly FilterOperator[];
3346
+ /** Placeholder for the value input. */
3347
+ placeholder?: string;
3348
+ }
3349
+
3350
+ /** Kind of value a field holds, which decides its operators and its input. */
3351
+ export declare type FilterFieldType = "text" | "number" | "date" | "select" | "boolean";
3352
+
3353
+ /** Comparison a filter can make. */
3354
+ export declare type FilterOperator = "eq" | "ne" | "contains" | "gt" | "gte" | "lt" | "lte" | "between" | "in" | "empty" | "notEmpty";
3355
+
3077
3356
  export declare type FilterPredicate<T> = (item: T, search: string) => boolean;
3078
3357
 
3358
+ /**
3359
+ * Read filters back from URL search params.
3360
+ *
3361
+ * Anything that does not parse is dropped rather than guessed at: a hand-edited URL
3362
+ * is the normal way this input arrives, and rendering a filter the app cannot
3363
+ * evaluate would show a list that does not match what the chips claim.
3364
+ *
3365
+ * @param params - Params from the location.
3366
+ * @param fields - Known fields; a param naming anything else is ignored.
3367
+ * @returns The filters that parsed.
3368
+ */
3369
+ export declare function filtersFromSearchParams(params: URLSearchParams, fields: readonly FilterField[]): Filter[];
3370
+
3371
+ /**
3372
+ * Serialize filters into URL search params.
3373
+ *
3374
+ * One param per filter, `field=operator:value`, with `|` between the values of a
3375
+ * multi-value operator. A filter set that cannot survive a reload is a filter set
3376
+ * people re-enter every time they open a link somebody sent them, so this is part
3377
+ * of the model rather than something each app reinvents.
3378
+ *
3379
+ * Repeated fields are kept: `status=eq:paid&status=eq:sent` is two filters, and
3380
+ * collapsing them would silently drop one.
3381
+ *
3382
+ * @param filters - Applied filters.
3383
+ * @returns Params ready to merge into a location.
3384
+ */
3385
+ export declare function filtersToSearchParams(filters: readonly Filter[]): URLSearchParams;
3386
+
3079
3387
  /**
3080
3388
  * Build a projection that fits `bounds` into a `width × height` viewport while
3081
3389
  * preserving aspect ratio (uniform scale, centered). This is what powers the
@@ -3575,6 +3883,33 @@ export declare interface GridProps extends HTMLAttributes<HTMLDivElement> {
3575
3883
  */
3576
3884
  export declare function groupBy<T, K extends PropertyKey>(items: T[], key: (item: T) => K): Record<K, T[]>;
3577
3885
 
3886
+ /**
3887
+ * Turn a flat message list into the sections a thread renders: a date heading
3888
+ * whenever the local day changes, and runs of consecutive messages from the same
3889
+ * author.
3890
+ *
3891
+ * Grouping is what makes a thread readable — repeating the avatar and the name on
3892
+ * every line of a five-line burst turns a conversation into a list of receipts.
3893
+ * The run breaks on a different author, a different day, or a gap longer than
3894
+ * `windowMs`: a reply an hour later is a new beat in the conversation even when
3895
+ * nobody else spoke, and joining it to the earlier burst would put one timestamp
3896
+ * on messages an hour apart.
3897
+ *
3898
+ * Order is taken as given, oldest first, and never sorted here: a thread that
3899
+ * reorders what the server sent would fight optimistic inserts, where the
3900
+ * pending message is deliberately last.
3901
+ *
3902
+ * @param params.messages - Oldest first.
3903
+ * @param params.currentUserId - Author id treated as "own".
3904
+ * @param params.windowMs - Gap that still keeps a run together. Default 5 min.
3905
+ * @returns Sections in render order.
3906
+ */
3907
+ export declare function groupMessages({ messages, currentUserId, windowMs, }: {
3908
+ messages: readonly ChatMessage[];
3909
+ currentUserId?: string;
3910
+ windowMs?: number;
3911
+ }): ChatSection[];
3912
+
3578
3913
  /**
3579
3914
  * Minimal subset of [`@growthbook/growthbook`](https://docs.growthbook.io/lib/js)
3580
3915
  * used by the adapter. Pass a `GrowthBook` instance directly.
@@ -4611,6 +4946,138 @@ export declare interface LongPressHandlers {
4611
4946
  onContextMenu: (event: MouseEvent_2) => void;
4612
4947
  }
4613
4948
 
4949
+ /**
4950
+ * Rendered Markdown, from a node tree — never from an HTML string.
4951
+ *
4952
+ * `dangerouslySetInnerHTML` appears nowhere in this component. That is what makes
4953
+ * rendering somebody else's Markdown safe by construction rather than by a promise
4954
+ * about escaping: a `<script>` in a comment is four characters of text, because text
4955
+ * is all a React child can be.
4956
+ *
4957
+ * Link and image URLs go through a scheme **allowlist** (`http`, `https`, `mailto`,
4958
+ * `tel`, `sms`, plus relative), so `[click](javascript:alert(1))` renders as plain
4959
+ * text. A blocklist would have to enumerate every spelling of `javascript:` and
4960
+ * would miss one.
4961
+ *
4962
+ * @example
4963
+ * <Markdown source={comentario.corpo} linkProps={{ target: "_blank", rel: "noreferrer" }} />
4964
+ */
4965
+ export declare function Markdown({ source, headingOffset, highlightCode, showLineNumbers, linkProps, className, ...rest }: MarkdownProps): JSX.Element;
4966
+
4967
+ /** Column alignment of a table, from the delimiter row. */
4968
+ export declare type MarkdownAlign = "left" | "center" | "right" | null;
4969
+
4970
+ /** Block content. */
4971
+ export declare type MarkdownBlock = {
4972
+ type: "heading";
4973
+ level: number;
4974
+ children: MarkdownInline[];
4975
+ } | {
4976
+ type: "paragraph";
4977
+ children: MarkdownInline[];
4978
+ } | {
4979
+ type: "code";
4980
+ language: string | null;
4981
+ value: string;
4982
+ } | {
4983
+ type: "quote";
4984
+ children: MarkdownBlock[];
4985
+ } | {
4986
+ type: "list";
4987
+ ordered: boolean;
4988
+ start: number;
4989
+ items: MarkdownBlock[][];
4990
+ } | {
4991
+ type: "table";
4992
+ align: MarkdownAlign[];
4993
+ head: MarkdownInline[][];
4994
+ rows: MarkdownInline[][][];
4995
+ } | {
4996
+ type: "rule";
4997
+ };
4998
+
4999
+ /** Inline content. */
5000
+ export declare type MarkdownInline = {
5001
+ type: "text";
5002
+ value: string;
5003
+ } | {
5004
+ type: "strong";
5005
+ children: MarkdownInline[];
5006
+ } | {
5007
+ type: "em";
5008
+ children: MarkdownInline[];
5009
+ } | {
5010
+ type: "del";
5011
+ children: MarkdownInline[];
5012
+ } | {
5013
+ type: "code";
5014
+ value: string;
5015
+ } | {
5016
+ type: "link";
5017
+ href: string;
5018
+ children: MarkdownInline[];
5019
+ } | {
5020
+ type: "image";
5021
+ src: string;
5022
+ alt: string;
5023
+ } | {
5024
+ type: "break";
5025
+ };
5026
+
5027
+ export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_6> {
5028
+ /** The Markdown source. */
5029
+ source: string;
5030
+ /**
5031
+ * Heading level the document's `#` maps to. Default 2.
5032
+ *
5033
+ * A comment body rendered inside a page whose `<h1>` is the page title must not
5034
+ * emit a second `<h1>`; shifting the whole scale keeps the outline valid.
5035
+ */
5036
+ headingOffset?: number;
5037
+ /** Render fenced code with `CodeBlock` (copy button, line numbers). Default `true`. */
5038
+ highlightCode?: boolean;
5039
+ /** Show line numbers in fenced code. Default `false`. */
5040
+ showLineNumbers?: boolean;
5041
+ /** Extra props for every link — `target="_blank"`, an analytics handler. */
5042
+ linkProps?: HTMLAttributes<HTMLAnchorElement> & {
5043
+ target?: string;
5044
+ rel?: string;
5045
+ };
5046
+ }
5047
+
5048
+ /**
5049
+ * Masonry layout: cards of uneven height packed into columns with an even bottom
5050
+ * edge.
5051
+ *
5052
+ * Measures the rendered cards and deals each one into the shortest column, rather
5053
+ * than using CSS `columns` or `grid-auto-flow: dense`. Both of those are one line
5054
+ * of CSS and neither does this job: CSS `columns` breaks a card across the column
5055
+ * boundary, and a dense grid keeps every row the height of its tallest cell, which
5056
+ * is the ragged bottom edge people reach for masonry to avoid.
5057
+ *
5058
+ * @example
5059
+ * <Masonry items={fotos} itemKey={(foto) => foto.id} columns={{ 0: 1, 700: 2, 1100: 4 }}>
5060
+ * {(foto) => <img src={foto.url} alt={foto.alt} />}
5061
+ * </Masonry>
5062
+ */
5063
+ export declare function Masonry<T>({ items, children, itemKey, columns, gap, className, style, ...rest }: MasonryProps<T>): JSX.Element;
5064
+
5065
+ export declare interface MasonryProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_5> {
5066
+ /** What to lay out. */
5067
+ items: readonly T[];
5068
+ /** Render one card. */
5069
+ children: (item: T, index: number) => ReactNode;
5070
+ /** Stable key per item. Index is a fallback nobody should rely on. */
5071
+ itemKey?: (item: T, index: number) => string | number;
5072
+ /**
5073
+ * Column count: a fixed number, or a `width → columns` map read as
5074
+ * "from this width up". Default `{ 0: 1, 640: 2, 1024: 3 }`.
5075
+ */
5076
+ columns?: number | Record<number, number>;
5077
+ /** Gap between cards, any CSS length. Default `var(--tempest-space-4)`. */
5078
+ gap?: string;
5079
+ }
5080
+
4614
5081
  /**
4615
5082
  * The matrix as an SVG path, one `M…h…v…h…z` rectangle per dark module.
4616
5083
  *
@@ -5461,6 +5928,9 @@ export declare interface OpenModalOptions {
5461
5928
  onClose?: () => void;
5462
5929
  }
5463
5930
 
5931
+ /** The operators a field offers. */
5932
+ export declare function operatorsFor(field: FilterField): FilterOperator[];
5933
+
5464
5934
  /**
5465
5935
  * First sequential step that clears 2:1 against the chart surface.
5466
5936
  *
@@ -5544,6 +6014,24 @@ export { Outlet }
5544
6014
  */
5545
6015
  declare type OverriddenDomProps = "children" | "title" | "onSelect";
5546
6016
 
6017
+ /** DOM attributes this component redefines. */
6018
+ declare type OverriddenDomProps_2 = "children" | "onSubmit";
6019
+
6020
+ /** DOM attributes the composer redefines. */
6021
+ declare type OverriddenDomProps_3 = "onSubmit" | "value" | "defaultValue" | "rows";
6022
+
6023
+ /** DOM attributes this component redefines. */
6024
+ declare type OverriddenDomProps_4 = "children" | "onChange" | "defaultValue";
6025
+
6026
+ /** DOM attributes this component redefines. */
6027
+ declare type OverriddenDomProps_5 = "children";
6028
+
6029
+ /** DOM attributes this component redefines. */
6030
+ declare type OverriddenDomProps_6 = "children";
6031
+
6032
+ /** DOM attributes this component redefines. */
6033
+ declare type OverriddenDomProps_7 = "children" | "onChange";
6034
+
5547
6035
  /**
5548
6036
  * Page wrapper with header + (optional) toolbar + content + footer. Pairs
5549
6037
  * with `Container` when you want a max-width content well.
@@ -5597,6 +6085,14 @@ export { Params }
5597
6085
  /** Query-param values accepted by the API client for a list request. */
5598
6086
  declare type ParamValue = string | number | boolean | undefined | null;
5599
6087
 
6088
+ /**
6089
+ * Parse a Markdown document into blocks.
6090
+ *
6091
+ * @param source - Raw Markdown.
6092
+ * @returns Block nodes in document order.
6093
+ */
6094
+ export declare function parseMarkdown(source: string): MarkdownBlock[];
6095
+
5600
6096
  /**
5601
6097
  * Validate an unknown response payload against a zod schema.
5602
6098
  *
@@ -6645,6 +7141,28 @@ export declare interface SafeAreaProps extends HTMLAttributes<HTMLDivElement> {
6645
7141
  children?: ReactNode;
6646
7142
  }
6647
7143
 
7144
+ /**
7145
+ * URL vetting for links and images in rendered Markdown.
7146
+ *
7147
+ * This is the security boundary of the whole component. Markdown that arrives from
7148
+ * a user — a comment, a ticket description, a review — reaches the DOM as a real
7149
+ * `href`, and `javascript:alert(1)` in a link is script execution on click. So the
7150
+ * scheme is checked against an allowlist rather than a blocklist: a blocklist has
7151
+ * to enumerate `javascript:`, `JaVaScRiPt:`, `java\tscript:`, `&#106;avascript:`
7152
+ * and whatever comes next, and misses the one nobody thought of.
7153
+ */
7154
+ /**
7155
+ * The href to render, or `null` when the URL must not be linked.
7156
+ *
7157
+ * Relative URLs (`/docs`, `./x`, `#anchor`, `foo/bar`) are kept: they cannot carry
7158
+ * a scheme, so they cannot execute anything, and dropping them would break every
7159
+ * in-app link.
7160
+ *
7161
+ * @param raw - URL as written in the Markdown.
7162
+ * @returns A safe href, or `null`.
7163
+ */
7164
+ export declare function safeLinkUrl(raw: string): string | null;
7165
+
6648
7166
  /** The ten steps of a Tempest tint scale, lightest to darkest. */
6649
7167
  export declare type ScaleStep = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
6650
7168
 
@@ -7289,6 +7807,25 @@ export declare interface SpinnerProps {
7289
7807
 
7290
7808
  export declare type SpinnerSize = "xs" | "sm" | "md" | "lg" | "xl";
7291
7809
 
7810
+ /**
7811
+ * Split the catalogue into the two panes.
7812
+ *
7813
+ * The selected ids are the single source of truth — the panes are derived, never
7814
+ * stored. Two stored lists drift the moment the catalogue changes under them: a
7815
+ * permission that is removed upstream lingers in whichever pane held it, and an
7816
+ * id that appears in both is a bug nobody can see.
7817
+ *
7818
+ * Order follows `items`, so both panes read in the catalogue's order rather than
7819
+ * in the order somebody happened to click.
7820
+ *
7821
+ * @param items - The whole catalogue.
7822
+ * @param value - Ids currently on the target side.
7823
+ */
7824
+ export declare function splitTransferSides(items: readonly TransferItem[], value: readonly string[]): {
7825
+ source: TransferItem[];
7826
+ target: TransferItem[];
7827
+ };
7828
+
7292
7829
  /** Flex-based vertical or horizontal stack with a numeric `gap`. */
7293
7830
  export declare function Stack({ direction, gap, align, justify, wrap, className, style, children, ...props }: StackProps): JSX.Element;
7294
7831
 
@@ -7916,6 +8453,9 @@ export declare function throttle<A extends unknown[]>(fn: (...args: A) => void,
7916
8453
  cancel: () => void;
7917
8454
  };
7918
8455
 
8456
+ /** Clock label for a single message — the time, not a relative phrase. */
8457
+ export declare function timeLabel(timestamp: number, locale?: "pt-BR" | "en"): string;
8458
+
7919
8459
  /**
7920
8460
  * Vertical event timeline — activity feeds, order trackers, audit logs.
7921
8461
  * Each entry has a marker (color or custom icon), title, optional
@@ -8165,6 +8705,76 @@ export declare interface TooltipProps {
8165
8705
  /** Convert degrees to radians. */
8166
8706
  export declare function toRadians(degrees: number): number;
8167
8707
 
8708
+ /**
8709
+ * A guided tour: dim the page, highlight one element at a time, explain it.
8710
+ *
8711
+ * The highlighted element stays **clickable** while everything else is blocked,
8712
+ * because the useful kind of coachmark says "press this" and lets you press it. That
8713
+ * is why the backdrop is four rectangles around the target rather than one overlay
8714
+ * with a `box-shadow` hole — a shadow is not hit-testable, so a hole made that way
8715
+ * would not block anything.
8716
+ *
8717
+ * Whether a user has seen the tour is the app's business: this component takes
8718
+ * `open` and emits `onClose`/`onFinish`. Persisting a flag in `localStorage` is one
8719
+ * line in the app and a wrong default here.
8720
+ *
8721
+ * @example
8722
+ * const [open, setOpen] = useState(!storage.get("tour-v1"));
8723
+ *
8724
+ * <Tour
8725
+ * open={open}
8726
+ * steps={[
8727
+ * { target: "#novo-pedido", title: "Comece aqui", body: "Todo pedido nasce deste botão." },
8728
+ * { target: "[data-tour='filtros']", body: "E filtre por período aqui." },
8729
+ * ]}
8730
+ * onClose={() => setOpen(false)}
8731
+ * onFinish={() => storage.set("tour-v1", true)}
8732
+ * />
8733
+ */
8734
+ export declare function Tour({ steps, open, onClose, onFinish, index, onIndexChange, locale, spotlightPadding, className, }: TourProps): JSX.Element | null;
8735
+
8736
+ /** Where the card sits relative to the highlighted element. */
8737
+ export declare type TourPlacement = "top" | "bottom" | "left" | "right" | "center";
8738
+
8739
+ export declare interface TourProps {
8740
+ /** The stops, in order. */
8741
+ steps: readonly TourStep[];
8742
+ /** Whether the tour is showing. Controlled. */
8743
+ open: boolean;
8744
+ /** Closed by `Esc`, by the close button or by "skip". */
8745
+ onClose: () => void;
8746
+ /** Called after the last step is confirmed. `onClose` follows it. */
8747
+ onFinish?: () => void;
8748
+ /** Current step index, when the app wants to drive it. */
8749
+ index?: number;
8750
+ /** Step changed — required only when `index` is given. */
8751
+ onIndexChange?: (index: number) => void;
8752
+ /** Locale for the labels. Default `"pt-BR"`. */
8753
+ locale?: "pt-BR" | "en";
8754
+ /** Space kept clear around the highlighted element, in px. Default 4. */
8755
+ spotlightPadding?: number;
8756
+ /** Extra class on the card. */
8757
+ className?: string;
8758
+ }
8759
+
8760
+ /** One stop of the tour. */
8761
+ export declare interface TourStep {
8762
+ /**
8763
+ * CSS selector of the element to point at.
8764
+ *
8765
+ * A selector rather than a ref, so a tour can be declared as data — in a config
8766
+ * file, from the backend, next to the copy — without every screen having to
8767
+ * thread refs up to whoever renders the tour.
8768
+ */
8769
+ target?: string;
8770
+ /** Heading of the card. */
8771
+ title?: ReactNode;
8772
+ /** The explanation. */
8773
+ body: ReactNode;
8774
+ /** Preferred side. Default `"bottom"`, flipped when it does not fit. */
8775
+ placement?: TourPlacement;
8776
+ }
8777
+
8168
8778
  /** Lifecycle status of a {@link PositionTracker}. */
8169
8779
  export declare type TrackerStatus = "idle" | "tracking" | "error";
8170
8780
 
@@ -8227,6 +8837,67 @@ export declare interface TrajectoryMapProps extends Omit<HTMLAttributes<HTMLDivE
8227
8837
  onMarkerClick?: (marker: GeoMarker, index: number) => void;
8228
8838
  }
8229
8839
 
8840
+ /**
8841
+ * Two panes and a set of move controls: pick a subset out of a catalogue.
8842
+ *
8843
+ * Controlled on **ids of the target side only**. The panes are derived on every
8844
+ * render, never stored, because two stored lists drift the moment the catalogue
8845
+ * changes under them — a permission removed upstream lingers in whichever pane
8846
+ * held it, and an id in both panes is a bug nobody can see.
8847
+ *
8848
+ * @example
8849
+ * const [roles, setRoles] = useState<string[]>([]);
8850
+ *
8851
+ * <Transfer
8852
+ * items={allRoles}
8853
+ * value={roles}
8854
+ * onChange={setRoles}
8855
+ * sourceTitle="Papéis disponíveis"
8856
+ * targetTitle="Papéis do usuário"
8857
+ * />
8858
+ */
8859
+ export declare function Transfer({ items, value, onChange, sourceTitle, targetTitle, searchable, renderItem, locale, height, disabled, className, ...rest }: TransferProps): JSX.Element;
8860
+
8861
+ /** One movable entry. */
8862
+ export declare interface TransferItem {
8863
+ /** Stable identity. What `value`/`onChange` carry. */
8864
+ id: string;
8865
+ /** What the row shows. */
8866
+ label: ReactNode;
8867
+ /** Text the search box matches against. Falls back to `label` when it is a string. */
8868
+ searchText?: string;
8869
+ /** Row that cannot move — a mandatory permission, a locked seat. */
8870
+ disabled?: boolean;
8871
+ /** Anything the app wants back in `renderItem`. */
8872
+ data?: Record<string, unknown>;
8873
+ }
8874
+
8875
+ export declare interface TransferProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_4> {
8876
+ /** The whole catalogue. Both panes are derived from it. */
8877
+ items: readonly TransferItem[];
8878
+ /** Ids on the target side. Controlled. */
8879
+ value: readonly string[];
8880
+ /** Next value, always in catalogue order. */
8881
+ onChange: (value: string[]) => void;
8882
+ /** Heading of the left pane. Default `"Disponíveis"`. */
8883
+ sourceTitle?: ReactNode;
8884
+ /** Heading of the right pane. Default `"Selecionados"`. */
8885
+ targetTitle?: ReactNode;
8886
+ /** Show a search box above each pane. Default `true` past 8 items. */
8887
+ searchable?: boolean;
8888
+ /** Custom row body. Gets the item and which side it is on. */
8889
+ renderItem?: (item: TransferItem, side: TransferSide) => ReactNode;
8890
+ /** Locale for labels. Default `"pt-BR"`. */
8891
+ locale?: "pt-BR" | "en";
8892
+ /** Height of each pane's scroll area, any CSS length. Default `"16rem"`. */
8893
+ height?: string;
8894
+ /** Block every move. */
8895
+ disabled?: boolean;
8896
+ }
8897
+
8898
+ /** Which pane an operation is about. */
8899
+ export declare type TransferSide = "source" | "target";
8900
+
8230
8901
  /**
8231
8902
  * Estimated travel between two coordinates. Mirrors the `TravelEstimate`
8232
8903
  * schema from `tempest-fastapi-sdk` (`geo/schemas.py`), snake_case preserved so
@@ -8350,6 +9021,9 @@ export declare interface TruncateTextProps extends HTMLAttributes<HTMLDivElement
8350
9021
  children: ReactNode;
8351
9022
  }
8352
9023
 
9024
+ /** Sentence for the typing indicator, or `null` when nobody is typing. */
9025
+ export declare function typingLabel(names: readonly string[], locale?: "pt-BR" | "en"): string | null;
9026
+
8353
9027
  /**
8354
9028
  * Remove duplicate items, keeping the first occurrence of each distinct key.
8355
9029
  *