@bysages/react 0.2.3 → 0.3.1

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 (92) hide show
  1. package/README.md +16 -2
  2. package/dist/{ai-response-jZy-0Tvv.mjs → ai-response-BfKTmtCt.mjs} +8 -4
  3. package/dist/components/ai/index.d.mts +2 -2
  4. package/dist/components/ai/index.mjs +32 -17
  5. package/dist/components/ai-attachments/index.mjs +3 -1
  6. package/dist/components/ai-prompt-input/index.d.mts +1 -1
  7. package/dist/components/ai-prompt-input/index.mjs +8 -4
  8. package/dist/components/ai-response/index.d.mts +4 -2
  9. package/dist/components/ai-response/index.mjs +1 -1
  10. package/dist/components/autocomplete/index.mjs +3 -1
  11. package/dist/components/avatar/index.d.mts +4 -1
  12. package/dist/components/avatar/index.mjs +3 -2
  13. package/dist/components/banner/index.mjs +21 -17
  14. package/dist/components/bento/index.d.mts +26 -0
  15. package/dist/components/bento/index.mjs +41 -0
  16. package/dist/components/block-ui/index.d.mts +12 -0
  17. package/dist/components/block-ui/index.mjs +24 -0
  18. package/dist/components/breadcrumb/index.d.mts +3 -8
  19. package/dist/components/breadcrumb/index.mjs +11 -1
  20. package/dist/components/browser/index.d.mts +23 -0
  21. package/dist/components/browser/index.mjs +70 -0
  22. package/dist/components/cascade-select/index.mjs +15 -5
  23. package/dist/components/command/index.mjs +9 -3
  24. package/dist/components/config-provider/index.d.mts +5 -2
  25. package/dist/components/config-provider/index.mjs +3 -2
  26. package/dist/components/data-view/index.d.mts +18 -0
  27. package/dist/components/data-view/index.mjs +66 -0
  28. package/dist/components/deferred-content/index.d.mts +16 -0
  29. package/dist/components/deferred-content/index.mjs +34 -0
  30. package/dist/components/descriptions/index.d.mts +13 -5
  31. package/dist/components/descriptions/index.mjs +20 -2
  32. package/dist/components/dock/index.d.mts +25 -0
  33. package/dist/components/dock/index.mjs +51 -0
  34. package/dist/components/dynamic-input/index.mjs +4 -2
  35. package/dist/components/file-upload/index.d.mts +8 -1
  36. package/dist/components/file-upload/index.mjs +20 -1
  37. package/dist/components/float-button/index.mjs +3 -1
  38. package/dist/components/form/index.mjs +1 -1
  39. package/dist/components/icon/index.d.mts +10 -5
  40. package/dist/components/icon/index.mjs +7 -7
  41. package/dist/components/image/index.d.mts +7 -1
  42. package/dist/components/image/index.mjs +3 -1
  43. package/dist/components/image-viewer/index.d.mts +7 -1
  44. package/dist/components/image-viewer/index.mjs +8 -4
  45. package/dist/components/input/index.d.mts +4 -1
  46. package/dist/components/input/index.mjs +1 -20
  47. package/dist/components/json-tree-view/index.d.mts +3 -3
  48. package/dist/components/json-tree-view/index.mjs +17 -4
  49. package/dist/components/layout/index.mjs +3 -1
  50. package/dist/components/list/index.d.mts +5 -4
  51. package/dist/components/list/index.mjs +10 -1
  52. package/dist/components/menubar/index.mjs +1 -0
  53. package/dist/components/order-list/index.d.mts +21 -0
  54. package/dist/components/order-list/index.mjs +161 -0
  55. package/dist/components/result/index.d.mts +31 -0
  56. package/dist/components/result/index.mjs +59 -0
  57. package/dist/components/select/index.d.mts +2 -17
  58. package/dist/components/select/index.mjs +2 -18
  59. package/dist/components/spinner/index.mjs +3 -1
  60. package/dist/components/split-button/index.mjs +3 -1
  61. package/dist/components/spotlight/index.d.mts +12 -0
  62. package/dist/components/spotlight/index.mjs +33 -0
  63. package/dist/components/steps/index.d.mts +5 -1
  64. package/dist/components/steps/index.mjs +10 -1
  65. package/dist/components/table/index.mjs +19 -15
  66. package/dist/components/tabs/index.d.mts +3 -1
  67. package/dist/components/tabs/index.mjs +3 -2
  68. package/dist/components/terminal/index.d.mts +17 -0
  69. package/dist/components/terminal/index.mjs +68 -0
  70. package/dist/components/timeline/index.d.mts +13 -11
  71. package/dist/components/timeline/index.mjs +11 -1
  72. package/dist/components/toc/index.d.mts +7 -1
  73. package/dist/components/toc/index.mjs +13 -1
  74. package/dist/components/toolbar/index.d.mts +17 -0
  75. package/dist/components/toolbar/index.mjs +29 -0
  76. package/dist/components/transfer/index.mjs +7 -5
  77. package/dist/components/tree-select/index.mjs +5 -3
  78. package/dist/components/tree-view/index.d.mts +10 -1
  79. package/dist/components/tree-view/index.mjs +22 -1
  80. package/dist/components/user/index.d.mts +20 -0
  81. package/dist/components/user/index.mjs +42 -0
  82. package/dist/components/virtual-list/index.d.mts +17 -0
  83. package/dist/components/virtual-list/index.mjs +53 -0
  84. package/dist/glyph-VI989p8H.mjs +14 -0
  85. package/dist/{index-DaAbbSz9.d.mts → index-Dn5mHf1g.d.mts} +738 -3786
  86. package/dist/index-Iy8m0Qev.d.mts +42 -0
  87. package/dist/index.d.mts +16 -3
  88. package/dist/index.mjs +28 -15
  89. package/dist/input-2oezH-dY.mjs +58 -0
  90. package/dist/messages-1jJWtaYU.mjs +16 -0
  91. package/dist/select-eAHutw56.mjs +70 -0
  92. package/package.json +30 -9
