@iyulab/chat-components 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/assets/action-prompt.md.js +3 -0
  3. package/dist/assets/widget-prompt.md.js +3 -0
  4. package/dist/components/actions/UQuestionAction.component.d.ts +18 -0
  5. package/dist/components/actions/UQuestionAction.component.js +58 -0
  6. package/dist/components/actions/UQuestionAction.d.ts +7 -0
  7. package/dist/components/actions/UQuestionAction.js +5 -0
  8. package/dist/components/actions/UQuestionAction.styles.js +45 -0
  9. package/dist/components/blocks/UCodeBlock.component.d.ts +5 -3
  10. package/dist/components/blocks/UCodeBlock.component.js +14 -2
  11. package/dist/components/blocks/UCodeBlock.styles.js +6 -0
  12. package/dist/components/blocks/UFilesBlock.component.d.ts +22 -0
  13. package/dist/components/blocks/UFilesBlock.component.js +192 -0
  14. package/dist/components/blocks/UFilesBlock.d.ts +7 -0
  15. package/dist/components/blocks/UFilesBlock.js +5 -0
  16. package/dist/components/blocks/UFilesBlock.styles.d.ts +1 -0
  17. package/dist/components/blocks/UFilesBlock.styles.js +206 -0
  18. package/dist/components/blocks/UJsonBlock.component.d.ts +3 -3
  19. package/dist/components/blocks/UJsonBlock.component.js +2 -2
  20. package/dist/components/blocks/UMarkedBlock.component.d.ts +17 -22
  21. package/dist/components/blocks/UMarkedBlock.component.js +92 -62
  22. package/dist/components/blocks/URefBlock.component.d.ts +3 -3
  23. package/dist/components/blocks/URefBlock.component.js +6 -7
  24. package/dist/components/blocks/UTableBlock.component.d.ts +49 -0
  25. package/dist/components/blocks/UTableBlock.component.js +228 -0
  26. package/dist/components/blocks/UTableBlock.d.ts +7 -0
  27. package/dist/components/blocks/UTableBlock.js +5 -0
  28. package/dist/components/blocks/UTableBlock.styles.d.ts +1 -0
  29. package/dist/components/blocks/UTableBlock.styles.js +134 -0
  30. package/dist/components/blocks/UTextBlock.component.d.ts +3 -3
  31. package/dist/components/blocks/UTextBlock.component.js +2 -2
  32. package/dist/components/blocks/UThinkBlock.component.d.ts +3 -3
  33. package/dist/components/blocks/UThinkBlock.component.js +2 -2
  34. package/dist/components/blocks/UToolBlock.component.d.ts +3 -3
  35. package/dist/components/blocks/UToolBlock.component.js +2 -2
  36. package/dist/components/buttons/UAttachButton.component.d.ts +3 -3
  37. package/dist/components/buttons/UAttachButton.component.js +2 -2
  38. package/dist/components/buttons/UCopyButton.component.d.ts +3 -3
  39. package/dist/components/buttons/UCopyButton.component.js +2 -2
  40. package/dist/components/buttons/UReportButton.component.d.ts +3 -3
  41. package/dist/components/buttons/UReportButton.component.js +2 -2
  42. package/dist/components/buttons/URetryButton.component.d.ts +3 -3
  43. package/dist/components/buttons/URetryButton.component.js +2 -2
  44. package/dist/components/buttons/UShareButton.component.d.ts +3 -3
  45. package/dist/components/buttons/UShareButton.component.js +2 -2
  46. package/dist/components/buttons/UVoteButton.component.d.ts +3 -3
  47. package/dist/components/buttons/UVoteButton.component.js +7 -4
  48. package/dist/components/message/UMessage.component.d.ts +7 -7
  49. package/dist/components/message/UMessage.component.js +16 -50
  50. package/dist/components/message/UMessage.styles.js +38 -11
  51. package/dist/components/prompt/UPrompt.component.d.ts +3 -3
  52. package/dist/components/prompt/UPrompt.component.js +2 -2
  53. package/dist/components/prompt/UPrompt.styles.js +28 -0
  54. package/dist/components/references/URefCard.component.d.ts +9 -6
  55. package/dist/components/references/URefCard.component.js +14 -10
  56. package/dist/components/references/URefCardGroup.component.d.ts +4 -3
  57. package/dist/components/references/URefCardGroup.component.js +3 -3
  58. package/dist/components/references/URefTag.component.d.ts +3 -3
  59. package/dist/components/references/URefTag.component.js +2 -2
  60. package/dist/components/widgets/UChartWidget.component.d.ts +36 -0
  61. package/dist/components/widgets/UChartWidget.component.js +180 -0
  62. package/dist/components/widgets/UChartWidget.d.ts +7 -0
  63. package/dist/components/widgets/UChartWidget.js +5 -0
  64. package/dist/components/widgets/UChartWidget.styles.d.ts +1 -0
  65. package/dist/components/widgets/UChartWidget.styles.js +86 -0
  66. package/dist/components/widgets/UImagesWidget.component.d.ts +30 -0
  67. package/dist/components/widgets/UImagesWidget.component.js +164 -0
  68. package/dist/components/widgets/UImagesWidget.d.ts +7 -0
  69. package/dist/components/widgets/UImagesWidget.js +5 -0
  70. package/dist/components/widgets/UImagesWidget.styles.d.ts +1 -0
  71. package/dist/components/widgets/UImagesWidget.styles.js +218 -0
  72. package/dist/components/widgets/UMapWidget.component.d.ts +20 -0
  73. package/dist/components/widgets/UMapWidget.component.js +65 -0
  74. package/dist/components/widgets/UMapWidget.d.ts +7 -0
  75. package/dist/components/widgets/UMapWidget.js +5 -0
  76. package/dist/components/widgets/UMapWidget.styles.d.ts +1 -0
  77. package/dist/components/widgets/UMapWidget.styles.js +47 -0
  78. package/dist/components/widgets/UVideoWidget.component.d.ts +21 -0
  79. package/dist/components/widgets/UVideoWidget.component.js +106 -0
  80. package/dist/components/widgets/UVideoWidget.d.ts +7 -0
  81. package/dist/components/widgets/UVideoWidget.js +5 -0
  82. package/dist/components/widgets/UVideoWidget.styles.d.ts +1 -0
  83. package/dist/components/widgets/UVideoWidget.styles.js +36 -0
  84. package/dist/components/widgets/UWidget.component.d.ts +43 -0
  85. package/dist/components/widgets/UWidget.component.js +140 -0
  86. package/dist/components/widgets/UWidget.d.ts +7 -0
  87. package/dist/components/widgets/UWidget.js +5 -0
  88. package/dist/components/widgets/UWidget.styles.d.ts +1 -0
  89. package/dist/components/widgets/UWidget.styles.js +33 -0
  90. package/dist/index.d.ts +13 -1
  91. package/dist/index.js +20 -2
  92. package/dist/types/Actions.d.ts +24 -0
  93. package/dist/types/Actions.js +34 -0
  94. package/dist/types/BlockItem.d.ts +32 -1
  95. package/dist/types/JsonSchema.d.ts +59 -0
  96. package/dist/types/Widgets.d.ts +34 -0
  97. package/dist/types/Widgets.js +115 -0
  98. package/dist/utilities/ActionPromptBuilder.d.ts +40 -0
  99. package/dist/utilities/ActionPromptBuilder.js +93 -0
  100. package/dist/utilities/WidgetPromptBuilder.d.ts +28 -0
  101. package/dist/utilities/WidgetPromptBuilder.js +87 -0
  102. package/package.json +12 -12
  103. package/dist/components/loaders/UDotLoader.component.d.ts +0 -9
  104. package/dist/components/loaders/UDotLoader.component.js +0 -23
  105. package/dist/components/loaders/UDotLoader.d.ts +0 -7
  106. package/dist/components/loaders/UDotLoader.js +0 -5
  107. package/dist/components/loaders/UDotLoader.styles.js +0 -50
  108. /package/dist/components/{loaders/UDotLoader.styles.d.ts → actions/UQuestionAction.styles.d.ts} +0 -0
