@iyulab/chat-components 0.14.0 → 0.15.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 +27 -0
- package/dist/components/blocks/UMarkedBlock.d.ts +2 -0
- package/dist/components/blocks/UMarkedBlock.js +24 -12
- package/dist/components-extra/UChartBlock.d.ts +5 -2
- package/dist/components-extra/UChartBlock.js +119 -20
- package/dist/utilities/HtmlPlaceholder.d.ts +8 -0
- package/dist/utilities/HtmlPlaceholder.js +13 -1
- package/package.json +4 -4
- package/skills/iyulab-chat-components/references/components/chart-block.md +18 -0
- package/skills/iyulab-chat-components/references/components/marked-block.md +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.15.0] - 2026-09-30
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **`u-chart-block` no longer changes Chart.js global defaults.** Its theme colors (text, ticks,
|
|
8
|
+
grid, tooltip) used to be written to `Chart.defaults`, which also recolored any other Chart.js chart
|
|
9
|
+
on the page. They are now options of that chart instance, merged under the `options` you pass —
|
|
10
|
+
your values win, down to a single key.
|
|
11
|
+
- **`u-chart-block` uses the design-token chart palette.** Datasets that set no `backgroundColor` or
|
|
12
|
+
`borderColor` take `--u-chart-color-1..N` (one color per slice for `pie`, `doughnut`, and
|
|
13
|
+
`polarArea`), matching dashboards and `@iyulab/u-widgets`. Colors you set are kept, and the `data`
|
|
14
|
+
object you pass is not modified. Without the token sheet, Chart.js defaults apply as before.
|
|
15
|
+
- **Peer ranges promise only tested majors:** `chart.js` is `^4.5.1` (was `>=4.5.1`), `@lit/react`
|
|
16
|
+
`^1.0.8` (was `>=1.0.8`), and `react` `^18.0.0 || ^19.0.0` (was `>=18.0.0`).
|
|
17
|
+
|
|
18
|
+
## [0.14.1] - 2026-09-30
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **A citation whose index falls inside a link URL, an image, or inline code no longer breaks it.**
|
|
23
|
+
The citation markup was restored into the `href` attribute (the link pointed at a truncated URL
|
|
24
|
+
followed by markup) or into the `<code>` text. It is now placed right after the link, image, or code.
|
|
25
|
+
- **A citation that points past the text received so far is held until that text arrives.** During
|
|
26
|
+
streaming it used to be drawn at the end of the partial text and then jump to its place.
|
|
27
|
+
- A citation with a negative or non-integer index is ignored. A negative index used to be counted
|
|
28
|
+
from the end of the text and inserted mid-word.
|
|
29
|
+
|
|
3
30
|
## [0.14.0] - 2026-09-30
|
|
4
31
|
|
|
5
32
|
### Security
|
|
@@ -69,6 +69,8 @@ export declare class UMarkedBlock extends UElement {
|
|
|
69
69
|
* 요청 자체가 반출 경로이므로 대체 텍스트만 그린다.
|
|
70
70
|
*/
|
|
71
71
|
private renderImage;
|
|
72
|
+
/** 인라인 코드 안에 떨어진 인용은 코드 뒤로 옮긴다 — 코드는 글자 그대로여야 한다. */
|
|
73
|
+
private renderCodespan;
|
|
72
74
|
/**
|
|
73
75
|
* 인용/출처 참조객체가 있을때 ref 태그 HTML을 this.placeholder에 보관하고
|
|
74
76
|
* 마크다운 문자열의 해당 위치에 플레이스홀더 센티널을 삽입합니다.
|
|
@@ -11,7 +11,7 @@ import { URefCard } from "../references/URefCard.js";
|
|
|
11
11
|
import "../references/URefCardGroup.js";
|
|
12
12
|
import { UTableBlock } from "./UTableBlock.js";
|
|
13
13
|
import { resolveImageSource } from "../../utilities/imageSources.js";
|
|
14
|
-
import { HtmlPlaceholder, stripRefPlaceholders } from "../../utilities/HtmlPlaceholder.js";
|
|
14
|
+
import { HtmlPlaceholder, extractRefPlaceholders, stripRefPlaceholders } from "../../utilities/HtmlPlaceholder.js";
|
|
15
15
|
import { styles } from "./UMarkedBlock.styles.js";
|
|
16
16
|
import { nothing } from "lit";
|
|
17
17
|
import { customElement, property, state } from "lit/decorators.js";
|
|
@@ -32,7 +32,8 @@ var UMarkedBlock = class UMarkedBlock extends UElement {
|
|
|
32
32
|
table: (token) => this.renderTable(token),
|
|
33
33
|
html: (token) => this.renderHtml(token),
|
|
34
34
|
link: (token) => this.renderLink(token),
|
|
35
|
-
image: (token) => this.renderImage(token)
|
|
35
|
+
image: (token) => this.renderImage(token),
|
|
36
|
+
codespan: (token) => this.renderCodespan(token)
|
|
36
37
|
}
|
|
37
38
|
}).use(markedKatex({ output: "mathml" }));
|
|
38
39
|
this.placeholder = new HtmlPlaceholder();
|
|
@@ -130,10 +131,12 @@ var UMarkedBlock = class UMarkedBlock extends UElement {
|
|
|
130
131
|
*/
|
|
131
132
|
renderLink(token) {
|
|
132
133
|
const text = token.tokens ? Parser.parseInline(token.tokens, this.parser.defaults) : token.text;
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
const [href, inHref] = extractRefPlaceholders(token.href);
|
|
135
|
+
const [title, inTitle] = extractRefPlaceholders(token.title ?? "");
|
|
136
|
+
let out = `<a href="${escapeHtmlHref(href)}"`;
|
|
137
|
+
if (title) out += ` title="${escapeHtmlAttr(title)}"`;
|
|
135
138
|
out += `>${text}</a>`;
|
|
136
|
-
return out;
|
|
139
|
+
return out + inHref + inTitle;
|
|
137
140
|
}
|
|
138
141
|
/**
|
|
139
142
|
* 마크다운 이미지의 src도 `renderLink`와 동일하게 protocol을 검사하고, 이미지 출처 정책
|
|
@@ -141,22 +144,31 @@ var UMarkedBlock = class UMarkedBlock extends UElement {
|
|
|
141
144
|
* 요청 자체가 반출 경로이므로 대체 텍스트만 그린다.
|
|
142
145
|
*/
|
|
143
146
|
renderImage(token) {
|
|
144
|
-
const
|
|
147
|
+
const [href, inHref] = extractRefPlaceholders(token.href);
|
|
148
|
+
const [alt, inAlt] = extractRefPlaceholders(token.text);
|
|
149
|
+
const [title, inTitle] = extractRefPlaceholders(token.title ?? "");
|
|
150
|
+
const refs = inHref + inAlt + inTitle;
|
|
151
|
+
const src = resolveImageSource(href);
|
|
145
152
|
if (src === null) {
|
|
146
|
-
const label =
|
|
147
|
-
return `<span class="image-blocked" part="image-blocked">${escapeHtmlText(label)}</span
|
|
153
|
+
const label = alt ? messages.text("imageBlockedNamed", { name: alt }) : messages.text("imageBlocked");
|
|
154
|
+
return `<span class="image-blocked" part="image-blocked">${escapeHtmlText(label)}</span>` + refs;
|
|
148
155
|
}
|
|
149
|
-
let out = `<img src="${escapeHtmlAttr(src)}" alt="${escapeHtmlAttr(
|
|
150
|
-
if (
|
|
156
|
+
let out = `<img src="${escapeHtmlAttr(src)}" alt="${escapeHtmlAttr(alt)}"`;
|
|
157
|
+
if (title) out += ` title="${escapeHtmlAttr(title)}"`;
|
|
151
158
|
out += `>`;
|
|
152
|
-
return out;
|
|
159
|
+
return out + refs;
|
|
160
|
+
}
|
|
161
|
+
/** 인라인 코드 안에 떨어진 인용은 코드 뒤로 옮긴다 — 코드는 글자 그대로여야 한다. */
|
|
162
|
+
renderCodespan(token) {
|
|
163
|
+
const [text, refs] = extractRefPlaceholders(token.text);
|
|
164
|
+
return `<code>${escapeHtmlText(text)}</code>${refs}`;
|
|
153
165
|
}
|
|
154
166
|
/**
|
|
155
167
|
* 인용/출처 참조객체가 있을때 ref 태그 HTML을 this.placeholder에 보관하고
|
|
156
168
|
* 마크다운 문자열의 해당 위치에 플레이스홀더 센티널을 삽입합니다.
|
|
157
169
|
*/
|
|
158
170
|
insertRefs(value, refs) {
|
|
159
|
-
const sorted =
|
|
171
|
+
const sorted = refs.filter((r) => Number.isInteger(r.endIndex) && r.endIndex >= 0 && r.endIndex <= value.length).sort((a, b) => b.endIndex - a.endIndex);
|
|
160
172
|
for (const ref of sorted) {
|
|
161
173
|
const sources = ref.sources ?? [];
|
|
162
174
|
const label = escapeHtmlText(ref.label ?? `[${refs.indexOf(ref) + 1}]`);
|
|
@@ -26,8 +26,11 @@ export declare class UChartBlock extends UElement {
|
|
|
26
26
|
private createChart;
|
|
27
27
|
/** 기존 차트 인스턴스 제거 */
|
|
28
28
|
private destroyChart;
|
|
29
|
-
/**
|
|
30
|
-
|
|
29
|
+
/**
|
|
30
|
+
* 현재 테마의 CSS 변수를 읽는다. ⚠`Chart.defaults` 를 바꾸지 않는다 — 전역이라 같은 페이지에서
|
|
31
|
+
* 소비자가 직접 만든 chart.js 차트의 색까지 바꿨다. 값은 이 인스턴스의 옵션으로만 들어간다.
|
|
32
|
+
*/
|
|
33
|
+
private readTheme;
|
|
31
34
|
private handleDownloadPNG;
|
|
32
35
|
private handleDownloadJSON;
|
|
33
36
|
private handleFullscreen;
|
|
@@ -85,15 +85,15 @@ var UChartBlock = class UChartBlock extends UElement {
|
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
87
|
try {
|
|
88
|
-
this.
|
|
88
|
+
const theme = this.readTheme();
|
|
89
89
|
this.chartjs = new Chart(ctx, {
|
|
90
90
|
type: this.type,
|
|
91
|
-
data: this.data,
|
|
92
|
-
options: {
|
|
91
|
+
data: paintDatasets(this.type, this.data, theme),
|
|
92
|
+
options: mergeOptions(themeOptions(this.type, this.data, this.options, theme), {
|
|
93
93
|
responsive: true,
|
|
94
94
|
maintainAspectRatio: true,
|
|
95
95
|
...this.options
|
|
96
|
-
}
|
|
96
|
+
})
|
|
97
97
|
});
|
|
98
98
|
} catch (e) {
|
|
99
99
|
this.error = e instanceof Error ? e.message : String(e);
|
|
@@ -106,22 +106,26 @@ var UChartBlock = class UChartBlock extends UElement {
|
|
|
106
106
|
this.chartjs = null;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
109
|
+
/**
|
|
110
|
+
* 현재 테마의 CSS 변수를 읽는다. ⚠`Chart.defaults` 를 바꾸지 않는다 — 전역이라 같은 페이지에서
|
|
111
|
+
* 소비자가 직접 만든 chart.js 차트의 색까지 바꿨다. 값은 이 인스턴스의 옵션으로만 들어간다.
|
|
112
|
+
*/
|
|
113
|
+
readTheme() {
|
|
114
|
+
const style = getComputedStyle(this);
|
|
115
|
+
const css = (v) => style.getPropertyValue(v).trim();
|
|
116
|
+
const palette = [];
|
|
117
|
+
for (let i = 1; i <= PALETTE_MAX; i++) {
|
|
118
|
+
const c = css(`--u-chart-color-${i}`);
|
|
119
|
+
if (!c) break;
|
|
120
|
+
palette.push(c);
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
text: css("--u-txt-color"),
|
|
124
|
+
weak: css("--u-txt-color-weak"),
|
|
125
|
+
border: css("--u-border-color"),
|
|
126
|
+
background: css("--u-bg-color"),
|
|
127
|
+
palette
|
|
128
|
+
};
|
|
125
129
|
}
|
|
126
130
|
handleDownloadPNG() {
|
|
127
131
|
if (!this.chartjs) return;
|
|
@@ -155,5 +159,100 @@ __decorate([query("canvas"), __decorateMetadata("design:type", typeof HTMLCanvas
|
|
|
155
159
|
__decorate([query(".viewport"), __decorateMetadata("design:type", typeof HTMLElement === "undefined" ? Object : HTMLElement)], UChartBlock.prototype, "viewport", void 0);
|
|
156
160
|
__decorate([state(), __decorateMetadata("design:type", Object)], UChartBlock.prototype, "error", void 0);
|
|
157
161
|
UChartBlock = __decorate([customElement("u-chart-block")], UChartBlock);
|
|
162
|
+
/** 읽어 볼 팔레트 토큰의 상한 — 시트는 여덟을 선언한다. 비어 있는 첫 번호에서 멈춘다. */
|
|
163
|
+
var PALETTE_MAX = 12;
|
|
164
|
+
function isPlain(v) {
|
|
165
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
166
|
+
}
|
|
167
|
+
/** `base` 위에 `over` 를 깊게 덮는다 — 소비자가 준 값이 항상 이긴다. 입력은 바꾸지 않는다. */
|
|
168
|
+
function mergeOptions(base, over) {
|
|
169
|
+
const out = { ...base };
|
|
170
|
+
for (const [k, v] of Object.entries(over)) out[k] = isPlain(v) && isPlain(out[k]) ? mergeOptions(out[k], v) : v;
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
var CARTESIAN = /* @__PURE__ */ new Set([
|
|
174
|
+
"bar",
|
|
175
|
+
"line",
|
|
176
|
+
"scatter",
|
|
177
|
+
"bubble"
|
|
178
|
+
]);
|
|
179
|
+
var RADIAL = /* @__PURE__ */ new Set(["radar", "polarArea"]);
|
|
180
|
+
var PER_POINT = /* @__PURE__ */ new Set([
|
|
181
|
+
"pie",
|
|
182
|
+
"doughnut",
|
|
183
|
+
"polarArea"
|
|
184
|
+
]);
|
|
185
|
+
/**
|
|
186
|
+
* 테마 색을 담은 인스턴스 옵션. 축은 «이 차트에 실제로 생길 축» 에만 준다 — 원형 차트에 `x`/`y`
|
|
187
|
+
* 설정을 주면 축이 생길 수 있어서다. 축 id 는 차트 종류의 기본 축 · 소비자가 선언한 축 · 데이터셋이
|
|
188
|
+
* 가리키는 축의 합집합이다.
|
|
189
|
+
*/
|
|
190
|
+
function themeOptions(type, data, options, t) {
|
|
191
|
+
const tooltip = {
|
|
192
|
+
backgroundColor: t.background,
|
|
193
|
+
titleColor: t.text,
|
|
194
|
+
bodyColor: t.weak,
|
|
195
|
+
borderColor: t.border,
|
|
196
|
+
borderWidth: 1
|
|
197
|
+
};
|
|
198
|
+
const ids = new Set(Object.keys(options?.scales ?? {}));
|
|
199
|
+
if (CARTESIAN.has(type)) {
|
|
200
|
+
ids.add("x");
|
|
201
|
+
ids.add("y");
|
|
202
|
+
}
|
|
203
|
+
if (RADIAL.has(type)) ids.add("r");
|
|
204
|
+
for (const ds of data.datasets ?? []) {
|
|
205
|
+
const d = ds;
|
|
206
|
+
for (const key of [
|
|
207
|
+
"xAxisID",
|
|
208
|
+
"yAxisID",
|
|
209
|
+
"rAxisID"
|
|
210
|
+
]) if (typeof d[key] === "string") ids.add(d[key]);
|
|
211
|
+
}
|
|
212
|
+
const scales = {};
|
|
213
|
+
for (const id of ids) scales[id] = {
|
|
214
|
+
ticks: { color: t.weak },
|
|
215
|
+
grid: { color: t.border },
|
|
216
|
+
...RADIAL.has(type) && id === "r" ? {
|
|
217
|
+
angleLines: { color: t.border },
|
|
218
|
+
pointLabels: { color: t.text }
|
|
219
|
+
} : {}
|
|
220
|
+
};
|
|
221
|
+
return {
|
|
222
|
+
color: t.text,
|
|
223
|
+
borderColor: t.border,
|
|
224
|
+
plugins: {
|
|
225
|
+
tooltip,
|
|
226
|
+
legend: { labels: { color: t.text } }
|
|
227
|
+
},
|
|
228
|
+
...ids.size ? { scales } : {}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* 색을 지정하지 않은 데이터셋에 팔레트를 입힌다. 소비자가 준 `backgroundColor`/`borderColor` 는
|
|
233
|
+
* 건드리지 않고, 입력 객체도 바꾸지 않는다(사본을 돌려준다). 원형 차트는 조각마다 한 색이다.
|
|
234
|
+
*/
|
|
235
|
+
function paintDatasets(type, data, t) {
|
|
236
|
+
const p = t.palette;
|
|
237
|
+
if (!p.length || !data.datasets) return data;
|
|
238
|
+
const datasets = data.datasets.map((ds, i) => {
|
|
239
|
+
const d = { ...ds };
|
|
240
|
+
const has = (k) => d[k] !== void 0;
|
|
241
|
+
if (PER_POINT.has(type)) {
|
|
242
|
+
const n = Array.isArray(d.data) ? d.data.length : 0;
|
|
243
|
+
if (!has("backgroundColor")) d.backgroundColor = Array.from({ length: n }, (_, j) => p[j % p.length]);
|
|
244
|
+
if (!has("borderColor") && t.background) d.borderColor = t.background;
|
|
245
|
+
} else {
|
|
246
|
+
const c = p[i % p.length];
|
|
247
|
+
if (!has("borderColor")) d.borderColor = c;
|
|
248
|
+
if (!has("backgroundColor")) d.backgroundColor = c;
|
|
249
|
+
}
|
|
250
|
+
return d;
|
|
251
|
+
});
|
|
252
|
+
return {
|
|
253
|
+
...data,
|
|
254
|
+
datasets
|
|
255
|
+
};
|
|
256
|
+
}
|
|
158
257
|
//#endregion
|
|
159
258
|
export { UChartBlock };
|
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
* 종전처럼 한쪽만 바뀌어 어긋난다.
|
|
12
12
|
*/
|
|
13
13
|
export declare function stripRefPlaceholders(value: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* 문자열에서 ref 플레이스홀더 센티널을 떼어 낸다 — `[센티널 없는 문자열, 떼어 낸 센티널들]`.
|
|
16
|
+
*
|
|
17
|
+
* 링크 주소·이미지 속성·인라인 코드처럼 **태그가 들어갈 수 없는 자리**에 인용이 떨어졌을 때 쓴다.
|
|
18
|
+
* 그 자리에 남기면 `restore()` 가 속성 값이나 `<code>` 안에 HTML 을 넣는다(링크가 깨지고 코드에
|
|
19
|
+
* 인용 태그가 섞인다). 지우면 인용을 잃으므로, 호출부가 떼어 낸 것을 그 구문 **바로 뒤**에 둔다.
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractRefPlaceholders(value: string): [string, string];
|
|
14
22
|
export declare class HtmlPlaceholder {
|
|
15
23
|
private map;
|
|
16
24
|
private idx;
|
|
@@ -50,6 +50,18 @@ var sentinelPattern = () => /\u{E000}\d+\u{E001}/gu;
|
|
|
50
50
|
function stripRefPlaceholders(value) {
|
|
51
51
|
return value.replace(sentinelPattern(), "");
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* 문자열에서 ref 플레이스홀더 센티널을 떼어 낸다 — `[센티널 없는 문자열, 떼어 낸 센티널들]`.
|
|
55
|
+
*
|
|
56
|
+
* 링크 주소·이미지 속성·인라인 코드처럼 **태그가 들어갈 수 없는 자리**에 인용이 떨어졌을 때 쓴다.
|
|
57
|
+
* 그 자리에 남기면 `restore()` 가 속성 값이나 `<code>` 안에 HTML 을 넣는다(링크가 깨지고 코드에
|
|
58
|
+
* 인용 태그가 섞인다). 지우면 인용을 잃으므로, 호출부가 떼어 낸 것을 그 구문 **바로 뒤**에 둔다.
|
|
59
|
+
*/
|
|
60
|
+
function extractRefPlaceholders(value) {
|
|
61
|
+
const keys = value.match(sentinelPattern());
|
|
62
|
+
if (!keys) return [value, ""];
|
|
63
|
+
return [value.replace(sentinelPattern(), ""), keys.join("")];
|
|
64
|
+
}
|
|
53
65
|
var HtmlPlaceholder = class {
|
|
54
66
|
constructor() {
|
|
55
67
|
this.map = {};
|
|
@@ -78,4 +90,4 @@ var HtmlPlaceholder = class {
|
|
|
78
90
|
}
|
|
79
91
|
};
|
|
80
92
|
//#endregion
|
|
81
|
-
export { HtmlPlaceholder, stripRefPlaceholders };
|
|
93
|
+
export { HtmlPlaceholder, extractRefPlaceholders, stripRefPlaceholders };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/chat-components",
|
|
3
3
|
"description": "llm chat components for building chat interfaces",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.15.0",
|
|
5
5
|
"author": "iyulab",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@iyulab/components": ">=1.51.0",
|
|
73
|
-
"@lit/react": "
|
|
74
|
-
"chart.js": "
|
|
75
|
-
"react": "
|
|
73
|
+
"@lit/react": "^1.0.8",
|
|
74
|
+
"chart.js": "^4.5.1",
|
|
75
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
76
76
|
},
|
|
77
77
|
"peerDependenciesMeta": {
|
|
78
78
|
"@lit/react": {
|
|
@@ -65,6 +65,23 @@ of it was clipped by the block's `overflow: hidden` with no scrollbar left to re
|
|
|
65
65
|
|
|
66
66
|
There is no size property or custom property for this — the host is the lever.
|
|
67
67
|
|
|
68
|
+
## Colors and theme
|
|
69
|
+
|
|
70
|
+
Text, tick, grid, and tooltip colors come from the design tokens (`--u-txt-color`,
|
|
71
|
+
`--u-txt-color-weak`, `--u-border-color`, `--u-bg-color`), and dataset colors from the chart palette
|
|
72
|
+
`--u-chart-color-1..N` — the same palette dashboards and `@iyulab/u-widgets` use. Both apply to **this
|
|
73
|
+
chart only**: `Chart.defaults` is not modified, so other Chart.js charts on the page keep their own
|
|
74
|
+
look.
|
|
75
|
+
|
|
76
|
+
Anything you pass wins: a dataset's own `backgroundColor`/`borderColor` is kept, and `options` are
|
|
77
|
+
merged over the theme (`options.scales.x.ticks.color` overrides just that value). Without the token
|
|
78
|
+
sheet the palette is empty and Chart.js defaults apply.
|
|
79
|
+
|
|
80
|
+
```css
|
|
81
|
+
/* Recolour the palette for one area */
|
|
82
|
+
.report u-chart-block { --u-chart-color-1: #0b6e4f; }
|
|
83
|
+
```
|
|
84
|
+
|
|
68
85
|
## Properties
|
|
69
86
|
|
|
70
87
|
| Property | Type | Default | Description |
|
|
@@ -80,6 +97,7 @@ There is no size property or custom property for this — the host is the lever.
|
|
|
80
97
|
| Download | Export chart as PNG or raw JSON data |
|
|
81
98
|
| Full screen | Toggle the chart viewport into full-screen mode |
|
|
82
99
|
| Theme sync | Watches `document.documentElement[theme]` and re-renders on change |
|
|
100
|
+
| Palette | Datasets without `backgroundColor`/`borderColor` take `--u-chart-color-1..N` from the design-token sheet (per slice for `pie`/`doughnut`/`polarArea`) |
|
|
83
101
|
|
|
84
102
|
## Requires
|
|
85
103
|
|
|
@@ -79,6 +79,11 @@ Markdown images (table cells included) follow the page-wide image origin policy
|
|
|
79
79
|
|
|
80
80
|
## ReferenceCitation Type
|
|
81
81
|
|
|
82
|
+
A citation is drawn at `endIndex` in the markdown source. While a response streams, a citation whose
|
|
83
|
+
`endIndex` is past the text received so far is held until that text arrives; a negative or non-integer
|
|
84
|
+
index is ignored. If `endIndex` falls inside a link URL, an image, or inline code, the citation is drawn
|
|
85
|
+
right after that element; inside a fenced code block it is dropped.
|
|
86
|
+
|
|
82
87
|
```ts
|
|
83
88
|
interface ReferenceCitation {
|
|
84
89
|
startIndex: number; // Start character index in the markdown text
|