Skip to content

Commit ec11022

Browse files
committed
Merge branch 'main' into fix/mark-lit-as-external
2 parents 39a8442 + 360d0cf commit ec11022

File tree

13 files changed

+202
-111
lines changed

13 files changed

+202
-111
lines changed

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
components.d.ts
2-
renders.lit.ts
2+
renders.lit.ts
3+
structure.lit.ts

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@genexus/chameleon-controls-library",
3-
"version": "6.21.0",
3+
"version": "6.22.1",
44
"description": "chameleon - A library of white-label, highly-customizable and reusable web components",
55
"main": "dist/index.cjs.js",
66
"module": "dist/index.js",

src/components/action-list/action-list-render.tsx

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,37 @@
11
import {
22
Component,
33
Element,
4+
Event,
5+
EventEmitter,
46
Host,
5-
h,
7+
Listen,
8+
Method,
9+
// EventEmitter
610
Prop,
711
State,
8-
Listen,
912
Watch,
1013
forceUpdate,
11-
Event,
12-
EventEmitter,
13-
Method
14-
// EventEmitter
14+
h
1515
} from "@stencil/core";
16+
import { removeElement } from "../../common/array";
17+
import { SCROLLABLE_CLASS } from "../../common/reserved-names";
18+
import { adoptCommonThemes } from "../../common/theme";
19+
import {
20+
ActionListTranslations,
21+
ChActionListItemCustomEvent
22+
} from "../../components";
23+
import { mouseEventModifierKey } from "../common/helpers";
24+
import { flattenActionListUIModel } from "./flatten-model";
25+
import {
26+
ActionListCaptionChangeEventDetail,
27+
ActionListFixedChangeEventDetail
28+
} from "./internal/action-list-item/types";
29+
import { actionListKeyboardNavigation } from "./keyboard-navigation";
30+
import {
31+
selectedItemsChangeShouldBeEmitted,
32+
setActionListSelectedItems
33+
} from "./selections";
34+
import { actionListDefaultTranslations } from "./translations";
1635
import {
1736
ActionListImagePathCallback,
1837
ActionListItemActionable,
@@ -25,32 +44,13 @@ import {
2544
ActionListItemType,
2645
ActionListModel
2746
} from "./types";
28-
import {
29-
ActionListTranslations,
30-
ChActionListItemCustomEvent
31-
} from "../../components";
32-
import {
33-
ActionListCaptionChangeEventDetail,
34-
ActionListFixedChangeEventDetail
35-
} from "./internal/action-list-item/types";
36-
import { mouseEventModifierKey } from "../common/helpers";
37-
import { removeElement } from "../../common/array";
38-
import { SCROLLABLE_CLASS } from "../../common/reserved-names";
39-
import { adoptCommonThemes } from "../../common/theme";
40-
import { actionListKeyboardNavigation } from "./keyboard-navigation";
47+
import { updateItemProperty } from "./update-item-property";
4148
import {
4249
ACTION_LIST_ITEM_TAG,
4350
getActionListItemOrGroupInfo,
4451
getActionListOrGroupItemFromEvent,
4552
getParentArray
4653
} from "./utils";
47-
import { updateItemProperty } from "./update-item-property";
48-
import { actionListDefaultTranslations } from "./translations";
49-
import {
50-
selectedItemsChangeShouldBeEmitted,
51-
setActionListSelectedItems
52-
} from "./selections";
53-
import { flattenActionListUIModel } from "./flatten-model";
5454

5555
const DEFAULT_EDITABLE_ITEMS_VALUE = true;
5656
// const DEFAULT_ORDER_VALUE = 0;
@@ -209,12 +209,6 @@ export class ChActionListRender {
209209

210210
@State() expanded: boolean = true;
211211

212-
/**
213-
* This property lets you specify if the tree is waiting to process the drop
214-
* of items.
215-
*/
216-
@State() waitDropProcessing = false;
217-
218212
/**
219213
* Set this attribute if you want display a checkbox in all items by default.
220214
*/
@@ -355,7 +349,7 @@ export class ChActionListRender {
355349
) => Promise<void>;
356350

357351
/**
358-
* This property allows us to implement custom rendering of tree items.
352+
* This property allows us to implement custom rendering of action-list items.
359353
*/
360354
@Prop() readonly renderItem: (
361355
itemModel: ActionListItemModel,
@@ -384,7 +378,7 @@ export class ChActionListRender {
384378
}
385379

386380
/**
387-
* Callback that is executed when the treeModel is changed to order its items.
381+
* Callback that is executed when the action-list model is changed to order its items.
388382
*/
389383
@Prop() readonly sortItemsCallback: (subModel: ActionListModel) => void =
390384
defaultSortItemsCallback;

src/components/action-list/readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
| `model` | -- | This property lets you define the model of the control. | `ActionListItemModel[]` | `[]` |
2121
| `modifyItemCaptionCallback` | -- | Callback that is executed when a item request to modify its caption. | `(actionListItemId: string, newCaption: string) => Promise<void>` | `undefined` |
2222
| `removeItemCallback` | -- | Callback that is executed when and item requests to be removed. If the callback is not defined, the item will be removed without further confirmation. | `(itemInfo: ActionListItemActionable) => Promise<boolean>` | `undefined` |
23-
| `renderItem` | -- | This property allows us to implement custom rendering of tree items. | `(itemModel: ActionListItemModel, actionListRenderState: ChActionListRender, disabled?: boolean, nested?: boolean, nestedExpandable?: boolean) => any` | `defaultRenderItem` |
23+
| `renderItem` | -- | This property allows us to implement custom rendering of action-list items. | `(itemModel: ActionListItemModel, actionListRenderState: ChActionListRender, disabled?: boolean, nested?: boolean, nestedExpandable?: boolean) => any` | `defaultRenderItem` |
2424
| `selection` | `selection` | Specifies the type of selection implemented by the control. | `"multiple" \| "none" \| "single"` | `"none"` |
25-
| `sortItemsCallback` | -- | Callback that is executed when the treeModel is changed to order its items. | `(subModel: ActionListModel) => void` | `defaultSortItemsCallback` |
25+
| `sortItemsCallback` | -- | Callback that is executed when the action-list model is changed to order its items. | `(subModel: ActionListModel) => void` | `defaultSortItemsCallback` |
2626
| `translations` | -- | Specifies the literals required for the control. | `{ confirmDelete: string; cancelDelete: string; confirmModify: string; cancelModify: string; }` | `actionListDefaultTranslations` |
2727

2828

Lines changed: 46 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { html, nothing } from "lit";
2-
import { when } from "lit/directives/when.js";
32
import { getMimeTypeFileFormat } from "../../../../common/mimeTypes/mime-types-utils";
43
import { ArgumentTypes } from "../../../../common/types";
54
import { tokenMap } from "../../../../common/utils";
@@ -38,65 +37,62 @@ export const defaultMessageStructureRender: ChatMessageStructureRender = (
3837
const { files, sources } = getMessageFilesAndSources(message);
3938
const { sourceFiles } = chatRef.translations.text;
4039

41-
return html`<div
42-
part=${tokenMap({
43-
[`content-container ${message.role} ${message.id}`]: true,
44-
[assistantStatus]: !!assistantStatus,
45-
[message.parts]: !!message.parts
46-
})}
47-
>
48-
${renders.contentBefore
49-
? renders.contentBefore(message, chatRef, renders.codeBlock)
50-
: nothing}
51-
${renders.content(message, chatRef, renders.codeBlock)}
52-
${renders.contentAfter
53-
? renders.contentAfter(message, chatRef, renders.codeBlock)
54-
: nothing}
55-
${
56-
// Files
57-
when(
58-
files.length !== 0,
59-
() => html`<ul
40+
const contentBefore = renders.contentBefore
41+
? renders.contentBefore(message, chatRef, renders.codeBlock)
42+
: nothing;
43+
44+
const content = renders.content(message, chatRef, renders.codeBlock);
45+
46+
const contentAfter = renders.contentAfter
47+
? renders.contentAfter(message, chatRef, renders.codeBlock)
48+
: nothing;
49+
50+
const filesRender =
51+
files.length !== 0
52+
? html`<ul
6053
class="files-container"
6154
part=${tokenMap({
6255
[`files-container ${message.role} ${message.id}`]: true,
6356
[assistantStatus]: !!assistantStatus,
6457
[message.parts]: !!message.parts
6558
})}
66-
>
67-
${files.map(file => applyFileRenders(file, chatRef, renders.file))}
68-
</ul>`
69-
)
70-
}
71-
${
72-
// Sources
73-
when(
74-
sources.length !== 0,
75-
() => html`<ul
59+
>${files.map(file => applyFileRenders(file, chatRef, renders.file))}</ul>`
60+
: nothing;
61+
62+
const sourcesCaption = sourceFiles
63+
? // TODO: Test the accessibility of this span
64+
html`<span
65+
part=${tokenMap({
66+
[`sources-caption ${message.role} ${message.id}`]: true,
67+
[assistantStatus]: !!assistantStatus,
68+
[message.parts]: !!message.parts
69+
})}
70+
>${sourceFiles}</span
71+
>`
72+
: nothing;
73+
74+
const sourcesRender =
75+
sources.length !== 0
76+
? html`<ul
7677
class="sources-container"
7778
part=${tokenMap({
7879
[`sources-container ${message.role} ${message.id}`]: true,
7980
[assistantStatus]: !!assistantStatus,
8081
[message.parts]: !!message.parts
8182
})}
82-
>
83-
${when(
84-
sourceFiles,
85-
// TODO: Test the accessibility of this span
86-
() => html`<span
87-
part=${tokenMap({
88-
[`sources-caption ${message.role} ${message.id}`]: true,
89-
[assistantStatus]: !!assistantStatus,
90-
[message.parts]: !!message.parts
91-
})}
92-
>
93-
${sourceFiles}
94-
</span>`
95-
)}
96-
${sources.map(source => renders.source(source, chatRef))}
97-
</ul>`
98-
)
99-
}
100-
${renders.actions(message, chatRef)}
101-
</div>`;
83+
>${sourcesCaption}${sources.map(source =>
84+
renders.source(source, chatRef)
85+
)}</ul>`
86+
: nothing;
87+
88+
return html`<div
89+
part=${tokenMap({
90+
[`content-container ${message.role} ${message.id}`]: true,
91+
[assistantStatus]: !!assistantStatus,
92+
[message.parts]: !!message.parts
93+
})}
94+
>${contentBefore}${content}${contentAfter}${filesRender}${sourcesRender}${renders.actions(
95+
message,
96+
chatRef
97+
)}</div>`;
10298
};

src/components/combo-box/combo-box.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,20 @@
8989
*/
9090
--ch-combo-box__placeholder-color: currentColor;
9191

92+
/**
93+
* @prop --ch-combo-box__popover-max-block-size:
94+
* Specifies the maximum block size of the popover. Only px values are supported.
95+
* @default auto
96+
*/
97+
--ch-combo-box__popover-max-block-size: auto;
98+
99+
/**
100+
* @prop --ch-combo-box__popover-max-inline-size:
101+
* Specifies the maximum inline size of the popover. Only px values are supported.
102+
* @default auto
103+
*/
104+
--ch-combo-box__popover-max-inline-size: auto;
105+
92106
/**
93107
* @prop --ch-combo-box-item-gap:
94108
* Specifies the spacing between the images, text and the expandable button
@@ -209,6 +223,9 @@ select {
209223
// Separation
210224
// - - - - - - - - - - - - - - - -
211225
ch-popover {
226+
// TODO: Add e2e tests for these assignments
227+
--ch-popover-max-inline-size: var(--ch-combo-box__popover-max-inline-size);
228+
--ch-popover-max-block-size: var(--ch-combo-box__popover-max-block-size);
212229
--ch-popover-separation-x: var(--ch-combo-box-separation-x);
213230
--ch-popover-separation-y: var(--ch-combo-box-separation-y);
214231

src/components/combo-box/readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
| `--ch-combo-box__picker-mask-size` | Specifies the image size of the combo-box's picker. @default 100% |
6060
| `--ch-combo-box__picker-size` | Specifies the box size that contains the combo-box's picker. @default 0.875em |
6161
| `--ch-combo-box__placeholder-color` | Define the placeholder color when the combo-box does not have a value set. (currentColor by default) |
62+
| `--ch-combo-box__popover-max-block-size` | Specifies the maximum block size of the popover. Only px values are supported. @default auto |
63+
| `--ch-combo-box__popover-max-inline-size` | Specifies the maximum inline size of the popover. Only px values are supported. @default auto |
6264

6365

6466
## Dependencies

src/components/markdown-viewer/parsers/markdown-to-template-result.lit.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ export const LAST_NESTED_CHILD_CLASS = "last-nested-child";
1414
const findLastNestedChild = (elementWithChildren: MdAstParent | Root) => {
1515
const lastChild = elementWithChildren.children.at(-1);
1616

17+
// When rendering special values like "\n\n" or "\r\n", the root has no
18+
// children
19+
if (lastChild === undefined) {
20+
return elementWithChildren;
21+
}
22+
1723
// The last element have children. We must check its sub children
1824
if ((lastChild as MdAstParent).children?.length > 0) {
1925
return findLastNestedChild(lastChild as MdAstParent);

src/components/markdown-viewer/tests/value.e2e.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,12 @@ describe("[ch-markdown-viewer][value]", () => {
184184
const testValueRender = (
185185
value: string,
186186
render: string,
187-
description: string
187+
description: string,
188+
valueDescription?: string | undefined
188189
) => {
189-
it(`should render ${description} when the "value" property is "${value}"`, async () => {
190+
it(`should render ${description} when the "value" property is "${
191+
valueDescription ?? value
192+
}"`, async () => {
190193
markdownViewerRef.setProperty("value", value);
191194
await page.waitForChanges();
192195
markdownViewerRef = await page.find("ch-markdown-viewer"); // Refresh the reference
@@ -215,6 +218,39 @@ describe("[ch-markdown-viewer][value]", () => {
215218
"the paragraph without the bold because it ends with a dot"
216219
);
217220

221+
/**
222+
* These test cases validate that the root doesn't throw when trying to
223+
* render empty children, using an actual value with special characters.
224+
*/
225+
const testThrowEmptyChildren = (description: string, value: string) =>
226+
it(`should not throw when the value ("${description}") is defined but the root has empty children`, async () => {
227+
markdownViewerRef.setProperty("value", value);
228+
await page.waitForChanges();
229+
markdownViewerRef = await page.find("ch-markdown-viewer"); // Refresh the reference
230+
});
231+
232+
testThrowEmptyChildren("\\n\\n", "\n\n");
233+
testThrowEmptyChildren("\\r\\n", "\r\n");
234+
testThrowEmptyChildren("\\r\\r", "\r\r");
235+
testThrowEmptyChildren("%0A%0A", "%0A%0A");
236+
testThrowEmptyChildren("- \\n\\n", "- \n\n");
237+
testThrowEmptyChildren("> \\n\\n", "> \n\n");
238+
testThrowEmptyChildren("- \\r\\n", "- \r\n");
239+
testThrowEmptyChildren("> \\r\\n", "> \r\n");
240+
testThrowEmptyChildren("- \\r\\r", "- \r\r");
241+
testThrowEmptyChildren("> \\r\\r", "> \r\r");
242+
testThrowEmptyChildren("- %0A%0A", "- %0A%0A");
243+
testThrowEmptyChildren("> %0A%0A", "> %0A%0A");
244+
245+
testValueRender("\n\n", "", "nothing", "\\n\\n");
246+
testValueRender("\r\n", "", "nothing", "\\r\\n");
247+
testValueRender(
248+
"%0A%0A",
249+
`<p${LAST_NESTED_CHILD_CLASS}>%0A%0A</p>`,
250+
"%0A%0A"
251+
);
252+
253+
// TODO: Add the previous e2e test for validating the crash in the ch-code
218254
// TODO: Add unit test for updating the value at runtime
219255
// TODO: Add unit test for checking that the DOM is reused
220256
// TODO: Add unit test for checking the ch-code value bindings

0 commit comments

Comments
 (0)