@cardstack/boxel-cli 0.11.0-unstable.2 → 0.11.0-unstable.3
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.
- package/bundled-realms/pretui/components/agent-mark.gts +98 -0
- package/bundled-realms/pretui/components/agent-question.gts +340 -37
- package/bundled-realms/pretui/components/answer-footer.gts +249 -0
- package/bundled-realms/pretui/components/card-embed.gts +523 -0
- package/bundled-realms/pretui/components/card-pills.gts +725 -0
- package/bundled-realms/pretui/components/code-block.gts +87 -45
- package/bundled-realms/pretui/components/collapsed-turn.gts +133 -12
- package/bundled-realms/pretui/components/compaction-chip.gts +81 -67
- package/bundled-realms/pretui/components/composer-cap.gts +516 -0
- package/bundled-realms/pretui/components/context-ring.gts +108 -0
- package/bundled-realms/pretui/components/diff-block.gts +1002 -31
- package/bundled-realms/pretui/components/diff-stat.gts +102 -0
- package/bundled-realms/pretui/components/jump-chip.gts +86 -53
- package/bundled-realms/pretui/components/markdown-stream.gts +799 -0
- package/bundled-realms/pretui/components/markdown-surface.gts +71 -0
- package/bundled-realms/pretui/components/plan-mark.gts +147 -0
- package/bundled-realms/pretui/components/prose.gts +185 -8
- package/bundled-realms/pretui/components/prose.md +6 -8
- package/bundled-realms/pretui/components/quick-look.gts +377 -0
- package/bundled-realms/pretui/components/reactions.gts +136 -0
- package/bundled-realms/pretui/components/recommendation.gts +67 -36
- package/bundled-realms/pretui/components/result-card.gts +58 -22
- package/bundled-realms/pretui/components/segmented-control.gts +13 -8
- package/bundled-realms/pretui/components/session-prep.gts +12 -11
- package/bundled-realms/pretui/components/sliding-highlight.gts +8 -3
- package/bundled-realms/pretui/components/speaker-label.gts +132 -0
- package/bundled-realms/pretui/components/state-glyph.gts +121 -0
- package/bundled-realms/pretui/components/step-list.gts +62 -60
- package/bundled-realms/pretui/components/stick-to-bottom.gts +1150 -0
- package/bundled-realms/pretui/components/system-line.gts +143 -0
- package/bundled-realms/pretui/components/task-checklist.gts +184 -0
- package/bundled-realms/pretui/components/thinking.gts +63 -94
- package/bundled-realms/pretui/components/tool-change-table.gts +285 -0
- package/bundled-realms/pretui/components/tool-gate.gts +462 -0
- package/bundled-realms/pretui/components/tool-group.gts +920 -0
- package/bundled-realms/pretui/components/tool-icon.ts +64 -0
- package/bundled-realms/pretui/components/tool-meta.gts +82 -0
- package/bundled-realms/pretui/components/tool-plan.gts +197 -0
- package/bundled-realms/pretui/components/tool-row.gts +2087 -0
- package/bundled-realms/pretui/components/turn-changes.gts +227 -0
- package/bundled-realms/pretui/components/user-bubble.gts +575 -0
- package/bundled-realms/pretui/components/work-item.gts +185 -48
- package/bundled-realms/pretui/docs/scroll-anchoring-protocol.md +136 -0
- package/bundled-realms/pretui/internal/markdown-projection.ts +438 -0
- package/bundled-realms/pretui/internal/mount-queue.ts +79 -0
- package/bundled-realms/pretui/internal/tool-phrases.ts +168 -0
- package/bundled-realms/pretui/package.json +2 -1
- package/bundled-test-harness/assets/{ai-module-creation-test-beRNwH-e.js → ai-module-creation-test-B6FQKqIl.js} +1 -1
- package/bundled-test-harness/assets/{app-CtezUCip.js → app-KpPqdyX3.js} +4 -4
- package/bundled-test-harness/assets/{binary-upload-dedupe-test-bI8T0QLl.js → binary-upload-dedupe-test-DN00y1tM.js} +1 -1
- package/bundled-test-harness/assets/{can-invoke-test-DVaU_yRT.js → can-invoke-test-Bl-EUFM3.js} +1 -1
- package/bundled-test-harness/assets/{card-chooser-paging-test-DnxMnXKR.js → card-chooser-paging-test-BNuZRHX3.js} +1 -1
- package/bundled-test-harness/assets/{card-chooser-test-DUSnLr-u.js → card-chooser-test-wKfPOOT4.js} +1 -1
- package/bundled-test-harness/assets/{card-def-field-def-relationships-test-GBUr3tFK.js → card-def-field-def-relationships-test-CduQ6zan.js} +1 -1
- package/bundled-test-harness/assets/{card-delete-test-CQveO1VC.js → card-delete-test-DKxolj5o.js} +1 -1
- package/bundled-test-harness/assets/{check-correctness-test-D2M2p66N.js → check-correctness-test-B-kgHztp.js} +1 -1
- package/bundled-test-harness/assets/{codeblocks-test-AdolhdCA.js → codeblocks-test-BDD7qK_V.js} +1 -1
- package/bundled-test-harness/assets/{compaction-test-DvyAQq56.js → compaction-test-BweolkhG.js} +1 -1
- package/bundled-test-harness/assets/{container-DIF_9lZ9.css → container-B5B6u-xm.css} +29 -22
- package/bundled-test-harness/assets/{container-DvvqmNpg.js → container-BnJjIM6J.js} +9 -6
- package/bundled-test-harness/assets/{create-listing-modal-test-D95JfQab.js → create-listing-modal-test-FvcAKpIa.js} +1 -1
- package/bundled-test-harness/assets/{debug-message-test-BcNtj7Wr.js → debug-message-test-CJ18Evt7.js} +1 -1
- package/bundled-test-harness/assets/{externals-DCnB4XSS.js → externals-BWjhmCD4.js} +1 -1
- package/bundled-test-harness/assets/{fallback-banner-live-delete-test-5lnN1pv2.js → fallback-banner-live-delete-test-C2H3BrT-.js} +1 -1
- package/bundled-test-harness/assets/{fallback-banner-test-DFb_m_Kq.js → fallback-banner-test-C10aYjkj.js} +1 -1
- package/bundled-test-harness/assets/{fallback-models-test-p3YIwj1L.js → fallback-models-test-BxoPiaGF.js} +1 -1
- package/bundled-test-harness/assets/{file-attachment-test-CmyjNWRR.js → file-attachment-test-DeKyzYaz.js} +1 -1
- package/bundled-test-harness/assets/{general-test-CX-TFDuX.js → general-test-BewzrpoB.js} +1 -1
- package/bundled-test-harness/assets/{index-query-engine-test-CY2tAkot.js → index-query-engine-test-BtI8Y2LR.js} +1 -1
- package/bundled-test-harness/assets/{instance-filter-matcher-test-CMBTh8xn.js → instance-filter-matcher-test-BHXHGHjE.js} +1 -1
- package/bundled-test-harness/assets/{main-BOZbZVem.js → main-CqAHZ2kK.js} +1 -1
- package/bundled-test-harness/assets/{message-tool-test-CfjRSJvt.js → message-tool-test-NMaPJFsd.js} +1 -1
- package/bundled-test-harness/assets/{model-cost-tier-test-mZG84Uso.js → model-cost-tier-test-BgbfN2LH.js} +1 -1
- package/bundled-test-harness/assets/{operation-lowering-test-CHnjKSJb.js → operation-lowering-test-C4IaOjsA.js} +1 -1
- package/bundled-test-harness/assets/{operator-mode-card-chooser-test-KWS8lq16.js → operator-mode-card-chooser-test-Bwe47Rn7.js} +1 -1
- package/bundled-test-harness/assets/{operator-mode-links-test-CViFt0Ws.js → operator-mode-links-test-BU4jkC-B.js} +1 -1
- package/bundled-test-harness/assets/{operator-mode-test-D0gZM2yw.js → operator-mode-test-Bh0rGM9z.js} +1 -1
- package/bundled-test-harness/assets/{operator-mode-ui-test-CEvHJ9DS.js → operator-mode-ui-test-whgUw0ju.js} +1 -1
- package/bundled-test-harness/assets/{overlay-menu-items-test-Pw80RXsr.js → overlay-menu-items-test-Cwn1vr8q.js} +1 -1
- package/bundled-test-harness/assets/{past-sessions-test-CW0-Bjav.js → past-sessions-test-Bh24N-Kz.js} +1 -1
- package/bundled-test-harness/assets/{permission-checking-realm-test-D5uXQypS.js → permission-checking-realm-test-DKnnAy0f.js} +1 -1
- package/bundled-test-harness/assets/{realm-config-policy-standing-test-Btatheni.js → realm-config-policy-standing-test-DngdYypq.js} +1 -1
- package/bundled-test-harness/assets/{realm-config-routing-rule-edit-test-Dh5zW13o.js → realm-config-routing-rule-edit-test-_rkFU8SN.js} +1 -1
- package/bundled-test-harness/assets/{realm-config-settings-test-BJa8gv_C.js → realm-config-settings-test-CR9NH0Zn.js} +1 -1
- package/bundled-test-harness/assets/{reasoning-test-2Zp37cQB.js → reasoning-test-0lH10kRl.js} +1 -1
- package/bundled-test-harness/assets/{room-message-test-BsrON13e.js → room-message-test-C-PddE4Y.js} +1 -1
- package/bundled-test-harness/assets/{run-realm-code-BxktQf6R.js → run-realm-code-C8N7DtN-.js} +1 -1
- package/bundled-test-harness/assets/{run-realm-code-test-7grpTos-.js → run-realm-code-test-DBdp147q.js} +1 -1
- package/bundled-test-harness/assets/{schema-generation-test-CM9ggQji.js → schema-generation-test-CB1Hb7GQ.js} +1 -1
- package/bundled-test-harness/assets/{scrolling-test-BER00htB.js → scrolling-test-3PhVin8h.js} +1 -1
- package/bundled-test-harness/assets/{searchable-option-test-Ctf8r3HZ.js → searchable-option-test-BAdOiL4U.js} +1 -1
- package/bundled-test-harness/assets/{sending-test-BJGobs2E.js → sending-test-KSmu1tSJ.js} +1 -1
- package/bundled-test-harness/assets/{skills-test-GPOsHRN6.js → skills-test-D-dlcFpd.js} +1 -1
- package/bundled-test-harness/assets/{store-test-QvvHimzH.js → store-test-CEW7xQjZ.js} +1 -1
- package/bundled-test-harness/assets/{tests-DoTEpvcF.js → tests-QYqqa6nv.js} +47 -47
- package/bundled-test-harness/assets/{text-input-validator-test-CYYH2N0L.js → text-input-validator-test-D8iNOWep.js} +1 -1
- package/bundled-test-harness/assets/{to-device-streaming-test-Ctqa0bVp.js → to-device-streaming-test-trCX-505.js} +1 -1
- package/bundled-test-harness/assets/{token-usage-test-BQVbK3X0.js → token-usage-test-C6sULooH.js} +1 -1
- package/bundled-test-harness/assets/{tools-DU8Rc15s.js → tools-UJfD-_al.js} +1 -1
- package/bundled-test-harness/assets/{tools-test-B13yvEKE.js → tools-test-Brav31AV.js} +1 -1
- package/bundled-test-harness/assets/{worker-DHBEBihX.js → worker-9ph9_Lpv.js} +31 -26
- package/bundled-test-harness/index.html +8 -8
- package/bundled-test-harness/tests/index.html +8 -8
- package/bundled-types/host-app/lib/realm-runner/worker.ts +8 -51
- package/bundled-types/runtime-common/realm-runner-script.d.ts +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,725 @@
|
|
|
1
|
+
// Pretui — CardPills: the cards a call found or touched, as pills or a grid, that open, select and fold.
|
|
2
|
+
import Component from '@glimmer/component';
|
|
3
|
+
import { StateGlyph } from './state-glyph';
|
|
4
|
+
import { tracked } from '@glimmer/tracking';
|
|
5
|
+
import { on } from '@ember/modifier';
|
|
6
|
+
import { fn } from '@ember/helper';
|
|
7
|
+
import { modifier } from 'ember-modifier';
|
|
8
|
+
import { VisuallyHidden } from './visually-hidden';
|
|
9
|
+
|
|
10
|
+
export interface CardPillItem {
|
|
11
|
+
/** stable: the card's id. Default: its title */
|
|
12
|
+
id?: string;
|
|
13
|
+
/** the card's title */
|
|
14
|
+
title: string;
|
|
15
|
+
/** its type, as the card shows it: 'Runner', 'Race' */
|
|
16
|
+
kind?: string;
|
|
17
|
+
/** a thumbnail; without one the pill shows the title's initial */
|
|
18
|
+
image?: string;
|
|
19
|
+
/** a quieter line, for the grid: '4 runs this month' */
|
|
20
|
+
sub?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface CardPillsSignature {
|
|
24
|
+
Args: {
|
|
25
|
+
cards: CardPillItem[];
|
|
26
|
+
/** 'pills' (default): a wrap of pills, for a search row's result.
|
|
27
|
+
* 'grid': small tiles, for members and other sets worth seeing */
|
|
28
|
+
layout?: 'pills' | 'grid';
|
|
29
|
+
/** how many show before "Show all N". Default: all */
|
|
30
|
+
limit?: number;
|
|
31
|
+
/** the reader opened a card; the caller opens it where they work */
|
|
32
|
+
onOpen?: (card: CardPillItem) => void;
|
|
33
|
+
/** the card open on the stack, by id: its pill stays highlighted, and
|
|
34
|
+
* pressing it again (or Escape) closes it */
|
|
35
|
+
open?: string;
|
|
36
|
+
onClose?: (card: CardPillItem) => void;
|
|
37
|
+
/** pick cards instead of opening them: a press toggles a check, and a
|
|
38
|
+
* bar offers what to do with the picked ones */
|
|
39
|
+
selectable?: boolean;
|
|
40
|
+
/** the picked cards, by id; controlled */
|
|
41
|
+
selected?: string[];
|
|
42
|
+
onSelectionChange?: (ids: string[]) => void;
|
|
43
|
+
/** the bar's verb for the picked cards: 'Attach', 'Message'. With
|
|
44
|
+
* `@onUseSelection` */
|
|
45
|
+
useLabel?: string;
|
|
46
|
+
onUseSelection?: (cards: CardPillItem[]) => void;
|
|
47
|
+
/** the list's accessible name. Default 'Cards' */
|
|
48
|
+
label?: string;
|
|
49
|
+
/** hovering or focusing a pill peeks at its card: a hover card with
|
|
50
|
+
* the `<:peek>` block (the host's fitted card), Open on stack and Show
|
|
51
|
+
* here. `@onPeek` lets the host start loading it */
|
|
52
|
+
peek?: boolean;
|
|
53
|
+
onPeek?: (card: CardPillItem) => void;
|
|
54
|
+
/** the card shown in place, by id: the `<:expanded>` block renders it
|
|
55
|
+
* under the set, embedded, with Hide */
|
|
56
|
+
expanded?: string;
|
|
57
|
+
onExpand?: (card: CardPillItem) => void;
|
|
58
|
+
onCollapse?: (card: CardPillItem) => void;
|
|
59
|
+
};
|
|
60
|
+
Blocks: {
|
|
61
|
+
/** a card's fitted view, inside the peek */
|
|
62
|
+
peek: [card: CardPillItem];
|
|
63
|
+
/** a card's embedded view, in place under the set */
|
|
64
|
+
expanded: [card: CardPillItem];
|
|
65
|
+
};
|
|
66
|
+
Element: HTMLDivElement;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* What a `cards.search`, `cards.get` or `entries.search` returned, as the
|
|
71
|
+
* cards themselves. The whole interaction is here:
|
|
72
|
+
*
|
|
73
|
+
* - **Open.** A press opens the card where the reader works; that pill
|
|
74
|
+
* stays highlighted as open, and a second press (or Escape) closes it.
|
|
75
|
+
* - **Pick.** With `@selectable` a press toggles a check instead, and a
|
|
76
|
+
* bar says "3 picked · Attach · Clear"; Escape clears.
|
|
77
|
+
* - **Move.** Arrow keys move between cards (one tab stop for the set),
|
|
78
|
+
* Home and End jump to the ends.
|
|
79
|
+
* - **Fold.** Past `@limit`, "Show all N"; once open, "Show fewer".
|
|
80
|
+
*/
|
|
81
|
+
export class CardPills extends Component<CardPillsSignature> {
|
|
82
|
+
@tracked showAll = false;
|
|
83
|
+
@tracked private innerSelected: string[] = [];
|
|
84
|
+
@tracked private focusIndex = 0;
|
|
85
|
+
/** the pill being peeked at */
|
|
86
|
+
@tracked private peekId: string | undefined;
|
|
87
|
+
private list: HTMLElement | undefined;
|
|
88
|
+
|
|
89
|
+
get layout() {
|
|
90
|
+
return this.args.layout ?? 'pills';
|
|
91
|
+
}
|
|
92
|
+
get folds(): boolean {
|
|
93
|
+
let { limit, cards } = this.args;
|
|
94
|
+
return limit !== undefined && cards.length > limit;
|
|
95
|
+
}
|
|
96
|
+
get shown(): CardPillItem[] {
|
|
97
|
+
let { cards, limit } = this.args;
|
|
98
|
+
return this.showAll || limit === undefined ? cards : cards.slice(0, limit);
|
|
99
|
+
}
|
|
100
|
+
get hidden(): number {
|
|
101
|
+
return this.args.cards.length - this.shown.length;
|
|
102
|
+
}
|
|
103
|
+
get selectedIds(): string[] {
|
|
104
|
+
return this.args.selected ?? this.innerSelected;
|
|
105
|
+
}
|
|
106
|
+
get pickedCards(): CardPillItem[] {
|
|
107
|
+
let ids = new Set(this.selectedIds);
|
|
108
|
+
return this.args.cards.filter((c) => ids.has(this.idOf(c)));
|
|
109
|
+
}
|
|
110
|
+
get pickedLabel(): string {
|
|
111
|
+
return `${this.selectedIds.length} picked`;
|
|
112
|
+
}
|
|
113
|
+
get hasPicks(): boolean {
|
|
114
|
+
return this.selectedIds.length > 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
idOf = (card: CardPillItem) => card.id ?? card.title;
|
|
118
|
+
initial = (card: CardPillItem) => card.title.trim()[0] ?? '?';
|
|
119
|
+
isOpen = (card: CardPillItem) =>
|
|
120
|
+
!this.args.selectable && this.args.open === this.idOf(card);
|
|
121
|
+
isPicked = (card: CardPillItem) => this.selectedIds.includes(this.idOf(card));
|
|
122
|
+
pressedOf = (card: CardPillItem) =>
|
|
123
|
+
this.args.selectable
|
|
124
|
+
? this.isPicked(card)
|
|
125
|
+
? 'true'
|
|
126
|
+
: 'false'
|
|
127
|
+
: this.isOpen(card)
|
|
128
|
+
? 'true'
|
|
129
|
+
: 'false';
|
|
130
|
+
tabIndexOf = (index: number) => (index === this.focusIndex ? '0' : '-1');
|
|
131
|
+
stateOf = (card: CardPillItem) =>
|
|
132
|
+
this.isPicked(card) ? 'picked' : this.isOpen(card) ? 'open' : undefined;
|
|
133
|
+
|
|
134
|
+
private setSelected(ids: string[]) {
|
|
135
|
+
this.innerSelected = ids;
|
|
136
|
+
this.args.onSelectionChange?.(ids);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
press = (card: CardPillItem, index: number) => {
|
|
140
|
+
this.focusIndex = index;
|
|
141
|
+
if (this.args.selectable) {
|
|
142
|
+
let id = this.idOf(card);
|
|
143
|
+
let ids = this.selectedIds;
|
|
144
|
+
this.setSelected(
|
|
145
|
+
ids.includes(id) ? ids.filter((x) => x !== id) : [...ids, id],
|
|
146
|
+
);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (this.isOpen(card)) {
|
|
150
|
+
this.args.onClose?.(card);
|
|
151
|
+
} else {
|
|
152
|
+
this.args.onOpen?.(card);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
isPeeking = (card: CardPillItem) =>
|
|
156
|
+
this.args.peek === true && this.peekId === this.idOf(card);
|
|
157
|
+
peekIdOf = (card: CardPillItem) =>
|
|
158
|
+
`${this.idOf(card)}-peek`.replace(/\s+/g, '-');
|
|
159
|
+
startPeek = (card: CardPillItem) => {
|
|
160
|
+
if (!this.args.peek || this.peekId === this.idOf(card)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
this.peekId = this.idOf(card);
|
|
164
|
+
this.args.onPeek?.(card);
|
|
165
|
+
};
|
|
166
|
+
endPeek = (card: CardPillItem, event?: Event) => {
|
|
167
|
+
let to = (event as FocusEvent | PointerEvent | undefined)?.relatedTarget as
|
|
168
|
+
| Node
|
|
169
|
+
| null
|
|
170
|
+
| undefined;
|
|
171
|
+
let li = (event?.currentTarget as HTMLElement | undefined) ?? undefined;
|
|
172
|
+
if (to && li?.contains(to)) {
|
|
173
|
+
return; // moving into the peek keeps it
|
|
174
|
+
}
|
|
175
|
+
if (this.peekId === this.idOf(card)) {
|
|
176
|
+
this.peekId = undefined;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
openFromPeek = (card: CardPillItem) => {
|
|
180
|
+
this.peekId = undefined;
|
|
181
|
+
this.args.onOpen?.(card);
|
|
182
|
+
};
|
|
183
|
+
expandFromPeek = (card: CardPillItem) => {
|
|
184
|
+
this.peekId = undefined;
|
|
185
|
+
this.args.onExpand?.(card);
|
|
186
|
+
};
|
|
187
|
+
get expandedCard(): CardPillItem | undefined {
|
|
188
|
+
return this.args.expanded
|
|
189
|
+
? this.args.cards.find((c) => this.idOf(c) === this.args.expanded)
|
|
190
|
+
: undefined;
|
|
191
|
+
}
|
|
192
|
+
collapse_ = () => {
|
|
193
|
+
let card = this.expandedCard;
|
|
194
|
+
if (card) {
|
|
195
|
+
this.args.onCollapse?.(card);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
clear = () => this.setSelected([]);
|
|
199
|
+
use = () => this.args.onUseSelection?.(this.pickedCards);
|
|
200
|
+
expand = () => (this.showAll = true);
|
|
201
|
+
collapse = () => {
|
|
202
|
+
this.showAll = false;
|
|
203
|
+
this.focusIndex = Math.min(this.focusIndex, (this.args.limit ?? 1) - 1);
|
|
204
|
+
};
|
|
205
|
+
/** one button folds and unfolds, so focus stays on it when its words
|
|
206
|
+
* change */
|
|
207
|
+
toggleAll = () => (this.showAll ? this.collapse() : this.expand());
|
|
208
|
+
|
|
209
|
+
private focusAt(index: number) {
|
|
210
|
+
let n = this.shown.length;
|
|
211
|
+
if (!n) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
this.focusIndex = Math.min(Math.max(index, 0), n - 1);
|
|
215
|
+
let buttons =
|
|
216
|
+
this.list?.querySelectorAll<HTMLButtonElement>('[data-card-pill]');
|
|
217
|
+
buttons?.[this.focusIndex]?.focus();
|
|
218
|
+
}
|
|
219
|
+
/** the grid's columns, for Up and Down */
|
|
220
|
+
private columns(): number {
|
|
221
|
+
let buttons = [
|
|
222
|
+
...(this.list?.querySelectorAll<HTMLElement>('[data-card-pill]') ?? []),
|
|
223
|
+
];
|
|
224
|
+
if (buttons.length < 2) {
|
|
225
|
+
return 1;
|
|
226
|
+
}
|
|
227
|
+
let top = buttons[0]!.getBoundingClientRect().top;
|
|
228
|
+
let perRow = buttons.findIndex(
|
|
229
|
+
(b) => b.getBoundingClientRect().top > top + 1,
|
|
230
|
+
);
|
|
231
|
+
return perRow > 0 ? perRow : buttons.length;
|
|
232
|
+
}
|
|
233
|
+
keydown = (e: Event) => {
|
|
234
|
+
let event = e as KeyboardEvent;
|
|
235
|
+
let i = this.focusIndex;
|
|
236
|
+
let cols = this.layout === 'grid' ? this.columns() : 1;
|
|
237
|
+
let next: number | undefined;
|
|
238
|
+
switch (event.key) {
|
|
239
|
+
case 'ArrowRight':
|
|
240
|
+
next = i + 1;
|
|
241
|
+
break;
|
|
242
|
+
case 'ArrowLeft':
|
|
243
|
+
next = i - 1;
|
|
244
|
+
break;
|
|
245
|
+
case 'ArrowDown':
|
|
246
|
+
next = i + cols;
|
|
247
|
+
break;
|
|
248
|
+
case 'ArrowUp':
|
|
249
|
+
next = i - cols;
|
|
250
|
+
break;
|
|
251
|
+
case 'Home':
|
|
252
|
+
next = 0;
|
|
253
|
+
break;
|
|
254
|
+
case 'End':
|
|
255
|
+
next = this.shown.length - 1;
|
|
256
|
+
break;
|
|
257
|
+
case 'Escape': {
|
|
258
|
+
// an Escape the set uses stops here, so a host's document-level
|
|
259
|
+
// Escape does not also close what holds it
|
|
260
|
+
if (this.peekId) {
|
|
261
|
+
event.preventDefault();
|
|
262
|
+
event.stopPropagation();
|
|
263
|
+
this.peekId = undefined;
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (this.args.selectable && this.hasPicks) {
|
|
267
|
+
event.preventDefault();
|
|
268
|
+
event.stopPropagation();
|
|
269
|
+
this.clear();
|
|
270
|
+
} else {
|
|
271
|
+
let open = this.args.cards.find((c) => this.isOpen(c));
|
|
272
|
+
if (open) {
|
|
273
|
+
event.preventDefault();
|
|
274
|
+
event.stopPropagation();
|
|
275
|
+
this.args.onClose?.(open);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
default:
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
event.preventDefault();
|
|
284
|
+
this.focusAt(next);
|
|
285
|
+
};
|
|
286
|
+
setupList = modifier((element: HTMLElement) => {
|
|
287
|
+
this.list = element;
|
|
288
|
+
return () => (this.list = undefined);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
<template>
|
|
292
|
+
<div
|
|
293
|
+
class='pretui-cardpills'
|
|
294
|
+
data-layout={{this.layout}}
|
|
295
|
+
data-selectable={{if @selectable 'true'}}
|
|
296
|
+
data-test-pretui-card-pills
|
|
297
|
+
...attributes
|
|
298
|
+
>
|
|
299
|
+
{{! the arrow keys move a roving focus through the set, handled on
|
|
300
|
+
the list that holds it }}
|
|
301
|
+
{{! template-lint-disable no-invalid-interactive }}
|
|
302
|
+
<ul
|
|
303
|
+
class='pretui-cardpills-list'
|
|
304
|
+
aria-label={{if @label @label 'Cards'}}
|
|
305
|
+
{{this.setupList}}
|
|
306
|
+
{{on 'keydown' this.keydown}}
|
|
307
|
+
>
|
|
308
|
+
{{#each this.shown as |card index|}}
|
|
309
|
+
{{! the item holds the pill and its peek, so moving the pointer or
|
|
310
|
+
focus from one to the other keeps the peek open }}
|
|
311
|
+
{{! template-lint-disable no-invalid-interactive no-positive-tabindex }}
|
|
312
|
+
<li
|
|
313
|
+
class='pretui-cardpill-item'
|
|
314
|
+
{{on 'pointerenter' (fn this.startPeek card)}}
|
|
315
|
+
{{on 'pointerleave' (fn this.endPeek card)}}
|
|
316
|
+
{{on 'focusin' (fn this.startPeek card)}}
|
|
317
|
+
{{on 'focusout' (fn this.endPeek card)}}
|
|
318
|
+
>
|
|
319
|
+
<button
|
|
320
|
+
type='button'
|
|
321
|
+
class='pretui-cardpill'
|
|
322
|
+
title={{if card.kind card.kind}}
|
|
323
|
+
{{! a roving tabindex: 0 for the set's one stop, -1 for the rest }}
|
|
324
|
+
tabindex={{this.tabIndexOf index}}
|
|
325
|
+
aria-pressed={{this.pressedOf card}}
|
|
326
|
+
aria-describedby={{if (this.isPeeking card) (this.peekIdOf card)}}
|
|
327
|
+
data-card-pill
|
|
328
|
+
data-state={{this.stateOf card}}
|
|
329
|
+
{{on 'click' (fn this.press card index)}}
|
|
330
|
+
data-test-pretui-card-pill={{card.title}}
|
|
331
|
+
>
|
|
332
|
+
<span
|
|
333
|
+
class='pretui-cardpill-mark'
|
|
334
|
+
aria-hidden='true'
|
|
335
|
+
>{{#if (this.isPicked card)}}<StateGlyph
|
|
336
|
+
@glyph='done'
|
|
337
|
+
@size={{10}}
|
|
338
|
+
/>{{else if card.image}}<img
|
|
339
|
+
class='pretui-cardpill-image'
|
|
340
|
+
src={{card.image}}
|
|
341
|
+
alt=''
|
|
342
|
+
data-test-pretui-card-pill-image
|
|
343
|
+
/>{{else}}{{this.initial card}}{{/if}}</span>
|
|
344
|
+
<span class='pretui-cardpill-text'>
|
|
345
|
+
<span class='pretui-cardpill-title'>{{card.title}}</span>
|
|
346
|
+
{{#if card.sub}}<span
|
|
347
|
+
class='pretui-cardpill-sub'
|
|
348
|
+
>{{card.sub}}</span>{{/if}}
|
|
349
|
+
</span>
|
|
350
|
+
{{#if (this.isOpen card)}}<span
|
|
351
|
+
class='pretui-cardpill-open'
|
|
352
|
+
data-test-pretui-card-pill-open
|
|
353
|
+
>open</span>{{/if}}
|
|
354
|
+
</button>
|
|
355
|
+
{{#if (this.isPeeking card)}}
|
|
356
|
+
<div
|
|
357
|
+
class='pretui-cardpill-peek'
|
|
358
|
+
id={{this.peekIdOf card}}
|
|
359
|
+
role='group'
|
|
360
|
+
aria-label={{card.title}}
|
|
361
|
+
data-test-pretui-card-pill-peek={{card.title}}
|
|
362
|
+
>
|
|
363
|
+
<div class='pretui-cardpill-peek-card'>{{yield
|
|
364
|
+
card
|
|
365
|
+
to='peek'
|
|
366
|
+
}}</div>
|
|
367
|
+
<div class='pretui-cardpill-peek-actions'>
|
|
368
|
+
{{#if @onOpen}}<button
|
|
369
|
+
type='button'
|
|
370
|
+
class='pretui-cardpills-act'
|
|
371
|
+
data-test-pretui-card-pill-peek-open
|
|
372
|
+
{{on 'click' (fn this.openFromPeek card)}}
|
|
373
|
+
>Open on stack</button>{{/if}}
|
|
374
|
+
{{#if @onExpand}}<button
|
|
375
|
+
type='button'
|
|
376
|
+
class='pretui-cardpills-act'
|
|
377
|
+
data-test-pretui-card-pill-peek-expand
|
|
378
|
+
{{on 'click' (fn this.expandFromPeek card)}}
|
|
379
|
+
>Show here</button>{{/if}}
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
{{/if}}
|
|
383
|
+
</li>
|
|
384
|
+
{{/each}}
|
|
385
|
+
</ul>
|
|
386
|
+
{{#if this.folds}}
|
|
387
|
+
<button
|
|
388
|
+
type='button'
|
|
389
|
+
class='pretui-cardpills-all'
|
|
390
|
+
aria-expanded={{if this.showAll 'true' 'false'}}
|
|
391
|
+
{{on 'click' this.toggleAll}}
|
|
392
|
+
data-test-pretui-card-pills-all
|
|
393
|
+
>{{#if this.showAll}}Show fewer{{else}}Show all
|
|
394
|
+
{{@cards.length}}{{/if}}</button>
|
|
395
|
+
{{/if}}
|
|
396
|
+
{{#if this.expandedCard}}
|
|
397
|
+
<div
|
|
398
|
+
class='pretui-cardpills-expanded'
|
|
399
|
+
data-test-pretui-card-pills-expanded={{this.expandedCard.title}}
|
|
400
|
+
>
|
|
401
|
+
<div class='pretui-cardpills-expanded-head'>
|
|
402
|
+
<span>{{this.expandedCard.title}}</span>
|
|
403
|
+
<button
|
|
404
|
+
type='button'
|
|
405
|
+
class='pretui-cardpills-act'
|
|
406
|
+
{{on 'click' this.collapse_}}
|
|
407
|
+
data-test-pretui-card-pills-collapse
|
|
408
|
+
>Hide</button>
|
|
409
|
+
</div>
|
|
410
|
+
{{yield this.expandedCard to='expanded'}}
|
|
411
|
+
</div>
|
|
412
|
+
{{/if}}
|
|
413
|
+
{{#if (if @selectable this.hasPicks)}}
|
|
414
|
+
<div class='pretui-cardpills-bar' data-test-pretui-card-pills-bar>
|
|
415
|
+
<span class='pretui-cardpills-count'>{{this.pickedLabel}}</span>
|
|
416
|
+
{{#if @onUseSelection}}
|
|
417
|
+
<button
|
|
418
|
+
type='button'
|
|
419
|
+
class='pretui-cardpills-act'
|
|
420
|
+
data-kind='primary'
|
|
421
|
+
{{on 'click' this.use}}
|
|
422
|
+
data-test-pretui-card-pills-use
|
|
423
|
+
>{{if @useLabel @useLabel 'Attach'}}</button>
|
|
424
|
+
{{/if}}
|
|
425
|
+
<button
|
|
426
|
+
type='button'
|
|
427
|
+
class='pretui-cardpills-act'
|
|
428
|
+
{{on 'click' this.clear}}
|
|
429
|
+
data-test-pretui-card-pills-clear
|
|
430
|
+
>Clear</button>
|
|
431
|
+
</div>
|
|
432
|
+
{{/if}}
|
|
433
|
+
{{! the count is announced from a region that is always there, apart
|
|
434
|
+
from the bar's buttons, so a change says the count and nothing else }}
|
|
435
|
+
<VisuallyHidden
|
|
436
|
+
role='status'
|
|
437
|
+
aria-atomic='true'
|
|
438
|
+
data-test-pretui-card-pills-status
|
|
439
|
+
>{{if (if @selectable this.hasPicks) this.pickedLabel}}</VisuallyHidden>
|
|
440
|
+
</div>
|
|
441
|
+
<style scoped>
|
|
442
|
+
@layer PretComponent {
|
|
443
|
+
.pretui-cardpills {
|
|
444
|
+
/* the peek's distance from its pill, which the bridge over it
|
|
445
|
+
must span */
|
|
446
|
+
--_cardpills-peek-gap: var(--boxel-sp-2xs);
|
|
447
|
+
display: grid;
|
|
448
|
+
gap: var(--boxel-sp-xs);
|
|
449
|
+
justify-items: start;
|
|
450
|
+
}
|
|
451
|
+
.pretui-cardpills-list {
|
|
452
|
+
display: flex;
|
|
453
|
+
flex-wrap: wrap;
|
|
454
|
+
gap: var(--boxel-sp-4xs);
|
|
455
|
+
margin: 0;
|
|
456
|
+
padding: 0;
|
|
457
|
+
list-style: none;
|
|
458
|
+
}
|
|
459
|
+
.pretui-cardpills[data-layout='grid'] {
|
|
460
|
+
justify-items: stretch;
|
|
461
|
+
}
|
|
462
|
+
.pretui-cardpills[data-layout='grid'] .pretui-cardpills-list {
|
|
463
|
+
display: grid;
|
|
464
|
+
grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
|
|
465
|
+
gap: var(--boxel-sp-xs);
|
|
466
|
+
}
|
|
467
|
+
/* a pill: an outlined token on the inset, the card's mark and its
|
|
468
|
+
title in ink-1. It is 1.5rem tall, the least a pointer target
|
|
469
|
+
takes */
|
|
470
|
+
.pretui-cardpill {
|
|
471
|
+
position: relative;
|
|
472
|
+
display: inline-flex;
|
|
473
|
+
align-items: center;
|
|
474
|
+
gap: var(--boxel-sp-4xs);
|
|
475
|
+
max-width: 100%;
|
|
476
|
+
height: 1.5rem;
|
|
477
|
+
padding: 0 var(--boxel-sp-2xs) 0 var(--boxel-sp-5xs);
|
|
478
|
+
border: 0;
|
|
479
|
+
border-radius: var(--boxel-border-radius-sm);
|
|
480
|
+
background-color: var(--inset);
|
|
481
|
+
box-shadow: inset 0 0 0 1px var(--border);
|
|
482
|
+
font-family: inherit;
|
|
483
|
+
font-size: var(--boxel-ui-label-font-size);
|
|
484
|
+
line-height: var(--boxel-ui-label-line-height);
|
|
485
|
+
font-weight: 600;
|
|
486
|
+
color: var(--foreground);
|
|
487
|
+
vertical-align: middle;
|
|
488
|
+
cursor: pointer;
|
|
489
|
+
transition:
|
|
490
|
+
background-color 120ms ease-out,
|
|
491
|
+
box-shadow 120ms ease-out;
|
|
492
|
+
}
|
|
493
|
+
.pretui-cardpill:hover {
|
|
494
|
+
background-color: var(--hover);
|
|
495
|
+
box-shadow: inset 0 0 0 1px var(--border-strong);
|
|
496
|
+
}
|
|
497
|
+
.pretui-cardpill:active {
|
|
498
|
+
transform: translateY(0.5px);
|
|
499
|
+
}
|
|
500
|
+
.pretui-cardpill:focus-visible {
|
|
501
|
+
outline: 2px solid var(--ring);
|
|
502
|
+
outline-offset: 1px;
|
|
503
|
+
}
|
|
504
|
+
/* open on the stack: the outline and the "open" word take the live
|
|
505
|
+
state, never the fill */
|
|
506
|
+
.pretui-cardpill[data-state='open'] {
|
|
507
|
+
box-shadow: inset 0 0 0 1px var(--primary-ink);
|
|
508
|
+
}
|
|
509
|
+
/* picked: done is ink with a check, the outline in ink-1 */
|
|
510
|
+
.pretui-cardpill[data-state='picked'] {
|
|
511
|
+
box-shadow: inset 0 0 0 1px var(--foreground);
|
|
512
|
+
}
|
|
513
|
+
.pretui-cardpill[data-state='picked'] .pretui-cardpill-mark {
|
|
514
|
+
background-color: var(--foreground);
|
|
515
|
+
color: var(--background);
|
|
516
|
+
}
|
|
517
|
+
.pretui-cardpill-mark {
|
|
518
|
+
flex: none;
|
|
519
|
+
display: grid;
|
|
520
|
+
place-items: center;
|
|
521
|
+
width: 0.875rem;
|
|
522
|
+
height: 0.875rem;
|
|
523
|
+
overflow: hidden;
|
|
524
|
+
border-radius: 50%;
|
|
525
|
+
background-color: var(--card);
|
|
526
|
+
font-size: var(--boxel-caption-font-size);
|
|
527
|
+
line-height: 1;
|
|
528
|
+
font-weight: 600;
|
|
529
|
+
color: var(--muted-foreground);
|
|
530
|
+
}
|
|
531
|
+
.pretui-cardpill-image {
|
|
532
|
+
width: 100%;
|
|
533
|
+
height: 100%;
|
|
534
|
+
object-fit: cover;
|
|
535
|
+
}
|
|
536
|
+
.pretui-cardpill-text {
|
|
537
|
+
display: grid;
|
|
538
|
+
min-width: 0;
|
|
539
|
+
text-align: start;
|
|
540
|
+
}
|
|
541
|
+
.pretui-cardpill-title,
|
|
542
|
+
.pretui-cardpill-sub {
|
|
543
|
+
overflow: hidden;
|
|
544
|
+
text-overflow: ellipsis;
|
|
545
|
+
white-space: nowrap;
|
|
546
|
+
}
|
|
547
|
+
.pretui-cardpill-sub {
|
|
548
|
+
display: none;
|
|
549
|
+
}
|
|
550
|
+
.pretui-cardpill-open {
|
|
551
|
+
margin-inline-start: var(--boxel-sp-6xs);
|
|
552
|
+
font-size: var(--boxel-caption-font-size);
|
|
553
|
+
line-height: var(--boxel-caption-line-height);
|
|
554
|
+
font-weight: 400;
|
|
555
|
+
color: var(--primary-ink);
|
|
556
|
+
}
|
|
557
|
+
/* the grid: a tile per card, the mark larger, the type under it */
|
|
558
|
+
.pretui-cardpills[data-layout='grid'] .pretui-cardpill {
|
|
559
|
+
width: 100%;
|
|
560
|
+
height: auto;
|
|
561
|
+
gap: var(--boxel-sp-xs);
|
|
562
|
+
padding: var(--boxel-sp-2xs) var(--boxel-sp-xs) var(--boxel-sp-2xs)
|
|
563
|
+
var(--boxel-sp-2xs);
|
|
564
|
+
border-radius: var(--boxel-border-radius-sm);
|
|
565
|
+
}
|
|
566
|
+
.pretui-cardpills[data-layout='grid'] .pretui-cardpill-mark {
|
|
567
|
+
width: 1.625rem;
|
|
568
|
+
height: 1.625rem;
|
|
569
|
+
}
|
|
570
|
+
.pretui-cardpills[data-layout='grid'] .pretui-cardpill-sub {
|
|
571
|
+
display: block;
|
|
572
|
+
font-size: var(--boxel-caption-font-size);
|
|
573
|
+
line-height: var(--boxel-caption-line-height);
|
|
574
|
+
font-weight: 400;
|
|
575
|
+
color: var(--muted-foreground);
|
|
576
|
+
}
|
|
577
|
+
.pretui-cardpills[data-layout='grid'] .pretui-cardpill-open {
|
|
578
|
+
position: absolute;
|
|
579
|
+
inset-block-start: var(--boxel-sp-4xs);
|
|
580
|
+
inset-inline-end: var(--boxel-sp-2xs);
|
|
581
|
+
}
|
|
582
|
+
.pretui-cardpills-all {
|
|
583
|
+
min-height: 1.5rem;
|
|
584
|
+
padding: 0 var(--boxel-sp-4xs);
|
|
585
|
+
border: 0;
|
|
586
|
+
border-radius: var(--boxel-border-radius-xs);
|
|
587
|
+
background-color: transparent;
|
|
588
|
+
font-family: inherit;
|
|
589
|
+
font-size: var(--boxel-ui-label-font-size);
|
|
590
|
+
line-height: var(--boxel-ui-label-line-height);
|
|
591
|
+
font-weight: 400;
|
|
592
|
+
font-variant-numeric: tabular-nums;
|
|
593
|
+
color: var(--muted-foreground);
|
|
594
|
+
cursor: pointer;
|
|
595
|
+
}
|
|
596
|
+
.pretui-cardpills-all:hover {
|
|
597
|
+
color: var(--foreground);
|
|
598
|
+
}
|
|
599
|
+
.pretui-cardpills-all:focus-visible,
|
|
600
|
+
.pretui-cardpills-act:focus-visible {
|
|
601
|
+
outline: 2px solid var(--ring);
|
|
602
|
+
outline-offset: 1px;
|
|
603
|
+
}
|
|
604
|
+
/* the peek: a hover card under the pill with the fitted card. It
|
|
605
|
+
fades in after a beat (a CSS delay, no clock), so a pointer
|
|
606
|
+
passing over pills does not flash them */
|
|
607
|
+
.pretui-cardpill-item {
|
|
608
|
+
position: relative;
|
|
609
|
+
}
|
|
610
|
+
.pretui-cardpill-peek {
|
|
611
|
+
position: absolute;
|
|
612
|
+
inset-block-start: calc(100% + var(--_cardpills-peek-gap));
|
|
613
|
+
inset-inline-start: 0;
|
|
614
|
+
z-index: var(--pretui-z-popover, 30);
|
|
615
|
+
display: grid;
|
|
616
|
+
gap: var(--boxel-sp-xs);
|
|
617
|
+
width: 15rem;
|
|
618
|
+
padding: var(--boxel-sp-xs);
|
|
619
|
+
border-radius: var(--boxel-border-radius-lg);
|
|
620
|
+
background-color: var(--popover);
|
|
621
|
+
color: var(--popover-foreground);
|
|
622
|
+
box-shadow:
|
|
623
|
+
0 0 0 1px var(--border),
|
|
624
|
+
var(--shadow-md);
|
|
625
|
+
animation: pretui-peek-in 160ms ease-out 280ms both;
|
|
626
|
+
}
|
|
627
|
+
/* a bridge over the gap, so moving from the pill into the peek
|
|
628
|
+
never leaves the item */
|
|
629
|
+
.pretui-cardpill-peek::before {
|
|
630
|
+
content: '';
|
|
631
|
+
position: absolute;
|
|
632
|
+
inset-inline: 0;
|
|
633
|
+
inset-block-start: calc(-1 * var(--_cardpills-peek-gap));
|
|
634
|
+
height: var(--_cardpills-peek-gap);
|
|
635
|
+
}
|
|
636
|
+
@keyframes pretui-peek-in {
|
|
637
|
+
from {
|
|
638
|
+
opacity: 0;
|
|
639
|
+
transform: translateY(-0.125rem);
|
|
640
|
+
}
|
|
641
|
+
to {
|
|
642
|
+
opacity: 1;
|
|
643
|
+
transform: none;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
.pretui-cardpill-peek-card {
|
|
647
|
+
display: grid;
|
|
648
|
+
min-height: 4rem;
|
|
649
|
+
overflow: hidden;
|
|
650
|
+
border-radius: var(--boxel-border-radius-sm);
|
|
651
|
+
}
|
|
652
|
+
.pretui-cardpill-peek-actions {
|
|
653
|
+
display: flex;
|
|
654
|
+
gap: var(--boxel-sp-4xs);
|
|
655
|
+
justify-content: flex-end;
|
|
656
|
+
}
|
|
657
|
+
/* the card shown in place, embedded, under the set */
|
|
658
|
+
.pretui-cardpills-expanded {
|
|
659
|
+
display: grid;
|
|
660
|
+
gap: var(--boxel-sp-xs);
|
|
661
|
+
justify-self: stretch;
|
|
662
|
+
}
|
|
663
|
+
.pretui-cardpills-expanded-head {
|
|
664
|
+
display: flex;
|
|
665
|
+
align-items: center;
|
|
666
|
+
justify-content: space-between;
|
|
667
|
+
font-size: var(--boxel-ui-label-font-size);
|
|
668
|
+
line-height: var(--boxel-ui-label-line-height);
|
|
669
|
+
font-weight: 600;
|
|
670
|
+
color: var(--foreground);
|
|
671
|
+
}
|
|
672
|
+
@media (prefers-reduced-motion: reduce) {
|
|
673
|
+
.pretui-cardpill-peek {
|
|
674
|
+
animation: none;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
/* what to do with the picked cards, under the set */
|
|
678
|
+
.pretui-cardpills-bar {
|
|
679
|
+
display: flex;
|
|
680
|
+
align-items: center;
|
|
681
|
+
gap: var(--boxel-sp-xs);
|
|
682
|
+
justify-self: stretch;
|
|
683
|
+
padding: var(--boxel-sp-6xs) var(--boxel-sp-6xs) var(--boxel-sp-6xs)
|
|
684
|
+
var(--boxel-sp-sm);
|
|
685
|
+
border-radius: var(--boxel-border-radius-sm);
|
|
686
|
+
background-color: var(--inset);
|
|
687
|
+
color: var(--foreground);
|
|
688
|
+
box-shadow: inset 0 0 0 1px var(--border);
|
|
689
|
+
font-size: var(--boxel-ui-label-font-size);
|
|
690
|
+
line-height: var(--boxel-ui-label-line-height);
|
|
691
|
+
}
|
|
692
|
+
.pretui-cardpills-count {
|
|
693
|
+
margin-inline-end: auto;
|
|
694
|
+
font-weight: 600;
|
|
695
|
+
font-variant-numeric: tabular-nums;
|
|
696
|
+
}
|
|
697
|
+
.pretui-cardpills-act {
|
|
698
|
+
height: 1.75rem;
|
|
699
|
+
padding: 0 var(--boxel-sp-sm);
|
|
700
|
+
border: 0;
|
|
701
|
+
border-radius: var(--boxel-border-radius-sm);
|
|
702
|
+
background-color: transparent;
|
|
703
|
+
font-family: inherit;
|
|
704
|
+
font-size: inherit;
|
|
705
|
+
font-weight: 600;
|
|
706
|
+
color: var(--muted-foreground);
|
|
707
|
+
cursor: pointer;
|
|
708
|
+
}
|
|
709
|
+
/* the bar's verb is the moment's one action */
|
|
710
|
+
.pretui-cardpills-act[data-kind='primary'] {
|
|
711
|
+
background-color: var(--primary);
|
|
712
|
+
color: var(--primary-foreground);
|
|
713
|
+
}
|
|
714
|
+
.pretui-cardpills-act:not([data-kind='primary']):hover {
|
|
715
|
+
color: var(--foreground);
|
|
716
|
+
}
|
|
717
|
+
@media (prefers-reduced-motion: reduce) {
|
|
718
|
+
.pretui-cardpill {
|
|
719
|
+
transition: none;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
</style>
|
|
724
|
+
</template>
|
|
725
|
+
}
|