@artooi/ag-ui-web-component 0.48.0 → 0.49.0

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.
@@ -39,10 +39,18 @@ export interface Surface {
39
39
  readonly collapseTo: CollapseTarget;
40
40
  /**
41
41
  * Whether a gesture may move the launcher. The rest have nowhere to put it:
42
- * the rail is a docked edge, `header` and `null` have no launcher, and a
43
- * full-bleed panel covers the screen it would be opening into.
42
+ * the rail is a docked edge, `header` and `null` have no launcher, a
43
+ * full-bleed panel covers the screen it would be opening into, and the bar
44
+ * and the host's own control are not a launcher at all.
44
45
  */
45
46
  readonly launcherDraggable: boolean;
47
+ /**
48
+ * Whether the header drag and `moveTo` may move the open panel. The same
49
+ * answer as {@link launcherDraggable} for every placement on its own; the two
50
+ * part under `collapse-to="bar"` and `"none"`, where a corner panel still
51
+ * moves like one but has no launcher left to drag.
52
+ */
53
+ readonly panelMovable: boolean;
46
54
  /**
47
55
  * Which axes the resize grips may change. A full-bleed layout is the whole
48
56
  * viewport by definition and cannot be resized; a docked panel owns its
@@ -67,6 +75,7 @@ export interface Surface {
67
75
  const CORNER: Surface = {
68
76
  collapseTo: "launcher",
69
77
  launcherDraggable: true,
78
+ panelMovable: true,
70
79
  resizeAxis: "both",
71
80
  startsCollapsed: true,
72
81
  };
@@ -74,6 +83,7 @@ const CORNER: Surface = {
74
83
  const DOCKED: Surface = {
75
84
  collapseTo: "launcher",
76
85
  launcherDraggable: false,
86
+ panelMovable: false,
77
87
  resizeAxis: "width",
78
88
  startsCollapsed: false,
79
89
  };
@@ -94,17 +104,30 @@ const SURFACES: ReadonlyMap<string | null, Surface> = new Map<string | null, Sur
94
104
  {
95
105
  collapseTo: "launcher",
96
106
  launcherDraggable: false,
107
+ panelMovable: false,
97
108
  resizeAxis: "none",
98
109
  startsCollapsed: false,
99
110
  },
100
111
  ],
101
112
  [
102
113
  "page",
103
- { collapseTo: null, launcherDraggable: false, resizeAxis: "none", startsCollapsed: false },
114
+ {
115
+ collapseTo: null,
116
+ launcherDraggable: false,
117
+ panelMovable: false,
118
+ resizeAxis: "none",
119
+ startsCollapsed: false,
120
+ },
104
121
  ],
105
122
  [
106
123
  "embedded",
107
- { collapseTo: "header", launcherDraggable: false, resizeAxis: "both", startsCollapsed: false },
124
+ {
125
+ collapseTo: "header",
126
+ launcherDraggable: false,
127
+ panelMovable: false,
128
+ resizeAxis: "both",
129
+ startsCollapsed: false,
130
+ },
108
131
  ],
109
132
  ]);
110
133
 
@@ -117,6 +140,7 @@ const SURFACES: ReadonlyMap<string | null, Surface> = new Map<string | null, Sur
117
140
  const UNKNOWN: Surface = {
118
141
  collapseTo: "launcher",
119
142
  launcherDraggable: false,
143
+ panelMovable: false,
120
144
  resizeAxis: "both",
121
145
  startsCollapsed: false,
122
146
  };
@@ -129,10 +153,11 @@ const UNKNOWN: Surface = {
129
153
  * state, never a placement's own shape: `bar` applies where the placement
130
154
  * collapses to `launcher`, so the sidebar keeps its rail and an embedded chat
131
155
  * its header bar, and `none` applies to every collapsible placement. Absent,
132
- * `auto` and any other value leave the placement as it was. A docked surface
133
- * cannot be moved -- the panel rises from the bar or the host's anchor, and a
134
- * position the user dragged would take it away from either -- so both turn
135
- * the launcher drag off, and with it the header drag and `moveTo`.
156
+ * `auto` and any other value leave the placement as it was. Both turn the
157
+ * launcher drag off, because there is no launcher left to drag, and keep the
158
+ * placement's own answer for moving the panel: a corner panel rises from the
159
+ * bar or the anchor until the user drags it somewhere else, and a placement
160
+ * that owns its position keeps owning it.
136
161
  */
137
162
  export function surfaceFor(placement: string | null, collapseTo: string | null = null): Surface {
138
163
  const surface = SURFACES.get(placement) ?? UNKNOWN;
@@ -173,7 +173,8 @@ ${GROUPED} .tool-group[data-open="false"] .tool-group-list {
173
173
 
174
174
  /* A card inside the group is one line of the list: icon, name, and its
175
175
  Details control at the end, with the arguments and result opening under
176
- the whole row. */
176
+ the whole row. Its ink is the second ink in every theme, unless the host
177
+ set the tool token, which then reaches the grouped calls too. */
177
178
  ${GROUPED} .tool-group .tool-call {
178
179
  max-width: 100%;
179
180
  align-self: stretch;
@@ -184,7 +185,7 @@ ${GROUPED} .tool-group .tool-call {
184
185
  border: 0;
185
186
  border-radius: 0;
186
187
  background: transparent;
187
- color: var(--_ink-2);
188
+ color: var(--_tool-fg-set, var(--_ink-2));
188
189
  font-family: inherit;
189
190
  font-size: var(--_text-sm);
190
191
  }
@@ -58,6 +58,23 @@ export const TOKEN_STYLES: string = `
58
58
  --_tool-fg: var(--ag-ui-tool-fg, var(--_ink-2));
59
59
  --_header-bg: var(--ag-ui-header-bg, var(--_bg));
60
60
  --_header-fg: var(--ag-ui-header-fg, var(--_fg));
61
+ /* Switches: a public token read with no fallback, named for it with -set.
62
+ With the token unset the switch computes to the guaranteed-invalid value,
63
+ so a rule that reads it with a fallback gets the fallback; that is how a
64
+ rule tells a token the host set from the theme's default for it. The
65
+ default theme's header buttons follow the header text only once a host
66
+ sets it, and a step group's calls follow the tool token only once a host
67
+ sets it (classic defaults --_tool-fg to the accent, which a group never
68
+ drew). */
69
+ --_header-fg-set: var(--ag-ui-header-fg);
70
+ --_tool-fg-set: var(--ag-ui-tool-fg);
71
+ /* The header buttons' hover square, by default, once the header text is
72
+ set. Here it is the text at about a fifth, which every browser can mix;
73
+ where relative colour syntax is supported (see the block at the end) it
74
+ is the text's opposite instead. It reads the switch, so it is unset with
75
+ it, and the square below falls to the panel's hover shade. */
76
+ --_header-btn-hover-auto: color-mix(in srgb, var(--_header-fg-set) 18%, transparent);
77
+ --_header-btn-hover: var(--ag-ui-header-btn-hover, var(--_header-btn-hover-auto, var(--_hover)));
61
78
  --_border: var(--ag-ui-border, var(--_line));
62
79
  --_radius: var(--ag-ui-radius, 12px);
63
80
  /* The panel's own frame, which is the one corner a placement can put against
@@ -430,4 +447,17 @@ export const TOKEN_STYLES: string = `
430
447
  --_on-accent: var(--ag-ui-on-accent, #ffffff);
431
448
  }
432
449
  }
450
+
451
+ /* The header buttons' default hover square as the header text's opposite,
452
+ so white text gets a darker square and dark text a lighter one. A square
453
+ mixed from the text itself moves the ground toward the glyph: white on a
454
+ mid-blue header fell from 5.1:1 to 3.75:1 under the pointer. Moving away
455
+ from it can only raise what the host's own pair reads. Gated on this
456
+ exact expression, so a browser that cannot compute it keeps the square
457
+ mixed from the text rather than losing the square altogether. */
458
+ @supports (color: rgb(from red calc(255 - r) calc(255 - g) calc(255 - b))) {
459
+ :host {
460
+ --_header-btn-hover-auto: color-mix(in srgb, rgb(from var(--_header-fg-set) calc(255 - r) calc(255 - g) calc(255 - b)) 18%, transparent);
461
+ }
462
+ }
433
463
  `;
@@ -24,14 +24,30 @@ ${THEME_HOST.quiet} .header-title {
24
24
  letter-spacing: -0.01em;
25
25
  }
26
26
 
27
+ /* The buttons sit back in the third ink on the panel. Once the host sets the
28
+ header text they draw in it instead, since the header behind them is then
29
+ the host's colour (see the switches in the token defaults). So does their
30
+ rest opacity: the frame's 0.85 lets the header through the glyph, which
31
+ took white on a mid-blue header from 5.1:1 to 4.2:1. With the header text
32
+ set, the opacity below reads a colour, which no opacity can be, so it is
33
+ invalid at computed-value time and falls to the initial 1; unset, it reads
34
+ the fallback, the frame's own 0.85. */
27
35
  ${THEME_HOST.quiet} .header-btn {
28
- color: var(--_ink-3);
36
+ color: var(--_header-fg-set, var(--_ink-3));
37
+ opacity: var(--_header-fg-set, 0.85);
29
38
  border-radius: 8px;
30
39
  }
31
40
 
41
+ /* The hover square is the host's own when it set one; otherwise it is mixed
42
+ from the header text when the host set that, so it reads on any header the
43
+ host painted; otherwise it is the panel shade.
44
+ The glyph takes the header text, which is the full ink when that is unset.
45
+ The opacity restates the frame's hover value, which the rest rule above
46
+ outweighs. */
32
47
  ${THEME_HOST.quiet} .header-btn:hover {
33
- color: var(--_fg);
34
- background: var(--_hover);
48
+ color: var(--_header-fg);
49
+ opacity: 1;
50
+ background: var(--_header-btn-hover);
35
51
  }
36
52
 
37
53
  ${THEME_HOST.quiet} .message--user {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION: string = "0.48.0";
1
+ export const VERSION: string = "0.49.0";