@@ -0,0 +1,93 @@
1
+ import template from '../assets/action-prompt.md.js';
2
+ import { PRESET_ACTION_LIST, PRESET_ACTION_DEFINITIONS } from '../types/Actions.js';
3
+
4
+ class ActionPromptBuilder {
5
+ constructor() {
6
+ this.actions = /* @__PURE__ */ new Map();
7
+ }
8
+ /**
9
+ * 싱글톤 인스턴스를 반환합니다. 최초 호출 시 인스턴스가 생성됩니다.
10
+ */
11
+ static get instance() {
12
+ if (!this._instance) {
13
+ this._instance = new ActionPromptBuilder();
14
+ }
15
+ return this._instance;
16
+ }
17
+ /**
18
+ * Action 정의를 등록합니다. 같은 type이 이미 등록되어 있으면 에러를 던집니다.
19
+ * @throws {Error} 같은 type의 action이 이미 등록된 경우
20
+ */
21
+ add(definition) {
22
+ if (this.actions.has(definition.type)) {
23
+ throw new Error(`Action with type "${definition.type}" is already registered.`);
24
+ }
25
+ this.actions.set(definition.type, definition);
26
+ return this;
27
+ }
28
+ /**
29
+ * 미리 정의된 프리셋 Action을 등록합니다.
30
+ * @example
31
+ * ActionPromptBuilder.use(PresetAction.Questions);
32
+ * ActionPromptBuilder.use(PresetAction.All);
33
+ */
34
+ use(flags) {
35
+ for (const flag of PRESET_ACTION_LIST) {
36
+ if (flags & flag) {
37
+ const definition = PRESET_ACTION_DEFINITIONS.get(flag);
38
+ if (definition && !this.actions.has(definition.type)) {
39
+ this.actions.set(definition.type, definition);
40
+ }
41
+ }
42
+ }
43
+ return this;
44
+ }
45
+ /**
46
+ * 등록된 action들에 대한 LLM 시스템 프롬프트 인스트럭션을 생성합니다.
47
+ */
48
+ build() {
49
+ if (this.actions.size === 0) return "";
50
+ const defs = Array.from(this.actions.values());
51
+ const actionList = defs.map((d) => `- \`${d.type}\`: ${d.description}`).join("\n");
52
+ const actionDocs = defs.map((def) => {
53
+ const lines = [
54
+ `### ${def.type}`,
55
+ "",
56
+ def.description,
57
+ "",
58
+ `**Type:** \`${def.type}\``
59
+ ];
60
+ if (def.properties) {
61
+ lines.push(
62
+ "",
63
+ "**Properties (JSON Schema):**",
64
+ "```json",
65
+ JSON.stringify({ type: "object", properties: def.properties }, null, 2),
66
+ "```"
67
+ );
68
+ }
69
+ return lines.join("\n");
70
+ }).join("\n\n---\n\n");
71
+ return template.replace("{{ACTION_LIST}}", actionList).replace("{{ACTION_DOCS}}", actionDocs);
72
+ }
73
+ /**
74
+ * LLM 응답 텍스트에서 `action-json` 코드블록을 추출합니다.
75
+ *
76
+ * @param value - LLM 응답 텍스트
77
+ * @returns `[actions, rest]` — actions는 파싱된 JSON 객체 배열, rest는 블록이 제거된 나머지 텍스트
78
+ */
79
+ parse(value) {
80
+ const pattern = /```action-json\s*([\s\S]*?)```/g;
81
+ const actions = [];
82
+ const rest = value.replace(pattern, (_, json) => {
83
+ try {
84
+ actions.push(JSON.parse(json.trim()));
85
+ } catch {
86
+ }
87
+ return "";
88
+ }).trim();
89
+ return [actions, rest];
90
+ }
91
+ }
92
+
93
+ export { ActionPromptBuilder };
@@ -0,0 +1,28 @@
1
+ import { PresetWidget, WidgetDefinition } from '../types/Widgets.js';
2
+ /**
3
+ * 위젯 등록, LLM 인스트럭션 빌드, HTML 렌더링을 통합 제공하는 유틸리티
4
+ */
5
+ export declare class WidgetPromptBuilder {
6
+ private static _instance;
7
+ private widgets;
8
+ /**
9
+ * 싱글톤 인스턴스를 반환합니다. 최초 호출 시 인스턴스가 생성됩니다.
10
+ */
11
+ static get instance(): WidgetPromptBuilder;
12
+ /**
13
+ * 위젯 정의를 등록합니다. 같은 이름의 위젯이 이미 등록되어 있으면 에러를 던집니다.
14
+ * @throws {Error} 같은 이름의 위젯이 이미 등록된 경우 또는 같은 태그의 커스텀 요소가 다른 클래스에 의해 정의된 경우
15
+ */
16
+ add(definition: WidgetDefinition): WidgetPromptBuilder;
17
+ /**
18
+ * 미리 정의된 프리셋 위젯을 사용합니다.
19
+ * @example
20
+ * WidgetRegistry.use(Widget.Images | Widget.Chart);
21
+ * WidgetRegistry.use(Widget.All);
22
+ */
23
+ use(flags: PresetWidget): WidgetPromptBuilder;
24
+ /**
25
+ * 등록된 위젯들에 대한 LLM 인스트럭션 문자열을 생성합니다.
26
+ */
27
+ build(): string;
28
+ }
@@ -0,0 +1,87 @@
1
+ import template from '../assets/widget-prompt.md.js';
2
+ import { UElement } from '@iyulab/components/dist/components/UElement.js';
3
+ import { PRESET_WIDGET_LIST, PRESET_WIDGET_DEFINITIONS } from '../types/Widgets.js';
4
+
5
+ class WidgetPromptBuilder {
6
+ constructor() {
7
+ this.widgets = /* @__PURE__ */ new Map();
8
+ }
9
+ /**
10
+ * 싱글톤 인스턴스를 반환합니다. 최초 호출 시 인스턴스가 생성됩니다.
11
+ */
12
+ static get instance() {
13
+ if (!this._instance) {
14
+ this._instance = new WidgetPromptBuilder();
15
+ }
16
+ return this._instance;
17
+ }
18
+ /**
19
+ * 위젯 정의를 등록합니다. 같은 이름의 위젯이 이미 등록되어 있으면 에러를 던집니다.
20
+ * @throws {Error} 같은 이름의 위젯이 이미 등록된 경우 또는 같은 태그의 커스텀 요소가 다른 클래스에 의해 정의된 경우
21
+ */
22
+ add(definition) {
23
+ if (this.widgets.has(definition.tag)) {
24
+ throw new Error(`Widget with tag "${definition.tag}" is already registered.`);
25
+ }
26
+ const constructor = customElements.get(definition.tag);
27
+ if (constructor && constructor !== definition.element) {
28
+ throw new Error(`Custom element with tag "${definition.tag}" is already defined to a different class.`);
29
+ }
30
+ if (definition.element.prototype instanceof UElement) {
31
+ definition.element.define(definition.tag);
32
+ } else {
33
+ customElements.define(definition.tag, definition.element);
34
+ }
35
+ this.widgets.set(definition.tag, definition);
36
+ return this;
37
+ }
38
+ /**
39
+ * 미리 정의된 프리셋 위젯을 사용합니다.
40
+ * @example
41
+ * WidgetRegistry.use(Widget.Images | Widget.Chart);
42
+ * WidgetRegistry.use(Widget.All);
43
+ */
44
+ use(flags) {
45
+ for (const flag of PRESET_WIDGET_LIST) {
46
+ if (flags & flag) {
47
+ const definition = PRESET_WIDGET_DEFINITIONS.get(flag);
48
+ if (definition) {
49
+ this.add(definition);
50
+ }
51
+ }
52
+ }
53
+ return this;
54
+ }
55
+ /**
56
+ * 등록된 위젯들에 대한 LLM 인스트럭션 문자열을 생성합니다.
57
+ */
58
+ build() {
59
+ if (this.widgets.size === 0) return "";
60
+ const widgets = Array.from(this.widgets.values());
61
+ const widgetList = widgets.map((w) => `- \`${w.tag}\`: ${w.description}`).join("\n");
62
+ const widgetDocs = widgets.map((w) => {
63
+ const lines = [
64
+ `### ${w.tag}`,
65
+ "",
66
+ `**Tag:** \`${w.tag}\``
67
+ ];
68
+ if (w.properties) {
69
+ lines.push(
70
+ "",
71
+ "**Properties (JSON Schema):**",
72
+ "```json",
73
+ JSON.stringify({
74
+ type: "object",
75
+ properties: w.properties,
76
+ ...w.required ? { required: w.required } : {}
77
+ }, null, 2),
78
+ "```"
79
+ );
80
+ }
81
+ return lines.join("\n");
82
+ }).join("\n\n---\n\n");
83
+ return template.replace("{{WIDGET_LIST}}", widgetList).replace("{{WIDGET_DOCS}}", widgetDocs);
84
+ }
85
+ }
86
+
87
+ export { WidgetPromptBuilder };
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.3.0",
4
+ "version": "0.4.0",
5
5
  "author": "iyulab",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -41,23 +41,23 @@
