@websolutespa/llm-plugin-maxmeyer 0.0.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 (110) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +159 -0
  3. package/dist/esm/__tests/example.test.js +9 -0
  4. package/dist/esm/__tests/example.test.js.map +1 -0
  5. package/dist/esm/blocks/Action/action.js +32 -0
  6. package/dist/esm/blocks/Action/action.js.map +1 -0
  7. package/dist/esm/blocks/Action/action.module.scss +5 -0
  8. package/dist/esm/blocks/ActionGroup/action-group.js +17 -0
  9. package/dist/esm/blocks/ActionGroup/action-group.js.map +1 -0
  10. package/dist/esm/blocks/ActionGroup/action-group.module.scss +8 -0
  11. package/dist/esm/blocks/AssistantMessage/assistant-message.js +18 -0
  12. package/dist/esm/blocks/AssistantMessage/assistant-message.js.map +1 -0
  13. package/dist/esm/blocks/CustomCard/custom-card.js +68 -0
  14. package/dist/esm/blocks/CustomCard/custom-card.js.map +1 -0
  15. package/dist/esm/blocks/CustomCard/custom-card.module.scss +64 -0
  16. package/dist/esm/blocks/CustomCardGroup/custom-card-group.js +65 -0
  17. package/dist/esm/blocks/CustomCardGroup/custom-card-group.js.map +1 -0
  18. package/dist/esm/blocks/CustomCardGroup/custom-card-group.module.scss +58 -0
  19. package/dist/esm/blocks/FormRecap/FormRecap.js +250 -0
  20. package/dist/esm/blocks/FormRecap/FormRecap.js.map +1 -0
  21. package/dist/esm/blocks/FormRecap/form-recap.module.scss +103 -0
  22. package/dist/esm/blocks/FormRecapError/FormRecapError.js +19 -0
  23. package/dist/esm/blocks/FormRecapError/FormRecapError.js.map +1 -0
  24. package/dist/esm/blocks/FormRecapError/form-recap-error.module.scss +7 -0
  25. package/dist/esm/blocks/FormRecapSuccess/FormRecapSuccess.js +19 -0
  26. package/dist/esm/blocks/FormRecapSuccess/FormRecapSuccess.js.map +1 -0
  27. package/dist/esm/blocks/FormRecapSuccess/form-recap-success.module.scss +7 -0
  28. package/dist/esm/blocks/FormRequest/FormRequest.js +36 -0
  29. package/dist/esm/blocks/FormRequest/FormRequest.js.map +1 -0
  30. package/dist/esm/blocks/FormRequest/form-request.module.scss +17 -0
  31. package/dist/esm/blocks/NotFound/not-found.js +15 -0
  32. package/dist/esm/blocks/NotFound/not-found.js.map +1 -0
  33. package/dist/esm/blocks/NotFound/not-found.module.scss +5 -0
  34. package/dist/esm/blocks/StreamError/StreamError.js +46 -0
  35. package/dist/esm/blocks/StreamError/StreamError.js.map +1 -0
  36. package/dist/esm/blocks/StreamError/_style.scss +34 -0
  37. package/dist/esm/blocks/UserMessage/user-message.js +22 -0
  38. package/dist/esm/blocks/UserMessage/user-message.js.map +1 -0
  39. package/dist/esm/blocks/UserMessage/user-message.module.scss +13 -0
  40. package/dist/esm/blocks/index.js +28 -0
  41. package/dist/esm/blocks/index.js.map +1 -0
  42. package/dist/esm/components/chat/Root/root.js +36 -0
  43. package/dist/esm/components/chat/Root/root.js.map +1 -0
  44. package/dist/esm/components/chat/Root/root.module.scss +58 -0
  45. package/dist/esm/components/chat/Thread/thread.js +40 -0
  46. package/dist/esm/components/chat/Thread/thread.js.map +1 -0
  47. package/dist/esm/components/chat/Thread/thread.module.scss +30 -0
  48. package/dist/esm/components/chat/index.js +8 -0
  49. package/dist/esm/components/chat/index.js.map +1 -0
  50. package/dist/esm/components/index.js +3 -0
  51. package/dist/esm/components/index.js.map +1 -0
  52. package/dist/esm/components/page/PageLoading/page-loading.js +32 -0
  53. package/dist/esm/components/page/PageLoading/page-loading.js.map +1 -0
  54. package/dist/esm/components/page/PageLoading/page-loading.module.scss +302 -0
  55. package/dist/esm/components/page/PageRoot/page-root.js +31 -0
  56. package/dist/esm/components/page/PageRoot/page-root.js.map +1 -0
  57. package/dist/esm/components/page/PageRoot/page-root.module.scss +24 -0
  58. package/dist/esm/components/page/PageStreamingIndicator/page-streaming-indicator.js +18 -0
  59. package/dist/esm/components/page/PageStreamingIndicator/page-streaming-indicator.js.map +1 -0
  60. package/dist/esm/components/page/PageStreamingIndicator/page-streaming-indicator.module.scss +38 -0
  61. package/dist/esm/components/page/PageTrigger/page-trigger.js +20 -0
  62. package/dist/esm/components/page/PageTrigger/page-trigger.js.map +1 -0
  63. package/dist/esm/components/page/PageTrigger/page-trigger.module.scss +16 -0
  64. package/dist/esm/components/page/index.js +12 -0
  65. package/dist/esm/components/page/index.js.map +1 -0
  66. package/dist/esm/global.d.js +2 -0
  67. package/dist/esm/global.d.js.map +1 -0
  68. package/dist/esm/index.js +12 -0
  69. package/dist/esm/index.js.map +1 -0
  70. package/dist/esm/llm.js +42 -0
  71. package/dist/esm/llm.js.map +1 -0
  72. package/dist/esm/mock/chat/app.js +76 -0
  73. package/dist/esm/mock/chat/app.js.map +1 -0
  74. package/dist/esm/mock/chat/theme.js +337 -0
  75. package/dist/esm/mock/chat/theme.js.map +1 -0
  76. package/dist/esm/mock/chat/thread.js +450 -0
  77. package/dist/esm/mock/chat/thread.js.map +1 -0
  78. package/dist/esm/mock/index.js +8 -0
  79. package/dist/esm/mock/index.js.map +1 -0
  80. package/dist/esm/mock/page/app.js +74 -0
  81. package/dist/esm/mock/page/app.js.map +1 -0
  82. package/dist/esm/mock/page/theme.js +337 -0
  83. package/dist/esm/mock/page/theme.js.map +1 -0
  84. package/dist/esm/mock/page/thread.js +756 -0
  85. package/dist/esm/mock/page/thread.js.map +1 -0
  86. package/dist/esm/plugin.js +21 -0
  87. package/dist/esm/plugin.js.map +1 -0
  88. package/dist/esm/scss/_base.scss +63 -0
  89. package/dist/esm/scss/_mixin.scss +10 -0
  90. package/dist/esm/scss/_reset.scss +63 -0
  91. package/dist/esm/scss/_thread.scss +35 -0
  92. package/dist/esm/scss/_typography.scss +19 -0
  93. package/dist/esm/scss/mixin/_breakpoint.scss +7 -0
  94. package/dist/esm/scss/mixin/_button.scss +64 -0
  95. package/dist/esm/scss/mixin/_container.scss +14 -0
  96. package/dist/esm/scss/mixin/_markdown.scss +180 -0
  97. package/dist/esm/scss/mixin/_scrollbar.scss +50 -0
  98. package/dist/esm/scss/mixin/_shadow.scss +19 -0
  99. package/dist/esm/scss/mixin/_size.scss +42 -0
  100. package/dist/esm/scss/mixin/_typography.scss +129 -0
  101. package/dist/esm/scss/mixin/_utils.scss +103 -0
  102. package/dist/esm/scss/mixin/_vars.scss +4 -0
  103. package/dist/esm/scss/style.scss +14 -0
  104. package/dist/index.css +5460 -0
  105. package/dist/index.css.map +1 -0
  106. package/dist/index.d.ts +78 -0
  107. package/dist/umd/index.js +48828 -0
  108. package/dist/umd/index.js.map +1 -0
  109. package/dist/umd/index.min.js +20 -0
  110. package/package.json +119 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @websolutespa/llm-plugin-maxmeyer
