Skip to content

Commit 32be607

Browse files
committed
Merge branch 'main' into introduce-boxel-spec
2 parents a4801a0 + 006d4f6 commit 32be607

File tree

32 files changed

+401
-129
lines changed

32 files changed

+401
-129
lines changed

Diff for: packages/base/card-api.gts

+14-10
Original file line numberDiff line numberDiff line change
@@ -1699,7 +1699,10 @@ export class BaseDef {
16991699
}
17001700
return Object.fromEntries(
17011701
Object.entries(
1702-
getFields(value, { includeComputeds: true, usedFieldsOnly: true }),
1702+
getFields(value, {
1703+
includeComputeds: true,
1704+
usedLinksToFieldsOnly: true,
1705+
}),
17031706
).map(([fieldName, field]) => {
17041707
let rawValue = peekAtField(value, fieldName);
17051708
if (field?.fieldType === 'linksToMany') {
@@ -1967,7 +1970,7 @@ export function subscribeToChanges(
19671970
changeSubscribers.add(subscriber);
19681971

19691972
let fields = getFields(fieldOrCard, {
1970-
usedFieldsOnly: true,
1973+
usedLinksToFieldsOnly: true,
19711974
includeComputeds: false,
19721975
});
19731976
Object.keys(fields).forEach((fieldName) => {
@@ -2010,7 +2013,7 @@ export function unsubscribeFromChanges(
20102013
changeSubscribers.delete(subscriber);
20112014

20122015
let fields = getFields(fieldOrCard, {
2013-
usedFieldsOnly: true,
2016+
usedLinksToFieldsOnly: true,
20142017
includeComputeds: false,
20152018
});
20162019
Object.keys(fields).forEach((fieldName) => {
@@ -2308,7 +2311,7 @@ function serializeCardResource(
23082311
let { includeUnrenderedFields: remove, ...fieldOpts } = opts ?? {};
23092312
let { id: removedIdField, ...fields } = getFields(model, {
23102313
...fieldOpts,
2311-
usedFieldsOnly: !opts?.includeUnrenderedFields,
2314+
usedLinksToFieldsOnly: !opts?.includeUnrenderedFields,
23122315
});
23132316
let fieldResources = Object.entries(fields)
23142317
.filter(([_fieldName, field]) =>
@@ -2830,7 +2833,7 @@ export async function recompute(
28302833
Object.keys(
28312834
getFields(model, {
28322835
includeComputeds: true,
2833-
usedFieldsOnly: !opts?.recomputeAllFields,
2836+
usedLinksToFieldsOnly: !opts?.recomputeAllFields,
28342837
}),
28352838
),
28362839
);
@@ -2936,15 +2939,15 @@ export async function getIfReady<T extends BaseDef, K extends keyof T>(
29362939

29372940
export function getFields(
29382941
card: typeof BaseDef,
2939-
opts?: { usedFieldsOnly?: boolean; includeComputeds?: boolean },
2942+
opts?: { usedLinksToFieldsOnly?: boolean; includeComputeds?: boolean },
29402943
): { [fieldName: string]: Field<BaseDefConstructor> };
29412944
export function getFields<T extends BaseDef>(
29422945
card: T,
2943-
opts?: { usedFieldsOnly?: boolean; includeComputeds?: boolean },
2946+
opts?: { usedLinksToFieldsOnly?: boolean; includeComputeds?: boolean },
29442947
): { [P in keyof T]?: Field<BaseDefConstructor> };
29452948
export function getFields(
29462949
cardInstanceOrClass: BaseDef | typeof BaseDef,
2947-
opts?: { usedFieldsOnly?: boolean; includeComputeds?: boolean },
2950+
opts?: { usedLinksToFieldsOnly?: boolean; includeComputeds?: boolean },
29482951
): { [fieldName: string]: Field<BaseDefConstructor> } {
29492952
let obj: object | null;
29502953
let usedFields: string[] = [];
@@ -2979,9 +2982,10 @@ export function getFields(
29792982
!['contains', 'containsMany'].includes(maybeField.fieldType)
29802983
) {
29812984
if (
2982-
opts?.usedFieldsOnly &&
2985+
opts?.usedLinksToFieldsOnly &&
29832986
!usedFields.includes(maybeFieldName) &&
2984-
!maybeField.isUsed
2987+
!maybeField.isUsed &&
2988+
!['contains', 'containsMany'].includes(maybeField.fieldType)
29852989
) {
29862990
return [];
29872991
}

Diff for: packages/base/default-templates/atom.gts

+13-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import GlimmerComponent from '@glimmer/component';
2-
import type { CardDef } from '../card-api';
2+
import { type CardDef, isCompoundField } from '../card-api';
3+
import { cn, not } from '@cardstack/boxel-ui/helpers';
34

45
export default class DefaultAtomViewTemplate extends GlimmerComponent<{
56
Args: {
@@ -8,26 +9,20 @@ export default class DefaultAtomViewTemplate extends GlimmerComponent<{
89
};
910
}> {
1011
get text() {
11-
let title =
12-
typeof this.args.model.title === 'string'
13-
? this.args.model.title.trim()
14-
: null;
15-
16-
return title
17-
? title
18-
: `Untitled ${this.args.model.constructor.displayName}`;
12+
if (!this.args.model) {
13+
return;
14+
}
15+
if (typeof this.args.model.title === 'string') {
16+
return this.args.model.title.trim();
17+
}
18+
if (isCompoundField(this.args.model)) {
19+
return;
20+
}
21+
return `Untitled ${this.args.model.constructor.displayName}`;
1922
}
2023
<template>
21-
<span class='atom-default-template'>
24+
<span class={{cn 'atom-default-template' empty-field=(not @model)}}>
2225
{{this.text}}
2326
</span>
24-
<style scoped>
25-
@layer {
26-
.atom-default-template {
27-
font: 600 var(--boxel-font-sm);
28-
letter-spacing: var(--boxel-lsp-xs);
29-
}
30-
}
31-
</style>
3227
</template>
3328
}

Diff for: packages/boxel-ui/addon/src/components/input/index.gts

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import cn from '../../helpers/cn.ts';
77
import element from '../../helpers/element.ts';
88
import optional from '../../helpers/optional.ts';
99
import pick from '../../helpers/pick.ts';
10-
import { and, eq, not } from '../../helpers/truth-helpers.ts';
10+
import { and, bool, eq, not } from '../../helpers/truth-helpers.ts';
1111
import FailureBordered from '../../icons/failure-bordered.gts';
1212
import IconSearch from '../../icons/icon-search.gts';
1313
import LoadingIndicator from '../../icons/loading-indicator.gts';
@@ -62,6 +62,7 @@ export interface Signature {
6262
id?: string;
6363
max?: string | number;
6464
onBlur?: (ev: Event) => void;
65+
onChange?: (ev: Event) => void;
6566
onFocus?: (ev: Event) => void;
6667
onInput?: (val: string) => void;
6768
onKeyPress?: (ev: KeyboardEvent) => void;
@@ -155,6 +156,7 @@ export default class BoxelInput extends Component<Signature> {
155156
id={{this.id}}
156157
type={{this.type}}
157158
value={{@value}}
159+
checked={{if (and (eq @type 'checkbox') (bool @value)) @value}}
158160
placeholder={{@placeholder}}
159161
max={{@max}}
160162
required={{@required}}
@@ -177,6 +179,7 @@ export default class BoxelInput extends Component<Signature> {
177179
{{on 'blur' (optional @onBlur)}}
178180
{{on 'keypress' (optional @onKeyPress)}}
179181
{{on 'focus' (optional @onFocus)}}
182+
{{on 'change' (optional @onChange)}}
180183
...attributes
181184
/>
182185
{{#if this.isSearch}}

Diff for: packages/experiments-realm/AtomExamples/d7aa387b-6514-47c0-ace2-7de011453e51.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@
193193
},
194194
"contacts.0": {
195195
"links": {
196-
"self": "../Customer/0e5aec99-798b-4417-9426-a338432e0ee5"
196+
"self": "../Customer/1274acf3-5b66-4373-89a2-fe8106c3d586"
197197
}
198198
},
199199
"contacts.1": {
@@ -203,7 +203,7 @@
203203
},
204204
"contacts.2": {
205205
"links": {
206-
"self": "../Customer/67e87a6c-00d0-4c48-9318-f0c96daa4cae"
206+
"self": "../Customer/0c71bda7-f4d8-451a-97cb-567a8fa31763"
207207
}
208208
}
209209
},

Diff for: packages/experiments-realm/atom-examples.gts

+4-16
Original file line numberDiff line numberDiff line change
@@ -74,32 +74,20 @@ class Isolated extends Component<typeof AtomExamples> {
7474
<h4>Using default atom template for Pet card:</h4>
7575
<div>
7676
Pet:
77-
{{#if @model.pet}}
78-
<@fields.pet @format='atom' />
79-
{{else}}
80-
(Bug: CS-7734)
81-
{{/if}}
77+
<@fields.pet @format='atom' />
8278
</div>
8379
<div>
8480
Pets:
85-
{{#if @model.pets}}
86-
<@fields.pets @format='atom' />
87-
{{else}}
88-
(Bug: CS-7734)
89-
{{/if}}
81+
<@fields.pets @format='atom' />
9082
</div>
9183
<h4>Default atom template without container:</h4>
9284
<div>
9385
Pet:
94-
{{#if @model.pet}}
95-
<@fields.pet @format='atom' @displayContainer={{false}} />
96-
{{/if}}
86+
<@fields.pet @format='atom' @displayContainer={{false}} />
9787
</div>
9888
<div>
9989
Pets:
100-
{{#if @model.pets}}
101-
<@fields.pets @format='atom' @displayContainer={{false}} />
102-
{{/if}}
90+
<@fields.pets @format='atom' @displayContainer={{false}} />
10391
</div>
10492
</section>
10593
<section>

Diff for: packages/host/app/components/matrix/room-message-command.gts

+14-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ export default class RoomMessageCommand extends Component<Signature> {
211211
monacoSDK=@monacoSDK
212212
language='json'
213213
readOnly=true
214-
darkTheme=true
215214
editorDisplayOptions=this.editorDisplayOptions
216215
}}
217216
data-test-editor
@@ -241,6 +240,9 @@ export default class RoomMessageCommand extends Component<Signature> {
241240
</CardContainer>
242241
{{/if}}
243242
</div>
243+
244+
{{! template-lint-disable no-whitespace-for-layout }}
245+
{{! ignore the above error because ember-template-lint complains about the whitespace in the multi-line comment below }}
244246
<style scoped>
245247
.is-pending .view-code-button,
246248
.is-error .view-code-button {
@@ -319,6 +321,17 @@ export default class RoomMessageCommand extends Component<Signature> {
319321
.options-menu :deep(.check-icon) {
320322
display: none;
321323
}
324+
/*
325+
This filter is a best-effort approximation of a good looking dark theme that is a function of the white theme that
326+
we use for code previews in the AI panel. While Monaco editor does support multiple themes, it does not support
327+
monaco instances with different themes *on the same page*. This is why we are using a filter to approximate the
328+
dark theme. More details here: https://github.com/Microsoft/monaco-editor/issues/338 (monaco uses global style tags
329+
with hardcoded colors; any instance will override the global style tag, making all code editors look the same,
330+
effectively disabling multiple themes to be used on the same page)
331+
*/
332+
:global(.preview-code .monaco-editor) {
333+
filter: invert(1) hue-rotate(151deg) brightness(0.8) grayscale(0.1);
334+
}
322335
</style>
323336
</template>
324337
}

Diff for: packages/host/app/components/matrix/room.gts

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { registerDestructor } from '@ember/destroyable';
12
import { fn } from '@ember/helper';
23
import { on } from '@ember/modifier';
34
import { action } from '@ember/object';
@@ -235,6 +236,9 @@ export default class Room extends Component<Signature> {
235236
constructor(owner: Owner, args: Signature['Args']) {
236237
super(owner, args);
237238
this.doMatrixEventFlush.perform();
239+
registerDestructor(this, () => {
240+
this.scrollState().messageVisibilityObserver.disconnect();
241+
});
238242
}
239243

240244
private scrollState() {

Diff for: packages/host/app/components/operator-mode/code-editor.gts

+9-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,15 @@ export default class CodeEditor extends Component<Signature> {
324324
padding: var(--boxel-sp) 0;
325325
}
326326
327-
.monaco-container.readonly {
327+
:global(.monaco-container.readonly) {
328+
background-color: #ebeaed;
329+
}
330+
331+
:global(.monaco-container.readonly .margin) {
332+
background-color: #ebeaed;
333+
}
334+
335+
:global(.monaco-container.readonly .monaco-editor-background) {
328336
background-color: #ebeaed;
329337
}
330338

Diff for: packages/host/app/components/operator-mode/code-submode.gts

-1
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,6 @@ export default class CodeSubmode extends Component<Signature> {
782782
{{/let}}
783783
<SubmodeLayout
784784
@onCardSelectFromSearch={{this.openSearchResultInEditor}}
785-
@hideAiAssistant={{true}}
786785
as |search|
787786
>
788787
<div

Diff for: packages/host/app/components/operator-mode/submode-layout.gts

+11-18
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { TrackedObject } from 'tracked-built-ins';
1717

1818
import { ResizablePanelGroup } from '@cardstack/boxel-ui/components';
1919
import { Avatar, IconButton } from '@cardstack/boxel-ui/components';
20-
import { and, cn, not } from '@cardstack/boxel-ui/helpers';
20+
import { cn, not } from '@cardstack/boxel-ui/helpers';
2121

2222
import { BoxelIcon } from '@cardstack/boxel-ui/icons';
2323

@@ -47,7 +47,6 @@ import type OperatorModeStateService from '../../services/operator-mode-state-se
4747
interface Signature {
4848
Element: HTMLDivElement;
4949
Args: {
50-
hideAiAssistant?: boolean;
5150
onSearchSheetOpened?: () => void;
5251
onSearchSheetClosed?: () => void;
5352
onCardSelectFromSearch: (cardId: string) => void;
@@ -309,23 +308,17 @@ export default class SubmodeLayout extends Component<Signature> {
309308
@onCardSelect={{this.handleCardSelectFromSearch}}
310309
@onInputInsertion={{this.storeSearchElement}}
311310
/>
312-
{{#if (not @hideAiAssistant)}}
313-
<AiAssistantToast
314-
@hide={{this.operatorModeStateService.aiAssistantOpen}}
315-
@onViewInChatClick={{this.operatorModeStateService.toggleAiAssistant}}
316-
/>
317-
<AiAssistantButton
318-
class='chat-btn'
319-
@isActive={{this.operatorModeStateService.aiAssistantOpen}}
320-
{{on 'click' this.operatorModeStateService.toggleAiAssistant}}
321-
/>
322-
{{/if}}
311+
<AiAssistantToast
312+
@hide={{this.operatorModeStateService.aiAssistantOpen}}
313+
@onViewInChatClick={{this.operatorModeStateService.toggleAiAssistant}}
314+
/>
315+
<AiAssistantButton
316+
class='chat-btn'
317+
@isActive={{this.operatorModeStateService.aiAssistantOpen}}
318+
{{on 'click' this.operatorModeStateService.toggleAiAssistant}}
319+
/>
323320
</ResizablePanel>
324-
{{#if
325-
(and
326-
(not @hideAiAssistant) this.operatorModeStateService.aiAssistantOpen
327-
)
328-
}}
321+
{{#if this.operatorModeStateService.aiAssistantOpen}}
329322
<ResizablePanel
330323
class='ai-assistant-resizable-panel'
331324
@defaultSize={{this.aiPanelWidths.defaultWidth}}

0 commit comments

Comments
 (0)