41
41
  "build": "eslint && vite build"
42
42
  },
43
43
  "dependencies": {
44
- "@iyulab/components": "0.2.0",
45
- "dompurify": "^3.3.1",
44
+ "@iyulab/components": "^0.4.0",
45
+ "chart.js": "^4.5.1",
46
46
  "highlight.js": "^11.11.1",
47
47
  "lit": "^3.3.2",
48
- "marked": "^17.0.1",
49
- "marked-katex-extension": "^5.1.6"
48
+ "marked": "^17.0.3",
49
+ "marked-katex-extension": "^5.1.7"
50
50
  },
51
51
  "devDependencies": {
52
- "@eslint/js": "^9.39.2",
52
+ "@eslint/js": "^9.39.3",
53
53
  "@lit/react": "^1.0.8",
54
- "@types/node": "^25.0.9",
55
- "eslint": "^9.39.2",
56
- "eslint-plugin-lit": "^2.1.1",
57
- "globals": "^17.0.0",
58
- "openai": "^6.16.0",
54
+ "@types/node": "^25.3.2",
55
+ "eslint": "^9.39.3",
56
+ "eslint-plugin-lit": "^2.2.1",
57
+ "globals": "^17.3.0",
58
+ "openai": "^6.25.0",
59
59
  "typescript": "^5.9.3",
60
- "typescript-eslint": "^8.53.1",
60
+ "typescript-eslint": "^8.56.1",
61
61
  "vite": "^7.3.1",
62
62
  "vite-plugin-dts": "^4.5.4"
63
63
  }