2
+
3
+ ## 0.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - init
package/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # @websolutespa/llm-plugin
2
+
3
+ [![npm version](https://badge.fury.io/js/%40websolutespa%2Fllm-plugin.svg)](https://badge.fury.io/js/%40websolutespa%2Fllm-plugin)
4
+
5
+ [![status alpha](https://img.shields.io/badge/status-alpha-red.svg)](https://shields.io/)
6
+
7
+ LLM module of the [BOM Repository](https://github.com/websolutespa/bom) by [websolute](https://www.websolute.com/).
8
+
9
+ # Bom LLM Plugin
10
+
11
+ This plugin automatically adds UI components to manage LLM Chatbot by [websolute](https://www.websolute.com/).
12
+
13
+ ### Requirements:
14
+
15
+ - You need a personal appKey and apiKey to use this plugin, for more info contact [websolute](https://www.websolute.com/contatti)
16
+
17
+ ## Usage
18
+
19
+ You can load the script directly via jsDelivr or installing via npm.
20
+
21
+ ### Using jsDelivr
22
+
23
+ ```html
24
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@websolutespa/llm-plugin@latest/dist/index.css">
25
+ <script type="module"
26
+ src="https://cdn.jsdelivr.net/npm/@websolutespa/llm-plugin@latest/dist/umd/index.min.js"></script>
27
+ <script type="module">
28
+
29
+ document.addEventListener('DOMContentLoaded', () => {
30
+ if ('llmDefault' in window) {
31
+ const searchParams = new URLSearchParams(window.location.search);
32
+ const options = {
33
+ endpoint: 'https://platform-ai-dev.ws-deploy-01.wslabs.it',
34
+ appKey: 'MY_APP_KEY',
35
+ apiKey: 'MY_API_KEY',
36
+ threadId: searchParams.get('llmThreadId'),
37
+ test: searchParams.get('mock') === 'true' ? llm.mock : undefined,
38
+ idleTime: 1000 * 60,
39
+ };
40
+ llmDefault(options);
41
+ }
42
+ });
43
+
44
+ </script>
45
+ ```
46
+
47
+ ### Using npm
48
+
49
+ Install library using npm.
50
+
51
+ ```bash
52
+ npm i @websolutespa/llm-plugin --save
53
+ ```
54
+
55
+ Import css from node_modules.
56
+
57
+ ```html
58
+ <link rel="stylesheet" href="node_modules/@websolutespa/llm-plugin/dist/umd/index.css">
59
+ ```
60
+
61
+ Import and consume plugin.
62
+
63
+ ```js
64
+ import { llmDefault } from '@websolutespa/llm-plugin';
65
+
66
+ document.addEventListener('DOMContentLoaded', () => {
67
+ if ('llmDefault' in window) {
68
+ const searchParams = new URLSearchParams(window.location.search);
69
+ const options = {
70
+ appKey: 'MY_APP_KEY',
71
+ apiKey: 'MY_API_KEY',
72
+ threadId: searchParams.get('llmThreadId'),
73
+ };
74
+ // returned instance
75
+ const llm = llmDefault(options);
76
+ }
77
+ });
78
+ ```
79
+
80
+ Using imperatively.
81
+
82
+ ```js
83
+ const options = {
84
+ appKey: 'MY_APP_KEY',
85
+ apiKey: 'MY_API_KEY',
86
+ imperative: true, // hide trigger button
87
+ };
88
+ const llm = llmDefault(options);
89
+ // using open command imperatively
90
+ setTimeout(() => {
91
+ llm.open();
92
+ }, 4000);
93
+ ```
94
+
95
+ Using embed tag.
96
+
97
+ ```html
98
+ <llm-embed />
99
+ ```
100
+
101
+ ### Running test
102
+
103
+ Add parameter test = true.
104
+
105
+ ```js
106
+ const searchParams = new URLSearchParams(window.location.search);
107
+ const options = {
108
+ appKey: 'MY_APP_KEY',
109
+ apiKey: 'MY_API_KEY',
110
+ threadId: searchParams.get('llmThreadId'),
111
+ test: true,
112
+ };
113
+ llmDefault(options);
114
+ ```
115
+
116
+ ### Decorate external url
117
+
118
+ You can decorate every json item from the knowledgeBase customizing its external url.
119
+ decorateUrl method can be a promise.
120
+
121
+ ```js
122
+ const searchParams = new URLSearchParams(window.location.search);
123
+ const options = {
124
+ appKey: 'MY_APP_KEY',
125
+ apiKey: 'MY_API_KEY',
126
+ threadId: searchParams.get('llmThreadId'),
127
+ decorateUrl: (item) => {
128
+ switch (item.type) {
129
+ case 'event':
130
+ case 'eventItem':
131
+ return `https://acme.com/event?id=${item.id}`;
132
+ default:
133
+ return;
134
+ }
135
+ },
136
+ };
137
+ llmDefault(options);
138
+ ```
139
+
140
+ ### Handling external actions
141
+
142
+ You can handle the click event of the generated cta action with the onAction handler.
143
+
144
+ ```js
145
+ const searchParams = new URLSearchParams(window.location.search);
146
+ const options = {
147
+ appKey: 'MY_APP_KEY',
148
+ apiKey: 'MY_API_KEY',
149
+ threadId: searchParams.get('llmThreadId'),
150
+ onAction: (item) => {
151
+ console.log('onAction', item.id, item.title);
152
+ },
153
+ };
154
+ llmDefault(options);
155
+ ```
156
+
157
+ ---
158
+
159
+ ##### *this library is for internal usage and not production ready*
@@ -0,0 +1,9 @@
1
+ import '@testing-library/jest-dom';
2
+ describe('Example', ()=>{
3
+ it('passes', async ()=>{
4
+ const value = 'test';
5
+ expect(value).toEqual(value);
6
+ });
7
+ });
8
+
9
+ //# sourceMappingURL=example.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/__tests/example.test.ts"],"sourcesContent":["import '@testing-library/jest-dom';\n\ndescribe('Example', () => {\n it('passes', async () => {\n const value = 'test';\n expect(value).toEqual(value);\n });\n});\n"],"names":["describe","it","value","expect","toEqual"],"mappings":"AAAA,OAAO,4BAA4B;AAEnCA,SAAS,WAAW;IAClBC,GAAG,UAAU;QACX,MAAMC,QAAQ;QACdC,OAAOD,OAAOE,OAAO,CAACF;IACxB;AACF"}
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { getClassNames } from '@websolutespa/bom-core';
3
+ import { useLabel } from '@websolutespa/bom-mixer-hooks';
4
+ import { IconLlmArrowRight } from '@websolutespa/bom-mixer-icons';
5
+ import { Cta, useLlm, useLlmView } from '@websolutespa/bom-mixer-llm';
6
+ import style from './action.module.scss';
7
+ export const Action = (props)=>{
8
+ const { item } = props;
9
+ const label = useLabel();
10
+ const { onAction } = useLlm((state)=>state.actions);
11
+ const { open } = useLlmView((state)=>state.actions);
12
+ const dismissable = useLlmView((state)=>state.dismissable);
13
+ const onAction_ = async (event)=>{
14
+ // console.log('Action.onAction', props.id);
15
+ const shouldClose = await onAction(item);
16
+ if (dismissable && shouldClose !== false) {
17
+ open();
18
+ }
19
+ };
20
+ const classNames = getClassNames(style.action, {
21
+ [`llm__action--${item.type}`]: !!item.type
22
+ });
23
+ return /*#__PURE__*/ _jsx(Cta, {
24
+ type: "button",
25
+ className: classNames,
26
+ label: item.title || label('llm.tellMeMore'),
27
+ icon: /*#__PURE__*/ _jsx(IconLlmArrowRight, {}),
28
+ onClick: onAction_
29
+ });
30
+ };
31
+
32
+ //# sourceMappingURL=action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/Action/action.tsx"],"sourcesContent":["import { getClassNames } from '@websolutespa/bom-core';\nimport { useLabel } from '@websolutespa/bom-mixer-hooks';\nimport { IconLlmArrowRight } from '@websolutespa/bom-mixer-icons';\nimport { Cta, LlmBlock, LlmChunkAction, LlmChunkActionItem, useLlm, useLlmView } from '@websolutespa/bom-mixer-llm';\nimport style from './action.module.scss';\n\nexport const Action: React.FC<LlmBlock<LlmChunkActionItem | LlmChunkAction>> = (props) => {\n const { item } = props;\n const label = useLabel();\n const { onAction } = useLlm(state => state.actions);\n const { open } = useLlmView(state => state.actions);\n const dismissable = useLlmView(state => state.dismissable);\n const onAction_ = async (event: React.MouseEvent) => {\n // console.log('Action.onAction', props.id);\n const shouldClose = await onAction(item);\n if (dismissable && shouldClose !== false) {\n open();\n }\n };\n const classNames = getClassNames(style.action, { [`llm__action--${item.type}`]: !!item.type });\n return (\n <Cta\n type=\"button\"\n className={classNames} label={item.title || label('llm.tellMeMore')}\n icon={<IconLlmArrowRight />}\n onClick={onAction_}\n />\n );\n};\n\n"],"names":["getClassNames","useLabel","IconLlmArrowRight","Cta","useLlm","useLlmView","style","Action","props","item","label","onAction","state","actions","open","dismissable","onAction_","event","shouldClose","classNames","action","type","className","title","icon","onClick"],"mappings":";AAAA,SAASA,aAAa,QAAQ,yBAAyB;AACvD,SAASC,QAAQ,QAAQ,gCAAgC;AACzD,SAASC,iBAAiB,QAAQ,gCAAgC;AAClE,SAASC,GAAG,EAAgDC,MAAM,EAAEC,UAAU,QAAQ,8BAA8B;AACpH,OAAOC,WAAW,uBAAuB;AAEzC,OAAO,MAAMC,SAAkE,CAACC;IAC9E,MAAM,EAAEC,IAAI,EAAE,GAAGD;IACjB,MAAME,QAAQT;IACd,MAAM,EAAEU,QAAQ,EAAE,GAAGP,OAAOQ,CAAAA,QAASA,MAAMC,OAAO;IAClD,MAAM,EAAEC,IAAI,EAAE,GAAGT,WAAWO,CAAAA,QAASA,MAAMC,OAAO;IAClD,MAAME,cAAcV,WAAWO,CAAAA,QAASA,MAAMG,WAAW;IACzD,MAAMC,YAAY,OAAOC;QACvB,4CAA4C;QAC5C,MAAMC,cAAc,MAAMP,SAASF;QACnC,IAAIM,eAAeG,gBAAgB,OAAO;YACxCJ;QACF;IACF;IACA,MAAMK,aAAanB,cAAcM,MAAMc,MAAM,EAAE;QAAE,CAAC,CAAC,aAAa,EAAEX,KAAKY,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAACZ,KAAKY,IAAI;IAAC;IAC5F,qBACE,KAAClB;QACCkB,MAAK;QACLC,WAAWH;QAAYT,OAAOD,KAAKc,KAAK,IAAIb,MAAM;QAClDc,oBAAM,KAACtB;QACPuB,SAAST;;AAGf,EAAE"}
@@ -0,0 +1,5 @@
1
+ @import '../../scss/mixin';
2
+
3
+ .action {
4
+ // background: red;
5
+ }
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { getClassNames } from '@websolutespa/bom-core';
3
+ import { Action } from '../Action/action';
4
+ import style from './action-group.module.scss';
5
+ export const ActionGroup = (props)=>{
6
+ const { item } = props;
7
+ const classNames = getClassNames(style.actionGroup);
8
+ return /*#__PURE__*/ _jsx("div", {
9
+ className: classNames,
10
+ children: item.items.map((item, i)=>/*#__PURE__*/ _jsx(Action, {
11
+ ...props,
12
+ item: item
13
+ }, i))
14
+ });
15
+ };
16
+
17
+ //# sourceMappingURL=action-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/ActionGroup/action-group.tsx"],"sourcesContent":["import { getClassNames } from '@websolutespa/bom-core';\nimport { LlmBlock, LlmChunkActionGroup } from '@websolutespa/bom-mixer-llm';\nimport { Action } from '../Action/action';\nimport style from './action-group.module.scss';\n\nexport const ActionGroup: React.FC<LlmBlock<LlmChunkActionGroup>> = (props) => {\n const { item } = props;\n const classNames = getClassNames(style.actionGroup);\n return (\n <div className={classNames}>\n {item.items.map((item, i) => (\n <Action key={i} {...props} item={item} />\n ))}\n </div>\n );\n};\n\n"],"names":["getClassNames","Action","style","ActionGroup","props","item","classNames","actionGroup","div","className","items","map","i"],"mappings":";AAAA,SAASA,aAAa,QAAQ,yBAAyB;AAEvD,SAASC,MAAM,QAAQ,mBAAmB;AAC1C,OAAOC,WAAW,6BAA6B;AAE/C,OAAO,MAAMC,cAAuD,CAACC;IACnE,MAAM,EAAEC,IAAI,EAAE,GAAGD;IACjB,MAAME,aAAaN,cAAcE,MAAMK,WAAW;IAClD,qBACE,KAACC;QAAIC,WAAWH;kBACbD,KAAKK,KAAK,CAACC,GAAG,CAAC,CAACN,MAAMO,kBACrB,KAACX;gBAAgB,GAAGG,KAAK;gBAAEC,MAAMA;eAApBO;;AAIrB,EAAE"}
@@ -0,0 +1,8 @@
1
+ @import '../../scss/mixin';
2
+
3
+ .actionGroup {
4
+ display: flex;
5
+ gap: size(4);
6
+ padding-top: size(2);
7
+ margin-top: auto;
8
+ }
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text } from '@websolutespa/bom-mixer-llm';
3
+ export const AssistantMessage = (props)=>{
4
+ const { text, chunkIndex, index } = props;
5
+ return /*#__PURE__*/ _jsx("div", {
6
+ className: "llm__row",
7
+ children: /*#__PURE__*/ _jsx("div", {
8
+ className: "llm__col --sm-10 --sm-9 --md-8 --lg-7 --xl-6",
9
+ children: /*#__PURE__*/ _jsx(Text, {
10
+ body: text,
11
+ chunkIndex: chunkIndex,
12
+ index: index
13
+ })
14
+ })
15
+ });
16
+ };
17
+
18
+ //# sourceMappingURL=assistant-message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/AssistantMessage/assistant-message.tsx"],"sourcesContent":["import { LlmTextBlock, Text } from '@websolutespa/bom-mixer-llm';\n\nexport type AssistantMessageProps = LlmTextBlock<'assistant'>;\n\nexport const AssistantMessage: React.FC<AssistantMessageProps> = (props) => {\n const { text, chunkIndex, index } = props;\n return (\n <div className=\"llm__row\">\n <div className=\"llm__col --sm-10 --sm-9 --md-8 --lg-7 --xl-6\">\n <Text body={text} chunkIndex={chunkIndex} index={index} />\n </div>\n </div>\n );\n};\n\n"],"names":["Text","AssistantMessage","props","text","chunkIndex","index","div","className","body"],"mappings":";AAAA,SAAuBA,IAAI,QAAQ,8BAA8B;AAIjE,OAAO,MAAMC,mBAAoD,CAACC;IAChE,MAAM,EAAEC,IAAI,EAAEC,UAAU,EAAEC,KAAK,EAAE,GAAGH;IACpC,qBACE,KAACI;QAAIC,WAAU;kBACb,cAAA,KAACD;YAAIC,WAAU;sBACb,cAAA,KAACP;gBAAKQ,MAAML;gBAAMC,YAAYA;gBAAYC,OAAOA;;;;AAIzD,EAAE"}
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useLabel } from '@websolutespa/bom-mixer-hooks';
3
+ import { Cta, useLlmView } from '@websolutespa/bom-mixer-llm';
4
+ import style from './custom-card.module.scss';
5
+ export const CustomCard = (props)=>{
6
+ const { item } = props;
7
+ const label = useLabel();
8
+ const { send } = useLlmView((state)=>state.actions);
9
+ const onTellMeMore = async (event)=>{
10
+ const prompt = `${label('llm.tellMeMoreAbout')} ${item.title}`;
11
+ await send(prompt, (response)=>{
12
+ // console.log('Prompt.onChunk', response.chunks);
13
+ }, (response)=>{
14
+ // console.log('Prompt.onEnd', response);
15
+ });
16
+ };
17
+ const ariaLabel = label('llm.tellMeMore');
18
+ return /*#__PURE__*/ _jsxs("div", {
19
+ className: style.customCard,
20
+ children: [
21
+ item.media && /*#__PURE__*/ _jsx(_Fragment, {
22
+ children: item.href ? /*#__PURE__*/ _jsx("a", {
23
+ className: style.customCardMedia,
24
+ href: item.href,
25
+ target: "_blank",
26
+ rel: "noreferrer",
27
+ "aria-label": ariaLabel,
28
+ children: /*#__PURE__*/ _jsx("div", {
29
+ className: style.customCardAsset,
30
+ children: /*#__PURE__*/ _jsx("img", {
31
+ src: item.media.url,
32
+ alt: ""
33
+ })
34
+ })
35
+ }) : /*#__PURE__*/ _jsx("div", {
36
+ className: style.customCardMedia,
37
+ children: /*#__PURE__*/ _jsx("div", {
38
+ className: style.customCardAsset,
39
+ children: /*#__PURE__*/ _jsx("img", {
40
+ src: item.media.url,
41
+ alt: ""
42
+ })
43
+ })
44
+ })
45
+ }),
46
+ /*#__PURE__*/ _jsxs("div", {
47
+ className: style.customCardContent,
48
+ children: [
49
+ item.title && /*#__PURE__*/ _jsx("div", {
50
+ className: style.customCardTitle,
51
+ dangerouslySetInnerHTML: {
52
+ __html: item.title
53
+ }
54
+ }),
55
+ /*#__PURE__*/ _jsx(Cta, {
56
+ url: item.href,
57
+ className: style.customCardCta,
58
+ type: "button",
59
+ label: label('llm.tellMeMore'),
60
+ onClick: onTellMeMore
61
+ })
62
+ ]
63
+ })
64
+ ]
65
+ });
66
+ };
67
+
68
+ //# sourceMappingURL=custom-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/CustomCard/custom-card.tsx"],"sourcesContent":["import { useLabel } from '@websolutespa/bom-mixer-hooks';\nimport { Cta, LlmBlock, useLlmView } from '@websolutespa/bom-mixer-llm';\nimport style from './custom-card.module.scss';\n\nexport type LlmChunkCustomCard = {\n type: 'customCard';\n id: string;\n title?: string;\n abstract?: string;\n media?: {\n type: 'image';\n url: string;\n };\n href?: string;\n};\n\nexport const CustomCard: React.FC<LlmBlock<LlmChunkCustomCard>> = (props) => {\n const { item } = props;\n const label = useLabel();\n const { send } = useLlmView(state => state.actions);\n const onTellMeMore = async (event: React.MouseEvent) => {\n const prompt = `${label('llm.tellMeMoreAbout')} ${item.title}`;\n await send(prompt, (response) => {\n // console.log('Prompt.onChunk', response.chunks);\n }, (response) => {\n // console.log('Prompt.onEnd', response);\n });\n };\n const ariaLabel = label('llm.tellMeMore');\n return (\n <div className={style.customCard}>\n {item.media && (\n <>\n {item.href ? (\n <a className={style.customCardMedia} href={item.href} target=\"_blank\" rel=\"noreferrer\" aria-label={ariaLabel}>\n <div className={style.customCardAsset}>\n <img src={item.media.url} alt=\"\" />\n </div>\n </a>\n ) : (\n <div className={style.customCardMedia}>\n <div className={style.customCardAsset}>\n <img src={item.media.url} alt=\"\" />\n </div>\n </div>\n )}\n </>\n )}\n <div className={style.customCardContent}>\n {item.title && (\n <div className={style.customCardTitle} dangerouslySetInnerHTML={{ __html: item.title }} />\n )}\n <Cta url={item.href} className={style.customCardCta} type=\"button\" label={label('llm.tellMeMore')} onClick={onTellMeMore} />\n </div>\n </div>\n );\n};\n\n"],"names":["useLabel","Cta","useLlmView","style","CustomCard","props","item","label","send","state","actions","onTellMeMore","event","prompt","title","response","ariaLabel","div","className","customCard","media","href","a","customCardMedia","target","rel","aria-label","customCardAsset","img","src","url","alt","customCardContent","customCardTitle","dangerouslySetInnerHTML","__html","customCardCta","type","onClick"],"mappings":";AAAA,SAASA,QAAQ,QAAQ,gCAAgC;AACzD,SAASC,GAAG,EAAYC,UAAU,QAAQ,8BAA8B;AACxE,OAAOC,WAAW,4BAA4B;AAc9C,OAAO,MAAMC,aAAqD,CAACC;IACjE,MAAM,EAAEC,IAAI,EAAE,GAAGD;IACjB,MAAME,QAAQP;IACd,MAAM,EAAEQ,IAAI,EAAE,GAAGN,WAAWO,CAAAA,QAASA,MAAMC,OAAO;IAClD,MAAMC,eAAe,OAAOC;QAC1B,MAAMC,SAAS,CAAC,EAAEN,MAAM,uBAAuB,CAAC,EAAED,KAAKQ,KAAK,CAAC,CAAC;QAC9D,MAAMN,KAAKK,QAAQ,CAACE;QAClB,kDAAkD;QACpD,GAAG,CAACA;QACF,yCAAyC;QAC3C;IACF;IACA,MAAMC,YAAYT,MAAM;IACxB,qBACE,MAACU;QAAIC,WAAWf,MAAMgB,UAAU;;YAC7Bb,KAAKc,KAAK,kBACT;0BACGd,KAAKe,IAAI,iBACR,KAACC;oBAAEJ,WAAWf,MAAMoB,eAAe;oBAAEF,MAAMf,KAAKe,IAAI;oBAAEG,QAAO;oBAASC,KAAI;oBAAaC,cAAYV;8BACjG,cAAA,KAACC;wBAAIC,WAAWf,MAAMwB,eAAe;kCACnC,cAAA,KAACC;4BAAIC,KAAKvB,KAAKc,KAAK,CAACU,GAAG;4BAAEC,KAAI;;;mCAIlC,KAACd;oBAAIC,WAAWf,MAAMoB,eAAe;8BACnC,cAAA,KAACN;wBAAIC,WAAWf,MAAMwB,eAAe;kCACnC,cAAA,KAACC;4BAAIC,KAAKvB,KAAKc,KAAK,CAACU,GAAG;4BAAEC,KAAI;;;;;0BAMxC,MAACd;gBAAIC,WAAWf,MAAM6B,iBAAiB;;oBACpC1B,KAAKQ,KAAK,kBACT,KAACG;wBAAIC,WAAWf,MAAM8B,eAAe;wBAAEC,yBAAyB;4BAAEC,QAAQ7B,KAAKQ,KAAK;wBAAC;;kCAEvF,KAACb;wBAAI6B,KAAKxB,KAAKe,IAAI;wBAAEH,WAAWf,MAAMiC,aAAa;wBAAEC,MAAK;wBAAS9B,OAAOA,MAAM;wBAAmB+B,SAAS3B;;;;;;AAIpH,EAAE"}
@@ -0,0 +1,64 @@
1
+ @import '../../scss/mixin';
2
+
3
+ .customCard {
4
+ max-width: 700px;
5
+ position: relative;
6
+ display: flex;
7
+ flex-direction: row;
8
+ overflow: hidden;
9
+ border-radius: 6px;
10
+ background: var(--llm-color-neutral-100);
11
+ box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.05);
12
+ padding: size(4) size(3);
13
+ }
14
+
15
+ .customCardMedia {
16
+ position: relative;
17
+ width: 200px;
18
+ flex-shrink: 0;
19
+ }
20
+
21
+ .customCardAsset {
22
+ display: flex;
23
+ justify-content: center;
24
+ align-items: center;
25
+ aspect-ratio: 1;
26
+ border-radius: 0;
27
+ overflow: hidden;
28
+
29
+ &>img {
30
+ width: 100%;
31
+ height: 100%;
32
+ object-fit: contain;
33
+ object-position: center;
34
+ }
35
+ }
36
+
37
+ .customCardContent {
38
+ position: relative;
39
+ display: flex;
40
+ flex-direction: column;
41
+ padding: 0 size(3) ;
42
+ gap: size(3);
43
+ }
44
+
45
+ .customCardTitle {
46
+ @include text(display5);
47
+ }
48
+
49
+ .customCardCta {
50
+ color: var(--llm-color-neutral-100) !important;
51
+ background: var(--llm-color-base-900) !important;
52
+ border-radius: 50px;
53
+ padding: 12px 16px !important;
54
+ width: fit-content;
55
+ line-height: 1 !important;
56
+ display: flex !important;
57
+ min-height: 0 !important;
58
+ margin-top: auto;
59
+ > span {
60
+ font-size: 16px !important;
61
+ letter-spacing: 0.02em !important;
62
+ line-height: 1 !important;
63
+ }
64
+ }
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useWindowSize } from '@websolutespa/bom-mixer-hooks';
3
+ import { IconLlmArrowLeft, IconLlmArrowRight } from '@websolutespa/bom-mixer-icons';
4
+ import { clamp } from '@websolutespa/bom-mixer-llm';
5
+ import { useRef } from 'react';
6
+ import { Navigation } from 'swiper';
7
+ import { Swiper, SwiperSlide } from 'swiper/react';
8
+ import { CustomCard } from '../CustomCard/custom-card';
9
+ import style from './custom-card-group.module.scss';
10
+ export const CustomCardGroup = (props)=>{
11
+ const { item } = props;
12
+ useWindowSize();
13
+ const navigationPrevRef = useRef(null);
14
+ const navigationNextRef = useRef(null);
15
+ const swiperProps = {
16
+ modules: [
17
+ Navigation
18
+ ],
19
+ spaceBetween: clamp(16, 24),
20
+ slidesPerView: 1.1,
21
+ watchOverflow: true,
22
+ navigation: {
23
+ prevEl: navigationPrevRef.current,
24
+ nextEl: navigationNextRef.current
25
+ },
26
+ breakpoints: {
27
+ 630: {
28
+ slidesPerView: 1.5
29
+ },
30
+ 768: {
31
+ slidesPerView: 2
32
+ }
33
+ }
34
+ };
35
+ return /*#__PURE__*/ _jsx("div", {
36
+ className: style.customCardGroup,
37
+ children: /*#__PURE__*/ _jsxs(Swiper, {
38
+ ...swiperProps,
39
+ children: [
40
+ /*#__PURE__*/ _jsxs("div", {
41
+ className: style.customCardGroupNav,
42
+ children: [
43
+ /*#__PURE__*/ _jsx("button", {
44
+ ref: navigationPrevRef,
45
+ children: /*#__PURE__*/ _jsx(IconLlmArrowLeft, {})
46
+ }),
47
+ /*#__PURE__*/ _jsx("button", {
48
+ ref: navigationNextRef,
49
+ children: /*#__PURE__*/ _jsx(IconLlmArrowRight, {})
50
+ })
51
+ ]
52
+ }),
53
+ item.items.map((item, i)=>/*#__PURE__*/ _jsx(SwiperSlide, {
54
+ className: style.customCardGroupSlide,
55
+ children: /*#__PURE__*/ _jsx(CustomCard, {
56
+ ...props,
57
+ item: item
58
+ })
59
+ }, i))
60
+ ]
61
+ })
62
+ });
63
+ };
64
+
65
+ //# sourceMappingURL=custom-card-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/CustomCardGroup/custom-card-group.tsx"],"sourcesContent":["import { useWindowSize } from '@websolutespa/bom-mixer-hooks';\nimport { IconLlmArrowLeft, IconLlmArrowRight } from '@websolutespa/bom-mixer-icons';\nimport { clamp, LlmBlock } from '@websolutespa/bom-mixer-llm';\nimport { useRef } from 'react';\nimport { Navigation } from 'swiper';\nimport { Swiper, SwiperSlide } from 'swiper/react';\nimport { CustomCard, LlmChunkCustomCard } from '../CustomCard/custom-card';\nimport style from './custom-card-group.module.scss';\n\nexport type LlmChunkCustomCardGroup = {\n type: 'customCardGroup';\n id: string;\n items: LlmChunkCustomCard[];\n};\n\nexport const CustomCardGroup: React.FC<LlmBlock<LlmChunkCustomCardGroup>> = (props) => {\n const { item } = props;\n\n useWindowSize();\n\n const navigationPrevRef = useRef(null);\n const navigationNextRef = useRef(null);\n const swiperProps = {\n modules: [Navigation],\n spaceBetween: clamp(16, 24),\n slidesPerView: 1.1,\n watchOverflow: true,\n navigation: {\n prevEl: navigationPrevRef.current,\n nextEl: navigationNextRef.current,\n },\n breakpoints: {\n 630: {\n slidesPerView: 1.5,\n },\n 768: {\n slidesPerView: 2,\n },\n\n },\n };\n\n return (\n <div className={style.customCardGroup}>\n <Swiper {...swiperProps}>\n <div className={style.customCardGroupNav}>\n <button ref={navigationPrevRef}><IconLlmArrowLeft /></button>\n <button ref={navigationNextRef}><IconLlmArrowRight /></button>\n </div>\n {item.items.map((item, i) => (\n <SwiperSlide key={i} className={style.customCardGroupSlide}>\n <CustomCard {...props} item={item} />\n </SwiperSlide>\n ))}\n </Swiper>\n </div>\n );\n};\n\n"],"names":["useWindowSize","IconLlmArrowLeft","IconLlmArrowRight","clamp","useRef","Navigation","Swiper","SwiperSlide","CustomCard","style","CustomCardGroup","props","item","navigationPrevRef","navigationNextRef","swiperProps","modules","spaceBetween","slidesPerView","watchOverflow","navigation","prevEl","current","nextEl","breakpoints","div","className","customCardGroup","customCardGroupNav","button","ref","items","map","i","customCardGroupSlide"],"mappings":";AAAA,SAASA,aAAa,QAAQ,gCAAgC;AAC9D,SAASC,gBAAgB,EAAEC,iBAAiB,QAAQ,gCAAgC;AACpF,SAASC,KAAK,QAAkB,8BAA8B;AAC9D,SAASC,MAAM,QAAQ,QAAQ;AAC/B,SAASC,UAAU,QAAQ,SAAS;AACpC,SAASC,MAAM,EAAEC,WAAW,QAAQ,eAAe;AACnD,SAASC,UAAU,QAA4B,4BAA4B;AAC3E,OAAOC,WAAW,kCAAkC;AAQpD,OAAO,MAAMC,kBAA+D,CAACC;IAC3E,MAAM,EAAEC,IAAI,EAAE,GAAGD;IAEjBX;IAEA,MAAMa,oBAAoBT,OAAO;IACjC,MAAMU,oBAAoBV,OAAO;IACjC,MAAMW,cAAc;QAClBC,SAAS;YAACX;SAAW;QACrBY,cAAcd,MAAM,IAAI;QACxBe,eAAe;QACfC,eAAe;QACfC,YAAY;YACVC,QAAQR,kBAAkBS,OAAO;YACjCC,QAAQT,kBAAkBQ,OAAO;QACnC;QACAE,aAAa;YACX,KAAK;gBACHN,eAAe;YACjB;YACA,KAAK;gBACHA,eAAe;YACjB;QAEF;IACF;IAEA,qBACE,KAACO;QAAIC,WAAWjB,MAAMkB,eAAe;kBACnC,cAAA,MAACrB;YAAQ,GAAGS,WAAW;;8BACrB,MAACU;oBAAIC,WAAWjB,MAAMmB,kBAAkB;;sCACtC,KAACC;4BAAOC,KAAKjB;sCAAmB,cAAA,KAACZ;;sCACjC,KAAC4B;4BAAOC,KAAKhB;sCAAmB,cAAA,KAACZ;;;;gBAElCU,KAAKmB,KAAK,CAACC,GAAG,CAAC,CAACpB,MAAMqB,kBACrB,KAAC1B;wBAAoBmB,WAAWjB,MAAMyB,oBAAoB;kCACxD,cAAA,KAAC1B;4BAAY,GAAGG,KAAK;4BAAEC,MAAMA;;uBADbqB;;;;AAO5B,EAAE"}
@@ -0,0 +1,58 @@
1
+ @import '../../scss/mixin';
2
+
3
+ .customCardGroup {
4
+ @include containerNegative();
5
+
6
+ :global(.swiper) {
7
+ position: relative;
8
+ overflow: visible;
9
+ padding-top: size(10);
10
+ padding-bottom: size(5);
11
+ }
12
+
13
+ :global(.swiper-slide) {
14
+ height: auto;
15
+ }
16
+ }
17
+
18
+ .customCardGroupNav {
19
+ position: absolute;
20
+ top: 0;
21
+ left: 0;
22
+ color: var(--llm-color-foreground);
23
+ display: flex;
24
+ gap: size(3);
25
+
26
+ @include bp(md) {
27
+ right: 0;
28
+ left: auto;
29
+ }
30
+
31
+ button {
32
+ color: currentColor;
33
+ pointer-events: auto;
34
+ cursor: pointer;
35
+
36
+ &.swiper-button-disabled {
37
+ opacity: 0.2;
38
+ cursor: pointer;
39
+ }
40
+
41
+ &.swiper-button-lock {
42
+ display: none;
43
+ }
44
+
45
+ svg {
46
+ width: 24px;
47
+ height: 24px;
48
+ }
49
+ }
50
+ }
51
+
52
+ .customCardGroupSlide {
53
+ height: auto;
54
+
55
+ :global(.customCard) {
56
+ height: 100%;
57
+ }
58
+ }