@idyeah/diya 0.0.0 → 1.0.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.
- package/CHANGELOG.md +317 -0
- package/NOTICE +29 -0
- package/README.md +596 -5
- package/dist/DiyaProvider.d.ts +79 -0
- package/dist/DiyaProvider.js +77 -0
- package/dist/Icon.d.ts +10 -0
- package/dist/Icon.js +27 -0
- package/dist/accordion/Accordion.d.ts +34 -0
- package/dist/accordion/Accordion.js +15 -0
- package/dist/alert/Alert.d.ts +49 -0
- package/dist/alert/Alert.js +11 -0
- package/dist/alert/messages.d.ts +9 -0
- package/dist/alert/messages.js +2 -0
- package/dist/api.json +7277 -0
- package/dist/api.schema.json +214 -0
- package/dist/application-patterns/Chatbot.d.ts +114 -0
- package/dist/application-patterns/Chatbot.js +110 -0
- package/dist/application-patterns/SideNavigation.d.ts +74 -0
- package/dist/application-patterns/SideNavigation.js +31 -0
- package/dist/application-patterns/chatbot-messages.d.ts +20 -0
- package/dist/application-patterns/chatbot-messages.js +2 -0
- package/dist/application-patterns/side-navigation-messages.d.ts +5 -0
- package/dist/application-patterns/side-navigation-messages.js +2 -0
- package/dist/avatar/Avatar.d.ts +32 -0
- package/dist/avatar/Avatar.js +19 -0
- package/dist/avatar/messages.d.ts +7 -0
- package/dist/avatar/messages.js +2 -0
- package/dist/badge/Badge.d.ts +42 -0
- package/dist/badge/Badge.js +16 -0
- package/dist/badge/badge-utils.d.ts +6 -0
- package/dist/badge/badge-utils.js +24 -0
- package/dist/badge/messages.d.ts +4 -0
- package/dist/badge/messages.js +2 -0
- package/dist/breadcrumbs/Breadcrumbs.d.ts +34 -0
- package/dist/breadcrumbs/Breadcrumbs.js +19 -0
- package/dist/breadcrumbs/messages.d.ts +5 -0
- package/dist/breadcrumbs/messages.js +2 -0
- package/dist/button/Button.d.ts +46 -0
- package/dist/button/Button.js +44 -0
- package/dist/calendar/Calendar.d.ts +55 -0
- package/dist/calendar/Calendar.js +61 -0
- package/dist/calendar/messages.d.ts +8 -0
- package/dist/calendar/messages.js +2 -0
- package/dist/calendar/month.d.ts +61 -0
- package/dist/calendar/month.js +134 -0
- package/dist/card/Card.d.ts +46 -0
- package/dist/card/Card.js +8 -0
- package/dist/choice/Choice.d.ts +72 -0
- package/dist/choice/Choice.js +68 -0
- package/dist/choice/messages.d.ts +4 -0
- package/dist/choice/messages.js +2 -0
- package/dist/code-block/CodeBlock.d.ts +20 -0
- package/dist/code-block/CodeBlock.js +49 -0
- package/dist/code-block/messages.d.ts +8 -0
- package/dist/code-block/messages.js +2 -0
- package/dist/combobox/Combobox.d.ts +60 -0
- package/dist/combobox/Combobox.js +160 -0
- package/dist/combobox/messages.d.ts +9 -0
- package/dist/combobox/messages.js +2 -0
- package/dist/combobox/useAnchoredPopover.d.ts +5 -0
- package/dist/combobox/useAnchoredPopover.js +100 -0
- package/dist/data-viz/DataViz.d.ts +140 -0
- package/dist/data-viz/DataViz.js +469 -0
- package/dist/data-viz/index.d.ts +2 -0
- package/dist/data-viz/index.js +1 -0
- package/dist/data-viz/messages.d.ts +11 -0
- package/dist/data-viz/messages.js +2 -0
- package/dist/date-picker/DatePicker.d.ts +57 -0
- package/dist/date-picker/DatePicker.js +146 -0
- package/dist/date-picker/messages.d.ts +13 -0
- package/dist/date-picker/messages.js +2 -0
- package/dist/dialog/Dialog.d.ts +84 -0
- package/dist/dialog/Dialog.js +107 -0
- package/dist/dialog/messages.d.ts +9 -0
- package/dist/dialog/messages.js +2 -0
- package/dist/fonts/DIYASans-Italic.woff2 +0 -0
- package/dist/fonts/DIYASans.woff2 +0 -0
- package/dist/fonts/OFL.txt +94 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +46 -0
- package/dist/internal/brand.d.ts +33 -0
- package/dist/internal/brand.js +57 -0
- package/dist/internal/cx.d.ts +2 -0
- package/dist/internal/cx.js +4 -0
- package/dist/internal/link.d.ts +14 -0
- package/dist/internal/link.js +7 -0
- package/dist/internal/slot.d.ts +15 -0
- package/dist/internal/slot.js +67 -0
- package/dist/layout/Inline.d.ts +4 -0
- package/dist/layout/Inline.js +7 -0
- package/dist/layout/Stack.d.ts +4 -0
- package/dist/layout/Stack.js +7 -0
- package/dist/layout/layout.d.ts +32 -0
- package/dist/layout/layout.js +12 -0
- package/dist/link/TextLink.d.ts +23 -0
- package/dist/link/TextLink.js +17 -0
- package/dist/list/List.d.ts +48 -0
- package/dist/list/List.js +17 -0
- package/dist/list/messages.d.ts +4 -0
- package/dist/list/messages.js +2 -0
- package/dist/menu/Menu.d.ts +49 -0
- package/dist/menu/Menu.js +54 -0
- package/dist/messages-defaults.d.ts +201 -0
- package/dist/messages-defaults.js +61 -0
- package/dist/messages.d.ts +12 -0
- package/dist/messages.js +1 -0
- package/dist/metric/Metric.d.ts +42 -0
- package/dist/metric/Metric.js +11 -0
- package/dist/metric/messages.d.ts +9 -0
- package/dist/metric/messages.js +2 -0
- package/dist/overlay/FloatingSurface.d.ts +29 -0
- package/dist/overlay/FloatingSurface.js +254 -0
- package/dist/page-header/PageHeader.d.ts +38 -0
- package/dist/page-header/PageHeader.js +10 -0
- package/dist/pagination/Pagination.d.ts +44 -0
- package/dist/pagination/Pagination.js +26 -0
- package/dist/pagination/messages.d.ts +11 -0
- package/dist/pagination/messages.js +2 -0
- package/dist/popover/Popover.d.ts +23 -0
- package/dist/popover/Popover.js +8 -0
- package/dist/progress/Progress.d.ts +33 -0
- package/dist/progress/Progress.js +14 -0
- package/dist/progress/messages.d.ts +4 -0
- package/dist/progress/messages.js +2 -0
- package/dist/prose/Prose.d.ts +14 -0
- package/dist/prose/Prose.js +7 -0
- package/dist/rating/Rating.d.ts +32 -0
- package/dist/rating/Rating.js +27 -0
- package/dist/rating/messages.d.ts +6 -0
- package/dist/rating/messages.js +2 -0
- package/dist/search/Search.d.ts +11 -0
- package/dist/search/Search.js +9 -0
- package/dist/select/Select.d.ts +65 -0
- package/dist/select/Select.js +19 -0
- package/dist/select/messages.d.ts +4 -0
- package/dist/select/messages.js +2 -0
- package/dist/site-header/SiteHeader.d.ts +88 -0
- package/dist/site-header/SiteHeader.js +211 -0
- package/dist/site-header/messages.d.ts +8 -0
- package/dist/site-header/messages.js +2 -0
- package/dist/slider/Slider.d.ts +54 -0
- package/dist/slider/Slider.js +89 -0
- package/dist/slider/messages.d.ts +5 -0
- package/dist/slider/messages.js +2 -0
- package/dist/styles.css +3379 -0
- package/dist/switch/Switch.d.ts +47 -0
- package/dist/switch/Switch.js +18 -0
- package/dist/table/Table.d.ts +99 -0
- package/dist/table/Table.js +158 -0
- package/dist/table/messages.d.ts +23 -0
- package/dist/table/messages.js +2 -0
- package/dist/tabs/Tabs.d.ts +49 -0
- package/dist/tabs/Tabs.js +26 -0
- package/dist/tag/Tag.d.ts +37 -0
- package/dist/tag/Tag.js +20 -0
- package/dist/tag/messages.d.ts +4 -0
- package/dist/tag/messages.js +2 -0
- package/dist/text-area/TextArea.d.ts +47 -0
- package/dist/text-area/TextArea.js +19 -0
- package/dist/text-input/TextInput.d.ts +53 -0
- package/dist/text-input/TextInput.js +35 -0
- package/dist/text-input/messages.d.ts +4 -0
- package/dist/text-input/messages.js +3 -0
- package/dist/text-input/native-field.d.ts +15 -0
- package/dist/text-input/native-field.js +56 -0
- package/dist/toast/Toast.d.ts +24 -0
- package/dist/toast/Toast.js +79 -0
- package/dist/toast/messages.d.ts +4 -0
- package/dist/toast/messages.js +2 -0
- package/dist/tooltip/Tooltip.d.ts +22 -0
- package/dist/tooltip/Tooltip.js +92 -0
- package/dist/workflow/ContentState.d.ts +44 -0
- package/dist/workflow/ContentState.js +11 -0
- package/dist/workflow/Drawer.d.ts +48 -0
- package/dist/workflow/Drawer.js +51 -0
- package/dist/workflow/FileUpload.d.ts +67 -0
- package/dist/workflow/FileUpload.js +47 -0
- package/dist/workflow/Form.d.ts +52 -0
- package/dist/workflow/Form.js +16 -0
- package/dist/workflow/Wizard.d.ts +76 -0
- package/dist/workflow/Wizard.js +31 -0
- package/dist/workflow/drawer-messages.d.ts +4 -0
- package/dist/workflow/drawer-messages.js +2 -0
- package/dist/workflow/file-upload-messages.d.ts +11 -0
- package/dist/workflow/file-upload-messages.js +2 -0
- package/dist/workflow/form-messages.d.ts +5 -0
- package/dist/workflow/form-messages.js +2 -0
- package/dist/workflow/wizard-messages.d.ts +9 -0
- package/dist/workflow/wizard-messages.js +2 -0
- package/package.json +82 -7
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "DIYA API map",
|
|
4
|
+
"description": "The shape of api.json, schema version 1. Version 1 only gains fields: readers ignore fields they do not know, and enumerations are open, so an unknown kind or content value is valid.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schemaVersion", "package", "version", "entries", "items", "components", "types", "tokens", "messages"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"schemaVersion": { "const": 1 },
|
|
9
|
+
"package": { "type": "string", "description": "The npm package name." },
|
|
10
|
+
"version": { "type": "string", "description": "The package version this map describes." },
|
|
11
|
+
"entries": {
|
|
12
|
+
"description": "Export names of each package entry point, such as \".\" and \"./charts\".",
|
|
13
|
+
"type": "object",
|
|
14
|
+
"additionalProperties": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"required": ["values", "types"],
|
|
17
|
+
"properties": {
|
|
18
|
+
"values": { "$ref": "#/$defs/names", "description": "Runtime exports: components and plain values." },
|
|
19
|
+
"types": { "$ref": "#/$defs/names", "description": "Type-only exports." }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"items": {
|
|
24
|
+
"description": "Catalog items keyed by their permanent kebab-case id.",
|
|
25
|
+
"type": "object",
|
|
26
|
+
"propertyNames": { "$ref": "#/$defs/itemId" },
|
|
27
|
+
"additionalProperties": { "$ref": "#/$defs/item" }
|
|
28
|
+
},
|
|
29
|
+
"components": {
|
|
30
|
+
"description": "Props of every exported component, keyed by export name.",
|
|
31
|
+
"type": "object",
|
|
32
|
+
"additionalProperties": { "$ref": "#/$defs/component" }
|
|
33
|
+
},
|
|
34
|
+
"types": {
|
|
35
|
+
"description": "Every exported type as TypeScript source text, keyed by name.",
|
|
36
|
+
"type": "object",
|
|
37
|
+
"additionalProperties": { "type": "string" }
|
|
38
|
+
},
|
|
39
|
+
"tokens": {
|
|
40
|
+
"description": "Public CSS custom properties, keyed by name.",
|
|
41
|
+
"type": "object",
|
|
42
|
+
"propertyNames": { "pattern": "^--diya-" },
|
|
43
|
+
"additionalProperties": { "$ref": "#/$defs/token" }
|
|
44
|
+
},
|
|
45
|
+
"messages": {
|
|
46
|
+
"description": "Built-in English strings: namespace, then key. Override them through DiyaProvider `messages`.",
|
|
47
|
+
"type": "object",
|
|
48
|
+
"additionalProperties": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": { "$ref": "#/$defs/message" }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"$defs": {
|
|
55
|
+
"names": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
|
|
56
|
+
"itemId": { "type": "string", "pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$" },
|
|
57
|
+
"path": {
|
|
58
|
+
"description": "A prop name, or a path into it: `items[].content` is the content of each element of `items`; `search.value` is a field of the `search` object.",
|
|
59
|
+
"type": "string",
|
|
60
|
+
"pattern": "^[A-Za-z_$][\\w$]*(\\[\\])?(\\.[A-Za-z_$][\\w$]*(\\[\\])?)*$"
|
|
61
|
+
},
|
|
62
|
+
"content": {
|
|
63
|
+
"description": "Plain content, not a DIYA item, that fits: text, icon or image. Open enumeration.",
|
|
64
|
+
"type": "array",
|
|
65
|
+
"items": { "type": "string", "examples": ["text", "icon", "image"] },
|
|
66
|
+
"uniqueItems": true
|
|
67
|
+
},
|
|
68
|
+
"accepts": {
|
|
69
|
+
"description": "DIYA item ids that fit, or \"any\" for any React content.",
|
|
70
|
+
"oneOf": [
|
|
71
|
+
{ "const": "any" },
|
|
72
|
+
{ "type": "array", "items": { "$ref": "#/$defs/itemId" }, "uniqueItems": true }
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"item": {
|
|
76
|
+
"type": "object",
|
|
77
|
+
"required": ["kind", "title", "stability", "since", "exports", "requires", "slots", "children", "state", "tokens", "messages"],
|
|
78
|
+
"properties": {
|
|
79
|
+
"kind": { "type": "string", "examples": ["component", "pattern", "provider"] },
|
|
80
|
+
"title": { "type": "string" },
|
|
81
|
+
"stability": { "type": "string", "examples": ["stable", "experimental"], "description": "Anything marked experimental is outside semver." },
|
|
82
|
+
"since": { "type": "string", "description": "The version that added the item." },
|
|
83
|
+
"exports": {
|
|
84
|
+
"description": "The item's exports. slots, children and state describe the first; any other is a variant of it.",
|
|
85
|
+
"type": "array",
|
|
86
|
+
"minItems": 1,
|
|
87
|
+
"items": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"required": ["name", "entry"],
|
|
90
|
+
"properties": { "name": { "type": "string" }, "entry": { "type": "string" } }
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"requires": {
|
|
94
|
+
"type": "object",
|
|
95
|
+
"required": ["provider", "peers"],
|
|
96
|
+
"properties": {
|
|
97
|
+
"provider": { "type": "boolean", "description": "Renders inside DiyaProvider." },
|
|
98
|
+
"peers": { "$ref": "#/$defs/names", "description": "Optional peer dependencies it needs, such as echarts." }
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"slots": {
|
|
102
|
+
"description": "Every ReactNode prop other than children, keyed by prop name or path.",
|
|
103
|
+
"type": "object",
|
|
104
|
+
"propertyNames": { "$ref": "#/$defs/path" },
|
|
105
|
+
"additionalProperties": { "$ref": "#/$defs/slot" }
|
|
106
|
+
},
|
|
107
|
+
"children": { "$ref": "#/$defs/children" },
|
|
108
|
+
"state": {
|
|
109
|
+
"description": "Controlled value and change-callback pairs.",
|
|
110
|
+
"type": "array",
|
|
111
|
+
"items": { "$ref": "#/$defs/state" }
|
|
112
|
+
},
|
|
113
|
+
"tokens": { "type": "array", "items": { "type": "string", "pattern": "^--diya-" }, "uniqueItems": true },
|
|
114
|
+
"messages": { "type": ["string", "null"], "description": "The messages namespace the item reads, or null." }
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"slot": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"required": ["accepts"],
|
|
120
|
+
"properties": {
|
|
121
|
+
"accepts": { "$ref": "#/$defs/accepts" },
|
|
122
|
+
"content": { "$ref": "#/$defs/content" },
|
|
123
|
+
"multiple": { "type": "boolean", "description": "Takes several elements, such as two buttons." },
|
|
124
|
+
"as": { "type": "string", "examples": ["render"], "description": "\"render\": the prop is a function that returns the content." }
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"children": {
|
|
128
|
+
"type": "object",
|
|
129
|
+
"required": ["allowed"],
|
|
130
|
+
"properties": {
|
|
131
|
+
"allowed": { "type": "boolean" },
|
|
132
|
+
"accepts": { "$ref": "#/$defs/accepts" },
|
|
133
|
+
"content": { "$ref": "#/$defs/content" },
|
|
134
|
+
"multiple": { "type": "boolean" },
|
|
135
|
+
"as": { "type": "string", "examples": ["render"] }
|
|
136
|
+
},
|
|
137
|
+
"if": { "properties": { "allowed": { "const": true } } },
|
|
138
|
+
"then": { "required": ["accepts"] }
|
|
139
|
+
},
|
|
140
|
+
"state": {
|
|
141
|
+
"type": "object",
|
|
142
|
+
"required": ["value", "onChange"],
|
|
143
|
+
"properties": {
|
|
144
|
+
"value": { "$ref": "#/$defs/path" },
|
|
145
|
+
"onChange": { "$ref": "#/$defs/path" },
|
|
146
|
+
"default": { "$ref": "#/$defs/path", "description": "The uncontrolled starting value, when there is one." }
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"prop": {
|
|
150
|
+
"type": "object",
|
|
151
|
+
"required": ["type", "required"],
|
|
152
|
+
"properties": {
|
|
153
|
+
"type": { "type": "string" },
|
|
154
|
+
"required": { "type": "boolean" },
|
|
155
|
+
"description": { "type": "string" },
|
|
156
|
+
"values": { "type": "array", "items": { "type": ["string", "number"] } },
|
|
157
|
+
"default": true
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"props": { "type": "object", "additionalProperties": { "$ref": "#/$defs/prop" } },
|
|
161
|
+
"component": {
|
|
162
|
+
"type": "object",
|
|
163
|
+
"required": ["entry", "props"],
|
|
164
|
+
"properties": {
|
|
165
|
+
"entry": { "type": "string" },
|
|
166
|
+
"description": { "type": "string" },
|
|
167
|
+
"propsType": { "type": "string" },
|
|
168
|
+
"typeParameters": { "type": "array", "items": { "type": "string" } },
|
|
169
|
+
"props": { "$ref": "#/$defs/props" },
|
|
170
|
+
"modes": {
|
|
171
|
+
"description": "Props that depend on a discriminant, such as `multiple` or `range`.",
|
|
172
|
+
"type": "array",
|
|
173
|
+
"items": {
|
|
174
|
+
"type": "object",
|
|
175
|
+
"required": ["when", "props"],
|
|
176
|
+
"properties": {
|
|
177
|
+
"when": { "type": "object" },
|
|
178
|
+
"default": { "const": true },
|
|
179
|
+
"props": { "$ref": "#/$defs/props" }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"extendsDom": { "type": "string", "description": "The element whose native attributes it also takes." }
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"token": {
|
|
187
|
+
"type": "object",
|
|
188
|
+
"required": ["group", "kind", "pairsWith", "defaults"],
|
|
189
|
+
"properties": {
|
|
190
|
+
"group": { "type": "string" },
|
|
191
|
+
"kind": { "type": "string", "examples": ["color", "length", "number", "shadow", "font-family"] },
|
|
192
|
+
"pairsWith": { "type": "array", "items": { "type": "string", "pattern": "^--diya-" }, "uniqueItems": true, "description": "Tokens to change together with this one." },
|
|
193
|
+
"defaults": {
|
|
194
|
+
"description": "The value in each theme; null when it is unset.",
|
|
195
|
+
"type": "object",
|
|
196
|
+
"required": ["light", "dark"],
|
|
197
|
+
"properties": { "light": { "type": ["string", "null"] }, "dark": { "type": ["string", "null"] } }
|
|
198
|
+
},
|
|
199
|
+
"setBy": { "type": "string", "description": "The DiyaProvider prop that sets it; set the prop rather than the token." }
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"message": {
|
|
203
|
+
"type": "object",
|
|
204
|
+
"required": ["kind", "default"],
|
|
205
|
+
"properties": {
|
|
206
|
+
"kind": { "type": "string", "examples": ["string", "function"] },
|
|
207
|
+
"args": { "type": "array", "items": { "type": "string" } },
|
|
208
|
+
"default": { "type": "string", "description": "The English text, or a function's source." }
|
|
209
|
+
},
|
|
210
|
+
"if": { "properties": { "kind": { "const": "function" } } },
|
|
211
|
+
"then": { "required": ["args"] }
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
import { chatbotMessages } from './chatbot-messages.js';
|
|
3
|
+
declare module '../messages.js' {
|
|
4
|
+
interface DiyaMessages {
|
|
5
|
+
chatbot: typeof chatbotMessages;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export type ChatMessage = {
|
|
9
|
+
/** Stable key for the message. */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Who wrote it; assistant messages get a Copy button, once they are no longer being written. */
|
|
12
|
+
role: 'user' | 'assistant';
|
|
13
|
+
/** The message, shown as plain text. */
|
|
14
|
+
text: string;
|
|
15
|
+
/** Preformatted time shown after the author when `showTimestamps` is on, e.g. "9:41". */
|
|
16
|
+
timestamp?: string;
|
|
17
|
+
};
|
|
18
|
+
export type ChatbotProps = Omit<HTMLAttributes<HTMLElement>, 'title' | 'children' | 'onCopy'> & {
|
|
19
|
+
/** Visible header title; it also names the chat region and its message log. */
|
|
20
|
+
title: string;
|
|
21
|
+
/** The conversation, oldest first; the caller owns this list. */
|
|
22
|
+
messages: readonly ChatMessage[];
|
|
23
|
+
/** The composer's text; the caller owns this state. */
|
|
24
|
+
value: string;
|
|
25
|
+
/** Called with the composer's new text on every keystroke. */
|
|
26
|
+
onValueChange: (value: string) => void;
|
|
27
|
+
/** Called with the trimmed text and current attachments on Send, Enter or a suggestion; clear `value` and append messages yourself. */
|
|
28
|
+
onSend: (text: string, attachments: readonly File[]) => void;
|
|
29
|
+
/** A response is on its way: blocks sending and offers Stop when `onStop` is given. Until the reply starts, "Preparing a response…" shows; once the newest message is the assistant's, as when a reply streams in, it goes and the log is `aria-busy`, so screen readers read the reply once it is complete. Defaults to false. */
|
|
30
|
+
loading?: boolean;
|
|
31
|
+
/** Shows a Stop button in place of Send while loading. */
|
|
32
|
+
onStop?: () => void;
|
|
33
|
+
/** Shows a Retry button in the notice row. */
|
|
34
|
+
onRetry?: () => void;
|
|
35
|
+
/** Files attached to the next message; the caller owns this list. */
|
|
36
|
+
attachments?: readonly File[];
|
|
37
|
+
/** Shows the Attach button; called with the chosen files (replacing the list), or an empty list on Remove. */
|
|
38
|
+
onAttachmentsChange?: (files: File[]) => void;
|
|
39
|
+
/** Accepted attachment types, as in the native file input, e.g. "image/*,.pdf". */
|
|
40
|
+
accept?: string;
|
|
41
|
+
/** Small text under the header title. */
|
|
42
|
+
description?: ReactNode;
|
|
43
|
+
/** Shows the header with `title` and `description`; defaults to true. Turn it off when your page already has a heading for the chat: `title` still names the chat region and its message log, and a floating chat keeps its close button. */
|
|
44
|
+
showHeader?: boolean;
|
|
45
|
+
/** Shown in the thread before the first message, from its top. Give its heading `className="diya-chat-welcome-title"` to style it at any level; a plain h3 gets the same style. */
|
|
46
|
+
welcome?: ReactNode;
|
|
47
|
+
/** Starter prompts shown as pills before the first message; choosing one sends it. */
|
|
48
|
+
suggestions?: readonly string[];
|
|
49
|
+
/** Small text under the composer, such as a disclaimer or an error. */
|
|
50
|
+
notice?: ReactNode;
|
|
51
|
+
/** 'embedded' fills its container's width (default), 'floating' is a narrow raised panel, right-aligned, with a close button when `onOpenChange` is given, 'full-page' fills its container's width and height. The header and composer stay put while the thread scrolls; a height you set on the Chatbot is filled the same way. */
|
|
52
|
+
layout?: 'embedded' | 'floating' | 'full-page';
|
|
53
|
+
/** Shows each message's `timestamp`; defaults to false. */
|
|
54
|
+
showTimestamps?: boolean;
|
|
55
|
+
/** Whether the chat is shown; defaults to true. When false, an "Open chat" button shows if `onOpenChange` is given. */
|
|
56
|
+
open?: boolean;
|
|
57
|
+
/** Called with the next open state from the close and "Open chat" buttons. */
|
|
58
|
+
onOpenChange?: (open: boolean) => void;
|
|
59
|
+
/** Called with the message on Copy instead of writing its text to the clipboard. */
|
|
60
|
+
onCopy?: (message: ChatMessage) => void | Promise<void>;
|
|
61
|
+
/** Author name shown on the person's messages; defaults to "You". */
|
|
62
|
+
userLabel?: string;
|
|
63
|
+
/** Author name shown on assistant messages; defaults to "Assistant". */
|
|
64
|
+
assistantLabel?: string;
|
|
65
|
+
};
|
|
66
|
+
/** A controlled conversation surface with a message log and composer. It makes no AI, network or simulated-response requests. */
|
|
67
|
+
export declare const Chatbot: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, "children" | "title" | "onCopy"> & {
|
|
68
|
+
/** Visible header title; it also names the chat region and its message log. */
|
|
69
|
+
title: string;
|
|
70
|
+
/** The conversation, oldest first; the caller owns this list. */
|
|
71
|
+
messages: readonly ChatMessage[];
|
|
72
|
+
/** The composer's text; the caller owns this state. */
|
|
73
|
+
value: string;
|
|
74
|
+
/** Called with the composer's new text on every keystroke. */
|
|
75
|
+
onValueChange: (value: string) => void;
|
|
76
|
+
/** Called with the trimmed text and current attachments on Send, Enter or a suggestion; clear `value` and append messages yourself. */
|
|
77
|
+
onSend: (text: string, attachments: readonly File[]) => void;
|
|
78
|
+
/** A response is on its way: blocks sending and offers Stop when `onStop` is given. Until the reply starts, "Preparing a response…" shows; once the newest message is the assistant's, as when a reply streams in, it goes and the log is `aria-busy`, so screen readers read the reply once it is complete. Defaults to false. */
|
|
79
|
+
loading?: boolean;
|
|
80
|
+
/** Shows a Stop button in place of Send while loading. */
|
|
81
|
+
onStop?: () => void;
|
|
82
|
+
/** Shows a Retry button in the notice row. */
|
|
83
|
+
onRetry?: () => void;
|
|
84
|
+
/** Files attached to the next message; the caller owns this list. */
|
|
85
|
+
attachments?: readonly File[];
|
|
86
|
+
/** Shows the Attach button; called with the chosen files (replacing the list), or an empty list on Remove. */
|
|
87
|
+
onAttachmentsChange?: (files: File[]) => void;
|
|
88
|
+
/** Accepted attachment types, as in the native file input, e.g. "image/*,.pdf". */
|
|
89
|
+
accept?: string;
|
|
90
|
+
/** Small text under the header title. */
|
|
91
|
+
description?: ReactNode;
|
|
92
|
+
/** Shows the header with `title` and `description`; defaults to true. Turn it off when your page already has a heading for the chat: `title` still names the chat region and its message log, and a floating chat keeps its close button. */
|
|
93
|
+
showHeader?: boolean;
|
|
94
|
+
/** Shown in the thread before the first message, from its top. Give its heading `className="diya-chat-welcome-title"` to style it at any level; a plain h3 gets the same style. */
|
|
95
|
+
welcome?: ReactNode;
|
|
96
|
+
/** Starter prompts shown as pills before the first message; choosing one sends it. */
|
|
97
|
+
suggestions?: readonly string[];
|
|
98
|
+
/** Small text under the composer, such as a disclaimer or an error. */
|
|
99
|
+
notice?: ReactNode;
|
|
100
|
+
/** 'embedded' fills its container's width (default), 'floating' is a narrow raised panel, right-aligned, with a close button when `onOpenChange` is given, 'full-page' fills its container's width and height. The header and composer stay put while the thread scrolls; a height you set on the Chatbot is filled the same way. */
|
|
101
|
+
layout?: "embedded" | "floating" | "full-page";
|
|
102
|
+
/** Shows each message's `timestamp`; defaults to false. */
|
|
103
|
+
showTimestamps?: boolean;
|
|
104
|
+
/** Whether the chat is shown; defaults to true. When false, an "Open chat" button shows if `onOpenChange` is given. */
|
|
105
|
+
open?: boolean;
|
|
106
|
+
/** Called with the next open state from the close and "Open chat" buttons. */
|
|
107
|
+
onOpenChange?: (open: boolean) => void;
|
|
108
|
+
/** Called with the message on Copy instead of writing its text to the clipboard. */
|
|
109
|
+
onCopy?: (message: ChatMessage) => void | Promise<void>;
|
|
110
|
+
/** Author name shown on the person's messages; defaults to "You". */
|
|
111
|
+
userLabel?: string;
|
|
112
|
+
/** Author name shown on assistant messages; defaults to "Assistant". */
|
|
113
|
+
assistantLabel?: string;
|
|
114
|
+
} & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef, useEffect, useId, useRef, useState } from 'react';
|
|
4
|
+
import { Button } from '../button/Button.js';
|
|
5
|
+
import { Icon } from '../Icon.js';
|
|
6
|
+
import { cx } from '../internal/cx.js';
|
|
7
|
+
import { useDiyaMessages } from '../DiyaProvider.js';
|
|
8
|
+
import { chatbotMessages } from './chatbot-messages.js';
|
|
9
|
+
/** A controlled conversation surface with a message log and composer. It makes no AI, network or simulated-response requests. */
|
|
10
|
+
export const Chatbot = forwardRef(function Chatbot({ title, messages, value, onValueChange, onSend, loading = false, onStop, onRetry, attachments = [], onAttachmentsChange, accept, description, showHeader = true, welcome, suggestions = [], notice, layout = 'embedded', showTimestamps = false, open = true, onOpenChange, onCopy, userLabel, assistantLabel, className, ...props }, ref) {
|
|
11
|
+
const t = useDiyaMessages('chatbot', chatbotMessages);
|
|
12
|
+
const id = useId();
|
|
13
|
+
const composer = useRef(null);
|
|
14
|
+
const reopen = useRef(null);
|
|
15
|
+
const thread = useRef(null);
|
|
16
|
+
const follows = useRef(true);
|
|
17
|
+
const previousOpen = useRef(open);
|
|
18
|
+
const previousLoading = useRef(loading);
|
|
19
|
+
const actionHadFocus = useRef(false);
|
|
20
|
+
const copyOperation = useRef(0);
|
|
21
|
+
const copyContext = useRef({ open, title, messages });
|
|
22
|
+
copyContext.current = { open, title, messages };
|
|
23
|
+
const [copyNotice, setCopyNotice] = useState('');
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
copyOperation.current += 1;
|
|
26
|
+
setCopyNotice('');
|
|
27
|
+
return () => { copyOperation.current += 1; };
|
|
28
|
+
}, [open]);
|
|
29
|
+
// Before the first message only the welcome shows, read from its top; following starts with the first message.
|
|
30
|
+
const empty = messages.length === 0;
|
|
31
|
+
const welcomeOnly = useRef(empty);
|
|
32
|
+
welcomeOnly.current = empty;
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!empty)
|
|
35
|
+
return;
|
|
36
|
+
follows.current = true;
|
|
37
|
+
if (thread.current)
|
|
38
|
+
thread.current.scrollTop = 0;
|
|
39
|
+
}, [empty, open]);
|
|
40
|
+
useEffect(() => { if (!empty && follows.current && thread.current)
|
|
41
|
+
thread.current.scrollTop = thread.current.scrollHeight; }, [messages, loading, open]);
|
|
42
|
+
// A thread that fills its container changes height with it; keep the latest message in view unless the reader scrolled up.
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
const node = thread.current;
|
|
45
|
+
if (!node || typeof ResizeObserver === 'undefined')
|
|
46
|
+
return;
|
|
47
|
+
const observer = new ResizeObserver(() => { if (follows.current && !welcomeOnly.current)
|
|
48
|
+
node.scrollTop = node.scrollHeight; });
|
|
49
|
+
observer.observe(node);
|
|
50
|
+
return () => observer.disconnect();
|
|
51
|
+
}, [open]);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (previousOpen.current !== open) {
|
|
54
|
+
if (open)
|
|
55
|
+
composer.current?.focus();
|
|
56
|
+
else
|
|
57
|
+
reopen.current?.focus();
|
|
58
|
+
}
|
|
59
|
+
previousOpen.current = open;
|
|
60
|
+
}, [open]);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (previousLoading.current && !loading && actionHadFocus.current) {
|
|
63
|
+
composer.current?.focus();
|
|
64
|
+
actionHadFocus.current = false;
|
|
65
|
+
}
|
|
66
|
+
previousLoading.current = loading;
|
|
67
|
+
}, [loading]);
|
|
68
|
+
function send(text = value) {
|
|
69
|
+
if (!text.trim() || loading)
|
|
70
|
+
return;
|
|
71
|
+
follows.current = true;
|
|
72
|
+
copyOperation.current += 1;
|
|
73
|
+
setCopyNotice('');
|
|
74
|
+
onSend(text.trim(), attachments);
|
|
75
|
+
composer.current?.focus();
|
|
76
|
+
}
|
|
77
|
+
async function copy(message) {
|
|
78
|
+
const request = ++copyOperation.current;
|
|
79
|
+
setCopyNotice('');
|
|
80
|
+
const current = () => request === copyOperation.current && copyContext.current.open && copyContext.current.title === title &&
|
|
81
|
+
copyContext.current.messages.some(entry => entry.id === message.id && entry.role === message.role && entry.text === message.text);
|
|
82
|
+
try {
|
|
83
|
+
if (onCopy)
|
|
84
|
+
await onCopy(message);
|
|
85
|
+
else {
|
|
86
|
+
if (!navigator.clipboard)
|
|
87
|
+
throw new Error('Clipboard unavailable');
|
|
88
|
+
await navigator.clipboard.writeText(message.text);
|
|
89
|
+
}
|
|
90
|
+
if (current())
|
|
91
|
+
setCopyNotice(t.copied);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
if (current())
|
|
95
|
+
setCopyNotice(t.copyUnavailable);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!open)
|
|
99
|
+
return onOpenChange ? _jsx(Button, { ref: reopen, onClick: () => onOpenChange(true), children: t.openChat }) : null;
|
|
100
|
+
// A reply being written into the log is held back from screen readers until it is complete. Before it
|
|
101
|
+
// starts, the log stays live and shows "Preparing a response…", which goes once the reply's first words arrive.
|
|
102
|
+
const writing = loading && messages[messages.length - 1]?.role === 'assistant';
|
|
103
|
+
const closable = layout === 'floating' && onOpenChange;
|
|
104
|
+
return _jsxs("section", { "aria-label": title, ...props, ref: ref, className: cx('diya-chat diya-app-pattern-surface', className), "data-presentation": layout, children: [(showHeader || closable) && _jsxs("header", { className: "diya-chat-header", children: [_jsx("div", { children: showHeader && _jsxs(_Fragment, { children: [_jsx("strong", { children: title }), description && _jsx("small", { children: description })] }) }), closable && _jsx(Button, { variant: "quiet", iconOnly: true, "aria-label": t.closeChat, onClick: () => onOpenChange(false), children: _jsx(Icon, { name: "close" }) })] }), _jsxs("div", { className: "diya-chat-thread", ref: thread, role: "log", "aria-label": t.messages(title), "aria-live": "polite", "aria-relevant": "additions text", "aria-busy": writing || undefined, onScroll: () => { const node = thread.current; if (node && !empty)
|
|
105
|
+
follows.current = node.scrollHeight - node.scrollTop - node.clientHeight < 50; }, children: [!messages.length && (welcome || suggestions.length > 0) && _jsxs("div", { className: "diya-chat-welcome", children: [welcome, suggestions.length > 0 && _jsx("div", { className: "diya-chat-suggestions", children: suggestions.map(suggestion => _jsx(Button, { variant: "outline", shape: "pill", disabled: loading, onClick: () => send(suggestion), children: suggestion }, suggestion)) })] }), messages.map((message, index) => _jsxs("article", { className: "diya-chat-message", "data-role": message.role, children: [_jsxs("small", { children: [message.role === 'user' ? userLabel ?? t.you : assistantLabel ?? t.assistant, showTimestamps && message.timestamp && ` · ${message.timestamp}`] }), _jsx("p", { children: message.text }), message.role === 'assistant' && !(writing && index === messages.length - 1) && _jsx(Button, { size: "small", variant: "quiet", onClick: () => void copy(message), children: t.copy })] }, message.id)), loading && !writing && _jsx("p", { role: "status", children: t.preparing })] }), _jsxs("form", { className: "diya-chat-composer", onSubmit: event => { event.preventDefault(); send(); }, children: [_jsx("label", { className: "diya-chat-sr-only", htmlFor: `${id}-message`, children: t.message }), _jsx("textarea", { ref: composer, id: `${id}-message`, rows: 2, placeholder: t.placeholder, value: value, onChange: event => onValueChange(event.target.value), onKeyDown: event => { if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
send();
|
|
108
|
+
} } }), attachments.length > 0 && _jsxs("small", { children: [attachments.map(file => file.name).join(', '), onAttachmentsChange && _jsx("button", { type: "button", disabled: loading, onClick: () => { onAttachmentsChange([]); composer.current?.focus(); }, children: t.remove })] }), _jsxs("div", { children: [onAttachmentsChange ? _jsxs("label", { className: "diya-chat-attach", children: [_jsx(Icon, { name: "paperclip", size: 16 }), t.attach, _jsx("input", { type: "file", multiple: true, disabled: loading, accept: accept, onChange: event => { onAttachmentsChange(Array.from(event.target.files ?? [])); event.target.value = ''; composer.current?.focus(); } }), _jsxs("span", { className: "diya-chat-sr-only", children: [" ", t.attachFiles] })] }) : _jsx("span", {}), loading && onStop ? _jsx(Button, { onFocus: () => { actionHadFocus.current = true; }, onBlur: event => { if (event.relatedTarget)
|
|
109
|
+
actionHadFocus.current = false; }, onClick: () => { onStop(); composer.current?.focus(); }, children: t.stop }) : _jsx(Button, { type: "submit", disabled: loading || !value.trim(), children: t.send })] })] }), _jsxs("div", { className: "diya-chat-notice", role: "status", children: [notice, notice && copyNotice ? ' ' : '', copyNotice, onRetry && _jsx(Button, { variant: "quiet", size: "small", disabled: loading, onClick: () => { onRetry(); composer.current?.focus(); }, children: t.retry })] })] });
|
|
110
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
import { sideNavigationMessages } from './side-navigation-messages.js';
|
|
3
|
+
declare module '../messages.js' {
|
|
4
|
+
interface DiyaMessages {
|
|
5
|
+
sideNavigation: typeof sideNavigationMessages;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export type SideNavigationItem = {
|
|
9
|
+
/** Stable key; matched against the navigation's `value` and passed to `onValueChange`. */
|
|
10
|
+
value: string;
|
|
11
|
+
/** Visible text; when collapsed it becomes the item's accessible name. */
|
|
12
|
+
label: string;
|
|
13
|
+
/** Decorative icon before the label; when collapsed without one, the label's first letter shows. */
|
|
14
|
+
icon?: ReactNode;
|
|
15
|
+
/** Makes the item a real link to this URL, through the provider's `linkComponent`; a plain click calls `onValueChange` instead of navigating when it is given. */
|
|
16
|
+
href?: string;
|
|
17
|
+
/** Shows the item but prevents choosing it. */
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/** A quiet number after the label, such as unread messages: '99+' above 99, and a dot on the icon when collapsed. The accessible name keeps the real count ("Inbox, 120"). 0 shows nothing. */
|
|
20
|
+
count?: number;
|
|
21
|
+
};
|
|
22
|
+
export type SideNavigationGroup = {
|
|
23
|
+
/** Stable key for the group. */
|
|
24
|
+
id: string;
|
|
25
|
+
/** Small visible heading above the group; hidden when collapsed or `showGroups` is false. */
|
|
26
|
+
label?: string;
|
|
27
|
+
/** The group's items, in order. */
|
|
28
|
+
items: readonly SideNavigationItem[];
|
|
29
|
+
};
|
|
30
|
+
export type SideNavigationProps = HTMLAttributes<HTMLElement> & {
|
|
31
|
+
/** Item groups, in order. */
|
|
32
|
+
groups: readonly SideNavigationGroup[];
|
|
33
|
+
/** The current item's `value`; it is marked as the current page. */
|
|
34
|
+
value: string;
|
|
35
|
+
/** Called with an item's `value` when it is chosen; leave it out when every item has an `href` and the links do the routing. */
|
|
36
|
+
onValueChange?: (value: string) => void;
|
|
37
|
+
/** Logo or product name at the top. */
|
|
38
|
+
brand?: ReactNode;
|
|
39
|
+
/** Smaller brand shown when collapsed; defaults to `brand`. */
|
|
40
|
+
collapsedBrand?: ReactNode;
|
|
41
|
+
/** Pinned under the groups, such as an account or workspace Menu; it sits at the bottom when the navigation is given its full height. */
|
|
42
|
+
footer?: ReactNode;
|
|
43
|
+
/** Smaller footer shown when collapsed, such as the account Menu with just an Avatar; defaults to `footer`. */
|
|
44
|
+
collapsedFooter?: ReactNode;
|
|
45
|
+
/** Narrow, icon-only rail; defaults to false. */
|
|
46
|
+
collapsed?: boolean;
|
|
47
|
+
/** Shows group headings; defaults to true. */
|
|
48
|
+
showGroups?: boolean;
|
|
49
|
+
/** Accessible name for the navigation landmark (not shown); defaults to "Application navigation". */
|
|
50
|
+
label?: string;
|
|
51
|
+
};
|
|
52
|
+
/** A vertical app navigation with grouped items and an optional collapsed icon rail; items with `href` are links. The ref, `className`, `style` and other attributes go to the `nav`. */
|
|
53
|
+
export declare const SideNavigation: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
|
|
54
|
+
/** Item groups, in order. */
|
|
55
|
+
groups: readonly SideNavigationGroup[];
|
|
56
|
+
/** The current item's `value`; it is marked as the current page. */
|
|
57
|
+
value: string;
|
|
58
|
+
/** Called with an item's `value` when it is chosen; leave it out when every item has an `href` and the links do the routing. */
|
|
59
|
+
onValueChange?: (value: string) => void;
|
|
60
|
+
/** Logo or product name at the top. */
|
|
61
|
+
brand?: ReactNode;
|
|
62
|
+
/** Smaller brand shown when collapsed; defaults to `brand`. */
|
|
63
|
+
collapsedBrand?: ReactNode;
|
|
64
|
+
/** Pinned under the groups, such as an account or workspace Menu; it sits at the bottom when the navigation is given its full height. */
|
|
65
|
+
footer?: ReactNode;
|
|
66
|
+
/** Smaller footer shown when collapsed, such as the account Menu with just an Avatar; defaults to `footer`. */
|
|
67
|
+
collapsedFooter?: ReactNode;
|
|
68
|
+
/** Narrow, icon-only rail; defaults to false. */
|
|
69
|
+
collapsed?: boolean;
|
|
70
|
+
/** Shows group headings; defaults to true. */
|
|
71
|
+
showGroups?: boolean;
|
|
72
|
+
/** Accessible name for the navigation landmark (not shown); defaults to "Application navigation". */
|
|
73
|
+
label?: string;
|
|
74
|
+
} & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { countLabel } from '../badge/badge-utils.js';
|
|
5
|
+
import { useDiyaMessages } from '../DiyaProvider.js';
|
|
6
|
+
import { cx } from '../internal/cx.js';
|
|
7
|
+
import { useDiyaLinkComponent } from '../internal/link.js';
|
|
8
|
+
import { sideNavigationMessages } from './side-navigation-messages.js';
|
|
9
|
+
/** A vertical app navigation with grouped items and an optional collapsed icon rail; items with `href` are links. The ref, `className`, `style` and other attributes go to the `nav`. */
|
|
10
|
+
export const SideNavigation = forwardRef(function SideNavigation({ groups, value, onValueChange, brand, collapsedBrand, footer, collapsedFooter, collapsed = false, showGroups = true, label, className, ...props }, ref) {
|
|
11
|
+
const t = useDiyaMessages('sideNavigation', sideNavigationMessages);
|
|
12
|
+
const Link = useDiyaLinkComponent();
|
|
13
|
+
return _jsxs("nav", { "aria-label": label ?? t.label, ...props, ref: ref, className: cx('diya-side-navigation diya-app-pattern-surface', className), "data-collapsed": collapsed, children: [brand && _jsx("strong", { children: collapsed ? collapsedBrand ?? brand : brand }), groups.map(group => _jsxs("div", { children: [showGroups && !collapsed && group.label && _jsx("small", { children: group.label }), group.items.map(item => {
|
|
14
|
+
// Badge's cap: the shown number stops at 99+, the accessible name keeps the real count.
|
|
15
|
+
const count = countLabel(item.count ?? 0, 99);
|
|
16
|
+
const counted = count.count > 0;
|
|
17
|
+
const shared = { 'aria-current': value === item.value ? 'page' : undefined, 'aria-label': counted ? t.count(item.label, count.count) : collapsed ? item.label : undefined };
|
|
18
|
+
const glyph = item.icon || (collapsed ? Array.from(item.label)[0] : null);
|
|
19
|
+
const label = _jsx("span", { className: "diya-side-navigation-label", children: item.label });
|
|
20
|
+
const text = collapsed ? null : counted ? _jsxs("span", { className: "diya-side-navigation-text", children: [label, _jsx("span", { className: "diya-side-navigation-count", "aria-hidden": "true", children: count.text })] }) : label;
|
|
21
|
+
const inner = _jsxs(_Fragment, { children: [glyph && _jsxs("span", { className: "diya-side-navigation-icon", "aria-hidden": "true", children: [glyph, collapsed && counted && _jsx("span", { className: "diya-side-navigation-dot" })] }), text] });
|
|
22
|
+
return item.href && !item.disabled
|
|
23
|
+
? _jsx(Link, { href: item.href, ...shared, onClick: (event) => {
|
|
24
|
+
if (!onValueChange || event.defaultPrevented || event.button || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
|
|
25
|
+
return;
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
onValueChange(item.value);
|
|
28
|
+
}, children: inner }, item.value)
|
|
29
|
+
: _jsx("button", { type: "button", disabled: item.disabled, ...shared, onClick: () => onValueChange?.(item.value), children: inner }, item.value);
|
|
30
|
+
})] }, group.id)), footer && _jsx("div", { className: "diya-side-navigation-footer", children: collapsed ? collapsedFooter ?? footer : footer })] });
|
|
31
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** chatbot: English defaults, overridable through DiyaProvider `messages`. */
|
|
2
|
+
export declare const chatbotMessages: {
|
|
3
|
+
you: string;
|
|
4
|
+
assistant: string;
|
|
5
|
+
message: string;
|
|
6
|
+
placeholder: string;
|
|
7
|
+
send: string;
|
|
8
|
+
stop: string;
|
|
9
|
+
retry: string;
|
|
10
|
+
copy: string;
|
|
11
|
+
copied: string;
|
|
12
|
+
copyUnavailable: string;
|
|
13
|
+
attach: string;
|
|
14
|
+
attachFiles: string;
|
|
15
|
+
remove: string;
|
|
16
|
+
preparing: string;
|
|
17
|
+
openChat: string;
|
|
18
|
+
closeChat: string;
|
|
19
|
+
messages: (title: string) => string;
|
|
20
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/** chatbot: English defaults, overridable through DiyaProvider `messages`. */
|
|
2
|
+
export const chatbotMessages = { you: 'You', assistant: 'Assistant', message: 'Message', placeholder: 'Write a message', send: 'Send', stop: 'Stop', retry: 'Retry', copy: 'Copy', copied: 'Response copied.', copyUnavailable: 'Copy unavailable in this browser.', attach: 'Attach', attachFiles: 'files', remove: 'Remove', preparing: 'Preparing a response…', openChat: 'Open chat', closeChat: 'Close chat', messages: (title) => `${title} messages` };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type HTMLAttributes } from 'react';
|
|
2
|
+
import { avatarMessages } from './messages.js';
|
|
3
|
+
declare module '../messages.js' {
|
|
4
|
+
interface DiyaMessages {
|
|
5
|
+
avatar: typeof avatarMessages;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export type AvatarProps = Omit<HTMLAttributes<HTMLSpanElement>, 'children'> & {
|
|
9
|
+
/** The person's name: the avatar's accessible name, and the source of the visible initials (first letters of the first two words). */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Image URL; if it fails to load, the initials show instead, or a person icon when `name` is empty. */
|
|
12
|
+
src?: string;
|
|
13
|
+
/** Avatar diameter. Defaults to 'medium'. */
|
|
14
|
+
size?: 'small' | 'medium' | 'large';
|
|
15
|
+
/** 'circle' or a rounded square. Defaults to 'circle'. */
|
|
16
|
+
shape?: 'circle' | 'rounded';
|
|
17
|
+
/** Shows a presence dot and adds the status to the accessible name. */
|
|
18
|
+
status?: 'online' | 'away' | 'busy';
|
|
19
|
+
};
|
|
20
|
+
/** A person's picture or initials, with an optional presence dot. */
|
|
21
|
+
export declare const Avatar: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLSpanElement>, "children"> & {
|
|
22
|
+
/** The person's name: the avatar's accessible name, and the source of the visible initials (first letters of the first two words). */
|
|
23
|
+
name: string;
|
|
24
|
+
/** Image URL; if it fails to load, the initials show instead, or a person icon when `name` is empty. */
|
|
25
|
+
src?: string;
|
|
26
|
+
/** Avatar diameter. Defaults to 'medium'. */
|
|
27
|
+
size?: "small" | "medium" | "large";
|
|
28
|
+
/** 'circle' or a rounded square. Defaults to 'circle'. */
|
|
29
|
+
shape?: "circle" | "rounded";
|
|
30
|
+
/** Shows a presence dot and adds the status to the accessible name. */
|
|
31
|
+
status?: "online" | "away" | "busy";
|
|
32
|
+
} & import("react").RefAttributes<HTMLSpanElement>>;
|