Skip to content

Commit db93ca2

Browse files
committed
Merge branch 'main' into cs-7837-make-fitted-view-spec
2 parents 156c3ae + 371e36a commit db93ca2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1828
-1312
lines changed

.github/workflows/pr-boxel-host.yml

-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ jobs:
6363
AWS_S3_BUCKET: boxel-host-preview.stack.cards
6464
AWS_REGION: us-east-1
6565
AWS_CLOUDFRONT_DISTRIBUTION: EU4RGLH4EOCHJ
66-
ENABLE_PLAYGROUND: true
6766
AI_ASSISTANT_EXPERIMENTAL_ATTACHING_FILES_ENABLED: true
6867
with:
6968
package: boxel-host
@@ -94,7 +93,6 @@ jobs:
9493
AWS_S3_BUCKET: boxel-host-preview.boxel.ai
9594
AWS_REGION: us-east-1
9695
AWS_CLOUDFRONT_DISTRIBUTION: E2PZR9CIAW093B
97-
ENABLE_PLAYGROUND: true
9896
AI_ASSISTANT_EXPERIMENTAL_ATTACHING_FILES_ENABLED: true
9997
with:
10098
package: boxel-host

packages/base/code-ref.gts

+21-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ import {
1616
import { ResolvedCodeRef } from '@cardstack/runtime-common';
1717
import CodeIcon from '@cardstack/boxel-icons/code';
1818

19+
function moduleIsUrlLike(module: string) {
20+
return (
21+
module.startsWith('http') ||
22+
module.startsWith('.') ||
23+
module.startsWith('/')
24+
);
25+
}
26+
1927
class BaseView extends Component<typeof CodeRefField> {
2028
<template>
2129
<div data-test-ref>
@@ -39,7 +47,9 @@ export default class CodeRefField extends FieldDef {
3947
) {
4048
return {
4149
...codeRef,
42-
...(opts?.maybeRelativeURL && !opts?.useAbsoluteURL
50+
...(opts?.maybeRelativeURL &&
51+
!opts?.useAbsoluteURL &&
52+
moduleIsUrlLike(codeRef.module)
4353
? { module: opts.maybeRelativeURL(codeRef.module) }
4454
: {}),
4555
};
@@ -70,12 +80,16 @@ function maybeSerializeCodeRef(
7080
stack: CardDef[] = [],
7181
) {
7282
if (codeRef) {
73-
// if a stack is passed in, use the containing card to resolve relative references
74-
let moduleHref =
75-
stack.length > 0
76-
? new URL(codeRef.module, stack[0][relativeTo]).href
77-
: codeRef.module;
78-
return `${moduleHref}/${codeRef.name}`;
83+
if (moduleIsUrlLike(codeRef.module)) {
84+
// if a stack is passed in, use the containing card to resolve relative references
85+
let moduleHref =
86+
stack.length > 0
87+
? new URL(codeRef.module, stack[0][relativeTo]).href
88+
: codeRef.module;
89+
return `${moduleHref}/${codeRef.name}`;
90+
} else {
91+
return `${codeRef.module}/${codeRef.name}`;
92+
}
7993
}
8094
return undefined;
8195
}

packages/base/skill-card.gts

+47-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,57 @@
1+
import {
2+
CardDef,
3+
Component,
4+
FieldDef,
5+
field,
6+
contains,
7+
containsMany,
8+
} from './card-api';
9+
import BooleanField from './boolean';
10+
import CodeRefField from './code-ref';
111
import MarkdownField from './markdown';
2-
import { CardDef, Component, field, contains } from './card-api';
12+
import StringField from './string';
313
import RobotIcon from '@cardstack/boxel-icons/robot';
14+
import { simpleHash } from '@cardstack/runtime-common';
15+
16+
function friendlyModuleName(fullModuleUrl: string) {
17+
return fullModuleUrl
18+
.split('/')
19+
.pop()!
20+
.replace(/\.gts$/, '');
21+
}
22+
23+
export class CommandField extends FieldDef {
24+
static displayName = 'CommandField';
25+
@field codeRef = contains(CodeRefField, {
26+
description: 'An absolute code reference to the command to be executed',
27+
});
28+
@field requiresApproval = contains(BooleanField, {
29+
description:
30+
'If true, this command will require human approval before it is executed in the host.',
31+
});
32+
33+
@field functionName = contains(StringField, {
34+
description: 'The name of the function to be executed',
35+
computeVia: function (this: CommandField) {
36+
if (!this.codeRef?.module || !this.codeRef?.name) {
37+
return '';
38+
}
39+
40+
const hashed = simpleHash(`${this.codeRef.module}#${this.codeRef.name}`);
41+
let name =
42+
this.codeRef.name === 'default'
43+
? friendlyModuleName(this.codeRef.module)
44+
: this.codeRef.name;
45+
return `${name}_${hashed.slice(0, 4)}`;
46+
},
47+
});
48+
}
449

550
export class SkillCard extends CardDef {
651
static displayName = 'Skill';
752
static icon = RobotIcon;
853
@field instructions = contains(MarkdownField);
54+
@field commands = containsMany(CommandField);
955
static embedded = class Embedded extends Component<typeof this> {
1056
<template>
1157
<@fields.title />
Loading

packages/boxel-ui/addon/src/icons.gts

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import IconPencilCrossedOut from './icons/icon-pencil-crossed-out.gts';
4040
import IconPencilNotCrossedOut from './icons/icon-pencil-not-crossed-out.gts';
4141
import IconPlus from './icons/icon-plus.gts';
4242
import IconPlusCircle from './icons/icon-plus-circle.gts';
43+
import IconPlusThin from './icons/icon-plus-thin.gts';
4344
import IconSearch from './icons/icon-search.gts';
4445
import IconSearchThick from './icons/icon-search-thick.gts';
4546
import IconTrash from './icons/icon-trash.gts';
@@ -100,6 +101,7 @@ export const ALL_ICON_COMPONENTS = [
100101
IconPencilNotCrossedOut,
101102
IconPlus,
102103
IconPlusCircle,
104+
IconPlusThin,
103105
IconSearch,
104106
IconSearchThick,
105107
IconTrash,
@@ -161,6 +163,7 @@ export {
161163
IconPencilNotCrossedOut,
162164
IconPlus,
163165
IconPlusCircle,
166+
IconPlusThin,
164167
IconSearch,
165168
IconSearchThick,
166169
IconTrash,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// This file is auto-generated by 'pnpm rebuild:icons'
2+
import type { TemplateOnlyComponent } from '@ember/component/template-only';
3+
4+
import type { Signature } from './types.ts';
5+
6+
const IconComponent: TemplateOnlyComponent<Signature> = <template>
7+
<svg
8+
xmlns='http://www.w3.org/2000/svg'
9+
viewBox='3.5 3.5 17 17'
10+
...attributes
11+
><path
12+
fill='var(--icon-color, currentColor)'
13+
d='M19 11h-6V5a1 1 0 0 0-2 0v6H5a1 1 0 0 0 0 2h6v6a1 1 0 0 0 2 0v-6h6a1 1 0 0 0 0-2Z'
14+
/></svg>
15+
</template>;
16+
17+
// @ts-expect-error this is the only way to set a name on a Template Only Component currently
18+
IconComponent.name = 'IconPlusThin';
19+
export default IconComponent;

packages/experiments-realm/components/account-header.gts

+43-14
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,72 @@ class AccountHeader extends GlimmerComponent<AccountHeaderArgs> {
2626
<div class='account-header-info'>
2727
{{#if (has-block 'name')}}
2828
{{yield to='name'}}
29+
{{else}}
30+
<h3 class='account-header-name'>{{@name}}</h3>
2931
{{/if}}
32+
3033
{{#if (has-block 'content')}}
31-
{{yield to='content'}}
34+
<div class='account-header-info-content'>
35+
{{yield to='content'}}
36+
</div>
3237
{{/if}}
3338
</div>
3439
</header>
3540

3641
<style scoped>
3742
.account-header {
38-
display: flex;
39-
align-items: start;
40-
gap: var(--boxel-sp);
43+
display: var(--account-header-display, flex);
44+
align-items: var(--account-header-align-items, start);
45+
gap: var(--account-header-gap, var(--boxel-sp));
4146
min-width: 0;
4247
}
4348
.account-header-logo {
4449
flex-shrink: 0;
4550
width: var(--account-header-logo-size, 60px);
4651
height: var(--account-header-logo-size, 60px);
47-
object-fit: cover;
48-
border-radius: var(--boxel-border-radius-xl);
52+
object-fit: var(--account-header-logo-object-fit, cover);
53+
border-radius: var(
54+
--account-header-logo-border-radius,
55+
var(--boxel-border-radius-xl)
56+
);
4957
}
5058
.default-icon-container {
5159
display: var(--account-header-logo-display, flex);
52-
align-items: center;
53-
justify-content: center;
54-
background-color: var(--boxel-200);
55-
color: var(--boxel-400);
56-
padding: 5px;
60+
align-items: var(--account-header-logo-align-items, center);
61+
justify-content: var(--account-header-logo-justify-content, center);
62+
background-color: var(
63+
--account-header-logo-background-color,
64+
var(--boxel-200)
65+
);
66+
color: var(--account-header-logo-color, var(--boxel-400));
67+
padding: var(--account-header-logo-padding, 5px);
5768
}
5869
.account-header-info {
59-
display: flex;
60-
flex-direction: column;
61-
gap: var(--boxel-sp-xxs);
70+
display: var(--account-header-info-display, flex);
71+
flex-direction: var(--account-header-info-flex-direction, column);
72+
gap: var(--account-header-info-gap, var(--boxel-sp-xxs));
6273
min-width: 0;
6374
width: 100%;
6475
overflow: hidden;
6576
}
77+
.account-header-name {
78+
margin: 0;
79+
font: var(--account-header-name-font, 600 var(--boxel-font-med));
80+
letter-spacing: var(
81+
--account-header-name-letter-spacing,
82+
var(--boxel-lsp-sm)
83+
);
84+
overflow: hidden;
85+
text-overflow: ellipsis;
86+
display: -webkit-box;
87+
-webkit-box-orient: vertical;
88+
-webkit-line-clamp: var(--account-header-name-line-clamp, 1);
89+
}
90+
.account-header-info-content {
91+
display: var(--account-header-info-content-display, flex);
92+
flex-direction: var(--account-header-info-content-flex-direction, row);
93+
gap: var(--account-header-info-content-gap, var(--boxel-sp-xxs));
94+
}
6695
</style>
6796
</template>
6897
}

packages/experiments-realm/components/avatar-group.gts

+33-17
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ interface AvatarGroupSignature {
88
name?: string;
99
userId?: string | null;
1010
};
11-
Blocks: { content: [] };
11+
Blocks: {
12+
name: [];
13+
content: [];
14+
};
1215
Element: HTMLElement;
1316
}
1417

@@ -28,39 +31,52 @@ export default class AvatarGroup extends GlimmerComponent<AvatarGroupSignature>
2831
/>
2932

3033
<div class='avatar-info'>
31-
<h3 class='name'>
32-
{{if @name @name 'No Name Assigned'}}
33-
</h3>
34+
{{#if (has-block 'name')}}
35+
{{yield to='name'}}
36+
{{else}}
37+
<h3 class='avatar-name'>{{@name}}</h3>
38+
{{/if}}
3439

35-
{{yield to='content'}}
40+
{{#if (has-block 'content')}}
41+
<div class='avatar-info-content'>
42+
{{yield to='content'}}
43+
</div>
44+
{{/if}}
3645
</div>
3746
</div>
3847

3948
<style scoped>
4049
.avatar-group {
41-
display: flex;
42-
align-items: center;
43-
gap: var(--boxel-sp-sm);
50+
display: var(--avatar-group-display, flex);
51+
flex-direction: var(--avatar-group-flex-direction, row);
52+
align-items: var(--avatar-group-align-items, center);
53+
gap: var(--avatar-group-gap, var(--boxel-sp-sm));
4454
min-width: 0;
4555
}
4656
.avatar-thumbnail {
4757
flex-shrink: 0;
48-
--profile-avatar-icon-size: 60px;
58+
--profile-avatar-icon-size: var(--avatar-thumbnail-size, 60px);
59+
--profile-avatar-icon-border: var(--avatar-thumbnail-border, 0px);
4960
}
5061
.avatar-info {
5162
min-width: 0;
5263
width: 100%;
5364
overflow: hidden;
5465
}
55-
.name {
56-
-webkit-line-clamp: 1;
57-
text-wrap: nowrap;
58-
text-overflow: ellipsis;
59-
overflow: hidden;
66+
.avatar-name {
6067
margin: 0;
61-
font-size: var(--boxel-font-size);
62-
font-weight: 600;
63-
letter-spacing: var(--boxel-lsp-sm);
68+
font: var(--avatar-name-font, 600 var(--boxel-font-med));
69+
letter-spacing: var(--avatar-name-letter-spacing, var(--boxel-lsp-sm));
70+
overflow: hidden;
71+
text-overflow: ellipsis;
72+
display: -webkit-box;
73+
-webkit-box-orient: vertical;
74+
-webkit-line-clamp: var(--avatar-name-line-clamp, 1);
75+
}
76+
.avatar-info-content {
77+
display: var(--avatar-info-content-display, flex);
78+
flex-direction: var(--avatar-info-content-flex-direction, row);
79+
gap: var(--avatar-info-content-gap, var(--boxel-sp-xxs));
6480
}
6581
</style>
6682
</template>

0 commit comments

Comments
 (0)