package/README.md CHANGED
@@ -4,11 +4,11 @@
4
4
  ![npm downloads](https://img.shields.io/npm/dw/@bysages/react)
5
5
  ![npm license](https://img.shields.io/npm/l/@bysages/react)
6
6
 
7
- > By Sages Elements for React — 90+ accessible component families, headless by construction, dressed by the paper-and-ink style layer. Ported from the Vue reference implementation, API for API.
7
+ > By Sages Elements for React — 140+ accessible component families, headless by construction, dressed by the paper-and-ink style layer. Ported from the Vue reference implementation, API for API.
8
8
 
9
9
  ## Features
10
10
 
11
- - 🧩 **90+ families** — actions, forms, overlays, navigation, data, layout, and an AI conversation family on ai-sdk formats
11
+ - 🧩 **140+ families** — actions, forms, overlays, navigation, data, layout, an AI conversation family on ai-sdk formats, and a full generative vocabulary
12
12
  - 🏛️ **Headless inside** — interaction, state, ARIA, and positioning come from proven headless state machines; wrappers add API narrowing and style injection, no DOM of their own
13
13
  - 🎨 **Token-styled** — every visual value is a CSS custom property from `@bysages/core`; light/dark, accent pigments, contrast and density tiers are data, never hardcoded styles
14
14
  - 📦 **Container-driven** — components respond to `@container`, not the viewport; the same component composes in a sidebar, a card, or a page
@@ -66,6 +66,20 @@ export function App() {
66
66
  }
67
67
  ```
68
68
 
69
+ ## Generative UI
70
+
71
+ Every family carries a generative face — a zod-typed catalog entry that
72
+ lives beside the component. The faces compose into a
73
+ [json-render](https://json-render.dev) catalog and render through the
74
+ same package:
75
+
76
+ ```ts
77
+ import { catalog } from "@bysages/react/generative";
78
+ ```
79
+
80
+ Point an AI SDK stream at the renderer and a prompt becomes real,
81
+ on-brand components — constrained to the families you registered.
82
+
69
83
  ## Documentation
70
84
 
71
85
  The [documentation site](https://elements.bysages.com) carries every family with live demos and props tables.
@@ -1,3 +1,4 @@
1
+ import { n as useComponentMessages } from "./messages-1jJWtaYU.mjs";
1
2
  import { injectComponentStyle } from "@bysages/core";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  import { useEffect, useRef } from "react";
@@ -99,20 +100,23 @@ function wrapResponseTables(root) {
99
100
  }
100
101
  //#endregion
101
102
  //#region src/components/ai-response/index.tsx
102
- function Response({ content, highlighter, copyLabel = "Copy code", copiedLabel = "Copied", ...rest }) {
103
+ function Response({ content, highlighter, copyLabel, copiedLabel, ...rest }) {
103
104
  injectComponentStyle("ai");
105
+ const messages = useComponentMessages();
106
+ const resolvedCopyLabel = copyLabel ?? messages.ai.copyCode;
107
+ const resolvedCopiedLabel = copiedLabel ?? messages.ai.copied;
104
108
  const root = useRef(null);
105
109
  useEffect(() => {
106
110
  const host = root.current;
107
- if (host) decorateCodeCopy(host, copyLabel);
111
+ if (host) decorateCodeCopy(host, resolvedCopyLabel);
108
112
  if (host) wrapResponseTables(host);
109
113
  }, [
110
114
  content,
111
115
  highlighter,
112
- copyLabel
116
+ resolvedCopyLabel
113
117
  ]);
114
118
  const onClick = (event) => {
115
- clickCodeCopy(event.nativeEvent, copyLabel, copiedLabel);
119
+ clickCodeCopy(event.nativeEvent, resolvedCopyLabel, resolvedCopiedLabel);
116
120
  };
117
121
  return /* @__PURE__ */ jsx("div", {
118
122
  ...rest,
@@ -1,2 +1,2 @@
1
- import { a as SourceDocumentUIPart, c as TextUIPart, d as UIMessagePart, i as ReasoningUIPart, l as ToolUIPart, n as DataUIPart, o as SourceUrlUIPart, r as FileUIPart, s as StepStartUIPart, t as Ai, u as UIMessage } from "../../index-DaAbbSz9.mjs";
2
- export { Ai, type DataUIPart, type FileUIPart, type ReasoningUIPart, type SourceDocumentUIPart, type SourceUrlUIPart, type StepStartUIPart, type TextUIPart, type ToolUIPart, type UIMessage, type UIMessagePart };
1
+ import { a as FileUIPart, c as SourceUrlUIPart, d as ToolUIPart, f as UIMessage, i as DataUIPart, l as StepStartUIPart, n as AiActions, o as ReasoningUIPart, p as UIMessagePart, r as AiContent, s as SourceDocumentUIPart, t as Ai, u as TextUIPart } from "../../index-Dn5mHf1g.mjs";
2
+ export { Ai, AiActions, AiContent, type DataUIPart, type FileUIPart, type ReasoningUIPart, type SourceDocumentUIPart, type SourceUrlUIPart, type StepStartUIPart, type TextUIPart, type ToolUIPart, type UIMessage, type UIMessagePart };
@@ -1,8 +1,9 @@
1
+ import { n as useComponentMessages } from "../../messages-1jJWtaYU.mjs";
1
2
  import { Action } from "../ai-action/index.mjs";
2
3
  import { AiMessage as Message } from "../ai-message/index.mjs";
3
4
  import { AiPromptInput as PromptInput } from "../ai-prompt-input/index.mjs";
4
5
  import { AiReasoning as Reasoning } from "../ai-reasoning/index.mjs";
5
- import { t as Response } from "../../ai-response-jZy-0Tvv.mjs";
6
+ import { t as Response } from "../../ai-response-BfKTmtCt.mjs";
6
7
  import { AiSource as Source, AiSources as Sources } from "../ai-source/index.mjs";
7
8
  import { AiSuggestion as Suggestion } from "../ai-suggestion/index.mjs";
8
9
  import { AiTool as Tool } from "../ai-tool/index.mjs";
@@ -29,27 +30,41 @@ function part(name, tag, extra = {}) {
29
30
  }
30
31
  /** The log itself: the column every stroke lands in, a landmark to
31
32
  * screen readers. */
32
- const Conversation = part("Conversation", "div", {
33
- role: "log",
34
- "aria-label": "Conversation"
35
- });
33
+ function AiConversation({ children, ...rest }) {
34
+ const messages = useComponentMessages();
35
+ return /* @__PURE__ */ jsx("div", {
36
+ ...rest,
37
+ role: "log",
38
+ "aria-label": rest["aria-label"] ?? messages.ai.conversation,
39
+ "data-scope": "ai",
40
+ "data-part": "conversation",
41
+ children
42
+ });
43
+ }
36
44
  /** The bubble's inner measure — content that belongs to neither side
37
45
  * specifically. */
38
- const MessageContent = part("Content", "div");
46
+ const AiContent = part("Content", "div");
39
47
  /** The quiet row under a message — copy, retry, feedback. */
40
- const Actions = part("Actions", "div");
48
+ const AiActions = part("Actions", "div");
41
49
  /** The while-it-works whisper for the in-flight turns. */
42
- const Loader = part("Loader", "span", {
43
- role: "status",
44
- "aria-label": "Loading"
45
- });
50
+ function AiLoader({ children, ...rest }) {
51
+ const messages = useComponentMessages();
52
+ return /* @__PURE__ */ jsx("span", {
53
+ ...rest,
54
+ role: "status",
55
+ "aria-label": rest["aria-label"] ?? messages.ai.loading,
56
+ "data-scope": "ai",
57
+ "data-part": "loader",
58
+ children
59
+ });
60
+ }
46
61
  /** The whole family under one handle — `Ai.Conversation`,
47
62
  * `Ai.Message`, and the rest, exactly as before the split. */
48
- const Ai = Object.assign(Conversation, {
49
- Conversation,
50
- MessageContent,
51
- Actions,
52
- Loader,
63
+ const Ai = Object.assign(AiConversation, {
64
+ Conversation: AiConversation,
65
+ MessageContent: AiContent,
66
+ Actions: AiActions,
67
+ Loader: AiLoader,
53
68
  Message,
54
69
  Response,
55
70
  Reasoning,
@@ -62,4 +77,4 @@ const Ai = Object.assign(Conversation, {
62
77
  });
63
78
  injectComponentStyle("ai");
64
79
  //#endregion
65
- export { Ai };
80
+ export { Ai, AiActions, AiContent };
@@ -1,3 +1,4 @@
1
+ import { n as useComponentMessages, t as formatMessage } from "../../messages-1jJWtaYU.mjs";
1
2
  import { injectComponentStyle } from "@bysages/core";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
4
  //#region src/components/ai-attachments/index.tsx
@@ -74,6 +75,7 @@ const humanSize = (bytes) => {
74
75
  };
75
76
  function Attachment({ name, size, status = "ready", onRemove, ...rest }) {
76
77
  injectComponentStyle("ai");
78
+ const messages = useComponentMessages();
77
79
  return /* @__PURE__ */ jsxs("span", {
78
80
  ...rest,
79
81
  "data-scope": "ai",
@@ -86,7 +88,7 @@ function Attachment({ name, size, status = "ready", onRemove, ...rest }) {
86
88
  /* @__PURE__ */ jsx("button", {
87
89
  type: "button",
88
90
  "data-remove": "",
89
- "aria-label": `Remove ${name}`,
91
+ "aria-label": formatMessage(messages.ai.removeAttachment, { name }),
90
92
  onClick: () => onRemove?.(),
91
93
  children: removeGlyph
92
94
  })
@@ -42,6 +42,6 @@ export interface PromptInputProps extends Omit<HTMLAttributes<HTMLFormElement>,
42
42
  footer?: ReactNode;
43
43
  footerEnd?: ReactNode;
44
44
  }
45
- export declare function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder, disabled, busy, mentions, header, leading, trailing, footer, footerEnd, ...rest }: PromptInputProps): import("react").JSX.Element;
45
+ export declare function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder, "aria-label": ariaLabel, disabled, busy, mentions, header, leading, trailing, footer, footerEnd, ...rest }: PromptInputProps): import("react").JSX.Element;
46
46
  //#endregion
47
47
  export { PromptInput as AiPromptInput };
@@ -1,3 +1,4 @@
1
+ import { n as useComponentMessages } from "../../messages-1jJWtaYU.mjs";
1
2
  import { Button } from "../button/index.mjs";
2
3
  import { Field } from "../field/index.mjs";
3
4
  import { n as MentionsVessel, r as useMentions } from "../../mentions-DMIBCBOd.mjs";
@@ -39,9 +40,11 @@ function row(part, content) {
39
40
  children: content
40
41
  });
41
42
  }
42
- function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder = "Send a message", disabled = false, busy = false, mentions, header, leading, trailing, footer, footerEnd, ...rest }) {
43
+ function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder, "aria-label": ariaLabel, disabled = false, busy = false, mentions, header, leading, trailing, footer, footerEnd, ...rest }) {
43
44
  injectComponentStyle("ai");
44
45
  const fieldRef = useRef(null);
46
+ const messages = useComponentMessages();
47
+ const placeholderText = placeholder ?? messages.ai.conversation;
45
48
  const mentionState = useMentions(() => ({
46
49
  items: mentions?.items ?? [],
47
50
  trigger: mentions?.trigger
@@ -61,7 +64,7 @@ function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder = "Se
61
64
  size: "sm",
62
65
  square: true,
63
66
  type: "button",
64
- "aria-label": "Stop",
67
+ "aria-label": messages.ai.stop,
65
68
  disabled,
66
69
  onClick: () => onStop?.(),
67
70
  children: stopGlyph
@@ -70,7 +73,7 @@ function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder = "Se
70
73
  size: "sm",
71
74
  square: true,
72
75
  type: "submit",
73
- "aria-label": "Send",
76
+ "aria-label": messages.ai.send,
74
77
  disabled: disabled || !value.trim(),
75
78
  children: arrowUpGlyph
76
79
  });
@@ -95,7 +98,8 @@ function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder = "Se
95
98
  autoresize: true,
96
99
  rows: 1,
97
100
  value,
98
- placeholder,
101
+ placeholder: placeholderText,
102
+ "aria-label": ariaLabel ?? messages.ai.conversation,
99
103
  disabled,
100
104
  onChange: (event) => {
101
105
  onValueChange?.(event.target.value);
@@ -12,9 +12,11 @@ export interface ResponseProps extends HTMLAttributes<HTMLDivElement> {
12
12
  /** Optional code-highlighting function re-inking fenced blocks; the
13
13
  * component stays agnostic about which engine provides it. */
14
14
  highlighter?: (code: string, lang?: string) => string;
15
- /** The copy stamp's accessible name before the copy lands. */
15
+ /** The copy stamp's accessible name before the copy lands; leave
16
+ * unset for the resolved default. */
16
17
  copyLabel?: string;
17
- /** The copy stamp's accessible name once the text has landed. */
18
+ /** The copy stamp's accessible name once the text has landed; leave
19
+ * unset for the resolved default. */
18
20
  copiedLabel?: string;
19
21
  }
20
22
  export declare function Response({ content, highlighter, copyLabel, copiedLabel, ...rest }: ResponseProps): import("react").JSX.Element;
@@ -1,2 +1,2 @@
1
- import { t as Response } from "../../ai-response-jZy-0Tvv.mjs";
1
+ import { t as Response } from "../../ai-response-BfKTmtCt.mjs";
2
2
  export { Response as AiResponse, Response };
@@ -1,3 +1,4 @@
1
+ import { n as useComponentMessages } from "../../messages-1jJWtaYU.mjs";
1
2
  import { injectComponentStyle } from "@bysages/core";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
4
  import { Portal } from "@ark-ui/react/portal";
@@ -6,6 +7,7 @@ import { Combobox } from "@ark-ui/react/combobox";
6
7
  //#region src/components/autocomplete/index.tsx
7
8
  function AutoComplete({ value = "", items = [], placeholder, filter, size = "md", onValueChange, ...rest }) {
8
9
  injectComponentStyle("combobox");
10
+ const messages = useComponentMessages();
9
11
  const { collection, filter: filterItems } = useListCollection({
10
12
  initialItems: items,
11
13
  filter: (item, input) => filter ? filter(item, input) : item.toLowerCase().includes(input.toLowerCase())
@@ -25,7 +27,7 @@ function AutoComplete({ value = "", items = [], placeholder, filter, size = "md"
25
27
  onValueChange?.(details.inputValue);
26
28
  },
27
29
  positioning: { sameWidth: true },
28
- children: [/* @__PURE__ */ jsx(Combobox.Control, { children: /* @__PURE__ */ jsx(Combobox.Input, { placeholder }) }), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Combobox.Positioner, { children: /* @__PURE__ */ jsxs(Combobox.Content, { children: [/* @__PURE__ */ jsx(Combobox.Empty, { children: "No matches" }), collection.items.map((item) => /* @__PURE__ */ jsx(Combobox.Item, {
30
+ children: [/* @__PURE__ */ jsx(Combobox.Control, { children: /* @__PURE__ */ jsx(Combobox.Input, { placeholder }) }), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Combobox.Positioner, { children: /* @__PURE__ */ jsxs(Combobox.Content, { children: [/* @__PURE__ */ jsx(Combobox.Empty, { children: messages.command.noMatches }), collection.items.map((item) => /* @__PURE__ */ jsx(Combobox.Item, {
29
31
  item,
30
32
  children: /* @__PURE__ */ jsx(Combobox.ItemText, { children: item })
31
33
  }, item))] }) }) })]
@@ -12,8 +12,11 @@ export interface AvatarProps extends ComponentProps<typeof Avatar$1.Root> {
12
12
  * default (large) stands as tall as the biggest control so an avatar
13
13
  * rides a row without stretching it. */
14
14
  size?: AvatarSize;
15
+ /** The corner: round by default; square cuts it sharp, a stamp
16
+ * beside a round portrait. */
17
+ shape?: "circle" | "square";
15
18
  }
16
- declare function AvatarRoot({ size, ...rest }: AvatarProps): import("react").JSX.Element;
19
+ declare function AvatarRoot({ size, shape, ...rest }: AvatarProps): import("react").JSX.Element;
17
20
  export declare const Avatar: typeof Avatar$1 & {
18
21
  Root: typeof AvatarRoot;
19
22
  };
@@ -2,10 +2,11 @@ import { injectComponentStyle } from "@bysages/core";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { Avatar as Avatar$1 } from "@ark-ui/react/avatar";
4
4
  //#region src/components/avatar/index.tsx
5
- function AvatarRoot({ size, ...rest }) {
5
+ function AvatarRoot({ size, shape = "circle", ...rest }) {
6
6
  return /* @__PURE__ */ jsx(Avatar$1.Root, {
7
7
  ...rest,
8
- "data-size": size
8
+ "data-size": size,
9
+ "data-shape": shape
9
10
  });
10
11
  }
11
12
  const Avatar = Object.assign({}, Avatar$1, { Root: AvatarRoot });
@@ -1,3 +1,4 @@
1
+ import { n as useComponentMessages } from "../../messages-1jJWtaYU.mjs";
1
2
  import { injectComponentStyle } from "@bysages/core";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  //#region src/components/banner/index.tsx
@@ -31,24 +32,27 @@ const Description = part("Description", "p");
31
32
  const Actions = part("Actions", "div");
32
33
  /** The quiet close: a plain square-cut button; dismissal stays the
33
34
  * consumer's state. */
34
- const Close = (rest) => /* @__PURE__ */ jsx("button", {
35
- ...rest,
36
- type: rest.type ?? "button",
37
- "aria-label": rest["aria-label"] ?? "Dismiss",
38
- "data-scope": "banner",
39
- "data-part": "close",
40
- children: /* @__PURE__ */ jsx("svg", {
41
- viewBox: "0 0 16 16",
42
- fill: "none",
43
- "aria-hidden": true,
44
- children: /* @__PURE__ */ jsx("path", {
45
- d: "M4 4l8 8M12 4l-8 8",
46
- stroke: "currentColor",
47
- strokeWidth: 1.5,
48
- strokeLinecap: "round"
35
+ const Close = (rest) => {
36
+ const messages = useComponentMessages();
37
+ return /* @__PURE__ */ jsx("button", {
38
+ ...rest,
39
+ type: rest.type ?? "button",
40
+ "aria-label": rest["aria-label"] ?? messages.banner.dismiss,
41
+ "data-scope": "banner",
42
+ "data-part": "close",
43
+ children: /* @__PURE__ */ jsx("svg", {
44
+ viewBox: "0 0 16 16",
45
+ fill: "none",
46
+ "aria-hidden": true,
47
+ children: /* @__PURE__ */ jsx("path", {
48
+ d: "M4 4l8 8M12 4l-8 8",
49
+ stroke: "currentColor",
50
+ strokeWidth: 1.5,
51
+ strokeLinecap: "round"
52
+ })
49
53
  })
50
- })
51
- });
54
+ });
55
+ };
52
56
  const Banner = Object.assign(Root, {
53
57
  Root,
54
58
  Icon,
@@ -0,0 +1,26 @@
1
+ import { HTMLAttributes, ReactNode } from "react";
2
+ //#region src/components/bento/index.d.ts
3
+ export interface BentoProps extends HTMLAttributes<HTMLDivElement> {
4
+ /** Tracks across the lattice. */
5
+ columns?: number;
6
+ children?: ReactNode;
7
+ }
8
+ export interface BentoCellProps extends HTMLAttributes<HTMLDivElement> {
9
+ /** Columns this tile claims. */
10
+ span?: number;
11
+ /** Rows this tile claims. */
12
+ rowSpan?: number;
13
+ children?: ReactNode;
14
+ }
15
+ /** The bento lattice: a grid of unequal tiles that reads as one plate.
16
+ * The container owns the track count; each cell claims its own span. */
17
+ export declare function BentoRoot({ columns, children, ...rest }: BentoProps): import("react").JSX.Element;
18
+ /** One tile: `span` claims columns, `rowSpan` claims rows — the rest
19
+ * of the plate stays in measure. */
20
+ export declare function BentoCell({ span, rowSpan, children, ...rest }: BentoCellProps): import("react").JSX.Element;
21
+ /** The whole family under one handle — Bento.Root, Bento.Cell. */
22
+ export declare const Bento: typeof BentoRoot & {
23
+ Root: typeof BentoRoot;
24
+ Cell: typeof BentoCell;
25
+ };
26
+ //#endregion
@@ -0,0 +1,41 @@
1
+ import { injectComponentStyle } from "@bysages/core";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/bento/index.tsx
4
+ /** The bento lattice: a grid of unequal tiles that reads as one plate.
5
+ * The container owns the track count; each cell claims its own span. */
6
+ function BentoRoot({ columns = 3, children, ...rest }) {
7
+ injectComponentStyle("bento");
8
+ return /* @__PURE__ */ jsx("div", {
9
+ ...rest,
10
+ "data-scope": "bento",
11
+ "data-part": "root",
12
+ style: {
13
+ ...rest.style,
14
+ "--bs-bento-columns": String(columns)
15
+ },
16
+ children
17
+ });
18
+ }
19
+ /** One tile: `span` claims columns, `rowSpan` claims rows — the rest
20
+ * of the plate stays in measure. */
21
+ function BentoCell({ span = 1, rowSpan = 1, children, ...rest }) {
22
+ injectComponentStyle("bento");
23
+ return /* @__PURE__ */ jsx("div", {
24
+ ...rest,
25
+ "data-scope": "bento",
26
+ "data-part": "cell",
27
+ style: {
28
+ ...rest.style,
29
+ "--bs-bento-span-x": String(span),
30
+ "--bs-bento-span-y": String(rowSpan)
31
+ },
32
+ children
33
+ });
34
+ }
35
+ /** The whole family under one handle — Bento.Root, Bento.Cell. */
36
+ const Bento = Object.assign(BentoRoot, {
37
+ Root: BentoRoot,
38
+ Cell: BentoCell
39
+ });
40
+ //#endregion
41
+ export { Bento, BentoCell, BentoRoot };
@@ -0,0 +1,12 @@
1
+ import { HTMLAttributes, ReactNode } from "react";
2
+ //#region src/components/block-ui/index.d.ts
3
+ export interface BlockUIProps extends HTMLAttributes<HTMLDivElement> {
4
+ /** Whether the curtain is drawn. */
5
+ blocked?: boolean;
6
+ children?: ReactNode;
7
+ }
8
+ /** A curtain over content that must wait: the blocked region keeps its
9
+ * shape and dims under frosted paper while a quiet wheel reports the
10
+ * wait. Callers own the state; the curtain only answers it. */
11
+ export declare function BlockUI({ blocked, children, ...rest }: BlockUIProps): import("react").JSX.Element;
12
+ //#endregion
@@ -0,0 +1,24 @@
1
+ import { Spinner } from "../spinner/index.mjs";
2
+ import { injectComponentStyle } from "@bysages/core";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/components/block-ui/index.tsx
5
+ /** A curtain over content that must wait: the blocked region keeps its
6
+ * shape and dims under frosted paper while a quiet wheel reports the
7
+ * wait. Callers own the state; the curtain only answers it. */
8
+ function BlockUI({ blocked = false, children, ...rest }) {
9
+ injectComponentStyle("block-ui");
10
+ return /* @__PURE__ */ jsxs("div", {
11
+ ...rest,
12
+ "data-scope": "block-ui",
13
+ "data-part": "root",
14
+ "data-blocked": blocked ? "" : void 0,
15
+ "aria-busy": blocked || void 0,
16
+ children: [children, blocked ? /* @__PURE__ */ jsx("div", {
17
+ "data-scope": "block-ui",
18
+ "data-part": "mask",
19
+ children: /* @__PURE__ */ jsx(Spinner, { size: "lg" })
20
+ }) : null]
21
+ });
22
+ }
23
+ //#endregion
24
+ export { BlockUI };
@@ -1,13 +1,8 @@
1
1
  import { AnchorHTMLAttributes, HTMLAttributes } from "react";
2
2
  //#region src/components/breadcrumb/index.d.ts
3
- export declare const Breadcrumb: {
4
- ({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
5
- displayName: string;
6
- } & {
7
- Root: {
8
- ({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
9
- displayName: string;
10
- };
3
+ declare function Root({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
4
+ export declare const Breadcrumb: typeof Root & {
5
+ Root: typeof Root;
11
6
  List: {
12
7
  ({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
13
8
  displayName: string;
@@ -1,3 +1,4 @@
1
+ import { n as useComponentMessages } from "../../messages-1jJWtaYU.mjs";
1
2
  import { injectComponentStyle } from "@bysages/core";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  //#region src/components/breadcrumb/index.tsx
@@ -16,7 +17,16 @@ function part(name, tag, extra = {}, fallback) {
16
17
  Component.displayName = "Breadcrumb" + name;
17
18
  return Component;
18
19
  }
19
- const Root = part("Root", "nav", { "aria-label": "Breadcrumb" });
20
+ function Root({ children, ...rest }) {
21
+ const messages = useComponentMessages();
22
+ return /* @__PURE__ */ jsx("nav", {
23
+ ...rest,
24
+ "aria-label": rest["aria-label"] ?? messages.breadcrumb.label,
25
+ "data-scope": "breadcrumb",
26
+ "data-part": "root",
27
+ children
28
+ });
29
+ }
20
30
  const List = part("List", "ol");
21
31
  const Item = part("Item", "li");
22
32
  const Link = part("Link", "a");
@@ -0,0 +1,23 @@
1
+ import { HTMLAttributes, ReactNode } from "react";
2
+ //#region src/components/browser/index.d.ts
3
+ export interface BrowserPartProps extends HTMLAttributes<HTMLDivElement> {
4
+ children?: ReactNode;
5
+ }
6
+ /** The three lamps are the system's own fixed pigments — the same
7
+ * semantics reserved for danger, warning, and success. */
8
+ export declare function BrowserDots(props: BrowserPartProps): import("react").JSX.Element;
9
+ export declare function BrowserRoot(props: BrowserPartProps): import("react").JSX.Element;
10
+ export declare function BrowserTitleBar(props: BrowserPartProps): import("react").JSX.Element;
11
+ export declare function BrowserUrlBar(props: BrowserPartProps): import("react").JSX.Element;
12
+ export declare function BrowserBody(props: BrowserPartProps): import("react").JSX.Element;
13
+ /** A browser window as a vessel: title bar, the three lamps, the
14
+ * address well, and a body that carries whatever the site hangs in
15
+ * it — an iframe, a screenshot, a live page. */
16
+ export declare const Browser: typeof BrowserRoot & {
17
+ Root: typeof BrowserRoot;
18
+ TitleBar: typeof BrowserTitleBar;
19
+ Dots: typeof BrowserDots;
20
+ UrlBar: typeof BrowserUrlBar;
21
+ Body: typeof BrowserBody;
22
+ };
23
+ //#endregion
@@ -0,0 +1,70 @@
1
+ import { injectComponentStyle } from "@bysages/core";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/browser/index.tsx
4
+ /** The three lamps are the system's own fixed pigments — the same
5
+ * semantics reserved for danger, warning, and success. */
6
+ function BrowserDots(props) {
7
+ injectComponentStyle("browser");
8
+ return /* @__PURE__ */ jsx("div", {
9
+ ...props,
10
+ "data-scope": "browser",
11
+ "data-part": "dots",
12
+ children: [
13
+ "danger",
14
+ "warning",
15
+ "success"
16
+ ].map((tone) => /* @__PURE__ */ jsx("span", {
17
+ "data-scope": "browser",
18
+ "data-part": "dot",
19
+ "data-tone": tone
20
+ }, tone))
21
+ });
22
+ }
23
+ function BrowserRoot(props) {
24
+ injectComponentStyle("browser");
25
+ return /* @__PURE__ */ jsx("div", {
26
+ ...props,
27
+ "data-scope": "browser",
28
+ "data-part": "root",
29
+ children: props.children
30
+ });
31
+ }
32
+ function BrowserTitleBar(props) {
33
+ injectComponentStyle("browser");
34
+ return /* @__PURE__ */ jsx("div", {
35
+ ...props,
36
+ "data-scope": "browser",
37
+ "data-part": "titlebar",
38
+ children: props.children
39
+ });
40
+ }
41
+ function BrowserUrlBar(props) {
42
+ injectComponentStyle("browser");
43
+ return /* @__PURE__ */ jsx("div", {
44
+ ...props,
45
+ "data-scope": "browser",
46
+ "data-part": "urlbar",
47
+ children: props.children
48
+ });
49
+ }
50
+ function BrowserBody(props) {
51
+ injectComponentStyle("browser");
52
+ return /* @__PURE__ */ jsx("div", {
53
+ ...props,
54
+ "data-scope": "browser",
55
+ "data-part": "body",
56
+ children: props.children
57
+ });
58
+ }
59
+ /** A browser window as a vessel: title bar, the three lamps, the
60
+ * address well, and a body that carries whatever the site hangs in
61
+ * it — an iframe, a screenshot, a live page. */
62
+ const Browser = Object.assign(BrowserRoot, {
63
+ Root: BrowserRoot,
64
+ TitleBar: BrowserTitleBar,
65
+ Dots: BrowserDots,
66
+ UrlBar: BrowserUrlBar,
67
+ Body: BrowserBody
68
+ });
69
+ //#endregion
70
+ export { Browser, BrowserBody, BrowserDots, BrowserRoot, BrowserTitleBar, BrowserUrlBar };