@@ -1,9 +0,0 @@
1
- import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
2
- /**
3
- * 점 3개 로더 컴포넌트입니다.
4
- */
5
- export declare class UDotLoader extends BaseElement {
6
- static styles: import('lit').CSSResultGroup[];
7
- static dependencies: Record<string, typeof BaseElement>;
8
- render(): import('lit-html').TemplateResult<1>;
9
- }
@@ -1,23 +0,0 @@
1
- import { html } from 'lit';
2
- import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
3
- import { styles } from './UDotLoader.styles.js';
4
-
5
- class UDotLoader extends BaseElement {
6
- static {
7
- this.styles = [super.styles, styles];
8
- }
9
- static {
10
- this.dependencies = {};
11
- }
12
- render() {
13
- return html`
14
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
15
- <circle class="d0" cx="4" cy="12" r="3" />
16
- <circle class="d1" cx="12" cy="12" r="3" />
17
- <circle class="d2" cx="20" cy="12" r="3" />
18
- </svg>
19
- `;
20
- }
21
- }
22
-
23
- export { UDotLoader };
@@ -1,7 +0,0 @@
1
- import { UDotLoader } from './UDotLoader.component.js';
2
- declare global {
3
- interface HTMLElementTagNameMap {
4
- 'u-dot-loader': UDotLoader;
5
- }
6
- }
7
- export { UDotLoader };
@@ -1,5 +0,0 @@
1
- import { UDotLoader } from './UDotLoader.component.js';
2
-
3
- UDotLoader.define("u-dot-loader");
4
-
5
- export { UDotLoader };
@@ -1,50 +0,0 @@
1
- import { css } from 'lit';
2
-
3
- const styles = css`
4
- svg {
5
- width: 1em;
6
- height: 1em;
7
- fill: currentColor;
8
- display: inline-block;
9
- vertical-align: middle;
10
- }
11
-
12
- circle {
13
- animation: bounce 1.05s infinite;
14
- transform-box: fill-box;
15
- transform-origin: center;
16
- }
17
-
18
- circle.d1 {
19
- animation-delay: 0.1s;
20
- }
21
-
22
- circle.d2 {
23
- animation-delay: 0.2s;
24
- }
25
-
26
- @media (prefers-reduced-motion: reduce) {
27
- circle {
28
- animation: none;
29
- transform: none;
30
- }
31
- }
32
-
33
- @keyframes bounce {
34
- 0%,57.14% {
35
- animation-timing-function: cubic-bezier(0.33, 0.66, 0.66, 1);
36
- transform: translateY(0);
37
- }
38
-
39
- 28.57% {
40
- animation-timing-function: cubic-bezier(0.33, 0, 0.66, 0.33);
41
- transform: translateY(-6px);
42
- }
43
-
44
- 100% {
45
- transform: translateY(0);
46
- }
47
- }
48
- `;
49
-
50
- export { styles };