@threadplane/chat 0.0.57 → 0.0.59
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/README.md +5 -5
- package/fesm2022/threadplane-chat.mjs +1004 -663
- package/fesm2022/threadplane-chat.mjs.map +1 -1
- package/package.json +1 -1
- package/types/threadplane-chat.d.ts +243 -153
|
@@ -10,8 +10,8 @@ import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
|
10
10
|
import { Router, NavigationEnd } from '@angular/router';
|
|
11
11
|
import { filter, map, startWith } from 'rxjs/operators';
|
|
12
12
|
import { toJSONSchema } from 'zod/v4';
|
|
13
|
-
import { resolveDynamic, getByPointer,
|
|
14
|
-
export {
|
|
13
|
+
import { createA2uiFunctionRegistry, isPathRef, resolveDynamic, getByPointer, isFunctionCall, A2UI_WIRE_VERSION, deleteByPointer, setByPointer, createA2uiMessageParser, A2UI_BASIC_CATALOG_ID } from '@threadplane/a2ui';
|
|
14
|
+
export { A2UI_BASIC_CATALOG_ID, A2UI_MIME_TYPE, A2UI_WIRE_VERSION, isFunctionCall, isPathRef } from '@threadplane/a2ui';
|
|
15
15
|
import { materialize as materialize$1, createPartialJsonParser } from '@cacheplane/partial-json';
|
|
16
16
|
import { fromEvent, EMPTY } from 'rxjs';
|
|
17
17
|
|
|
@@ -9106,23 +9106,49 @@ function createClientToolsCoordinator(registry, options = {}) {
|
|
|
9106
9106
|
};
|
|
9107
9107
|
}
|
|
9108
9108
|
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
return { type, props: (props ?? {}) };
|
|
9118
|
-
}
|
|
9109
|
+
/** Shared standard-function registry (formatString, formatters, logic). */
|
|
9110
|
+
const A2UI_FUNCTIONS = createA2uiFunctionRegistry();
|
|
9111
|
+
/** Keys that are protocol structure (base fields + child/action wiring),
|
|
9112
|
+
* not renderable props. */
|
|
9113
|
+
const RESERVED_PROP_KEYS = new Set([
|
|
9114
|
+
'id', 'component', 'catalogId', 'weight', 'accessibility', 'checks',
|
|
9115
|
+
'child', 'children', 'action', 'tabs', 'trigger', 'content',
|
|
9116
|
+
]);
|
|
9119
9117
|
function resolveAction(action, surface, sourceComponentId) {
|
|
9120
|
-
if (!action)
|
|
9118
|
+
if (!action || typeof action !== 'object')
|
|
9119
|
+
return undefined;
|
|
9120
|
+
if (!('event' in action)) {
|
|
9121
|
+
// Local client-side function action — routed to the surface component's
|
|
9122
|
+
// built-in `a2ui:localAction` handler (openUrl et al.).
|
|
9123
|
+
if ('functionCall' in action && action.functionCall
|
|
9124
|
+
&& typeof action.functionCall.call === 'string') {
|
|
9125
|
+
return {
|
|
9126
|
+
click: {
|
|
9127
|
+
action: 'a2ui:localAction',
|
|
9128
|
+
params: {
|
|
9129
|
+
call: action.functionCall.call,
|
|
9130
|
+
args: action.functionCall.args ?? {},
|
|
9131
|
+
},
|
|
9132
|
+
},
|
|
9133
|
+
};
|
|
9134
|
+
}
|
|
9135
|
+
return undefined;
|
|
9136
|
+
}
|
|
9137
|
+
const event = action.event;
|
|
9138
|
+
if (!event || typeof event.name !== 'string')
|
|
9121
9139
|
return undefined;
|
|
9122
9140
|
const resolvedContext = {};
|
|
9123
|
-
if (
|
|
9124
|
-
for (const
|
|
9125
|
-
|
|
9141
|
+
if (event.context && typeof event.context === 'object') {
|
|
9142
|
+
for (const [key, value] of Object.entries(event.context)) {
|
|
9143
|
+
if (isPathRef(value)) {
|
|
9144
|
+
// Live marker: the surface component substitutes the CURRENT value
|
|
9145
|
+
// (user edits included) from its state store at dispatch time —
|
|
9146
|
+
// build-time resolution would freeze the agent-seeded snapshot.
|
|
9147
|
+
resolvedContext[key] = { $bindState: value.path };
|
|
9148
|
+
}
|
|
9149
|
+
else {
|
|
9150
|
+
resolvedContext[key] = resolveDynamic(value, surface.dataModel, undefined, A2UI_FUNCTIONS);
|
|
9151
|
+
}
|
|
9126
9152
|
}
|
|
9127
9153
|
}
|
|
9128
9154
|
return {
|
|
@@ -9131,7 +9157,7 @@ function resolveAction(action, surface, sourceComponentId) {
|
|
|
9131
9157
|
params: {
|
|
9132
9158
|
surfaceId: surface.surfaceId,
|
|
9133
9159
|
sourceComponentId,
|
|
9134
|
-
name:
|
|
9160
|
+
name: event.name,
|
|
9135
9161
|
context: resolvedContext,
|
|
9136
9162
|
},
|
|
9137
9163
|
},
|
|
@@ -9140,16 +9166,15 @@ function resolveAction(action, surface, sourceComponentId) {
|
|
|
9140
9166
|
function childrenToList(children, surface) {
|
|
9141
9167
|
if (!children)
|
|
9142
9168
|
return undefined;
|
|
9143
|
-
if (
|
|
9144
|
-
return { ids: children
|
|
9169
|
+
if (Array.isArray(children)) {
|
|
9170
|
+
return { ids: children };
|
|
9145
9171
|
}
|
|
9146
|
-
if ('
|
|
9147
|
-
const
|
|
9148
|
-
const arr = getByPointer(surface.dataModel, t.dataBinding);
|
|
9172
|
+
if (typeof children === 'object' && 'componentId' in children && 'path' in children) {
|
|
9173
|
+
const arr = getByPointer(surface.dataModel, children.path);
|
|
9149
9174
|
if (!Array.isArray(arr))
|
|
9150
9175
|
return { ids: [] };
|
|
9151
|
-
const ids = arr.map((_, i) => `${
|
|
9152
|
-
return { ids, templateExpand: { componentId:
|
|
9176
|
+
const ids = arr.map((_, i) => `${children.componentId}__${i}`);
|
|
9177
|
+
return { ids, templateExpand: { componentId: children.componentId, arrPath: children.path, arr } };
|
|
9153
9178
|
}
|
|
9154
9179
|
return undefined;
|
|
9155
9180
|
}
|
|
@@ -9158,7 +9183,8 @@ function surfaceToSpec(surface) {
|
|
|
9158
9183
|
return null;
|
|
9159
9184
|
const elements = {};
|
|
9160
9185
|
for (const [id, comp] of surface.components) {
|
|
9161
|
-
const
|
|
9186
|
+
const type = typeof comp.component === 'string' ? comp.component : 'Text';
|
|
9187
|
+
const rawProps = comp;
|
|
9162
9188
|
const resolvedProps = {};
|
|
9163
9189
|
const bindings = {};
|
|
9164
9190
|
for (const [key, value] of Object.entries(rawProps)) {
|
|
@@ -9177,62 +9203,73 @@ function surfaceToSpec(surface) {
|
|
|
9177
9203
|
bindings[key] = path;
|
|
9178
9204
|
resolvedProps[key] = { $bindState: path };
|
|
9179
9205
|
}
|
|
9206
|
+
else if (isFunctionCall(value)) {
|
|
9207
|
+
const resolved = resolveDynamic(value, surface.dataModel, undefined, A2UI_FUNCTIONS);
|
|
9208
|
+
if (resolved !== undefined)
|
|
9209
|
+
resolvedProps[key] = resolved;
|
|
9210
|
+
}
|
|
9180
9211
|
else {
|
|
9181
|
-
resolvedProps[key] = resolveDynamic(value, surface.dataModel);
|
|
9212
|
+
resolvedProps[key] = resolveDynamic(value, surface.dataModel, undefined, A2UI_FUNCTIONS);
|
|
9182
9213
|
}
|
|
9183
9214
|
}
|
|
9184
9215
|
if (Object.keys(bindings).length > 0) {
|
|
9185
9216
|
resolvedProps['_bindings'] = bindings;
|
|
9186
9217
|
}
|
|
9218
|
+
// Checkable components surface their live validation message through a
|
|
9219
|
+
// reserved store path the surface component writes on failed submits.
|
|
9220
|
+
if (componentHasChecks(rawProps)) {
|
|
9221
|
+
resolvedProps['errorText'] = { $bindState: `/_a2uiChecks/${id}` };
|
|
9222
|
+
}
|
|
9187
9223
|
const action = rawProps.action;
|
|
9188
9224
|
const on = resolveAction(action, surface, id);
|
|
9189
|
-
// Map children —
|
|
9225
|
+
// Map children — Card/Button single child, Modal trigger+content, Tabs tabs[].
|
|
9190
9226
|
let children;
|
|
9191
|
-
if (type === 'Card' && typeof rawProps
|
|
9192
|
-
children = [rawProps
|
|
9193
|
-
}
|
|
9194
|
-
else if (type === 'Button' && typeof rawProps.child === 'string') {
|
|
9195
|
-
children = [rawProps.child];
|
|
9227
|
+
if ((type === 'Card' || type === 'Button') && typeof rawProps['child'] === 'string') {
|
|
9228
|
+
children = [rawProps['child']];
|
|
9196
9229
|
}
|
|
9197
9230
|
else if (type === 'Modal') {
|
|
9198
|
-
const m = rawProps;
|
|
9199
9231
|
const ids = [];
|
|
9200
|
-
if (
|
|
9201
|
-
ids.push(
|
|
9202
|
-
if (
|
|
9203
|
-
ids.push(
|
|
9232
|
+
if (typeof rawProps['trigger'] === 'string')
|
|
9233
|
+
ids.push(rawProps['trigger']);
|
|
9234
|
+
if (typeof rawProps['content'] === 'string')
|
|
9235
|
+
ids.push(rawProps['content']);
|
|
9204
9236
|
children = ids;
|
|
9205
9237
|
}
|
|
9206
9238
|
else if (type === 'Tabs') {
|
|
9207
|
-
const items = rawProps.
|
|
9239
|
+
const items = rawProps.tabs ?? [];
|
|
9208
9240
|
children = items.map(t => t.child);
|
|
9209
9241
|
// Resolve tab titles and pass them as a plain string array for the Tabs component's tab bar.
|
|
9210
|
-
resolvedProps['tabTitles'] = items.map(t => t.title !== undefined
|
|
9242
|
+
resolvedProps['tabTitles'] = items.map(t => t.title !== undefined
|
|
9243
|
+
? String(resolveDynamic(t.title, surface.dataModel, undefined, A2UI_FUNCTIONS))
|
|
9244
|
+
: '');
|
|
9211
9245
|
}
|
|
9212
|
-
else if (type === '
|
|
9246
|
+
else if (type === 'ChoicePicker') {
|
|
9213
9247
|
// Resolve options[*].label (DynamicString) so the component receives plain strings.
|
|
9214
9248
|
const opts = rawProps.options ?? [];
|
|
9215
9249
|
resolvedProps['options'] = opts.map(o => ({
|
|
9216
|
-
label: o.label !== undefined
|
|
9250
|
+
label: o.label !== undefined
|
|
9251
|
+
? String(resolveDynamic(o.label, surface.dataModel, undefined, A2UI_FUNCTIONS))
|
|
9252
|
+
: '',
|
|
9217
9253
|
value: o.value,
|
|
9218
9254
|
}));
|
|
9219
9255
|
}
|
|
9220
9256
|
else {
|
|
9221
|
-
const childInfo = childrenToList(rawProps
|
|
9257
|
+
const childInfo = childrenToList(rawProps['children'], surface);
|
|
9222
9258
|
if (childInfo) {
|
|
9223
9259
|
children = childInfo.ids;
|
|
9224
9260
|
if (childInfo.templateExpand) {
|
|
9225
9261
|
const t = childInfo.templateExpand;
|
|
9226
9262
|
const templateComp = surface.components.get(t.componentId);
|
|
9227
9263
|
if (templateComp) {
|
|
9228
|
-
const
|
|
9264
|
+
const tType = typeof templateComp.component === 'string' ? templateComp.component : 'Text';
|
|
9265
|
+
const tRaw = templateComp;
|
|
9229
9266
|
for (let i = 0; i < t.arr.length; i++) {
|
|
9230
9267
|
const scope = { basePath: `${t.arrPath}/${i}`, item: t.arr[i] };
|
|
9231
9268
|
const itemProps = {};
|
|
9232
9269
|
for (const [k, v] of Object.entries(tRaw)) {
|
|
9233
9270
|
if (RESERVED_PROP_KEYS.has(k))
|
|
9234
9271
|
continue;
|
|
9235
|
-
itemProps[k] = resolveDynamic(v, surface.dataModel, scope);
|
|
9272
|
+
itemProps[k] = resolveDynamic(v, surface.dataModel, scope, A2UI_FUNCTIONS);
|
|
9236
9273
|
}
|
|
9237
9274
|
elements[`${t.componentId}__${i}`] = { type: tType, props: itemProps };
|
|
9238
9275
|
}
|
|
@@ -9251,24 +9288,35 @@ function surfaceToSpec(surface) {
|
|
|
9251
9288
|
const root = surface.components.has('root')
|
|
9252
9289
|
? 'root'
|
|
9253
9290
|
: surface.components.keys().next().value;
|
|
9254
|
-
|
|
9291
|
+
// Seed empty check messages so errorText $bindState bindings resolve
|
|
9292
|
+
// (render-element defers mounting while any bound prop is undefined).
|
|
9293
|
+
const checkSeeds = {};
|
|
9294
|
+
for (const [id, comp] of surface.components) {
|
|
9295
|
+
if (componentHasChecks(comp))
|
|
9296
|
+
checkSeeds[id] = '';
|
|
9297
|
+
}
|
|
9298
|
+
const state = Object.keys(checkSeeds).length > 0
|
|
9299
|
+
? { ...surface.dataModel, _a2uiChecks: { ...checkSeeds, ...(surface.dataModel['_a2uiChecks'] ?? {}) } }
|
|
9300
|
+
: surface.dataModel;
|
|
9301
|
+
return { root, elements, state };
|
|
9302
|
+
}
|
|
9303
|
+
/** True when the component carries validation rules the renderer enforces:
|
|
9304
|
+
* explicit `checks`, or a TextField `validationRegexp` with a bound value. */
|
|
9305
|
+
function componentHasChecks(raw) {
|
|
9306
|
+
if (Array.isArray(raw['checks']) && raw['checks'].length > 0)
|
|
9307
|
+
return true;
|
|
9308
|
+
return typeof raw['validationRegexp'] === 'string'
|
|
9309
|
+
&& raw['validationRegexp'].length > 0
|
|
9310
|
+
&& isPathRef(raw['value']);
|
|
9255
9311
|
}
|
|
9256
9312
|
|
|
9257
|
-
|
|
9258
|
-
if (typeof v === 'string')
|
|
9259
|
-
return { literalString: v };
|
|
9260
|
-
if (typeof v === 'number')
|
|
9261
|
-
return { literalNumber: v };
|
|
9262
|
-
if (typeof v === 'boolean')
|
|
9263
|
-
return { literalBoolean: v };
|
|
9264
|
-
return { literalString: String(v) };
|
|
9265
|
-
}
|
|
9313
|
+
// SPDX-License-Identifier: MIT
|
|
9266
9314
|
/**
|
|
9267
9315
|
* Derive a human-readable label for an outgoing action by walking from
|
|
9268
9316
|
* the source component to its authored visible text. Today supported:
|
|
9269
|
-
* Button → child Text →
|
|
9270
|
-
*
|
|
9271
|
-
*
|
|
9317
|
+
* Button → child Text → text. Returns null for other component types or
|
|
9318
|
+
* when the linkage isn't well-formed; callers fall back to a camelCase
|
|
9319
|
+
* humanization of `action.name`.
|
|
9272
9320
|
*
|
|
9273
9321
|
* Why: the chat-lib used to ship a hardcoded `KNOWN_LABELS` map
|
|
9274
9322
|
* (bookingSubmit → 'Search flights') that embedded app-specific
|
|
@@ -9278,49 +9326,38 @@ function toDynamicValue(v) {
|
|
|
9278
9326
|
*/
|
|
9279
9327
|
function deriveActionLabel(surface, sourceId) {
|
|
9280
9328
|
const source = surface.components.get(sourceId);
|
|
9281
|
-
if (!source)
|
|
9329
|
+
if (!source || source.component !== 'Button')
|
|
9282
9330
|
return null;
|
|
9283
|
-
const
|
|
9284
|
-
if (
|
|
9331
|
+
const childId = source.child;
|
|
9332
|
+
if (typeof childId !== 'string')
|
|
9285
9333
|
return null;
|
|
9286
|
-
const labelText = surface.components.get(
|
|
9287
|
-
if (!labelText)
|
|
9334
|
+
const labelText = surface.components.get(childId);
|
|
9335
|
+
if (!labelText || labelText.component !== 'Text')
|
|
9288
9336
|
return null;
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
// `text` may be either a raw string (LLM-author ergonomic shorthand) or
|
|
9293
|
-
// a wrapped DynamicString `{ literalString: "..." }` (canonical v1 shape).
|
|
9294
|
-
// Accept both so the label survives whichever form the LLM happens to emit.
|
|
9295
|
-
const text = textProps.text;
|
|
9337
|
+
// v0.9 dynamic strings are bare literals or `{ path }` bindings; only a
|
|
9338
|
+
// bare literal is a usable authored label.
|
|
9339
|
+
const text = labelText.text;
|
|
9296
9340
|
if (typeof text === 'string') {
|
|
9297
9341
|
return text.length > 0 ? text : null;
|
|
9298
9342
|
}
|
|
9299
|
-
if (text && typeof text === 'object' && typeof text.literalString === 'string') {
|
|
9300
|
-
const literal = text.literalString;
|
|
9301
|
-
return literal.length > 0 ? literal : null;
|
|
9302
|
-
}
|
|
9303
9343
|
return null;
|
|
9304
9344
|
}
|
|
9305
|
-
/** Builds
|
|
9306
|
-
* The action.context is
|
|
9307
|
-
*
|
|
9308
|
-
* child whose
|
|
9345
|
+
/** Builds a v0.9 A2uiActionMessage from handler params and the current
|
|
9346
|
+
* surface. The action.context is the resolved plain object the renderer
|
|
9347
|
+
* produced from the component's `action.event.context`. Sets action.label
|
|
9348
|
+
* when the source component is a Button with a Text child whose text is a
|
|
9349
|
+
* non-empty bare literal. */
|
|
9309
9350
|
function buildA2uiActionMessage(params, surface) {
|
|
9310
|
-
const
|
|
9311
|
-
const wrappedContext = {};
|
|
9312
|
-
for (const [k, v] of Object.entries(rawContext)) {
|
|
9313
|
-
wrappedContext[k] = toDynamicValue(v);
|
|
9314
|
-
}
|
|
9351
|
+
const context = params['context'] ?? {};
|
|
9315
9352
|
const sourceComponentId = params['sourceComponentId'];
|
|
9316
9353
|
const message = {
|
|
9317
|
-
version:
|
|
9354
|
+
version: A2UI_WIRE_VERSION,
|
|
9318
9355
|
action: {
|
|
9319
9356
|
name: params['name'],
|
|
9320
9357
|
surfaceId: surface.surfaceId,
|
|
9321
9358
|
sourceComponentId,
|
|
9322
9359
|
timestamp: new Date().toISOString(),
|
|
9323
|
-
context
|
|
9360
|
+
context,
|
|
9324
9361
|
},
|
|
9325
9362
|
};
|
|
9326
9363
|
const label = deriveActionLabel(surface, sourceComponentId);
|
|
@@ -9329,7 +9366,6 @@ function buildA2uiActionMessage(params, surface) {
|
|
|
9329
9366
|
if (surface.sendDataModel) {
|
|
9330
9367
|
message.metadata = {
|
|
9331
9368
|
a2uiClientDataModel: {
|
|
9332
|
-
version: 'v1',
|
|
9333
9369
|
surfaces: { [surface.surfaceId]: surface.dataModel },
|
|
9334
9370
|
},
|
|
9335
9371
|
};
|
|
@@ -9396,22 +9432,55 @@ class A2uiSurfaceComponent {
|
|
|
9396
9432
|
surfaceFallback = input(undefined, ...(ngDevMode ? [{ debugName: "surfaceFallback" }] : []));
|
|
9397
9433
|
events = output();
|
|
9398
9434
|
action = output();
|
|
9399
|
-
/**
|
|
9435
|
+
/** Emitted when a submit is blocked by failing validation checks —
|
|
9436
|
+
* the spec client → agent error message (code VALIDATION_FAILED). */
|
|
9437
|
+
validationError = output();
|
|
9438
|
+
/** Surface-owned live state store: `$bindState` props read it and input
|
|
9439
|
+
* components write user edits into it, so event-time logic (checks,
|
|
9440
|
+
* action context) sees CURRENT values instead of the agent-seeded
|
|
9441
|
+
* snapshot. Seeded from spec.state with user edits preserved. Public so
|
|
9442
|
+
* hosts (and tests) can read the live values of a rendered surface. */
|
|
9443
|
+
liveStore = signalStateStore({});
|
|
9444
|
+
/** Last value this component seeded per state path (see chat-generative-ui:
|
|
9445
|
+
* distinguishes "still our seed — safe to overwrite" from "user edited"). */
|
|
9446
|
+
seeded = new Map();
|
|
9447
|
+
constructor() {
|
|
9448
|
+
effect(() => {
|
|
9449
|
+
const s = this.spec();
|
|
9450
|
+
const state = s?.state;
|
|
9451
|
+
if (!state)
|
|
9452
|
+
return;
|
|
9453
|
+
untracked(() => {
|
|
9454
|
+
for (const [key, value] of Object.entries(state)) {
|
|
9455
|
+
const path = key.startsWith('/') ? key : `/${key}`;
|
|
9456
|
+
const current = this.liveStore.get(path);
|
|
9457
|
+
const untouched = current === undefined ||
|
|
9458
|
+
(this.seeded.has(path) && current === this.seeded.get(path));
|
|
9459
|
+
if (untouched) {
|
|
9460
|
+
if (current !== value)
|
|
9461
|
+
this.liveStore.set(path, value);
|
|
9462
|
+
this.seeded.set(path, value);
|
|
9463
|
+
}
|
|
9464
|
+
}
|
|
9465
|
+
});
|
|
9466
|
+
});
|
|
9467
|
+
}
|
|
9468
|
+
/** Agent-set primary color from `createSurface.theme.primaryColor`.
|
|
9400
9469
|
* Returns null when unset so the host binding doesn't override the
|
|
9401
9470
|
* consumer's `:root`-level `--a2ui-primary` default. */
|
|
9402
|
-
primaryColor = computed(() => (this.state()?.surface ?? this.surface())?.
|
|
9403
|
-
/** Agent
|
|
9404
|
-
*
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
*
|
|
9410
|
-
* multiple top-level
|
|
9471
|
+
primaryColor = computed(() => (this.state()?.surface ?? this.surface())?.theme?.primaryColor ?? null, ...(ngDevMode ? [{ debugName: "primaryColor" }] : []));
|
|
9472
|
+
/** Agent identity chrome from `createSurface.theme`. When neither
|
|
9473
|
+
* `agentDisplayName` nor `iconUrl` is set, no header renders at all
|
|
9474
|
+
* (zero layout impact for themeless surfaces — the common case). */
|
|
9475
|
+
agentDisplayName = computed(() => (this.state()?.surface ?? this.surface())?.theme?.agentDisplayName ?? null, ...(ngDevMode ? [{ debugName: "agentDisplayName" }] : []));
|
|
9476
|
+
iconUrl = computed(() => (this.state()?.surface ?? this.surface())?.theme?.iconUrl ?? null, ...(ngDevMode ? [{ debugName: "iconUrl" }] : []));
|
|
9477
|
+
/** Roots from the surface state. The v0.9 wire contract reserves the
|
|
9478
|
+
* component id `root` as the single tree root; we keep the renderer
|
|
9479
|
+
* permissive in case future surfaces emit multiple top-level
|
|
9480
|
+
* components.
|
|
9411
9481
|
*
|
|
9412
9482
|
* Conservative: returns only the first key from componentViews
|
|
9413
|
-
* insertion order.
|
|
9414
|
-
* true root id; plumbing it through A2uiSurfaceState is a follow-up. */
|
|
9483
|
+
* insertion order. */
|
|
9415
9484
|
rootIds = computed(() => {
|
|
9416
9485
|
const st = this.state();
|
|
9417
9486
|
if (!st)
|
|
@@ -9421,7 +9490,7 @@ class A2uiSurfaceComponent {
|
|
|
9421
9490
|
/** Convert the A2UI surface to a json-render Spec for rendering.
|
|
9422
9491
|
* Prefers `state().surface` (the progressively-built wire surface)
|
|
9423
9492
|
* over the legacy `surface` input. surfaceToSpec handles
|
|
9424
|
-
* children
|
|
9493
|
+
* children-id-list → spec.children translation + reserved-key
|
|
9425
9494
|
* filtering + path-ref → $bindState rewriting; the rendered tree
|
|
9426
9495
|
* then uses render-element's standard input-mapping
|
|
9427
9496
|
* (`childKeys: el.children`) so catalog components receive the
|
|
@@ -9447,7 +9516,50 @@ class A2uiSurfaceComponent {
|
|
|
9447
9516
|
const surf = this.state()?.surface ?? this.surface();
|
|
9448
9517
|
if (!surf)
|
|
9449
9518
|
return undefined;
|
|
9450
|
-
|
|
9519
|
+
// Live model: user edits in the store overlay the agent-seeded model.
|
|
9520
|
+
const liveModel = this.mergedLiveModel(surf);
|
|
9521
|
+
// Validation gate: every check rule on the surface must pass before
|
|
9522
|
+
// an event action dispatches (spec CheckRule semantics).
|
|
9523
|
+
const failures = evaluateSurfaceChecks(surf, liveModel);
|
|
9524
|
+
if (failures.length > 0) {
|
|
9525
|
+
for (const f of failures) {
|
|
9526
|
+
this.liveStore.set(`/_a2uiChecks/${f.componentId}`, f.message);
|
|
9527
|
+
}
|
|
9528
|
+
const first = failures[0];
|
|
9529
|
+
this.validationError.emit({
|
|
9530
|
+
version: A2UI_WIRE_VERSION,
|
|
9531
|
+
error: {
|
|
9532
|
+
code: 'VALIDATION_FAILED',
|
|
9533
|
+
surfaceId: surf.surfaceId,
|
|
9534
|
+
...(first.path ? { path: first.path } : {}),
|
|
9535
|
+
message: first.message,
|
|
9536
|
+
},
|
|
9537
|
+
});
|
|
9538
|
+
return undefined;
|
|
9539
|
+
}
|
|
9540
|
+
// Clear any stale messages from a previous failed submit.
|
|
9541
|
+
for (const [id, comp] of surf.components) {
|
|
9542
|
+
if (componentHasChecks(comp)) {
|
|
9543
|
+
this.liveStore.set(`/_a2uiChecks/${id}`, '');
|
|
9544
|
+
}
|
|
9545
|
+
}
|
|
9546
|
+
// Substitute live-context markers with current values.
|
|
9547
|
+
const rawContext = params['context'] ?? {};
|
|
9548
|
+
const context = {};
|
|
9549
|
+
for (const [k, v] of Object.entries(rawContext)) {
|
|
9550
|
+
if (v != null && typeof v === 'object' && '$bindState' in v) {
|
|
9551
|
+
const path = String(v['$bindState']);
|
|
9552
|
+
context[k] = getByPointer(liveModel, path);
|
|
9553
|
+
}
|
|
9554
|
+
else {
|
|
9555
|
+
context[k] = v;
|
|
9556
|
+
}
|
|
9557
|
+
}
|
|
9558
|
+
// sendDataModel metadata must carry the LIVE model (user edits
|
|
9559
|
+
// included), minus renderer-internal keys.
|
|
9560
|
+
const { _a2uiChecks, ...publicModel } = liveModel;
|
|
9561
|
+
void _a2uiChecks;
|
|
9562
|
+
const message = buildA2uiActionMessage({ ...params, context }, { ...surf, dataModel: publicModel });
|
|
9451
9563
|
this.action.emit(message);
|
|
9452
9564
|
return message;
|
|
9453
9565
|
},
|
|
@@ -9460,7 +9572,7 @@ class A2uiSurfaceComponent {
|
|
|
9460
9572
|
}
|
|
9461
9573
|
// Built-in fallback
|
|
9462
9574
|
if (call === 'openUrl' && typeof globalThis.window !== 'undefined') {
|
|
9463
|
-
globalThis.window.open(String(args['url'] ?? ''), '_blank');
|
|
9575
|
+
globalThis.window.open(String(args['url'] ?? ''), '_blank', 'noopener');
|
|
9464
9576
|
}
|
|
9465
9577
|
return undefined;
|
|
9466
9578
|
},
|
|
@@ -9469,12 +9581,30 @@ class A2uiSurfaceComponent {
|
|
|
9469
9581
|
onRenderEvent(event) {
|
|
9470
9582
|
this.events.emit(event);
|
|
9471
9583
|
}
|
|
9584
|
+
/** Agent-seeded data model overlaid with the store's current state
|
|
9585
|
+
* (user edits + check messages). Shallow per-key merge is sufficient:
|
|
9586
|
+
* store snapshots hold whole top-level values written via pointers. */
|
|
9587
|
+
mergedLiveModel(surf) {
|
|
9588
|
+
const snapshot = this.liveStore.getSnapshot();
|
|
9589
|
+
return deepOverlay(surf.dataModel, snapshot);
|
|
9590
|
+
}
|
|
9472
9591
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiSurfaceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9473
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiSurfaceComponent, isStandalone: true, selector: "a2ui-surface", inputs: { surface: { classPropertyName: "surface", publicName: "surface", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, catalog: { classPropertyName: "catalog", publicName: "catalog", isSignal: true, isRequired: true, transformFunction: null }, handlers: { classPropertyName: "handlers", publicName: "handlers", isSignal: true, isRequired: false, transformFunction: null }, surfaceFallback: { classPropertyName: "surfaceFallback", publicName: "surfaceFallback", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { events: "events", action: "action" }, host: { properties: { "style.--a2ui-primary": "primaryColor()"
|
|
9592
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiSurfaceComponent, isStandalone: true, selector: "a2ui-surface", inputs: { surface: { classPropertyName: "surface", publicName: "surface", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, catalog: { classPropertyName: "catalog", publicName: "catalog", isSignal: true, isRequired: true, transformFunction: null }, handlers: { classPropertyName: "handlers", publicName: "handlers", isSignal: true, isRequired: false, transformFunction: null }, surfaceFallback: { classPropertyName: "surfaceFallback", publicName: "surfaceFallback", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { events: "events", action: "action", validationError: "validationError" }, host: { properties: { "style.--a2ui-primary": "primaryColor()" } }, ngImport: i0, template: `
|
|
9593
|
+
@if (agentDisplayName() || iconUrl()) {
|
|
9594
|
+
<div class="a2ui-surface-chrome">
|
|
9595
|
+
@if (iconUrl(); as icon) {
|
|
9596
|
+
<img [src]="icon" alt="" referrerpolicy="no-referrer" />
|
|
9597
|
+
}
|
|
9598
|
+
@if (agentDisplayName(); as name) {
|
|
9599
|
+
<span>{{ name }}</span>
|
|
9600
|
+
}
|
|
9601
|
+
</div>
|
|
9602
|
+
}
|
|
9474
9603
|
@if (spec(); as s) {
|
|
9475
9604
|
<render-spec
|
|
9476
9605
|
[spec]="s"
|
|
9477
9606
|
[registry]="registry()"
|
|
9607
|
+
[store]="liveStore"
|
|
9478
9608
|
[handlers]="internalHandlers()"
|
|
9479
9609
|
(events)="onRenderEvent($event)"
|
|
9480
9610
|
/>
|
|
@@ -9485,32 +9615,32 @@ class A2uiSurfaceComponent {
|
|
|
9485
9615
|
<a2ui-default-fallback />
|
|
9486
9616
|
}
|
|
9487
9617
|
}
|
|
9488
|
-
`, isInline: true, dependencies: [{ kind: "component", type: RenderSpecComponent, selector: "render-spec", inputs: ["spec", "registry", "store", "functions", "handlers", "loading"], outputs: ["events"] }, { kind: "component", type: A2uiDefaultFallbackComponent, selector: "a2ui-default-fallback" }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9618
|
+
`, isInline: true, styles: [".a2ui-surface-chrome{display:flex;align-items:center;gap:var(--a2ui-spacing-2);margin-bottom:var(--a2ui-spacing-2);color:var(--a2ui-label);font-size:var(--a2ui-typography-label-size)}.a2ui-surface-chrome img{width:16px;height:16px;border-radius:50%;object-fit:cover}\n"], dependencies: [{ kind: "component", type: RenderSpecComponent, selector: "render-spec", inputs: ["spec", "registry", "store", "functions", "handlers", "loading"], outputs: ["events"] }, { kind: "component", type: A2uiDefaultFallbackComponent, selector: "a2ui-default-fallback" }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9489
9619
|
}
|
|
9490
9620
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiSurfaceComponent, decorators: [{
|
|
9491
9621
|
type: Component,
|
|
9492
|
-
args: [{
|
|
9493
|
-
selector: 'a2ui-surface',
|
|
9494
|
-
standalone: true,
|
|
9495
|
-
imports: [
|
|
9622
|
+
args: [{ selector: 'a2ui-surface', standalone: true, imports: [
|
|
9496
9623
|
RenderSpecComponent,
|
|
9497
9624
|
A2uiDefaultFallbackComponent,
|
|
9498
9625
|
NgComponentOutlet,
|
|
9499
|
-
],
|
|
9500
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9501
|
-
// The host applies the agent-set v1 styles (`beginRendering.styles`)
|
|
9502
|
-
// as inline CSS custom properties + font-family. Catalog components
|
|
9503
|
-
// consume `--a2ui-primary` for accents (buttons, sliders, focus,
|
|
9504
|
-
// etc.); `font-family` cascades naturally from the host.
|
|
9505
|
-
host: {
|
|
9626
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
9506
9627
|
'[style.--a2ui-primary]': 'primaryColor()',
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9628
|
+
}, template: `
|
|
9629
|
+
@if (agentDisplayName() || iconUrl()) {
|
|
9630
|
+
<div class="a2ui-surface-chrome">
|
|
9631
|
+
@if (iconUrl(); as icon) {
|
|
9632
|
+
<img [src]="icon" alt="" referrerpolicy="no-referrer" />
|
|
9633
|
+
}
|
|
9634
|
+
@if (agentDisplayName(); as name) {
|
|
9635
|
+
<span>{{ name }}</span>
|
|
9636
|
+
}
|
|
9637
|
+
</div>
|
|
9638
|
+
}
|
|
9510
9639
|
@if (spec(); as s) {
|
|
9511
9640
|
<render-spec
|
|
9512
9641
|
[spec]="s"
|
|
9513
9642
|
[registry]="registry()"
|
|
9643
|
+
[store]="liveStore"
|
|
9514
9644
|
[handlers]="internalHandlers()"
|
|
9515
9645
|
(events)="onRenderEvent($event)"
|
|
9516
9646
|
/>
|
|
@@ -9521,9 +9651,52 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
9521
9651
|
<a2ui-default-fallback />
|
|
9522
9652
|
}
|
|
9523
9653
|
}
|
|
9524
|
-
`,
|
|
9525
|
-
|
|
9526
|
-
|
|
9654
|
+
`, styles: [".a2ui-surface-chrome{display:flex;align-items:center;gap:var(--a2ui-spacing-2);margin-bottom:var(--a2ui-spacing-2);color:var(--a2ui-label);font-size:var(--a2ui-typography-label-size)}.a2ui-surface-chrome img{width:16px;height:16px;border-radius:50%;object-fit:cover}\n"] }]
|
|
9655
|
+
}], ctorParameters: () => [], propDecorators: { surface: [{ type: i0.Input, args: [{ isSignal: true, alias: "surface", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], catalog: [{ type: i0.Input, args: [{ isSignal: true, alias: "catalog", required: true }] }], handlers: [{ type: i0.Input, args: [{ isSignal: true, alias: "handlers", required: false }] }], surfaceFallback: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceFallback", required: false }] }], events: [{ type: i0.Output, args: ["events"] }], action: [{ type: i0.Output, args: ["action"] }], validationError: [{ type: i0.Output, args: ["validationError"] }] } });
|
|
9656
|
+
/** Recursively overlay `top` onto `base` (plain objects merge; anything
|
|
9657
|
+
* else in `top` wins). */
|
|
9658
|
+
function deepOverlay(base, top) {
|
|
9659
|
+
const out = { ...base };
|
|
9660
|
+
for (const [k, v] of Object.entries(top)) {
|
|
9661
|
+
const prev = out[k];
|
|
9662
|
+
if (v != null && typeof v === 'object' && !Array.isArray(v)
|
|
9663
|
+
&& prev != null && typeof prev === 'object' && !Array.isArray(prev)) {
|
|
9664
|
+
out[k] = deepOverlay(prev, v);
|
|
9665
|
+
}
|
|
9666
|
+
else {
|
|
9667
|
+
out[k] = v;
|
|
9668
|
+
}
|
|
9669
|
+
}
|
|
9670
|
+
return out;
|
|
9671
|
+
}
|
|
9672
|
+
const CHECK_FUNCTIONS = createA2uiFunctionRegistry();
|
|
9673
|
+
/** Evaluate every check rule on the surface against the live model.
|
|
9674
|
+
* A rule passes when its condition resolves to exactly `true`. TextField
|
|
9675
|
+
* `validationRegexp` (with a bound value) contributes an implicit rule. */
|
|
9676
|
+
function evaluateSurfaceChecks(surf, liveModel) {
|
|
9677
|
+
const failures = [];
|
|
9678
|
+
for (const [id, comp] of surf.components) {
|
|
9679
|
+
const raw = comp;
|
|
9680
|
+
const boundPath = isPathRef(raw['value']) ? raw['value'].path : undefined;
|
|
9681
|
+
const rules = Array.isArray(raw['checks']) ? [...raw['checks']] : [];
|
|
9682
|
+
if (typeof raw['validationRegexp'] === 'string' && raw['validationRegexp'].length > 0 && boundPath) {
|
|
9683
|
+
rules.push({
|
|
9684
|
+
condition: { call: 'regex', args: { value: { path: boundPath }, pattern: raw['validationRegexp'] } },
|
|
9685
|
+
message: 'Invalid format',
|
|
9686
|
+
});
|
|
9687
|
+
}
|
|
9688
|
+
for (const rule of rules) {
|
|
9689
|
+
if (!rule || typeof rule.message !== 'string')
|
|
9690
|
+
continue;
|
|
9691
|
+
const passed = resolveDynamic(rule.condition, liveModel, undefined, CHECK_FUNCTIONS) === true;
|
|
9692
|
+
if (!passed) {
|
|
9693
|
+
failures.push({ componentId: id, message: rule.message, ...(boundPath ? { path: boundPath } : {}) });
|
|
9694
|
+
break; // first failing rule per component
|
|
9695
|
+
}
|
|
9696
|
+
}
|
|
9697
|
+
}
|
|
9698
|
+
return failures;
|
|
9699
|
+
}
|
|
9527
9700
|
|
|
9528
9701
|
// SPDX-License-Identifier: MIT
|
|
9529
9702
|
/**
|
|
@@ -9586,7 +9759,9 @@ function createParseTreeStore(parser) {
|
|
|
9586
9759
|
};
|
|
9587
9760
|
}
|
|
9588
9761
|
|
|
9589
|
-
|
|
9762
|
+
// `[^{}]` (no nested braces) + a length bound keep the scan linear on
|
|
9763
|
+
// adversarial LLM-authored strings (CodeQL js/polynomial-redos).
|
|
9764
|
+
const REF_PATTERN = /\{(\$\.[^{}]{1,512})\}/g;
|
|
9590
9765
|
function walk(value, into) {
|
|
9591
9766
|
if (typeof value === 'string') {
|
|
9592
9767
|
let m;
|
|
@@ -9606,29 +9781,19 @@ function walk(value, into) {
|
|
|
9606
9781
|
}
|
|
9607
9782
|
}
|
|
9608
9783
|
/** Extracts the set of data-model paths (e.g. `$.form.name`) referenced
|
|
9609
|
-
* by `{$.path}` expressions inside a component's
|
|
9784
|
+
* by `{$.path}` expressions inside a component's props. Result is
|
|
9610
9785
|
* deduplicated and sorted for stable signal identity. */
|
|
9611
|
-
function extractBindings(
|
|
9786
|
+
function extractBindings(component) {
|
|
9612
9787
|
const out = new Set();
|
|
9613
|
-
walk(
|
|
9788
|
+
walk(component, out);
|
|
9614
9789
|
return [...out].sort();
|
|
9615
9790
|
}
|
|
9616
9791
|
|
|
9617
9792
|
// SPDX-License-Identifier: MIT
|
|
9618
|
-
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
out[e.key] = e.valueString;
|
|
9623
|
-
else if ('valueNumber' in e && e.valueNumber !== undefined)
|
|
9624
|
-
out[e.key] = e.valueNumber;
|
|
9625
|
-
else if ('valueBoolean' in e && e.valueBoolean !== undefined)
|
|
9626
|
-
out[e.key] = e.valueBoolean;
|
|
9627
|
-
else if ('valueMap' in e && Array.isArray(e.valueMap))
|
|
9628
|
-
out[e.key] = entriesToObject(e.valueMap);
|
|
9629
|
-
}
|
|
9630
|
-
return out;
|
|
9631
|
-
}
|
|
9793
|
+
/** Component-envelope keys that are protocol structure, not renderable props. */
|
|
9794
|
+
const RESERVED_VIEW_PROP_KEYS = new Set([
|
|
9795
|
+
'id', 'component', 'catalogId', 'weight', 'accessibility', 'checks',
|
|
9796
|
+
]);
|
|
9632
9797
|
/** Returns true if `path` (in `$.a.b.c` form) resolves to a defined,
|
|
9633
9798
|
* non-null value inside `dataModel`. Used to decide per-component
|
|
9634
9799
|
* readiness. */
|
|
@@ -9648,7 +9813,7 @@ function isResolved(dataModel, path) {
|
|
|
9648
9813
|
* nested objects/arrays are recursed. */
|
|
9649
9814
|
function resolveProps(value, dataModel) {
|
|
9650
9815
|
if (typeof value === 'string') {
|
|
9651
|
-
const full = value.match(/^\{(\$\.[^}]
|
|
9816
|
+
const full = value.match(/^\{(\$\.[^{}]{1,512})\}$/);
|
|
9652
9817
|
if (full) {
|
|
9653
9818
|
const segs = full[1].slice(2).split('.');
|
|
9654
9819
|
let cur = dataModel;
|
|
@@ -9659,7 +9824,9 @@ function resolveProps(value, dataModel) {
|
|
|
9659
9824
|
}
|
|
9660
9825
|
return cur;
|
|
9661
9826
|
}
|
|
9662
|
-
|
|
9827
|
+
// Bounded, brace-free class keeps the scan linear on adversarial
|
|
9828
|
+
// LLM-authored strings (CodeQL js/polynomial-redos).
|
|
9829
|
+
return value.replace(/\{(\$\.[^{}]{1,512})\}/g, (_, path) => {
|
|
9663
9830
|
const segs = path.slice(2).split('.');
|
|
9664
9831
|
let cur = dataModel;
|
|
9665
9832
|
for (const s of segs) {
|
|
@@ -9681,12 +9848,50 @@ function resolveProps(value, dataModel) {
|
|
|
9681
9848
|
}
|
|
9682
9849
|
return value;
|
|
9683
9850
|
}
|
|
9851
|
+
/** Resolve a flat v0.9 component into the renderable prop bag: reserved
|
|
9852
|
+
* protocol keys stripped, `{$.path}` references substituted. */
|
|
9853
|
+
function resolveViewProps(component, dataModel) {
|
|
9854
|
+
const out = {};
|
|
9855
|
+
for (const [k, v] of Object.entries(component)) {
|
|
9856
|
+
if (RESERVED_VIEW_PROP_KEYS.has(k))
|
|
9857
|
+
continue;
|
|
9858
|
+
out[k] = resolveProps(v, dataModel);
|
|
9859
|
+
}
|
|
9860
|
+
return out;
|
|
9861
|
+
}
|
|
9862
|
+
function projectView(component) {
|
|
9863
|
+
return {
|
|
9864
|
+
id: component.id,
|
|
9865
|
+
type: typeof component.component === 'string' ? component.component : 'Unknown',
|
|
9866
|
+
bindings: extractBindings(component),
|
|
9867
|
+
ready: false,
|
|
9868
|
+
props: {},
|
|
9869
|
+
def: component,
|
|
9870
|
+
};
|
|
9871
|
+
}
|
|
9872
|
+
/** Apply one v0.9 data-model mutation (set at path, whole-model replace,
|
|
9873
|
+
* or delete-at-path when `value` is omitted). */
|
|
9874
|
+
function applyDataModelDelta(dataModel, delta) {
|
|
9875
|
+
const path = delta.path && delta.path !== '/' ? delta.path : undefined;
|
|
9876
|
+
if (delta.del) {
|
|
9877
|
+
return path ? deleteByPointer(dataModel, path) : {};
|
|
9878
|
+
}
|
|
9879
|
+
if (!path) {
|
|
9880
|
+
return (delta.value ?? {});
|
|
9881
|
+
}
|
|
9882
|
+
return setByPointer(dataModel, path, delta.value);
|
|
9883
|
+
}
|
|
9684
9884
|
/**
|
|
9685
9885
|
* Create an {@link A2uiSurfaceStore} — the per-conversation store that buffers
|
|
9686
|
-
* streamed A2UI
|
|
9886
|
+
* streamed A2UI v0.9 envelopes, tracks each surface's data model + lifecycle
|
|
9687
9887
|
* state, and exposes them as signals for rendering. One store backs a chat
|
|
9688
9888
|
* thread's A2UI surfaces.
|
|
9689
9889
|
*
|
|
9890
|
+
* A surface becomes visible once its `createSurface` envelope has arrived AND
|
|
9891
|
+
* a component with id `root` has been defined (the v0.9 progressive-rendering
|
|
9892
|
+
* rule). Everything received earlier is buffered; afterwards, components merge
|
|
9893
|
+
* incrementally by id and data-model updates apply immediately.
|
|
9894
|
+
*
|
|
9690
9895
|
* @returns A fresh, empty {@link A2uiSurfaceStore}.
|
|
9691
9896
|
* @example
|
|
9692
9897
|
* ```ts
|
|
@@ -9701,145 +9906,115 @@ function createA2uiSurfaceStore() {
|
|
|
9701
9906
|
function bufferOf(surfaceId) {
|
|
9702
9907
|
let b = buffers.get(surfaceId);
|
|
9703
9908
|
if (!b) {
|
|
9704
|
-
b = { dataModelDeltas: [] };
|
|
9909
|
+
b = { components: new Map(), componentViews: new Map(), dataModelDeltas: [] };
|
|
9705
9910
|
buffers.set(surfaceId, b);
|
|
9706
9911
|
}
|
|
9707
9912
|
return b;
|
|
9708
9913
|
}
|
|
9914
|
+
function publish(surface, views) {
|
|
9915
|
+
const nextSurfaces = new Map(surfacesSignal());
|
|
9916
|
+
nextSurfaces.set(surface.surfaceId, surface);
|
|
9917
|
+
surfacesSignal.set(nextSurfaces);
|
|
9918
|
+
const nextStates = new Map(surfaceStatesSignal());
|
|
9919
|
+
nextStates.set(surface.surfaceId, { surface, componentViews: views });
|
|
9920
|
+
surfaceStatesSignal.set(nextStates);
|
|
9921
|
+
}
|
|
9922
|
+
/** Recompute readiness/props for every view against `dataModel`,
|
|
9923
|
+
* honoring the monotonic ready rule. */
|
|
9924
|
+
function refreshViews(views, dataModel) {
|
|
9925
|
+
const next = new Map();
|
|
9926
|
+
for (const [id, v] of views) {
|
|
9927
|
+
const allResolved = v.bindings.every((p) => isResolved(dataModel, p));
|
|
9928
|
+
// Monotonic: once ready=true, stays true even if a later update
|
|
9929
|
+
// clears a referenced path.
|
|
9930
|
+
const nextReady = v.ready || allResolved;
|
|
9931
|
+
next.set(id, {
|
|
9932
|
+
...v,
|
|
9933
|
+
ready: nextReady,
|
|
9934
|
+
props: nextReady ? resolveViewProps(v.def, dataModel) : v.props,
|
|
9935
|
+
});
|
|
9936
|
+
}
|
|
9937
|
+
return next;
|
|
9938
|
+
}
|
|
9939
|
+
/** Commit the buffer to a live surface if the v0.9 render condition holds:
|
|
9940
|
+
* createSurface seen AND a `root` component defined. */
|
|
9941
|
+
function tryCommit(surfaceId) {
|
|
9942
|
+
const b = buffers.get(surfaceId);
|
|
9943
|
+
if (!b || !b.create || !b.components.has('root'))
|
|
9944
|
+
return;
|
|
9945
|
+
let dataModel = {};
|
|
9946
|
+
for (const d of b.dataModelDeltas) {
|
|
9947
|
+
dataModel = applyDataModelDelta(dataModel, d);
|
|
9948
|
+
}
|
|
9949
|
+
const surface = {
|
|
9950
|
+
surfaceId,
|
|
9951
|
+
catalogId: b.create.catalogId,
|
|
9952
|
+
...(b.create.theme ? { theme: b.create.theme } : {}),
|
|
9953
|
+
...(b.create.sendDataModel !== undefined ? { sendDataModel: b.create.sendDataModel } : {}),
|
|
9954
|
+
components: new Map(b.components),
|
|
9955
|
+
dataModel,
|
|
9956
|
+
};
|
|
9957
|
+
publish(surface, refreshViews(b.componentViews, dataModel));
|
|
9958
|
+
buffers.delete(surfaceId);
|
|
9959
|
+
}
|
|
9709
9960
|
function apply(message) {
|
|
9710
|
-
if ('
|
|
9711
|
-
const
|
|
9712
|
-
const
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
views.set(c.id, {
|
|
9726
|
-
id: c.id,
|
|
9727
|
-
type: typeKey,
|
|
9728
|
-
bindings: extractBindings(def),
|
|
9729
|
-
ready: false,
|
|
9730
|
-
props: {},
|
|
9731
|
-
def,
|
|
9732
|
-
});
|
|
9961
|
+
if ('createSurface' in message) {
|
|
9962
|
+
const create = message.createSurface;
|
|
9963
|
+
const live = surfacesSignal().get(create.surfaceId);
|
|
9964
|
+
if (live) {
|
|
9965
|
+
// v0.9 calls createSurface-on-existing an agent error; tolerate it
|
|
9966
|
+
// as an idempotent refresh of the surface's create-time fields.
|
|
9967
|
+
const state = surfaceStatesSignal().get(create.surfaceId);
|
|
9968
|
+
const surface = {
|
|
9969
|
+
...live,
|
|
9970
|
+
catalogId: create.catalogId,
|
|
9971
|
+
...(create.theme !== undefined ? { theme: create.theme } : {}),
|
|
9972
|
+
...(create.sendDataModel !== undefined ? { sendDataModel: create.sendDataModel } : {}),
|
|
9973
|
+
};
|
|
9974
|
+
publish(surface, new Map(state?.componentViews ?? []));
|
|
9975
|
+
return;
|
|
9733
9976
|
}
|
|
9734
|
-
|
|
9977
|
+
bufferOf(create.surfaceId).create = create;
|
|
9978
|
+
tryCommit(create.surfaceId);
|
|
9735
9979
|
return;
|
|
9736
9980
|
}
|
|
9737
|
-
if ('
|
|
9738
|
-
const upd = message.
|
|
9739
|
-
const
|
|
9740
|
-
if (
|
|
9741
|
-
//
|
|
9742
|
-
|
|
9743
|
-
const
|
|
9744
|
-
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
}
|
|
9749
|
-
else {
|
|
9750
|
-
dataModel = { ...dataModel, ...obj };
|
|
9751
|
-
}
|
|
9752
|
-
const next = new Map(surfacesSignal());
|
|
9753
|
-
const nextSurface = { ...surface, dataModel };
|
|
9754
|
-
next.set(upd.surfaceId, nextSurface);
|
|
9755
|
-
surfacesSignal.set(next);
|
|
9756
|
-
// Recompute per-component readiness with the monotonic rule.
|
|
9757
|
-
const prevState = surfaceStatesSignal().get(upd.surfaceId);
|
|
9758
|
-
if (prevState) {
|
|
9759
|
-
const nextViews = new Map();
|
|
9760
|
-
for (const [id, v] of prevState.componentViews) {
|
|
9761
|
-
const allResolved = v.bindings.every((p) => isResolved(dataModel, p));
|
|
9762
|
-
// Monotonic: once ready=true, stays true even if a later
|
|
9763
|
-
// update clears a referenced path.
|
|
9764
|
-
const nextReady = v.ready || allResolved;
|
|
9765
|
-
nextViews.set(id, {
|
|
9766
|
-
...v,
|
|
9767
|
-
ready: nextReady,
|
|
9768
|
-
props: nextReady
|
|
9769
|
-
? resolveProps(v.def, dataModel)
|
|
9770
|
-
: v.props,
|
|
9771
|
-
});
|
|
9772
|
-
}
|
|
9773
|
-
const nextStatesMap = new Map(surfaceStatesSignal());
|
|
9774
|
-
nextStatesMap.set(upd.surfaceId, { surface: nextSurface, componentViews: nextViews });
|
|
9775
|
-
surfaceStatesSignal.set(nextStatesMap);
|
|
9981
|
+
if ('updateComponents' in message) {
|
|
9982
|
+
const upd = message.updateComponents;
|
|
9983
|
+
const live = surfacesSignal().get(upd.surfaceId);
|
|
9984
|
+
if (live) {
|
|
9985
|
+
// Incremental merge by id into the live surface.
|
|
9986
|
+
const components = new Map(live.components);
|
|
9987
|
+
const state = surfaceStatesSignal().get(upd.surfaceId);
|
|
9988
|
+
const views = new Map(state?.componentViews ?? []);
|
|
9989
|
+
for (const c of upd.components) {
|
|
9990
|
+
components.set(c.id, c);
|
|
9991
|
+
views.set(c.id, projectView(c));
|
|
9776
9992
|
}
|
|
9993
|
+
const surface = { ...live, components };
|
|
9994
|
+
publish(surface, refreshViews(views, surface.dataModel));
|
|
9995
|
+
return;
|
|
9777
9996
|
}
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
b.
|
|
9997
|
+
const b = bufferOf(upd.surfaceId);
|
|
9998
|
+
for (const c of upd.components) {
|
|
9999
|
+
b.components.set(c.id, c);
|
|
10000
|
+
b.componentViews.set(c.id, projectView(c));
|
|
9782
10001
|
}
|
|
10002
|
+
tryCommit(upd.surfaceId);
|
|
9783
10003
|
return;
|
|
9784
10004
|
}
|
|
9785
|
-
if ('
|
|
9786
|
-
const
|
|
9787
|
-
const
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
if (d.path && d.path !== '/') {
|
|
9795
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
9796
|
-
dataModel = setByPointer(dataModel, `${d.path}/${k}`, v);
|
|
9797
|
-
}
|
|
9798
|
-
}
|
|
9799
|
-
else {
|
|
9800
|
-
dataModel = { ...dataModel, ...obj };
|
|
9801
|
-
}
|
|
10005
|
+
if ('updateDataModel' in message) {
|
|
10006
|
+
const upd = message.updateDataModel;
|
|
10007
|
+
const delta = { path: upd.path, value: upd.value, del: !('value' in upd) || upd.value === undefined };
|
|
10008
|
+
const live = surfacesSignal().get(upd.surfaceId);
|
|
10009
|
+
if (live) {
|
|
10010
|
+
const dataModel = applyDataModelDelta(live.dataModel, delta);
|
|
10011
|
+
const surface = { ...live, dataModel };
|
|
10012
|
+
const state = surfaceStatesSignal().get(upd.surfaceId);
|
|
10013
|
+
publish(surface, refreshViews(state?.componentViews ?? new Map(), dataModel));
|
|
9802
10014
|
}
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
if (existing) {
|
|
9806
|
-
dataModel = { ...existing.dataModel, ...dataModel };
|
|
9807
|
-
}
|
|
9808
|
-
// Capture v1 styles (font, primaryColor) from beginRendering. A
|
|
9809
|
-
// re-render keeps any prior styles unless the new beginRendering
|
|
9810
|
-
// explicitly overrides them — this matches the agent's likely
|
|
9811
|
-
// intent ("change the data, keep the look").
|
|
9812
|
-
const nextStyles = begin.styles
|
|
9813
|
-
?? existing?.styles;
|
|
9814
|
-
const surface = {
|
|
9815
|
-
surfaceId: begin.surfaceId,
|
|
9816
|
-
catalogId: 'basic',
|
|
9817
|
-
components: b.components,
|
|
9818
|
-
dataModel,
|
|
9819
|
-
...(nextStyles ? { styles: nextStyles } : {}),
|
|
9820
|
-
};
|
|
9821
|
-
const next = new Map(surfacesSignal());
|
|
9822
|
-
next.set(begin.surfaceId, surface);
|
|
9823
|
-
surfacesSignal.set(next);
|
|
9824
|
-
// Project per-component views with initial readiness based on the
|
|
9825
|
-
// accumulated data model.
|
|
9826
|
-
const baseViews = b.componentViews ?? new Map();
|
|
9827
|
-
const initialViews = new Map();
|
|
9828
|
-
for (const [id, v] of baseViews) {
|
|
9829
|
-
const allResolved = v.bindings.every((p) => isResolved(dataModel, p));
|
|
9830
|
-
initialViews.set(id, {
|
|
9831
|
-
...v,
|
|
9832
|
-
ready: allResolved,
|
|
9833
|
-
props: allResolved
|
|
9834
|
-
? resolveProps(v.def, dataModel)
|
|
9835
|
-
: {},
|
|
9836
|
-
});
|
|
10015
|
+
else {
|
|
10016
|
+
bufferOf(upd.surfaceId).dataModelDeltas.push(delta);
|
|
9837
10017
|
}
|
|
9838
|
-
const nextStates = new Map(surfaceStatesSignal());
|
|
9839
|
-
nextStates.set(begin.surfaceId, { surface, componentViews: initialViews });
|
|
9840
|
-
surfaceStatesSignal.set(nextStates);
|
|
9841
|
-
// Reset buffer so subsequent surfaceUpdate is the next round.
|
|
9842
|
-
buffers.set(begin.surfaceId, { dataModelDeltas: [] });
|
|
9843
10018
|
return;
|
|
9844
10019
|
}
|
|
9845
10020
|
if ('deleteSurface' in message) {
|
|
@@ -10151,7 +10326,7 @@ function createContentClassifier() {
|
|
|
10151
10326
|
|
|
10152
10327
|
// libs/chat/src/lib/a2ui/envelope-normalizer.ts
|
|
10153
10328
|
// SPDX-License-Identifier: MIT
|
|
10154
|
-
const ENVELOPE_KEYS = ['
|
|
10329
|
+
const ENVELOPE_KEYS = ['createSurface', 'updateComponents', 'updateDataModel', 'deleteSurface'];
|
|
10155
10330
|
/**
|
|
10156
10331
|
* The parent LLM may emit envelope-tool arguments in four shapes (observed in
|
|
10157
10332
|
* the spike across gpt-5-mini and gpt-5): the canonical {envelopes: [...]},
|
|
@@ -10183,7 +10358,7 @@ function normalizeEnvelopeArgs(args) {
|
|
|
10183
10358
|
.sort((a, b) => a - b)
|
|
10184
10359
|
.map((k) => args[String(k)]);
|
|
10185
10360
|
}
|
|
10186
|
-
// (d) flat single envelope: {
|
|
10361
|
+
// (d) flat single envelope: { createSurface: {...} } | { updateComponents: ... } | etc
|
|
10187
10362
|
if (ENVELOPE_KEYS.some((k) => k in args)) {
|
|
10188
10363
|
return [args];
|
|
10189
10364
|
}
|
|
@@ -10374,17 +10549,15 @@ function isValidJsonPrefix(s) {
|
|
|
10374
10549
|
* tool_call.arguments JSON. Uses @cacheplane/partial-json to extract
|
|
10375
10550
|
* structurally-complete envelope objects from the growing args string.
|
|
10376
10551
|
*
|
|
10377
|
-
* Synthesis safety net:
|
|
10378
|
-
*
|
|
10379
|
-
*
|
|
10380
|
-
*
|
|
10381
|
-
*
|
|
10382
|
-
*
|
|
10383
|
-
* (PR #252) actually fires while dataModelUpdates flow in.
|
|
10552
|
+
* Synthesis safety net: v0.9 requires a `createSurface` envelope before
|
|
10553
|
+
* any `updateComponents`. If a complete `updateComponents` arrives for a
|
|
10554
|
+
* surface with no `createSurface` seen yet this turn, the bridge
|
|
10555
|
+
* synthesises one (basic catalog) so the surface can mount as soon as its
|
|
10556
|
+
* `root` component is defined — the store gates rendering on
|
|
10557
|
+
* createSurface + root, and fills the tree in progressively after that.
|
|
10384
10558
|
*
|
|
10385
|
-
* The store
|
|
10386
|
-
*
|
|
10387
|
-
* beginRendering (if any) is a no-op rather than a conflict.
|
|
10559
|
+
* The store treats a later "real" createSurface for the same surface as an
|
|
10560
|
+
* idempotent refresh, so LLMs that emit one out of order are harmless.
|
|
10388
10561
|
*/
|
|
10389
10562
|
function createPartialArgsBridge(store) {
|
|
10390
10563
|
const states = new Map();
|
|
@@ -10394,20 +10567,13 @@ function createPartialArgsBridge(store) {
|
|
|
10394
10567
|
s = {
|
|
10395
10568
|
parser: createPartialJsonParser(),
|
|
10396
10569
|
dispatchedCount: 0,
|
|
10397
|
-
|
|
10398
|
-
synthesisedSurfaceId: null,
|
|
10570
|
+
createDispatched: new Set(),
|
|
10399
10571
|
poisoned: false,
|
|
10400
10572
|
};
|
|
10401
10573
|
states.set(toolCallId, s);
|
|
10402
10574
|
}
|
|
10403
10575
|
return s;
|
|
10404
10576
|
}
|
|
10405
|
-
function pickRoot(components) {
|
|
10406
|
-
if (components.length === 0)
|
|
10407
|
-
return null;
|
|
10408
|
-
const explicitRoot = components.find((c) => c.id === 'root');
|
|
10409
|
-
return explicitRoot ? explicitRoot.id : components[0].id;
|
|
10410
|
-
}
|
|
10411
10577
|
function push(toolCallId, argsSoFar) {
|
|
10412
10578
|
const state = stateOf(toolCallId);
|
|
10413
10579
|
if (state.poisoned)
|
|
@@ -10437,32 +10603,8 @@ function createPartialArgsBridge(store) {
|
|
|
10437
10603
|
const envelopes = normalizeEnvelopeArgs(materialised);
|
|
10438
10604
|
if (!envelopes)
|
|
10439
10605
|
return;
|
|
10440
|
-
//
|
|
10441
|
-
//
|
|
10442
|
-
// — otherwise pickRoot returns null and synthesis silently no-ops, leaving
|
|
10443
|
-
// the surface unmounted forever. Once we have a pickable root, dispatch
|
|
10444
|
-
// the surfaceUpdate AND a synthesised beginRendering as an atomic pair.
|
|
10445
|
-
if (!state.surfacePairDispatched) {
|
|
10446
|
-
const firstEnv = envelopes[0];
|
|
10447
|
-
if (!firstEnv || !('surfaceUpdate' in firstEnv))
|
|
10448
|
-
return;
|
|
10449
|
-
if (!isStructurallyComplete(firstEnv))
|
|
10450
|
-
return;
|
|
10451
|
-
const upd = firstEnv.surfaceUpdate;
|
|
10452
|
-
if (upd.components.length === 0)
|
|
10453
|
-
return;
|
|
10454
|
-
const root = pickRoot(upd.components);
|
|
10455
|
-
if (!root)
|
|
10456
|
-
return;
|
|
10457
|
-
state.surfacePairDispatched = true;
|
|
10458
|
-
state.dispatchedCount = 1; // index 0 = the surfaceUpdate we just sent
|
|
10459
|
-
state.synthesisedSurfaceId = upd.surfaceId;
|
|
10460
|
-
store.applyPartialArgs(toolCallId, [
|
|
10461
|
-
firstEnv,
|
|
10462
|
-
{ beginRendering: { surfaceId: upd.surfaceId, root } },
|
|
10463
|
-
]);
|
|
10464
|
-
}
|
|
10465
|
-
// Phase 2: dispatch any newly-complete envelopes beyond the initial pair.
|
|
10606
|
+
// Dispatch newly-complete envelopes in order, synthesising the missing
|
|
10607
|
+
// createSurface when the stream leads with components.
|
|
10466
10608
|
const newEnvelopes = [];
|
|
10467
10609
|
for (let i = state.dispatchedCount; i < envelopes.length; i++) {
|
|
10468
10610
|
const env = envelopes[i];
|
|
@@ -10471,14 +10613,18 @@ function createPartialArgsBridge(store) {
|
|
|
10471
10613
|
// exist before earlier ones complete (envelopes are an ordered list).
|
|
10472
10614
|
break;
|
|
10473
10615
|
}
|
|
10474
|
-
|
|
10475
|
-
|
|
10476
|
-
|
|
10477
|
-
if ('
|
|
10478
|
-
env.
|
|
10479
|
-
|
|
10480
|
-
|
|
10481
|
-
|
|
10616
|
+
if ('createSurface' in env) {
|
|
10617
|
+
state.createDispatched.add(env.createSurface.surfaceId);
|
|
10618
|
+
}
|
|
10619
|
+
else if ('updateComponents' in env) {
|
|
10620
|
+
const surfaceId = env.updateComponents.surfaceId;
|
|
10621
|
+
if (!state.createDispatched.has(surfaceId)) {
|
|
10622
|
+
state.createDispatched.add(surfaceId);
|
|
10623
|
+
newEnvelopes.push({
|
|
10624
|
+
version: A2UI_WIRE_VERSION,
|
|
10625
|
+
createSurface: { surfaceId, catalogId: A2UI_BASIC_CATALOG_ID },
|
|
10626
|
+
});
|
|
10627
|
+
}
|
|
10482
10628
|
}
|
|
10483
10629
|
newEnvelopes.push(env);
|
|
10484
10630
|
state.dispatchedCount = i + 1;
|
|
@@ -10497,12 +10643,27 @@ function isStructurallyComplete(env) {
|
|
|
10497
10643
|
if (!env || typeof env !== 'object' || Array.isArray(env))
|
|
10498
10644
|
return false;
|
|
10499
10645
|
const obj = env;
|
|
10500
|
-
for (const k of ['
|
|
10646
|
+
for (const k of ['createSurface', 'updateComponents', 'updateDataModel', 'deleteSurface']) {
|
|
10501
10647
|
if (k in obj && typeof obj[k] === 'object' && obj[k] !== null) {
|
|
10502
|
-
// For
|
|
10503
|
-
|
|
10504
|
-
|
|
10505
|
-
|
|
10648
|
+
// For updateComponents, require surfaceId + components where every
|
|
10649
|
+
// component has at least parsed its `id` and `component` fields —
|
|
10650
|
+
// a half-streamed component object materialises as `{}` and must not
|
|
10651
|
+
// dispatch (it would consume the envelope index and drop the real
|
|
10652
|
+
// components forever, since re-parses skip dispatched indices).
|
|
10653
|
+
if (k === 'updateComponents') {
|
|
10654
|
+
const uc = obj[k];
|
|
10655
|
+
return typeof uc.surfaceId === 'string'
|
|
10656
|
+
&& Array.isArray(uc.components)
|
|
10657
|
+
&& uc.components.length > 0
|
|
10658
|
+
&& uc.components.every((c) => c != null && typeof c === 'object'
|
|
10659
|
+
&& typeof c.id === 'string'
|
|
10660
|
+
&& typeof c.component === 'string');
|
|
10661
|
+
}
|
|
10662
|
+
// For createSurface, require both ids so a half-streamed envelope
|
|
10663
|
+
// doesn't commit with an undefined catalogId.
|
|
10664
|
+
if (k === 'createSurface') {
|
|
10665
|
+
const cs = obj[k];
|
|
10666
|
+
return typeof cs.surfaceId === 'string' && typeof cs.catalogId === 'string';
|
|
10506
10667
|
}
|
|
10507
10668
|
return true;
|
|
10508
10669
|
}
|
|
@@ -10514,7 +10675,7 @@ function isStructurallyComplete(env) {
|
|
|
10514
10675
|
/**
|
|
10515
10676
|
* Synthesize a short human-readable label for a serialized A2UI action
|
|
10516
10677
|
* message, so the chat composition can render "Search flights" instead
|
|
10517
|
-
* of a raw `{"version":"
|
|
10678
|
+
* of a raw `{"version":"v0.9","action":...}` JSON dump as a user bubble.
|
|
10518
10679
|
*
|
|
10519
10680
|
* Per the A2UI spec, action messages flow on the client → agent
|
|
10520
10681
|
* return channel and are framed as typed events (closer to tool calls
|
|
@@ -10531,7 +10692,7 @@ function isStructurallyComplete(env) {
|
|
|
10531
10692
|
* "Booking submit"). Used when no label was stamped — typically
|
|
10532
10693
|
* because the source component isn't a Button-with-Text-child.
|
|
10533
10694
|
*
|
|
10534
|
-
* Returns null for any content that isn't
|
|
10695
|
+
* Returns null for any content that isn't an A2UI action message;
|
|
10535
10696
|
* callers should fall back to the original content in that case.
|
|
10536
10697
|
*
|
|
10537
10698
|
* Design context: a previous iteration shipped a hardcoded
|
|
@@ -10560,7 +10721,8 @@ function a2uiActionLabel(content) {
|
|
|
10560
10721
|
}
|
|
10561
10722
|
if (!isRecord$1(parsed))
|
|
10562
10723
|
return null;
|
|
10563
|
-
|
|
10724
|
+
const version = parsed['version'];
|
|
10725
|
+
if (typeof version !== 'string' || !version.startsWith('v'))
|
|
10564
10726
|
return null;
|
|
10565
10727
|
const action = parsed['action'];
|
|
10566
10728
|
if (!isRecord$1(action))
|
|
@@ -11256,10 +11418,10 @@ class ChatComponent {
|
|
|
11256
11418
|
// A2UI/json-render markers in the content string.
|
|
11257
11419
|
const projectedContent = m.content;
|
|
11258
11420
|
if (typeof projectedContent === 'string' && projectedContent.length > 0) {
|
|
11259
|
-
// A2UI
|
|
11260
|
-
if (projectedContent.includes('"
|
|
11261
|
-
|| projectedContent.includes('"
|
|
11262
|
-
|| projectedContent.includes('"
|
|
11421
|
+
// A2UI v0.9 envelope keys (canonical Google shape).
|
|
11422
|
+
if (projectedContent.includes('"createSurface"')
|
|
11423
|
+
|| projectedContent.includes('"updateComponents"')
|
|
11424
|
+
|| projectedContent.includes('"updateDataModel"')) {
|
|
11263
11425
|
return true;
|
|
11264
11426
|
}
|
|
11265
11427
|
// json-render spec shape — looks like `{ "root": "...", "elements": ... }`.
|
|
@@ -11548,7 +11710,7 @@ class ChatComponent {
|
|
|
11548
11710
|
</div>
|
|
11549
11711
|
</div>
|
|
11550
11712
|
}
|
|
11551
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:flex;flex-direction:column;flex:1 1 auto;height:100%;min-height:0;max-height:100%;overflow:hidden;background:var(--tplane-chat-bg)}:host>chat-welcome{display:flex;flex:1 1 auto;width:100%}.chat-shell{display:flex;flex:1;min-height:0;overflow:hidden}.chat-shell__sidebar{width:240px;flex-shrink:0;border-right:1px solid var(--tplane-chat-separator);background:var(--tplane-chat-surface-alt);overflow-y:auto;display:none}@media(min-width:768px){.chat-shell__sidebar{display:block}}.chat-shell__main{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0}.chat-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:60px 20px;color:var(--tplane-chat-text-muted);text-align:center;flex:1;min-height:0}.chat-empty[hidden]{display:none}.chat-empty__title{font-size:1.125rem;font-weight:500;color:var(--tplane-chat-text);margin:0}.chat-empty__sub{margin:0;font-size:var(--tplane-chat-font-size-sm)}.chat-scroll{flex:1;min-height:0;overflow-y:auto;padding-top:var(--tplane-chat-edge-pad)}.chat-scroll::-webkit-scrollbar{width:6px}.chat-scroll::-webkit-scrollbar-thumb{background:var(--tplane-chat-separator);border-radius:10px}[chatFooter]{padding-bottom:var(--tplane-chat-edge-pad)}.chat-footer-wrap{position:relative}\n"], dependencies: [{ kind: "component", type: ChatWindowComponent, selector: "chat-window" }, { kind: "component", type: ChatMessageListComponent, selector: "chat-message-list", inputs: ["agent"] }, { kind: "directive", type: MessageTemplateDirective, selector: "ng-template[chatMessageTemplate]", inputs: ["chatMessageTemplate"] }, { kind: "component", type: ChatMessageComponent, selector: "chat-message", inputs: ["role", "current", "streaming", "prevRole", "message"] }, { kind: "component", type: ChatInputComponent, selector: "chat-input", inputs: ["agent", "submitOnEnter", "placeholder", "showStopButton"], outputs: ["submitted", "stopped"] }, { kind: "component", type: ChatTypingIndicatorComponent, selector: "chat-typing-indicator", inputs: ["agent"] }, { kind: "component", type: ChatErrorComponent, selector: "chat-error", inputs: ["agent"] }, { kind: "component", type: ChatThreadListComponent, selector: "chat-thread-list", inputs: ["threads", "activeThreadId", "showNewThreadButton", "actions", "mode", "projects"], outputs: ["threadSelected", "newThreadRequested"] }, { kind: "component", type: ChatGenerativeUiComponent, selector: "chat-generative-ui", inputs: ["spec", "registry", "store", "handlers", "loading"], outputs: ["events"] }, { kind: "component", type: ChatStreamingMdComponent, selector: "chat-streaming-md", inputs: ["document", "viewRegistry"] }, { kind: "component", type: ChatToolCallsComponent, selector: "chat-tool-calls", inputs: ["agent", "message", "grouping", "groupSummary", "excludeToolNames"] }, { kind: "component", type: ChatToolViewsComponent, selector: "chat-tool-views", inputs: ["agent", "message", "views", "store", "handlers"], outputs: ["events"] }, { kind: "component", type: A2uiSurfaceComponent, selector: "a2ui-surface", inputs: ["surface", "state", "catalog", "handlers", "surfaceFallback"], outputs: ["events", "action"] }, { kind: "component", type: ChatMessageActionsComponent, selector: "chat-message-actions", inputs: ["content", "disabled"], outputs: ["regenerate", "rate", "contentCopied"] }, { kind: "component", type: ChatWelcomeComponent, selector: "chat-welcome" }, { kind: "component", type: ChatSelectComponent, selector: "chat-select", inputs: ["options", "value", "placeholder", "disabled", "menuLabel", "panelClass"], outputs: ["valueChange"] }, { kind: "component", type: ChatReasoningComponent, selector: "chat-reasoning", inputs: ["content", "delivery", "durationMs", "label", "defaultExpanded"] }, { kind: "component", type: ChatScrollBubbleComponent, selector: "chat-scroll-bubble", inputs: ["mode"], outputs: ["clicked"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11713
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:flex;flex-direction:column;flex:1 1 auto;height:100%;min-height:0;max-height:100%;overflow:hidden;background:var(--tplane-chat-bg)}:host>chat-welcome{display:flex;flex:1 1 auto;width:100%}.chat-shell{display:flex;flex:1;min-height:0;overflow:hidden}.chat-shell__sidebar{width:240px;flex-shrink:0;border-right:1px solid var(--tplane-chat-separator);background:var(--tplane-chat-surface-alt);overflow-y:auto;display:none}@media(min-width:768px){.chat-shell__sidebar{display:block}}.chat-shell__main{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0}.chat-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:60px 20px;color:var(--tplane-chat-text-muted);text-align:center;flex:1;min-height:0}.chat-empty[hidden]{display:none}.chat-empty__title{font-size:1.125rem;font-weight:500;color:var(--tplane-chat-text);margin:0}.chat-empty__sub{margin:0;font-size:var(--tplane-chat-font-size-sm)}.chat-scroll{flex:1;min-height:0;overflow-y:auto;padding-top:var(--tplane-chat-edge-pad)}.chat-scroll::-webkit-scrollbar{width:6px}.chat-scroll::-webkit-scrollbar-thumb{background:var(--tplane-chat-separator);border-radius:10px}[chatFooter]{padding-bottom:var(--tplane-chat-edge-pad)}.chat-footer-wrap{position:relative}\n"], dependencies: [{ kind: "component", type: ChatWindowComponent, selector: "chat-window" }, { kind: "component", type: ChatMessageListComponent, selector: "chat-message-list", inputs: ["agent"] }, { kind: "directive", type: MessageTemplateDirective, selector: "ng-template[chatMessageTemplate]", inputs: ["chatMessageTemplate"] }, { kind: "component", type: ChatMessageComponent, selector: "chat-message", inputs: ["role", "current", "streaming", "prevRole", "message"] }, { kind: "component", type: ChatInputComponent, selector: "chat-input", inputs: ["agent", "submitOnEnter", "placeholder", "showStopButton"], outputs: ["submitted", "stopped"] }, { kind: "component", type: ChatTypingIndicatorComponent, selector: "chat-typing-indicator", inputs: ["agent"] }, { kind: "component", type: ChatErrorComponent, selector: "chat-error", inputs: ["agent"] }, { kind: "component", type: ChatThreadListComponent, selector: "chat-thread-list", inputs: ["threads", "activeThreadId", "showNewThreadButton", "actions", "mode", "projects"], outputs: ["threadSelected", "newThreadRequested"] }, { kind: "component", type: ChatGenerativeUiComponent, selector: "chat-generative-ui", inputs: ["spec", "registry", "store", "handlers", "loading"], outputs: ["events"] }, { kind: "component", type: ChatStreamingMdComponent, selector: "chat-streaming-md", inputs: ["document", "viewRegistry"] }, { kind: "component", type: ChatToolCallsComponent, selector: "chat-tool-calls", inputs: ["agent", "message", "grouping", "groupSummary", "excludeToolNames"] }, { kind: "component", type: ChatToolViewsComponent, selector: "chat-tool-views", inputs: ["agent", "message", "views", "store", "handlers"], outputs: ["events"] }, { kind: "component", type: A2uiSurfaceComponent, selector: "a2ui-surface", inputs: ["surface", "state", "catalog", "handlers", "surfaceFallback"], outputs: ["events", "action", "validationError"] }, { kind: "component", type: ChatMessageActionsComponent, selector: "chat-message-actions", inputs: ["content", "disabled"], outputs: ["regenerate", "rate", "contentCopied"] }, { kind: "component", type: ChatWelcomeComponent, selector: "chat-welcome" }, { kind: "component", type: ChatSelectComponent, selector: "chat-select", inputs: ["options", "value", "placeholder", "disabled", "menuLabel", "panelClass"], outputs: ["valueChange"] }, { kind: "component", type: ChatReasoningComponent, selector: "chat-reasoning", inputs: ["content", "delivery", "durationMs", "label", "defaultExpanded"] }, { kind: "component", type: ChatScrollBubbleComponent, selector: "chat-scroll-bubble", inputs: ["mode"], outputs: ["clicked"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11552
11714
|
}
|
|
11553
11715
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatComponent, decorators: [{
|
|
11554
11716
|
type: Component,
|
|
@@ -12493,6 +12655,37 @@ const CHAT_DEBUG_INCLUDED = ngDevMode ||
|
|
|
12493
12655
|
|
|
12494
12656
|
// libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.ts
|
|
12495
12657
|
// SPDX-License-Identifier: MIT
|
|
12658
|
+
/**
|
|
12659
|
+
* The conversation sidebar: thread list, projects, search, and the new-chat
|
|
12660
|
+
* action. Pair it with a runtime's thread store (e.g. `LangGraphThreadsAdapter`)
|
|
12661
|
+
* and a {@link ThreadActionAdapter} for the per-row rename/delete/archive menu.
|
|
12662
|
+
*
|
|
12663
|
+
* **This component renders the sidebar only — it is not a layout wrapper.** Its
|
|
12664
|
+
* `<ng-content>` slots are all named (`sidenavHeader`, `sidenavPrimary`,
|
|
12665
|
+
* `sidenavSections`, `sidenavFooterLeft`, `sidenavFooterRight`,
|
|
12666
|
+
* `sidenavAccount`) and target regions *inside* the sidebar. There is no default
|
|
12667
|
+
* slot, so a `<chat>` placed between the tags is silently dropped. Render the
|
|
12668
|
+
* chat as a sibling and lay the two out yourself:
|
|
12669
|
+
*
|
|
12670
|
+
* @example
|
|
12671
|
+
* ```html
|
|
12672
|
+
* <chat-sidenav
|
|
12673
|
+
* [threads]="threads.threads()"
|
|
12674
|
+
* [activeThreadId]="activeThread()"
|
|
12675
|
+
* [actions]="threadActions"
|
|
12676
|
+
* [agent]="agent"
|
|
12677
|
+
* (newChat)="activeThread.set(null)"
|
|
12678
|
+
* (threadSelected)="activeThread.set($event)"
|
|
12679
|
+
* />
|
|
12680
|
+
* <main class="chat-pane">
|
|
12681
|
+
* <chat [agent]="agent" />
|
|
12682
|
+
* </main>
|
|
12683
|
+
* ```
|
|
12684
|
+
* ```css
|
|
12685
|
+
* :host { display: flex; height: 100dvh; }
|
|
12686
|
+
* .chat-pane { flex: 1; min-width: 0; }
|
|
12687
|
+
* ```
|
|
12688
|
+
*/
|
|
12496
12689
|
class ChatSidenavComponent {
|
|
12497
12690
|
mode = input('expanded', ...(ngDevMode ? [{ debugName: "mode" }] : []));
|
|
12498
12691
|
open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
@@ -13430,11 +13623,8 @@ function normalizeViewEntry(entry) {
|
|
|
13430
13623
|
// SPDX-License-Identifier: MIT
|
|
13431
13624
|
class A2uiAudioPlayerComponent {
|
|
13432
13625
|
url = input('', ...(ngDevMode ? [{ debugName: "url" }] : []));
|
|
13433
|
-
/**
|
|
13626
|
+
/** v0.9 prop: short description / title rendered above the player. */
|
|
13434
13627
|
description = input('', ...(ngDevMode ? [{ debugName: "description" }] : []));
|
|
13435
|
-
/** v1 prop name: autoPlay (camelCase). */
|
|
13436
|
-
autoPlay = input(false, ...(ngDevMode ? [{ debugName: "autoPlay" }] : []));
|
|
13437
|
-
controls = input(true, ...(ngDevMode ? [{ debugName: "controls" }] : []));
|
|
13438
13628
|
// Framework inputs required by the render harness.
|
|
13439
13629
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13440
13630
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
@@ -13442,7 +13632,7 @@ class A2uiAudioPlayerComponent {
|
|
|
13442
13632
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13443
13633
|
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13444
13634
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiAudioPlayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13445
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiAudioPlayerComponent, isStandalone: true, selector: "a2ui-audio-player", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null },
|
|
13635
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiAudioPlayerComponent, isStandalone: true, selector: "a2ui-audio-player", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13446
13636
|
<div class="a2ui-audio-wrap">
|
|
13447
13637
|
@if (description()) {
|
|
13448
13638
|
<span class="a2ui-audio-description">{{ description() }}</span>
|
|
@@ -13450,8 +13640,7 @@ class A2uiAudioPlayerComponent {
|
|
|
13450
13640
|
<audio
|
|
13451
13641
|
class="a2ui-audio"
|
|
13452
13642
|
[src]="url()"
|
|
13453
|
-
|
|
13454
|
-
[controls]="controls()"
|
|
13643
|
+
controls
|
|
13455
13644
|
></audio>
|
|
13456
13645
|
</div>
|
|
13457
13646
|
`, isInline: true, styles: [".a2ui-audio-wrap{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-audio-description{font-size:var(--a2ui-typography-caption-size);color:var(--a2ui-on-surface-variant)}.a2ui-audio{display:block;width:100%}\n"] });
|
|
@@ -13466,31 +13655,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
13466
13655
|
<audio
|
|
13467
13656
|
class="a2ui-audio"
|
|
13468
13657
|
[src]="url()"
|
|
13469
|
-
|
|
13470
|
-
[controls]="controls()"
|
|
13658
|
+
controls
|
|
13471
13659
|
></audio>
|
|
13472
13660
|
</div>
|
|
13473
13661
|
`, styles: [".a2ui-audio-wrap{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-audio-description{font-size:var(--a2ui-typography-caption-size);color:var(--a2ui-on-surface-variant)}.a2ui-audio{display:block;width:100%}\n"] }]
|
|
13474
|
-
}], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }],
|
|
13662
|
+
}], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
13475
13663
|
|
|
13476
13664
|
// SPDX-License-Identifier: MIT
|
|
13665
|
+
const VARIANT_CLASS = {
|
|
13666
|
+
default: 'a2ui-btn a2ui-btn--default',
|
|
13667
|
+
primary: 'a2ui-btn a2ui-btn--primary',
|
|
13668
|
+
borderless: 'a2ui-btn a2ui-btn--borderless',
|
|
13669
|
+
};
|
|
13477
13670
|
class A2uiButtonComponent {
|
|
13478
|
-
/**
|
|
13671
|
+
/** v0.9: child Text component is rendered inside the button via childKeys. */
|
|
13479
13672
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13480
13673
|
spec = input.required(...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13481
|
-
|
|
13674
|
+
/** v0.9 prop: visual style (default 'default'). */
|
|
13675
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
13482
13676
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
13483
13677
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
13484
13678
|
// Framework inputs required by the render harness.
|
|
13485
13679
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13486
13680
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
13681
|
+
cssClass() {
|
|
13682
|
+
return VARIANT_CLASS[this.variant()] ?? VARIANT_CLASS['default'];
|
|
13683
|
+
}
|
|
13487
13684
|
handleClick() {
|
|
13488
13685
|
this.emit()('click');
|
|
13489
13686
|
}
|
|
13490
13687
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13491
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiButtonComponent, isStandalone: true, selector: "a2ui-button", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null },
|
|
13688
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiButtonComponent, isStandalone: true, selector: "a2ui-button", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13492
13689
|
<button
|
|
13493
|
-
[class]="
|
|
13690
|
+
[class]="cssClass()"
|
|
13494
13691
|
[disabled]="disabled()"
|
|
13495
13692
|
(click)="handleClick()"
|
|
13496
13693
|
>
|
|
@@ -13498,13 +13695,13 @@ class A2uiButtonComponent {
|
|
|
13498
13695
|
<render-element [elementKey]="key" [spec]="spec()" />
|
|
13499
13696
|
}
|
|
13500
13697
|
</button>
|
|
13501
|
-
`, isInline: true, styles: [".a2ui-btn{display:inline-flex;align-items:center;justify-content:center;padding:var(--a2ui-spacing-2) var(--a2ui-spacing-4);border-radius:var(--a2ui-shape-small);font-size:var(--a2ui-typography-body-size);font-weight:500;cursor:pointer;transition:background var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard),opacity var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard);border:none}.a2ui-btn:disabled{opacity:.5;cursor:not-allowed}.a2ui-btn--primary{background:var(--a2ui-primary);color:var(--a2ui-on-primary)}.a2ui-btn--primary:hover:not(:disabled){background:var(--a2ui-primary-hover)}.a2ui-btn--
|
|
13698
|
+
`, isInline: true, styles: [".a2ui-btn{display:inline-flex;align-items:center;justify-content:center;padding:var(--a2ui-spacing-2) var(--a2ui-spacing-4);border-radius:var(--a2ui-shape-small);font-size:var(--a2ui-typography-body-size);font-weight:500;cursor:pointer;transition:background var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard),opacity var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard);border:none}.a2ui-btn:disabled{opacity:.5;cursor:not-allowed}.a2ui-btn--primary{background:var(--a2ui-primary);color:var(--a2ui-on-primary)}.a2ui-btn--primary:hover:not(:disabled){background:var(--a2ui-primary-hover)}.a2ui-btn--default{background:var(--a2ui-surface-variant);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline)}.a2ui-btn--default:hover:not(:disabled){background:var(--a2ui-outline)}.a2ui-btn--borderless{background:transparent;color:var(--a2ui-on-surface);border:none}.a2ui-btn--borderless:hover:not(:disabled){background:var(--a2ui-surface-variant)}\n"], dependencies: [{ kind: "component", type: RenderElementComponent, selector: "render-element", inputs: ["elementKey", "spec"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13502
13699
|
}
|
|
13503
13700
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiButtonComponent, decorators: [{
|
|
13504
13701
|
type: Component,
|
|
13505
13702
|
args: [{ selector: 'a2ui-button', standalone: true, imports: [RenderElementComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
13506
13703
|
<button
|
|
13507
|
-
[class]="
|
|
13704
|
+
[class]="cssClass()"
|
|
13508
13705
|
[disabled]="disabled()"
|
|
13509
13706
|
(click)="handleClick()"
|
|
13510
13707
|
>
|
|
@@ -13512,8 +13709,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
13512
13709
|
<render-element [elementKey]="key" [spec]="spec()" />
|
|
13513
13710
|
}
|
|
13514
13711
|
</button>
|
|
13515
|
-
`, styles: [".a2ui-btn{display:inline-flex;align-items:center;justify-content:center;padding:var(--a2ui-spacing-2) var(--a2ui-spacing-4);border-radius:var(--a2ui-shape-small);font-size:var(--a2ui-typography-body-size);font-weight:500;cursor:pointer;transition:background var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard),opacity var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard);border:none}.a2ui-btn:disabled{opacity:.5;cursor:not-allowed}.a2ui-btn--primary{background:var(--a2ui-primary);color:var(--a2ui-on-primary)}.a2ui-btn--primary:hover:not(:disabled){background:var(--a2ui-primary-hover)}.a2ui-btn--
|
|
13516
|
-
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }],
|
|
13712
|
+
`, styles: [".a2ui-btn{display:inline-flex;align-items:center;justify-content:center;padding:var(--a2ui-spacing-2) var(--a2ui-spacing-4);border-radius:var(--a2ui-shape-small);font-size:var(--a2ui-typography-body-size);font-weight:500;cursor:pointer;transition:background var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard),opacity var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard);border:none}.a2ui-btn:disabled{opacity:.5;cursor:not-allowed}.a2ui-btn--primary{background:var(--a2ui-primary);color:var(--a2ui-on-primary)}.a2ui-btn--primary:hover:not(:disabled){background:var(--a2ui-primary-hover)}.a2ui-btn--default{background:var(--a2ui-surface-variant);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline)}.a2ui-btn--default:hover:not(:disabled){background:var(--a2ui-outline)}.a2ui-btn--borderless{background:transparent;color:var(--a2ui-on-surface);border:none}.a2ui-btn--borderless:hover:not(:disabled){background:var(--a2ui-surface-variant)}\n"] }]
|
|
13713
|
+
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
13517
13714
|
|
|
13518
13715
|
// SPDX-License-Identifier: MIT
|
|
13519
13716
|
class A2uiCardComponent {
|
|
@@ -13556,83 +13753,302 @@ function emitBinding(host, bindings, prop, value) {
|
|
|
13556
13753
|
class A2uiCheckBoxComponent {
|
|
13557
13754
|
host = injectRenderHost();
|
|
13558
13755
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
13559
|
-
/**
|
|
13560
|
-
value = input(
|
|
13561
|
-
/**
|
|
13562
|
-
|
|
13756
|
+
/** v0.9 prop: boolean checked state. */
|
|
13757
|
+
value = input(false, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
13758
|
+
/** Live validation message written by the surface's check gate
|
|
13759
|
+
* (bound to /_a2uiChecks/<id>); empty when valid. */
|
|
13760
|
+
errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : []));
|
|
13563
13761
|
_bindings = input({}, ...(ngDevMode ? [{ debugName: "_bindings" }] : []));
|
|
13564
13762
|
// Framework inputs required by the render harness.
|
|
13565
13763
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13566
13764
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
13567
13765
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13568
13766
|
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13569
|
-
effectiveValue = computed(() => this.value() ?? this.checked(), ...(ngDevMode ? [{ debugName: "effectiveValue" }] : []));
|
|
13570
13767
|
onChange(event) {
|
|
13571
13768
|
const val = event.target.checked;
|
|
13572
|
-
|
|
13573
|
-
// `value`; pre-v1 used `checked`.
|
|
13574
|
-
const bound = this._bindings();
|
|
13575
|
-
if (bound['value']) {
|
|
13576
|
-
emitBinding(this.host, bound, 'value', val);
|
|
13577
|
-
}
|
|
13578
|
-
else {
|
|
13579
|
-
emitBinding(this.host, bound, 'checked', val);
|
|
13580
|
-
}
|
|
13769
|
+
emitBinding(this.host, this._bindings(), 'value', val);
|
|
13581
13770
|
}
|
|
13582
13771
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiCheckBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13583
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
13772
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiCheckBoxComponent, isStandalone: true, selector: "a2ui-check-box", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, _bindings: { classPropertyName: "_bindings", publicName: "_bindings", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13584
13773
|
<label class="a2ui-cb">
|
|
13585
|
-
<input type="checkbox" [checked]="
|
|
13774
|
+
<input type="checkbox" [checked]="value()" (change)="onChange($event)" class="a2ui-cb__input" />
|
|
13586
13775
|
{{ label() }}
|
|
13587
13776
|
</label>
|
|
13588
|
-
|
|
13777
|
+
@if (errorText()) {
|
|
13778
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
13779
|
+
}
|
|
13780
|
+
`, isInline: true, styles: [".a2ui-cb{display:flex;align-items:center;gap:var(--a2ui-spacing-2);font-size:var(--a2ui-typography-body-size);cursor:pointer}.a2ui-cb__input{width:16px;height:16px;border-radius:var(--a2ui-shape-extra-small);cursor:pointer;accent-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13589
13781
|
}
|
|
13590
13782
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiCheckBoxComponent, decorators: [{
|
|
13591
13783
|
type: Component,
|
|
13592
13784
|
args: [{ selector: 'a2ui-check-box', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
13593
13785
|
<label class="a2ui-cb">
|
|
13594
|
-
<input type="checkbox" [checked]="
|
|
13786
|
+
<input type="checkbox" [checked]="value()" (change)="onChange($event)" class="a2ui-cb__input" />
|
|
13595
13787
|
{{ label() }}
|
|
13596
13788
|
</label>
|
|
13597
|
-
|
|
13598
|
-
|
|
13789
|
+
@if (errorText()) {
|
|
13790
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
13791
|
+
}
|
|
13792
|
+
`, styles: [".a2ui-cb{display:flex;align-items:center;gap:var(--a2ui-spacing-2);font-size:var(--a2ui-typography-body-size);cursor:pointer}.a2ui-cb__input{width:16px;height:16px;border-radius:var(--a2ui-shape-extra-small);cursor:pointer;accent-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"] }]
|
|
13793
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], _bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "_bindings", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
13599
13794
|
|
|
13600
13795
|
// SPDX-License-Identifier: MIT
|
|
13601
|
-
|
|
13796
|
+
class A2uiChoicePickerComponent {
|
|
13797
|
+
static _idCounter = 0;
|
|
13798
|
+
/** Groups the radio inputs of this instance (mutuallyExclusive mode). */
|
|
13799
|
+
_groupName = `a2ui-choice-picker-${++A2uiChoicePickerComponent._idCounter}`;
|
|
13800
|
+
host = injectRenderHost();
|
|
13801
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
13802
|
+
/** v0.9 prop: current selection (string[]). Normalized in `valueArray`
|
|
13803
|
+
* because LLMs sometimes seed the data model with a scalar (e.g. `"5"`)
|
|
13804
|
+
* instead of an array (`["5"]`); we coerce so .includes() works either way. */
|
|
13805
|
+
value = input(undefined, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
13806
|
+
/** Resolved options with plain string labels (surface-to-spec resolves DynamicString). */
|
|
13807
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
13808
|
+
/** v0.9 prop: 'mutuallyExclusive' (single-select, default) or 'multipleSelection'. */
|
|
13809
|
+
variant = input('mutuallyExclusive', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
13810
|
+
/** v0.9 prop: render as 'checkbox' rows (default) or 'chips'. */
|
|
13811
|
+
displayStyle = input('checkbox', ...(ngDevMode ? [{ debugName: "displayStyle" }] : []));
|
|
13812
|
+
/** v0.9 prop: when true, show a client-side option filter input. */
|
|
13813
|
+
filterable = input(false, ...(ngDevMode ? [{ debugName: "filterable" }] : []));
|
|
13814
|
+
/** Live validation message written by the surface's check gate
|
|
13815
|
+
* (bound to /_a2uiChecks/<id>); empty when valid. */
|
|
13816
|
+
errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : []));
|
|
13817
|
+
_bindings = input({}, ...(ngDevMode ? [{ debugName: "_bindings" }] : []));
|
|
13818
|
+
// Framework inputs required by the render harness.
|
|
13819
|
+
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13820
|
+
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
13821
|
+
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13822
|
+
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13823
|
+
valueArray = computed(() => {
|
|
13824
|
+
const v = this.value();
|
|
13825
|
+
if (Array.isArray(v))
|
|
13826
|
+
return v;
|
|
13827
|
+
if (v == null || v === '')
|
|
13828
|
+
return [];
|
|
13829
|
+
return [String(v)];
|
|
13830
|
+
}, ...(ngDevMode ? [{ debugName: "valueArray" }] : []));
|
|
13831
|
+
isSingleSelect = computed(() => this.variant() !== 'multipleSelection', ...(ngDevMode ? [{ debugName: "isSingleSelect" }] : []));
|
|
13832
|
+
/** Local, client-side option filter (only rendered when filterable). */
|
|
13833
|
+
filterText = signal('', ...(ngDevMode ? [{ debugName: "filterText" }] : []));
|
|
13834
|
+
visibleOptions = computed(() => {
|
|
13835
|
+
const f = this.filterText().trim().toLowerCase();
|
|
13836
|
+
const opts = this.options();
|
|
13837
|
+
return f ? opts.filter(o => o.label.toLowerCase().includes(f)) : opts;
|
|
13838
|
+
}, ...(ngDevMode ? [{ debugName: "visibleOptions" }] : []));
|
|
13839
|
+
isSelected(value) {
|
|
13840
|
+
return this.valueArray().includes(value);
|
|
13841
|
+
}
|
|
13842
|
+
onFilterInput(event) {
|
|
13843
|
+
this.filterText.set(event.target.value);
|
|
13844
|
+
}
|
|
13845
|
+
onCheckChange(value, event) {
|
|
13846
|
+
const checked = event.target.checked;
|
|
13847
|
+
if (this.isSingleSelect()) {
|
|
13848
|
+
// Radio semantics: the chosen option replaces the selection. `value` is
|
|
13849
|
+
// a string list on the wire, so write a one-element array.
|
|
13850
|
+
if (checked)
|
|
13851
|
+
emitBinding(this.host, this._bindings(), 'value', [value]);
|
|
13852
|
+
return;
|
|
13853
|
+
}
|
|
13854
|
+
emitBinding(this.host, this._bindings(), 'value', this.toggled(value, checked));
|
|
13855
|
+
}
|
|
13856
|
+
onChipToggle(value) {
|
|
13857
|
+
if (this.isSingleSelect()) {
|
|
13858
|
+
emitBinding(this.host, this._bindings(), 'value', [value]);
|
|
13859
|
+
return;
|
|
13860
|
+
}
|
|
13861
|
+
const checked = !this.isSelected(value);
|
|
13862
|
+
emitBinding(this.host, this._bindings(), 'value', this.toggled(value, checked));
|
|
13863
|
+
}
|
|
13864
|
+
toggled(value, checked) {
|
|
13865
|
+
const current = [...this.valueArray()];
|
|
13866
|
+
const idx = current.indexOf(value);
|
|
13867
|
+
if (checked && idx === -1) {
|
|
13868
|
+
current.push(value);
|
|
13869
|
+
}
|
|
13870
|
+
else if (!checked && idx !== -1) {
|
|
13871
|
+
current.splice(idx, 1);
|
|
13872
|
+
}
|
|
13873
|
+
// Pass the updated array directly (typed value, no JSON stringification needed).
|
|
13874
|
+
return current;
|
|
13875
|
+
}
|
|
13876
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiChoicePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13877
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiChoicePickerComponent, isStandalone: true, selector: "a2ui-choice-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, displayStyle: { classPropertyName: "displayStyle", publicName: "displayStyle", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, _bindings: { classPropertyName: "_bindings", publicName: "_bindings", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13878
|
+
<div class="a2ui-cp">
|
|
13879
|
+
@if (label()) {
|
|
13880
|
+
<span class="a2ui-cp__label">{{ label() }}</span>
|
|
13881
|
+
}
|
|
13882
|
+
|
|
13883
|
+
@if (filterable()) {
|
|
13884
|
+
<input
|
|
13885
|
+
type="text"
|
|
13886
|
+
class="a2ui-cp__filter"
|
|
13887
|
+
placeholder="Filter options"
|
|
13888
|
+
[value]="filterText()"
|
|
13889
|
+
(input)="onFilterInput($event)"
|
|
13890
|
+
/>
|
|
13891
|
+
}
|
|
13892
|
+
|
|
13893
|
+
@if (displayStyle() === 'chips') {
|
|
13894
|
+
<!-- Chips: toggle buttons. -->
|
|
13895
|
+
<div class="a2ui-cp__chips">
|
|
13896
|
+
@for (opt of visibleOptions(); track opt.value) {
|
|
13897
|
+
<button
|
|
13898
|
+
type="button"
|
|
13899
|
+
[class]="isSelected(opt.value) ? 'a2ui-cp__chip a2ui-cp__chip--selected' : 'a2ui-cp__chip'"
|
|
13900
|
+
[attr.aria-pressed]="isSelected(opt.value)"
|
|
13901
|
+
(click)="onChipToggle(opt.value)"
|
|
13902
|
+
>{{ opt.label }}</button>
|
|
13903
|
+
}
|
|
13904
|
+
</div>
|
|
13905
|
+
} @else {
|
|
13906
|
+
<!-- Checkbox style: radio rows (mutuallyExclusive) or checkbox rows (multipleSelection). -->
|
|
13907
|
+
<div class="a2ui-cp__checks">
|
|
13908
|
+
@for (opt of visibleOptions(); track opt.value) {
|
|
13909
|
+
<label class="a2ui-cp__check-row">
|
|
13910
|
+
<input
|
|
13911
|
+
[type]="isSingleSelect() ? 'radio' : 'checkbox'"
|
|
13912
|
+
class="a2ui-cp__checkbox"
|
|
13913
|
+
[attr.name]="isSingleSelect() ? _groupName : null"
|
|
13914
|
+
[checked]="isSelected(opt.value)"
|
|
13915
|
+
(change)="onCheckChange(opt.value, $event)"
|
|
13916
|
+
/>
|
|
13917
|
+
{{ opt.label }}
|
|
13918
|
+
</label>
|
|
13919
|
+
}
|
|
13920
|
+
</div>
|
|
13921
|
+
}
|
|
13922
|
+
@if (errorText()) {
|
|
13923
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
13924
|
+
}
|
|
13925
|
+
</div>
|
|
13926
|
+
`, isInline: true, styles: [".a2ui-cp{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-cp__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-cp__filter{padding:var(--a2ui-spacing-1) var(--a2ui-spacing-2);font-size:var(--a2ui-typography-caption-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-cp__filter:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}.a2ui-cp__checks{display:flex;flex-direction:column;gap:var(--a2ui-spacing-2)}.a2ui-cp__check-row{display:flex;align-items:center;gap:var(--a2ui-spacing-2);font-size:var(--a2ui-typography-body-size);cursor:pointer}.a2ui-cp__checkbox{width:16px;height:16px;border-radius:var(--a2ui-shape-extra-small);cursor:pointer;accent-color:var(--a2ui-primary)}.a2ui-cp__chips{display:flex;flex-wrap:wrap;gap:var(--a2ui-spacing-2)}.a2ui-cp__chip{padding:var(--a2ui-spacing-1) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-large, 9999px);background:var(--a2ui-surface-variant);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);cursor:pointer;transition:background var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard),border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-cp__chip--selected{background:var(--a2ui-primary);color:var(--a2ui-on-primary);border-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13927
|
+
}
|
|
13928
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiChoicePickerComponent, decorators: [{
|
|
13929
|
+
type: Component,
|
|
13930
|
+
args: [{ selector: 'a2ui-choice-picker', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
13931
|
+
<div class="a2ui-cp">
|
|
13932
|
+
@if (label()) {
|
|
13933
|
+
<span class="a2ui-cp__label">{{ label() }}</span>
|
|
13934
|
+
}
|
|
13935
|
+
|
|
13936
|
+
@if (filterable()) {
|
|
13937
|
+
<input
|
|
13938
|
+
type="text"
|
|
13939
|
+
class="a2ui-cp__filter"
|
|
13940
|
+
placeholder="Filter options"
|
|
13941
|
+
[value]="filterText()"
|
|
13942
|
+
(input)="onFilterInput($event)"
|
|
13943
|
+
/>
|
|
13944
|
+
}
|
|
13945
|
+
|
|
13946
|
+
@if (displayStyle() === 'chips') {
|
|
13947
|
+
<!-- Chips: toggle buttons. -->
|
|
13948
|
+
<div class="a2ui-cp__chips">
|
|
13949
|
+
@for (opt of visibleOptions(); track opt.value) {
|
|
13950
|
+
<button
|
|
13951
|
+
type="button"
|
|
13952
|
+
[class]="isSelected(opt.value) ? 'a2ui-cp__chip a2ui-cp__chip--selected' : 'a2ui-cp__chip'"
|
|
13953
|
+
[attr.aria-pressed]="isSelected(opt.value)"
|
|
13954
|
+
(click)="onChipToggle(opt.value)"
|
|
13955
|
+
>{{ opt.label }}</button>
|
|
13956
|
+
}
|
|
13957
|
+
</div>
|
|
13958
|
+
} @else {
|
|
13959
|
+
<!-- Checkbox style: radio rows (mutuallyExclusive) or checkbox rows (multipleSelection). -->
|
|
13960
|
+
<div class="a2ui-cp__checks">
|
|
13961
|
+
@for (opt of visibleOptions(); track opt.value) {
|
|
13962
|
+
<label class="a2ui-cp__check-row">
|
|
13963
|
+
<input
|
|
13964
|
+
[type]="isSingleSelect() ? 'radio' : 'checkbox'"
|
|
13965
|
+
class="a2ui-cp__checkbox"
|
|
13966
|
+
[attr.name]="isSingleSelect() ? _groupName : null"
|
|
13967
|
+
[checked]="isSelected(opt.value)"
|
|
13968
|
+
(change)="onCheckChange(opt.value, $event)"
|
|
13969
|
+
/>
|
|
13970
|
+
{{ opt.label }}
|
|
13971
|
+
</label>
|
|
13972
|
+
}
|
|
13973
|
+
</div>
|
|
13974
|
+
}
|
|
13975
|
+
@if (errorText()) {
|
|
13976
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
13977
|
+
}
|
|
13978
|
+
</div>
|
|
13979
|
+
`, styles: [".a2ui-cp{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-cp__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-cp__filter{padding:var(--a2ui-spacing-1) var(--a2ui-spacing-2);font-size:var(--a2ui-typography-caption-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-cp__filter:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}.a2ui-cp__checks{display:flex;flex-direction:column;gap:var(--a2ui-spacing-2)}.a2ui-cp__check-row{display:flex;align-items:center;gap:var(--a2ui-spacing-2);font-size:var(--a2ui-typography-body-size);cursor:pointer}.a2ui-cp__checkbox{width:16px;height:16px;border-radius:var(--a2ui-shape-extra-small);cursor:pointer;accent-color:var(--a2ui-primary)}.a2ui-cp__chips{display:flex;flex-wrap:wrap;gap:var(--a2ui-spacing-2)}.a2ui-cp__chip{padding:var(--a2ui-spacing-1) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-large, 9999px);background:var(--a2ui-surface-variant);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);cursor:pointer;transition:background var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard),border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-cp__chip--selected{background:var(--a2ui-primary);color:var(--a2ui-on-primary);border-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"] }]
|
|
13980
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], displayStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayStyle", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], _bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "_bindings", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
13981
|
+
|
|
13982
|
+
// SPDX-License-Identifier: MIT
|
|
13983
|
+
const ALIGN_MAP$1 = {
|
|
13602
13984
|
start: 'flex-start', center: 'center', end: 'flex-end', stretch: 'stretch',
|
|
13603
13985
|
};
|
|
13986
|
+
/** justify 'stretch' has no justify-content equivalent — children grow instead
|
|
13987
|
+
* (see the --justify-stretch class below). */
|
|
13988
|
+
const JUSTIFY_MAP$1 = {
|
|
13989
|
+
start: 'flex-start', center: 'center', end: 'flex-end',
|
|
13990
|
+
spaceAround: 'space-around', spaceBetween: 'space-between',
|
|
13991
|
+
spaceEvenly: 'space-evenly', stretch: 'normal',
|
|
13992
|
+
};
|
|
13604
13993
|
class A2uiColumnComponent {
|
|
13605
13994
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13606
13995
|
spec = input.required(...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13996
|
+
/** v0.9 prop: cross-axis alignment (default 'stretch'). */
|
|
13997
|
+
align = input('stretch', ...(ngDevMode ? [{ debugName: "align" }] : []));
|
|
13998
|
+
/** v0.9 prop: main-axis distribution (default 'start'). */
|
|
13999
|
+
justify = input('start', ...(ngDevMode ? [{ debugName: "justify" }] : []));
|
|
14000
|
+
/** Not part of the v0.9 catalog — kept for json-render generative-ui
|
|
14001
|
+
* specs, which may set a numeric spacing unit (multiples of 4px) or a
|
|
14002
|
+
* named size. Unset falls back to the CSS default gap. */
|
|
14003
|
+
gap = input(undefined, ...(ngDevMode ? [{ debugName: "gap" }] : []));
|
|
13610
14004
|
// Framework inputs required by the render harness.
|
|
13611
14005
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13612
14006
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
13613
14007
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
13614
|
-
alignItems = computed(() => ALIGN_MAP[this.
|
|
13615
|
-
|
|
13616
|
-
|
|
14008
|
+
alignItems = computed(() => ALIGN_MAP$1[this.align()] ?? 'stretch', ...(ngDevMode ? [{ debugName: "alignItems" }] : []));
|
|
14009
|
+
justifyContent = computed(() => JUSTIFY_MAP$1[this.justify()] ?? 'flex-start', ...(ngDevMode ? [{ debugName: "justifyContent" }] : []));
|
|
14010
|
+
cssClass = computed(() => this.justify() === 'stretch' ? 'a2ui-col a2ui-col--justify-stretch' : 'a2ui-col', ...(ngDevMode ? [{ debugName: "cssClass" }] : []));
|
|
14011
|
+
gapPx = computed(() => {
|
|
14012
|
+
const g = this.gap();
|
|
14013
|
+
if (typeof g === 'number' && Number.isFinite(g))
|
|
14014
|
+
return g * 4;
|
|
14015
|
+
if (g === 'small')
|
|
14016
|
+
return 8;
|
|
14017
|
+
if (g === 'medium')
|
|
14018
|
+
return 12;
|
|
14019
|
+
if (g === 'large')
|
|
14020
|
+
return 16;
|
|
14021
|
+
return null;
|
|
14022
|
+
}, ...(ngDevMode ? [{ debugName: "gapPx" }] : []));
|
|
13617
14023
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13618
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiColumnComponent, isStandalone: true, selector: "a2ui-column", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null },
|
|
13619
|
-
<div
|
|
14024
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiColumnComponent, isStandalone: true, selector: "a2ui-column", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, justify: { classPropertyName: "justify", publicName: "justify", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
14025
|
+
<div
|
|
14026
|
+
[class]="cssClass()"
|
|
14027
|
+
[style.align-items]="alignItems()"
|
|
14028
|
+
[style.justify-content]="justifyContent()"
|
|
14029
|
+
[style.gap.px]="gapPx()"
|
|
14030
|
+
>
|
|
13620
14031
|
@for (key of childKeys(); track key) {
|
|
13621
14032
|
<render-element [elementKey]="key" [spec]="spec()" />
|
|
13622
14033
|
}
|
|
13623
14034
|
</div>
|
|
13624
|
-
`, isInline: true, styles: [".a2ui-col{display:flex;flex-direction:column}\n"], dependencies: [{ kind: "component", type: RenderElementComponent, selector: "render-element", inputs: ["elementKey", "spec"] }] });
|
|
14035
|
+
`, isInline: true, styles: [".a2ui-col{display:flex;flex-direction:column;gap:var(--a2ui-spacing-3)}.a2ui-col--justify-stretch>render-element{flex:1}\n"], dependencies: [{ kind: "component", type: RenderElementComponent, selector: "render-element", inputs: ["elementKey", "spec"] }] });
|
|
13625
14036
|
}
|
|
13626
14037
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiColumnComponent, decorators: [{
|
|
13627
14038
|
type: Component,
|
|
13628
14039
|
args: [{ selector: 'a2ui-column', standalone: true, imports: [RenderElementComponent], template: `
|
|
13629
|
-
<div
|
|
14040
|
+
<div
|
|
14041
|
+
[class]="cssClass()"
|
|
14042
|
+
[style.align-items]="alignItems()"
|
|
14043
|
+
[style.justify-content]="justifyContent()"
|
|
14044
|
+
[style.gap.px]="gapPx()"
|
|
14045
|
+
>
|
|
13630
14046
|
@for (key of childKeys(); track key) {
|
|
13631
14047
|
<render-element [elementKey]="key" [spec]="spec()" />
|
|
13632
14048
|
}
|
|
13633
14049
|
</div>
|
|
13634
|
-
`, styles: [".a2ui-col{display:flex;flex-direction:column}\n"] }]
|
|
13635
|
-
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }],
|
|
14050
|
+
`, styles: [".a2ui-col{display:flex;flex-direction:column;gap:var(--a2ui-spacing-3)}.a2ui-col--justify-stretch>render-element{flex:1}\n"] }]
|
|
14051
|
+
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], justify: [{ type: i0.Input, args: [{ isSignal: true, alias: "justify", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
13636
14052
|
|
|
13637
14053
|
// SPDX-License-Identifier: MIT
|
|
13638
14054
|
class A2uiDateTimeInputComponent {
|
|
@@ -13640,12 +14056,19 @@ class A2uiDateTimeInputComponent {
|
|
|
13640
14056
|
_inputId = `a2ui-date-time-input-${++A2uiDateTimeInputComponent._idCounter}`;
|
|
13641
14057
|
host = injectRenderHost();
|
|
13642
14058
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
13643
|
-
/**
|
|
14059
|
+
/** v0.9 prop: ISO 8601 value (resolved DynamicString). Still renders when absent. */
|
|
13644
14060
|
value = input('', ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
13645
|
-
/**
|
|
14061
|
+
/** v0.9 prop: enableDate — include date portion. */
|
|
13646
14062
|
enableDate = input(true, ...(ngDevMode ? [{ debugName: "enableDate" }] : []));
|
|
13647
|
-
/**
|
|
14063
|
+
/** v0.9 prop: enableTime — include time portion. */
|
|
13648
14064
|
enableTime = input(false, ...(ngDevMode ? [{ debugName: "enableTime" }] : []));
|
|
14065
|
+
/** v0.9 prop: ISO lower bound mapped to the native input's min. */
|
|
14066
|
+
min = input(undefined, ...(ngDevMode ? [{ debugName: "min" }] : []));
|
|
14067
|
+
/** v0.9 prop: ISO upper bound mapped to the native input's max. */
|
|
14068
|
+
max = input(undefined, ...(ngDevMode ? [{ debugName: "max" }] : []));
|
|
14069
|
+
/** Live validation message written by the surface's check gate
|
|
14070
|
+
* (bound to /_a2uiChecks/<id>); empty when valid. */
|
|
14071
|
+
errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : []));
|
|
13649
14072
|
_bindings = input({}, ...(ngDevMode ? [{ debugName: "_bindings" }] : []));
|
|
13650
14073
|
// Framework inputs required by the render harness.
|
|
13651
14074
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
@@ -13667,7 +14090,7 @@ class A2uiDateTimeInputComponent {
|
|
|
13667
14090
|
emitBinding(this.host, this._bindings(), 'value', val);
|
|
13668
14091
|
}
|
|
13669
14092
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiDateTimeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13670
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiDateTimeInputComponent, isStandalone: true, selector: "a2ui-date-time-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, enableDate: { classPropertyName: "enableDate", publicName: "enableDate", isSignal: true, isRequired: false, transformFunction: null }, enableTime: { classPropertyName: "enableTime", publicName: "enableTime", isSignal: true, isRequired: false, transformFunction: null }, _bindings: { classPropertyName: "_bindings", publicName: "_bindings", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
14093
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiDateTimeInputComponent, isStandalone: true, selector: "a2ui-date-time-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, enableDate: { classPropertyName: "enableDate", publicName: "enableDate", isSignal: true, isRequired: false, transformFunction: null }, enableTime: { classPropertyName: "enableTime", publicName: "enableTime", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, _bindings: { classPropertyName: "_bindings", publicName: "_bindings", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13671
14094
|
<div class="a2ui-dti">
|
|
13672
14095
|
@if (label()) {
|
|
13673
14096
|
<label [htmlFor]="_inputId" class="a2ui-dti__label">{{ label() }}</label>
|
|
@@ -13676,11 +14099,16 @@ class A2uiDateTimeInputComponent {
|
|
|
13676
14099
|
[id]="_inputId"
|
|
13677
14100
|
[type]="htmlInputType()"
|
|
13678
14101
|
[value]="value()"
|
|
14102
|
+
[attr.min]="min() || null"
|
|
14103
|
+
[attr.max]="max() || null"
|
|
13679
14104
|
class="a2ui-dti__input"
|
|
13680
14105
|
(change)="onChange($event)"
|
|
13681
14106
|
/>
|
|
14107
|
+
@if (errorText()) {
|
|
14108
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
14109
|
+
}
|
|
13682
14110
|
</div>
|
|
13683
|
-
`, isInline: true, styles: [".a2ui-dti{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-dti__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-dti__input{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-dti__input:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14111
|
+
`, isInline: true, styles: [".a2ui-dti{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-dti__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-dti__input{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-dti__input:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13684
14112
|
}
|
|
13685
14113
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiDateTimeInputComponent, decorators: [{
|
|
13686
14114
|
type: Component,
|
|
@@ -13693,21 +14121,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
13693
14121
|
[id]="_inputId"
|
|
13694
14122
|
[type]="htmlInputType()"
|
|
13695
14123
|
[value]="value()"
|
|
14124
|
+
[attr.min]="min() || null"
|
|
14125
|
+
[attr.max]="max() || null"
|
|
13696
14126
|
class="a2ui-dti__input"
|
|
13697
14127
|
(change)="onChange($event)"
|
|
13698
14128
|
/>
|
|
14129
|
+
@if (errorText()) {
|
|
14130
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
14131
|
+
}
|
|
13699
14132
|
</div>
|
|
13700
|
-
`, styles: [".a2ui-dti{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-dti__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-dti__input{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-dti__input:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}\n"] }]
|
|
13701
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], enableDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableDate", required: false }] }], enableTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableTime", required: false }] }], _bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "_bindings", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
14133
|
+
`, styles: [".a2ui-dti{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-dti__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-dti__input{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-dti__input:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"] }]
|
|
14134
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], enableDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableDate", required: false }] }], enableTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableTime", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], _bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "_bindings", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
13702
14135
|
|
|
13703
14136
|
// SPDX-License-Identifier: MIT
|
|
13704
14137
|
class A2uiDividerComponent {
|
|
13705
|
-
/**
|
|
13706
|
-
axis = input(
|
|
13707
|
-
|
|
13708
|
-
direction = input('horizontal', ...(ngDevMode ? [{ debugName: "direction" }] : []));
|
|
13709
|
-
/** Effective axis — `axis` wins if provided, otherwise fall back to `direction`. */
|
|
13710
|
-
orientation = computed(() => this.axis() ?? this.direction(), ...(ngDevMode ? [{ debugName: "orientation" }] : []));
|
|
14138
|
+
/** v0.9 prop: divider axis (default 'horizontal'). */
|
|
14139
|
+
axis = input('horizontal', ...(ngDevMode ? [{ debugName: "axis" }] : []));
|
|
14140
|
+
orientation = computed(() => this.axis(), ...(ngDevMode ? [{ debugName: "orientation" }] : []));
|
|
13711
14141
|
// Framework inputs required by the render harness.
|
|
13712
14142
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13713
14143
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
@@ -13715,7 +14145,7 @@ class A2uiDividerComponent {
|
|
|
13715
14145
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13716
14146
|
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13717
14147
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiDividerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13718
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiDividerComponent, isStandalone: true, selector: "a2ui-divider", inputs: { axis: { classPropertyName: "axis", publicName: "axis", isSignal: true, isRequired: false, transformFunction: null },
|
|
14148
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiDividerComponent, isStandalone: true, selector: "a2ui-divider", inputs: { axis: { classPropertyName: "axis", publicName: "axis", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13719
14149
|
@if (orientation() === 'vertical') {
|
|
13720
14150
|
<div class="a2ui-divider a2ui-divider--vertical"></div>
|
|
13721
14151
|
} @else {
|
|
@@ -13732,7 +14162,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
13732
14162
|
<hr class="a2ui-divider a2ui-divider--horizontal" />
|
|
13733
14163
|
}
|
|
13734
14164
|
`, styles: [".a2ui-divider--horizontal{display:block;width:100%;border:none;border-top:1px solid var(--a2ui-outline);margin:var(--a2ui-spacing-2) 0}.a2ui-divider--vertical{display:inline-block;align-self:stretch;width:1px;background:var(--a2ui-outline);margin:0 var(--a2ui-spacing-2)}\n"] }]
|
|
13735
|
-
}], propDecorators: { axis: [{ type: i0.Input, args: [{ isSignal: true, alias: "axis", required: false }] }],
|
|
14165
|
+
}], propDecorators: { axis: [{ type: i0.Input, args: [{ isSignal: true, alias: "axis", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
13736
14166
|
|
|
13737
14167
|
// SPDX-License-Identifier: MIT
|
|
13738
14168
|
/**
|
|
@@ -13749,119 +14179,118 @@ function toMaterialSymbolName(name) {
|
|
|
13749
14179
|
return name.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
|
|
13750
14180
|
}
|
|
13751
14181
|
class A2uiIconComponent {
|
|
13752
|
-
/**
|
|
14182
|
+
/** v0.9 prop: a Material Symbols name (string) or an inline `{ svgPath }`. */
|
|
13753
14183
|
name = input(undefined, ...(ngDevMode ? [{ debugName: "name" }] : []));
|
|
13754
|
-
/** Pre-v1 alias retained for back-compat. */
|
|
13755
|
-
icon = input('', ...(ngDevMode ? [{ debugName: "icon" }] : []));
|
|
13756
|
-
size = input(null, ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
13757
14184
|
// Framework inputs required by the render harness.
|
|
13758
14185
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13759
14186
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
13760
14187
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
13761
14188
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13762
14189
|
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13763
|
-
|
|
14190
|
+
/** Inline SVG path when `name` is the `{ svgPath }` object form. */
|
|
14191
|
+
svgPath = computed(() => {
|
|
14192
|
+
const n = this.name();
|
|
14193
|
+
return typeof n === 'object' && n !== null && typeof n.svgPath === 'string'
|
|
14194
|
+
? n.svgPath
|
|
14195
|
+
: null;
|
|
14196
|
+
}, ...(ngDevMode ? [{ debugName: "svgPath" }] : []));
|
|
14197
|
+
/** The string ligature name when `name` is a string. */
|
|
14198
|
+
ligatureName = computed(() => typeof this.name() === 'string' ? this.name() : '', ...(ngDevMode ? [{ debugName: "ligatureName" }] : []));
|
|
13764
14199
|
/** The effective name as a Material Symbols ligature (camelCase → snake_case). */
|
|
13765
|
-
glyphName = computed(() => toMaterialSymbolName(this.
|
|
14200
|
+
glyphName = computed(() => toMaterialSymbolName(this.ligatureName()), ...(ngDevMode ? [{ debugName: "glyphName" }] : []));
|
|
13766
14201
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13767
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiIconComponent, isStandalone: true, selector: "a2ui-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null },
|
|
13768
|
-
@if (
|
|
14202
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiIconComponent, isStandalone: true, selector: "a2ui-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
14203
|
+
@if (svgPath(); as path) {
|
|
14204
|
+
<svg
|
|
14205
|
+
class="a2ui-icon a2ui-icon--svg"
|
|
14206
|
+
viewBox="0 -960 960 960"
|
|
14207
|
+
fill="currentColor"
|
|
14208
|
+
role="img"
|
|
14209
|
+
aria-hidden="true"
|
|
14210
|
+
><path [attr.d]="path" /></svg>
|
|
14211
|
+
} @else if (ligatureName(); as name) {
|
|
13769
14212
|
<span
|
|
13770
14213
|
class="a2ui-icon material-symbols-outlined"
|
|
13771
|
-
[style.font-size]="size() ? size() + 'px' : '1.125rem'"
|
|
13772
14214
|
[attr.aria-label]="name"
|
|
13773
14215
|
role="img"
|
|
13774
14216
|
>{{ glyphName() }}</span>
|
|
13775
14217
|
}
|
|
13776
|
-
`, isInline: true, styles: [".a2ui-icon{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24;color:currentColor;display:inline-flex;align-items:center;justify-content:center;-webkit-user-select:none;user-select:none}\n"] });
|
|
14218
|
+
`, isInline: true, styles: [".a2ui-icon{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;font-size:1.125rem;line-height:1;letter-spacing:normal;text-transform:none;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24;color:currentColor;display:inline-flex;align-items:center;justify-content:center;-webkit-user-select:none;user-select:none}.a2ui-icon--svg{width:1.125rem;height:1.125rem}\n"] });
|
|
13777
14219
|
}
|
|
13778
14220
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiIconComponent, decorators: [{
|
|
13779
14221
|
type: Component,
|
|
13780
14222
|
args: [{ selector: 'a2ui-icon', standalone: true, template: `
|
|
13781
|
-
@if (
|
|
14223
|
+
@if (svgPath(); as path) {
|
|
14224
|
+
<svg
|
|
14225
|
+
class="a2ui-icon a2ui-icon--svg"
|
|
14226
|
+
viewBox="0 -960 960 960"
|
|
14227
|
+
fill="currentColor"
|
|
14228
|
+
role="img"
|
|
14229
|
+
aria-hidden="true"
|
|
14230
|
+
><path [attr.d]="path" /></svg>
|
|
14231
|
+
} @else if (ligatureName(); as name) {
|
|
13782
14232
|
<span
|
|
13783
14233
|
class="a2ui-icon material-symbols-outlined"
|
|
13784
|
-
[style.font-size]="size() ? size() + 'px' : '1.125rem'"
|
|
13785
14234
|
[attr.aria-label]="name"
|
|
13786
14235
|
role="img"
|
|
13787
14236
|
>{{ glyphName() }}</span>
|
|
13788
14237
|
}
|
|
13789
|
-
`, styles: [".a2ui-icon{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24;color:currentColor;display:inline-flex;align-items:center;justify-content:center;-webkit-user-select:none;user-select:none}\n"] }]
|
|
13790
|
-
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }],
|
|
14238
|
+
`, styles: [".a2ui-icon{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;font-size:1.125rem;line-height:1;letter-spacing:normal;text-transform:none;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24;color:currentColor;display:inline-flex;align-items:center;justify-content:center;-webkit-user-select:none;user-select:none}.a2ui-icon--svg{width:1.125rem;height:1.125rem}\n"] }]
|
|
14239
|
+
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
13791
14240
|
|
|
13792
14241
|
// SPDX-License-Identifier: MIT
|
|
13793
|
-
const
|
|
13794
|
-
|
|
13795
|
-
|
|
13796
|
-
|
|
13797
|
-
|
|
13798
|
-
|
|
13799
|
-
header: { maxWidth: '100%', aspectRatio: '16 / 5' },
|
|
14242
|
+
const FIT_MAP = {
|
|
14243
|
+
contain: 'contain',
|
|
14244
|
+
cover: 'cover',
|
|
14245
|
+
fill: 'fill',
|
|
14246
|
+
none: 'none',
|
|
14247
|
+
scaleDown: 'scale-down',
|
|
13800
14248
|
};
|
|
13801
14249
|
class A2uiImageComponent {
|
|
13802
14250
|
url = input('', ...(ngDevMode ? [{ debugName: "url" }] : []));
|
|
13803
|
-
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
13808
|
-
|
|
13809
|
-
usageHint = input(undefined, ...(ngDevMode ? [{ debugName: "usageHint" }] : []));
|
|
14251
|
+
/** v0.9 prop: alt text / accessible description. */
|
|
14252
|
+
description = input('', ...(ngDevMode ? [{ debugName: "description" }] : []));
|
|
14253
|
+
/** v0.9 prop: CSS object-fit equivalent ('scaleDown' → 'scale-down'). */
|
|
14254
|
+
fit = input('fill', ...(ngDevMode ? [{ debugName: "fit" }] : []));
|
|
14255
|
+
/** v0.9 prop: sizing preset. */
|
|
14256
|
+
variant = input('mediumFeature', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
13810
14257
|
// Framework inputs required by the render harness.
|
|
13811
14258
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13812
14259
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
13813
14260
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
13814
14261
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13815
14262
|
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13816
|
-
|
|
13817
|
-
|
|
13818
|
-
}
|
|
13819
|
-
explicitHeight() {
|
|
13820
|
-
return this.height() != null ? this.height() + 'px' : null;
|
|
13821
|
-
}
|
|
13822
|
-
hintStyle() {
|
|
13823
|
-
const h = this.usageHint();
|
|
13824
|
-
return h ? USAGE_HINT_STYLE[h] : null;
|
|
13825
|
-
}
|
|
14263
|
+
objectFit = computed(() => FIT_MAP[this.fit()] ?? 'fill', ...(ngDevMode ? [{ debugName: "objectFit" }] : []));
|
|
14264
|
+
cssClass = computed(() => `a2ui-img a2ui-img--${this.variant()}`, ...(ngDevMode ? [{ debugName: "cssClass" }] : []));
|
|
13826
14265
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiImageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13827
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.6", type: A2uiImageComponent, isStandalone: true, selector: "a2ui-image", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null },
|
|
14266
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.6", type: A2uiImageComponent, isStandalone: true, selector: "a2ui-image", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, fit: { classPropertyName: "fit", publicName: "fit", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13828
14267
|
<img
|
|
13829
|
-
class="
|
|
14268
|
+
[class]="cssClass()"
|
|
13830
14269
|
[src]="url()"
|
|
13831
|
-
[alt]="
|
|
13832
|
-
[style.
|
|
13833
|
-
[style.height]="explicitHeight()"
|
|
13834
|
-
[style.object-fit]="fit()"
|
|
13835
|
-
[style.max-width]="hintStyle()?.maxWidth"
|
|
13836
|
-
[style.aspect-ratio]="hintStyle()?.aspectRatio || null"
|
|
13837
|
-
[style.border-radius]="hintStyle()?.borderRadius || null"
|
|
14270
|
+
[alt]="description()"
|
|
14271
|
+
[style.object-fit]="objectFit()"
|
|
13838
14272
|
/>
|
|
13839
|
-
`, isInline: true, styles: [".a2ui-img{display:block;max-width:100%;border-radius:var(--a2ui-shape-extra-small)}\n"] });
|
|
14273
|
+
`, isInline: true, styles: [".a2ui-img{display:block;max-width:100%;border-radius:var(--a2ui-shape-extra-small)}.a2ui-img--icon{width:24px;height:24px}.a2ui-img--avatar{width:40px;height:40px;border-radius:50%}.a2ui-img--smallFeature{width:120px}.a2ui-img--mediumFeature{width:240px}.a2ui-img--largeFeature{width:400px}.a2ui-img--header{width:100%;aspect-ratio:16 / 5}\n"] });
|
|
13840
14274
|
}
|
|
13841
14275
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiImageComponent, decorators: [{
|
|
13842
14276
|
type: Component,
|
|
13843
14277
|
args: [{ selector: 'a2ui-image', standalone: true, template: `
|
|
13844
14278
|
<img
|
|
13845
|
-
class="
|
|
14279
|
+
[class]="cssClass()"
|
|
13846
14280
|
[src]="url()"
|
|
13847
|
-
[alt]="
|
|
13848
|
-
[style.
|
|
13849
|
-
[style.height]="explicitHeight()"
|
|
13850
|
-
[style.object-fit]="fit()"
|
|
13851
|
-
[style.max-width]="hintStyle()?.maxWidth"
|
|
13852
|
-
[style.aspect-ratio]="hintStyle()?.aspectRatio || null"
|
|
13853
|
-
[style.border-radius]="hintStyle()?.borderRadius || null"
|
|
14281
|
+
[alt]="description()"
|
|
14282
|
+
[style.object-fit]="objectFit()"
|
|
13854
14283
|
/>
|
|
13855
|
-
`, styles: [".a2ui-img{display:block;max-width:100%;border-radius:var(--a2ui-shape-extra-small)}\n"] }]
|
|
13856
|
-
}], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }],
|
|
14284
|
+
`, styles: [".a2ui-img{display:block;max-width:100%;border-radius:var(--a2ui-shape-extra-small)}.a2ui-img--icon{width:24px;height:24px}.a2ui-img--avatar{width:40px;height:40px;border-radius:50%}.a2ui-img--smallFeature{width:120px}.a2ui-img--mediumFeature{width:240px}.a2ui-img--largeFeature{width:400px}.a2ui-img--header{width:100%;aspect-ratio:16 / 5}\n"] }]
|
|
14285
|
+
}], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], fit: [{ type: i0.Input, args: [{ isSignal: true, alias: "fit", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
13857
14286
|
|
|
13858
14287
|
// SPDX-License-Identifier: MIT
|
|
13859
14288
|
class A2uiListComponent {
|
|
13860
14289
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13861
14290
|
spec = input.required(...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13862
14291
|
direction = input('vertical', ...(ngDevMode ? [{ debugName: "direction" }] : []));
|
|
13863
|
-
/**
|
|
13864
|
-
|
|
14292
|
+
/** v0.9 prop: cross-axis alignment (default 'stretch'). */
|
|
14293
|
+
align = input('stretch', ...(ngDevMode ? [{ debugName: "align" }] : []));
|
|
13865
14294
|
// Framework inputs required by the render harness.
|
|
13866
14295
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13867
14296
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
@@ -13872,15 +14301,13 @@ class A2uiListComponent {
|
|
|
13872
14301
|
: 'a2ui-list--vertical';
|
|
13873
14302
|
}, ...(ngDevMode ? [{ debugName: "listClass" }] : []));
|
|
13874
14303
|
alignmentCss = computed(() => {
|
|
13875
|
-
const a = this.
|
|
13876
|
-
if (!a)
|
|
13877
|
-
return null;
|
|
14304
|
+
const a = this.align();
|
|
13878
14305
|
return a === 'start' ? 'flex-start'
|
|
13879
14306
|
: a === 'end' ? 'flex-end'
|
|
13880
14307
|
: a; // center / stretch are valid CSS values as-is
|
|
13881
14308
|
}, ...(ngDevMode ? [{ debugName: "alignmentCss" }] : []));
|
|
13882
14309
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13883
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiListComponent, isStandalone: true, selector: "a2ui-list", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null },
|
|
14310
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiListComponent, isStandalone: true, selector: "a2ui-list", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13884
14311
|
<div [class]="listClass()" [style.align-items]="alignmentCss()">
|
|
13885
14312
|
@for (key of childKeys(); track key) {
|
|
13886
14313
|
<render-element [elementKey]="key" [spec]="spec()" />
|
|
@@ -13897,18 +14324,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
13897
14324
|
}
|
|
13898
14325
|
</div>
|
|
13899
14326
|
`, styles: [".a2ui-list--vertical{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1);overflow-y:auto;max-height:384px}.a2ui-list--horizontal{display:flex;flex-direction:row;gap:var(--a2ui-spacing-1);overflow-x:auto}\n"] }]
|
|
13900
|
-
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }],
|
|
14327
|
+
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
13901
14328
|
|
|
13902
14329
|
// SPDX-License-Identifier: MIT
|
|
13903
14330
|
class A2uiModalComponent {
|
|
13904
14331
|
/**
|
|
13905
|
-
*
|
|
13906
|
-
*
|
|
14332
|
+
* v0.9: childKeys[0] = trigger (inline entry point),
|
|
14333
|
+
* childKeys[1] = content (modal body).
|
|
13907
14334
|
*/
|
|
13908
14335
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
13909
14336
|
spec = input.required(...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
13910
|
-
/** Resolved title string (from optional title DynamicString). */
|
|
13911
|
-
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
13912
14337
|
// Framework inputs required by the render harness.
|
|
13913
14338
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
13914
14339
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
@@ -13917,7 +14342,7 @@ class A2uiModalComponent {
|
|
|
13917
14342
|
entryPointKey = computed(() => this.childKeys()[0] ?? null, ...(ngDevMode ? [{ debugName: "entryPointKey" }] : []));
|
|
13918
14343
|
contentKey = computed(() => this.childKeys()[1] ?? null, ...(ngDevMode ? [{ debugName: "contentKey" }] : []));
|
|
13919
14344
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13920
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiModalComponent, isStandalone: true, selector: "a2ui-modal", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null },
|
|
14345
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiModalComponent, isStandalone: true, selector: "a2ui-modal", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13921
14346
|
<!-- Entry point (trigger): always rendered inline, e.g. a button. -->
|
|
13922
14347
|
@if (entryPointKey(); as epKey) {
|
|
13923
14348
|
<div
|
|
@@ -13950,16 +14375,13 @@ class A2uiModalComponent {
|
|
|
13950
14375
|
(keydown.space)="open.set(false)"
|
|
13951
14376
|
></div>
|
|
13952
14377
|
<div class="a2ui-modal__panel">
|
|
13953
|
-
@if (title()) {
|
|
13954
|
-
<h2 class="a2ui-modal__title">{{ title() }}</h2>
|
|
13955
|
-
}
|
|
13956
14378
|
@if (contentKey(); as cKey) {
|
|
13957
14379
|
<render-element [elementKey]="cKey" [spec]="spec()" />
|
|
13958
14380
|
}
|
|
13959
14381
|
</div>
|
|
13960
14382
|
</div>
|
|
13961
14383
|
}
|
|
13962
|
-
`, isInline: true, styles: [".a2ui-modal__trigger{display:contents}.a2ui-modal__overlay{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center}.a2ui-modal__backdrop{position:absolute;inset:0;background:var(--a2ui-scrim);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.a2ui-modal__panel{position:relative;background:var(--a2ui-surface);border:1px solid var(--a2ui-outline);border-radius:var(--a2ui-shape-medium);padding:var(--a2ui-spacing-5);max-width:512px;width:100%;margin:0 var(--a2ui-spacing-4);box-shadow:var(--a2ui-elevation-4)}
|
|
14384
|
+
`, isInline: true, styles: [".a2ui-modal__trigger{display:contents}.a2ui-modal__overlay{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center}.a2ui-modal__backdrop{position:absolute;inset:0;background:var(--a2ui-scrim);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.a2ui-modal__panel{position:relative;background:var(--a2ui-surface);border:1px solid var(--a2ui-outline);border-radius:var(--a2ui-shape-medium);padding:var(--a2ui-spacing-5);max-width:512px;width:100%;margin:0 var(--a2ui-spacing-4);box-shadow:var(--a2ui-elevation-4)}\n"], dependencies: [{ kind: "component", type: RenderElementComponent, selector: "render-element", inputs: ["elementKey", "spec"] }] });
|
|
13963
14385
|
}
|
|
13964
14386
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiModalComponent, decorators: [{
|
|
13965
14387
|
type: Component,
|
|
@@ -13996,160 +14418,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
13996
14418
|
(keydown.space)="open.set(false)"
|
|
13997
14419
|
></div>
|
|
13998
14420
|
<div class="a2ui-modal__panel">
|
|
13999
|
-
@if (title()) {
|
|
14000
|
-
<h2 class="a2ui-modal__title">{{ title() }}</h2>
|
|
14001
|
-
}
|
|
14002
14421
|
@if (contentKey(); as cKey) {
|
|
14003
14422
|
<render-element [elementKey]="cKey" [spec]="spec()" />
|
|
14004
14423
|
}
|
|
14005
14424
|
</div>
|
|
14006
14425
|
</div>
|
|
14007
14426
|
}
|
|
14008
|
-
`, styles: [".a2ui-modal__trigger{display:contents}.a2ui-modal__overlay{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center}.a2ui-modal__backdrop{position:absolute;inset:0;background:var(--a2ui-scrim);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.a2ui-modal__panel{position:relative;background:var(--a2ui-surface);border:1px solid var(--a2ui-outline);border-radius:var(--a2ui-shape-medium);padding:var(--a2ui-spacing-5);max-width:512px;width:100%;margin:0 var(--a2ui-spacing-4);box-shadow:var(--a2ui-elevation-4)}
|
|
14009
|
-
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }],
|
|
14010
|
-
|
|
14011
|
-
// SPDX-License-Identifier: MIT
|
|
14012
|
-
class A2uiMultipleChoiceComponent {
|
|
14013
|
-
host = injectRenderHost();
|
|
14014
|
-
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
14015
|
-
/** Resolved current selections from surface-to-spec. Normalized in
|
|
14016
|
-
* `selectionsArray` because LLMs sometimes seed the data model with a
|
|
14017
|
-
* scalar (e.g. `"5"`) instead of an array (`["5"]`); we coerce so
|
|
14018
|
-
* .includes() works either way. */
|
|
14019
|
-
selections = input(undefined, ...(ngDevMode ? [{ debugName: "selections" }] : []));
|
|
14020
|
-
selectionsArray = computed(() => {
|
|
14021
|
-
const v = this.selections();
|
|
14022
|
-
if (Array.isArray(v))
|
|
14023
|
-
return v;
|
|
14024
|
-
if (v == null || v === '')
|
|
14025
|
-
return [];
|
|
14026
|
-
return [String(v)];
|
|
14027
|
-
}, ...(ngDevMode ? [{ debugName: "selectionsArray" }] : []));
|
|
14028
|
-
/** Resolved options with plain string labels (surface-to-spec resolves DynamicString). */
|
|
14029
|
-
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
14030
|
-
/** When ≤ 1 — render as single-select <select>; otherwise multi-select checkboxes. */
|
|
14031
|
-
maxAllowedSelections = input(1, ...(ngDevMode ? [{ debugName: "maxAllowedSelections" }] : []));
|
|
14032
|
-
_bindings = input({}, ...(ngDevMode ? [{ debugName: "_bindings" }] : []));
|
|
14033
|
-
// Framework inputs required by the render harness.
|
|
14034
|
-
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
14035
|
-
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
14036
|
-
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
14037
|
-
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
14038
|
-
isSingleSelect = computed(() => this.maxAllowedSelections() <= 1, ...(ngDevMode ? [{ debugName: "isSingleSelect" }] : []));
|
|
14039
|
-
isSelected(value) {
|
|
14040
|
-
return this.selectionsArray().includes(value);
|
|
14041
|
-
}
|
|
14042
|
-
onSelectChange(event) {
|
|
14043
|
-
const val = event.target.value;
|
|
14044
|
-
emitBinding(this.host, this._bindings(), 'selections', val);
|
|
14045
|
-
}
|
|
14046
|
-
onCheckChange(value, event) {
|
|
14047
|
-
const checked = event.target.checked;
|
|
14048
|
-
const current = [...this.selectionsArray()];
|
|
14049
|
-
const idx = current.indexOf(value);
|
|
14050
|
-
if (checked && idx === -1) {
|
|
14051
|
-
current.push(value);
|
|
14052
|
-
}
|
|
14053
|
-
else if (!checked && idx !== -1) {
|
|
14054
|
-
current.splice(idx, 1);
|
|
14055
|
-
}
|
|
14056
|
-
// Pass the updated selections array directly (typed value, no JSON stringification needed).
|
|
14057
|
-
emitBinding(this.host, this._bindings(), 'selections', current);
|
|
14058
|
-
}
|
|
14059
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiMultipleChoiceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14060
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiMultipleChoiceComponent, isStandalone: true, selector: "a2ui-multiple-choice", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, selections: { classPropertyName: "selections", publicName: "selections", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, maxAllowedSelections: { classPropertyName: "maxAllowedSelections", publicName: "maxAllowedSelections", isSignal: true, isRequired: false, transformFunction: null }, _bindings: { classPropertyName: "_bindings", publicName: "_bindings", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
14061
|
-
<div class="a2ui-mc">
|
|
14062
|
-
@if (label()) {
|
|
14063
|
-
<span class="a2ui-mc__label">{{ label() }}</span>
|
|
14064
|
-
}
|
|
14065
|
-
|
|
14066
|
-
@if (isSingleSelect()) {
|
|
14067
|
-
<!-- Single-select: HTML <select> -->
|
|
14068
|
-
<select class="a2ui-mc__select" (change)="onSelectChange($event)">
|
|
14069
|
-
@for (opt of options(); track opt.value) {
|
|
14070
|
-
<option [value]="opt.value" [selected]="isSelected(opt.value)">{{ opt.label }}</option>
|
|
14071
|
-
}
|
|
14072
|
-
</select>
|
|
14073
|
-
} @else {
|
|
14074
|
-
<!-- Multi-select: checkbox list -->
|
|
14075
|
-
<div class="a2ui-mc__checks">
|
|
14076
|
-
@for (opt of options(); track opt.value) {
|
|
14077
|
-
<label class="a2ui-mc__check-row">
|
|
14078
|
-
<input
|
|
14079
|
-
type="checkbox"
|
|
14080
|
-
class="a2ui-mc__checkbox"
|
|
14081
|
-
[checked]="isSelected(opt.value)"
|
|
14082
|
-
(change)="onCheckChange(opt.value, $event)"
|
|
14083
|
-
/>
|
|
14084
|
-
{{ opt.label }}
|
|
14085
|
-
</label>
|
|
14086
|
-
}
|
|
14087
|
-
</div>
|
|
14088
|
-
}
|
|
14089
|
-
</div>
|
|
14090
|
-
`, isInline: true, styles: [".a2ui-mc{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-mc__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-mc__select{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-mc__select:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}.a2ui-mc__checks{display:flex;flex-direction:column;gap:var(--a2ui-spacing-2)}.a2ui-mc__check-row{display:flex;align-items:center;gap:var(--a2ui-spacing-2);font-size:var(--a2ui-typography-body-size);cursor:pointer}.a2ui-mc__checkbox{width:16px;height:16px;border-radius:var(--a2ui-shape-extra-small);cursor:pointer;accent-color:var(--a2ui-primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14091
|
-
}
|
|
14092
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiMultipleChoiceComponent, decorators: [{
|
|
14093
|
-
type: Component,
|
|
14094
|
-
args: [{ selector: 'a2ui-multiple-choice', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
14095
|
-
<div class="a2ui-mc">
|
|
14096
|
-
@if (label()) {
|
|
14097
|
-
<span class="a2ui-mc__label">{{ label() }}</span>
|
|
14098
|
-
}
|
|
14099
|
-
|
|
14100
|
-
@if (isSingleSelect()) {
|
|
14101
|
-
<!-- Single-select: HTML <select> -->
|
|
14102
|
-
<select class="a2ui-mc__select" (change)="onSelectChange($event)">
|
|
14103
|
-
@for (opt of options(); track opt.value) {
|
|
14104
|
-
<option [value]="opt.value" [selected]="isSelected(opt.value)">{{ opt.label }}</option>
|
|
14105
|
-
}
|
|
14106
|
-
</select>
|
|
14107
|
-
} @else {
|
|
14108
|
-
<!-- Multi-select: checkbox list -->
|
|
14109
|
-
<div class="a2ui-mc__checks">
|
|
14110
|
-
@for (opt of options(); track opt.value) {
|
|
14111
|
-
<label class="a2ui-mc__check-row">
|
|
14112
|
-
<input
|
|
14113
|
-
type="checkbox"
|
|
14114
|
-
class="a2ui-mc__checkbox"
|
|
14115
|
-
[checked]="isSelected(opt.value)"
|
|
14116
|
-
(change)="onCheckChange(opt.value, $event)"
|
|
14117
|
-
/>
|
|
14118
|
-
{{ opt.label }}
|
|
14119
|
-
</label>
|
|
14120
|
-
}
|
|
14121
|
-
</div>
|
|
14122
|
-
}
|
|
14123
|
-
</div>
|
|
14124
|
-
`, styles: [".a2ui-mc{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-mc__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-mc__select{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard)}.a2ui-mc__select:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}.a2ui-mc__checks{display:flex;flex-direction:column;gap:var(--a2ui-spacing-2)}.a2ui-mc__check-row{display:flex;align-items:center;gap:var(--a2ui-spacing-2);font-size:var(--a2ui-typography-body-size);cursor:pointer}.a2ui-mc__checkbox{width:16px;height:16px;border-radius:var(--a2ui-shape-extra-small);cursor:pointer;accent-color:var(--a2ui-primary)}\n"] }]
|
|
14125
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], selections: [{ type: i0.Input, args: [{ isSignal: true, alias: "selections", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], maxAllowedSelections: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxAllowedSelections", required: false }] }], _bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "_bindings", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
14427
|
+
`, styles: [".a2ui-modal__trigger{display:contents}.a2ui-modal__overlay{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center}.a2ui-modal__backdrop{position:absolute;inset:0;background:var(--a2ui-scrim);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.a2ui-modal__panel{position:relative;background:var(--a2ui-surface);border:1px solid var(--a2ui-outline);border-radius:var(--a2ui-shape-medium);padding:var(--a2ui-spacing-5);max-width:512px;width:100%;margin:0 var(--a2ui-spacing-4);box-shadow:var(--a2ui-elevation-4)}\n"] }]
|
|
14428
|
+
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
14126
14429
|
|
|
14127
14430
|
// SPDX-License-Identifier: MIT
|
|
14128
|
-
const
|
|
14431
|
+
const ALIGN_MAP = {
|
|
14129
14432
|
start: 'flex-start', center: 'center', end: 'flex-end', stretch: 'stretch',
|
|
14130
14433
|
};
|
|
14131
|
-
|
|
14434
|
+
/** justify 'stretch' has no justify-content equivalent — children grow instead
|
|
14435
|
+
* (see the --justify-stretch class below). */
|
|
14436
|
+
const JUSTIFY_MAP = {
|
|
14132
14437
|
start: 'flex-start', center: 'center', end: 'flex-end',
|
|
14133
|
-
|
|
14438
|
+
spaceAround: 'space-around', spaceBetween: 'space-between',
|
|
14439
|
+
spaceEvenly: 'space-evenly', stretch: 'normal',
|
|
14134
14440
|
};
|
|
14135
14441
|
class A2uiRowComponent {
|
|
14136
14442
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
14137
14443
|
spec = input.required(...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
14138
|
-
|
|
14139
|
-
|
|
14140
|
-
|
|
14444
|
+
/** v0.9 prop: cross-axis alignment (default 'stretch'). */
|
|
14445
|
+
align = input('stretch', ...(ngDevMode ? [{ debugName: "align" }] : []));
|
|
14446
|
+
/** v0.9 prop: main-axis distribution (default 'start'). */
|
|
14447
|
+
justify = input('start', ...(ngDevMode ? [{ debugName: "justify" }] : []));
|
|
14448
|
+
/** Not part of the v0.9 catalog — kept for json-render generative-ui
|
|
14449
|
+
* specs, which may set a numeric spacing unit (multiples of 4px) or a
|
|
14450
|
+
* named size. Unset falls back to the CSS default gap. */
|
|
14451
|
+
gap = input(undefined, ...(ngDevMode ? [{ debugName: "gap" }] : []));
|
|
14141
14452
|
// Framework inputs required by the render harness.
|
|
14142
14453
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
14143
14454
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
14144
14455
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
14145
|
-
alignItems = computed(() =>
|
|
14146
|
-
justifyContent = computed(() =>
|
|
14147
|
-
|
|
14148
|
-
gapPx = computed(() =>
|
|
14456
|
+
alignItems = computed(() => ALIGN_MAP[this.align()] ?? 'stretch', ...(ngDevMode ? [{ debugName: "alignItems" }] : []));
|
|
14457
|
+
justifyContent = computed(() => JUSTIFY_MAP[this.justify()] ?? 'flex-start', ...(ngDevMode ? [{ debugName: "justifyContent" }] : []));
|
|
14458
|
+
cssClass = computed(() => this.justify() === 'stretch' ? 'a2ui-row a2ui-row--justify-stretch' : 'a2ui-row', ...(ngDevMode ? [{ debugName: "cssClass" }] : []));
|
|
14459
|
+
gapPx = computed(() => {
|
|
14460
|
+
const g = this.gap();
|
|
14461
|
+
if (typeof g === 'number' && Number.isFinite(g))
|
|
14462
|
+
return g * 4;
|
|
14463
|
+
if (g === 'small')
|
|
14464
|
+
return 8;
|
|
14465
|
+
if (g === 'medium')
|
|
14466
|
+
return 12;
|
|
14467
|
+
if (g === 'large')
|
|
14468
|
+
return 16;
|
|
14469
|
+
return null;
|
|
14470
|
+
}, ...(ngDevMode ? [{ debugName: "gapPx" }] : []));
|
|
14149
14471
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14150
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiRowComponent, isStandalone: true, selector: "a2ui-row", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null },
|
|
14472
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiRowComponent, isStandalone: true, selector: "a2ui-row", inputs: { childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: true, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, justify: { classPropertyName: "justify", publicName: "justify", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
14151
14473
|
<div
|
|
14152
|
-
class="
|
|
14474
|
+
[class]="cssClass()"
|
|
14153
14475
|
[style.align-items]="alignItems()"
|
|
14154
14476
|
[style.justify-content]="justifyContent()"
|
|
14155
14477
|
[style.gap.px]="gapPx()"
|
|
@@ -14158,13 +14480,13 @@ class A2uiRowComponent {
|
|
|
14158
14480
|
<render-element [elementKey]="key" [spec]="spec()" />
|
|
14159
14481
|
}
|
|
14160
14482
|
</div>
|
|
14161
|
-
`, isInline: true, styles: [".a2ui-row{display:flex;flex-direction:row;flex-wrap:wrap}\n"], dependencies: [{ kind: "component", type: RenderElementComponent, selector: "render-element", inputs: ["elementKey", "spec"] }] });
|
|
14483
|
+
`, isInline: true, styles: [".a2ui-row{display:flex;flex-direction:row;flex-wrap:wrap;gap:var(--a2ui-spacing-3)}.a2ui-row--justify-stretch>render-element{flex:1}\n"], dependencies: [{ kind: "component", type: RenderElementComponent, selector: "render-element", inputs: ["elementKey", "spec"] }] });
|
|
14162
14484
|
}
|
|
14163
14485
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiRowComponent, decorators: [{
|
|
14164
14486
|
type: Component,
|
|
14165
14487
|
args: [{ selector: 'a2ui-row', standalone: true, imports: [RenderElementComponent], template: `
|
|
14166
14488
|
<div
|
|
14167
|
-
class="
|
|
14489
|
+
[class]="cssClass()"
|
|
14168
14490
|
[style.align-items]="alignItems()"
|
|
14169
14491
|
[style.justify-content]="justifyContent()"
|
|
14170
14492
|
[style.gap.px]="gapPx()"
|
|
@@ -14173,8 +14495,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
14173
14495
|
<render-element [elementKey]="key" [spec]="spec()" />
|
|
14174
14496
|
}
|
|
14175
14497
|
</div>
|
|
14176
|
-
`, styles: [".a2ui-row{display:flex;flex-direction:row;flex-wrap:wrap}\n"] }]
|
|
14177
|
-
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }],
|
|
14498
|
+
`, styles: [".a2ui-row{display:flex;flex-direction:row;flex-wrap:wrap;gap:var(--a2ui-spacing-3)}.a2ui-row--justify-stretch>render-element{flex:1}\n"] }]
|
|
14499
|
+
}], propDecorators: { childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: true }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], justify: [{ type: i0.Input, args: [{ isSignal: true, alias: "justify", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
14178
14500
|
|
|
14179
14501
|
// SPDX-License-Identifier: MIT
|
|
14180
14502
|
class A2uiSliderComponent {
|
|
@@ -14182,13 +14504,15 @@ class A2uiSliderComponent {
|
|
|
14182
14504
|
_inputId = `a2ui-slider-${++A2uiSliderComponent._idCounter}`;
|
|
14183
14505
|
host = injectRenderHost();
|
|
14184
14506
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
14185
|
-
/**
|
|
14507
|
+
/** v0.9 prop: value (resolved DynamicNumber). */
|
|
14186
14508
|
value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
14187
|
-
/**
|
|
14188
|
-
|
|
14189
|
-
/**
|
|
14190
|
-
|
|
14191
|
-
|
|
14509
|
+
/** v0.9 prop: lower bound (default 0). */
|
|
14510
|
+
min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : []));
|
|
14511
|
+
/** v0.9 prop: upper bound. */
|
|
14512
|
+
max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : []));
|
|
14513
|
+
/** Live validation message written by the surface's check gate
|
|
14514
|
+
* (bound to /_a2uiChecks/<id>); empty when valid. */
|
|
14515
|
+
errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : []));
|
|
14192
14516
|
_bindings = input({}, ...(ngDevMode ? [{ debugName: "_bindings" }] : []));
|
|
14193
14517
|
// Framework inputs required by the render harness.
|
|
14194
14518
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
@@ -14200,7 +14524,7 @@ class A2uiSliderComponent {
|
|
|
14200
14524
|
emitBinding(this.host, this._bindings(), 'value', val);
|
|
14201
14525
|
}
|
|
14202
14526
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiSliderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14203
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiSliderComponent, isStandalone: true, selector: "a2ui-slider", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null },
|
|
14527
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiSliderComponent, isStandalone: true, selector: "a2ui-slider", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, _bindings: { classPropertyName: "_bindings", publicName: "_bindings", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
14204
14528
|
<div class="a2ui-slider">
|
|
14205
14529
|
@if (label()) {
|
|
14206
14530
|
<label [htmlFor]="_inputId" class="a2ui-slider__label">{{ label() }}: {{ value() }}</label>
|
|
@@ -14209,14 +14533,16 @@ class A2uiSliderComponent {
|
|
|
14209
14533
|
[id]="_inputId"
|
|
14210
14534
|
type="range"
|
|
14211
14535
|
class="a2ui-slider__input"
|
|
14212
|
-
[min]="
|
|
14213
|
-
[max]="
|
|
14214
|
-
[step]="step()"
|
|
14536
|
+
[min]="min()"
|
|
14537
|
+
[max]="max()"
|
|
14215
14538
|
[value]="value()"
|
|
14216
14539
|
(input)="onInput($event)"
|
|
14217
14540
|
/>
|
|
14541
|
+
@if (errorText()) {
|
|
14542
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
14543
|
+
}
|
|
14218
14544
|
</div>
|
|
14219
|
-
`, isInline: true, styles: [".a2ui-slider{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-slider__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-slider__input{width:100%;cursor:pointer;accent-color:var(--a2ui-primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14545
|
+
`, isInline: true, styles: [".a2ui-slider{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-slider__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-slider__input{width:100%;cursor:pointer;accent-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14220
14546
|
}
|
|
14221
14547
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiSliderComponent, decorators: [{
|
|
14222
14548
|
type: Component,
|
|
@@ -14229,21 +14555,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
14229
14555
|
[id]="_inputId"
|
|
14230
14556
|
type="range"
|
|
14231
14557
|
class="a2ui-slider__input"
|
|
14232
|
-
[min]="
|
|
14233
|
-
[max]="
|
|
14234
|
-
[step]="step()"
|
|
14558
|
+
[min]="min()"
|
|
14559
|
+
[max]="max()"
|
|
14235
14560
|
[value]="value()"
|
|
14236
14561
|
(input)="onInput($event)"
|
|
14237
14562
|
/>
|
|
14563
|
+
@if (errorText()) {
|
|
14564
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
14565
|
+
}
|
|
14238
14566
|
</div>
|
|
14239
|
-
`, styles: [".a2ui-slider{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-slider__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-slider__input{width:100%;cursor:pointer;accent-color:var(--a2ui-primary)}\n"] }]
|
|
14240
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }],
|
|
14567
|
+
`, styles: [".a2ui-slider{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-slider__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-slider__input{width:100%;cursor:pointer;accent-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"] }]
|
|
14568
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], _bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "_bindings", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
14241
14569
|
|
|
14242
14570
|
// SPDX-License-Identifier: MIT
|
|
14243
14571
|
class A2uiTabsComponent {
|
|
14244
|
-
/** Resolved tab titles from
|
|
14572
|
+
/** Resolved tab titles from tabs[*].title — produced by surface-to-spec. */
|
|
14245
14573
|
tabTitles = input([], ...(ngDevMode ? [{ debugName: "tabTitles" }] : []));
|
|
14246
|
-
/**
|
|
14574
|
+
/** v0.9: each child key corresponds to a tab's child (childKeys[i] ↔ tabTitles[i]). */
|
|
14247
14575
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
14248
14576
|
spec = input.required(...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
14249
14577
|
// Framework inputs required by the render harness.
|
|
@@ -14314,7 +14642,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
14314
14642
|
// SPDX-License-Identifier: MIT
|
|
14315
14643
|
class A2uiTextComponent {
|
|
14316
14644
|
text = input('', ...(ngDevMode ? [{ debugName: "text" }] : []));
|
|
14317
|
-
|
|
14645
|
+
/** v0.9 prop: typography variant. */
|
|
14646
|
+
variant = input('body', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
14318
14647
|
// Framework-mandated inputs the render harness passes to every element.
|
|
14319
14648
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
14320
14649
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
@@ -14322,62 +14651,57 @@ class A2uiTextComponent {
|
|
|
14322
14651
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
14323
14652
|
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
14324
14653
|
cssClass() {
|
|
14325
|
-
return `a2ui-text-${this.
|
|
14654
|
+
return `a2ui-text-${this.variant()}`;
|
|
14326
14655
|
}
|
|
14327
14656
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14328
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.6", type: A2uiTextComponent, isStandalone: true, selector: "a2ui-text", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null },
|
|
14657
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.6", type: A2uiTextComponent, isStandalone: true, selector: "a2ui-text", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `<span [class]="cssClass()">{{ text() }}</span>`, isInline: true, styles: [".a2ui-text-h1{display:block;font-size:var(--a2ui-typography-h1-size);font-weight:var(--a2ui-typography-h1-weight);line-height:var(--a2ui-typography-h1-line-height);margin:0}.a2ui-text-h2{display:block;font-size:var(--a2ui-typography-h2-size);font-weight:var(--a2ui-typography-h2-weight);line-height:var(--a2ui-typography-h2-line-height);margin:0}.a2ui-text-h3{display:block;font-size:var(--a2ui-typography-h3-size);font-weight:var(--a2ui-typography-h3-weight);line-height:var(--a2ui-typography-h3-line-height);margin:0}.a2ui-text-h4{display:block;font-size:var(--a2ui-typography-h4-size);font-weight:var(--a2ui-typography-h4-weight);line-height:var(--a2ui-typography-h4-line-height);margin:0}.a2ui-text-h5{display:block;font-size:var(--a2ui-typography-h5-size);font-weight:var(--a2ui-typography-h5-weight);line-height:var(--a2ui-typography-h5-line-height);margin:0}.a2ui-text-caption{display:block;font-size:var(--a2ui-typography-caption-size);font-weight:var(--a2ui-typography-caption-weight);color:var(--a2ui-caption);line-height:var(--a2ui-typography-caption-line-height)}.a2ui-text-body{display:block;font-size:var(--a2ui-typography-body-size);font-weight:var(--a2ui-typography-body-weight);line-height:var(--a2ui-typography-body-line-height)}\n"] });
|
|
14329
14658
|
}
|
|
14330
14659
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiTextComponent, decorators: [{
|
|
14331
14660
|
type: Component,
|
|
14332
14661
|
args: [{ selector: 'a2ui-text', standalone: true, template: `<span [class]="cssClass()">{{ text() }}</span>`, styles: [".a2ui-text-h1{display:block;font-size:var(--a2ui-typography-h1-size);font-weight:var(--a2ui-typography-h1-weight);line-height:var(--a2ui-typography-h1-line-height);margin:0}.a2ui-text-h2{display:block;font-size:var(--a2ui-typography-h2-size);font-weight:var(--a2ui-typography-h2-weight);line-height:var(--a2ui-typography-h2-line-height);margin:0}.a2ui-text-h3{display:block;font-size:var(--a2ui-typography-h3-size);font-weight:var(--a2ui-typography-h3-weight);line-height:var(--a2ui-typography-h3-line-height);margin:0}.a2ui-text-h4{display:block;font-size:var(--a2ui-typography-h4-size);font-weight:var(--a2ui-typography-h4-weight);line-height:var(--a2ui-typography-h4-line-height);margin:0}.a2ui-text-h5{display:block;font-size:var(--a2ui-typography-h5-size);font-weight:var(--a2ui-typography-h5-weight);line-height:var(--a2ui-typography-h5-line-height);margin:0}.a2ui-text-caption{display:block;font-size:var(--a2ui-typography-caption-size);font-weight:var(--a2ui-typography-caption-weight);color:var(--a2ui-caption);line-height:var(--a2ui-typography-caption-line-height)}.a2ui-text-body{display:block;font-size:var(--a2ui-typography-body-size);font-weight:var(--a2ui-typography-body-weight);line-height:var(--a2ui-typography-body-line-height)}\n"] }]
|
|
14333
|
-
}], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }],
|
|
14662
|
+
}], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
14334
14663
|
|
|
14335
14664
|
// SPDX-License-Identifier: MIT
|
|
14336
|
-
/** Maps
|
|
14665
|
+
/** Maps v0.9 variant to HTML input[type] or textarea. */
|
|
14337
14666
|
const TYPE_MAP = {
|
|
14338
14667
|
shortText: 'text',
|
|
14339
14668
|
longText: 'text', // handled by textarea below
|
|
14340
14669
|
number: 'number',
|
|
14341
14670
|
obscured: 'password',
|
|
14342
|
-
date: 'date',
|
|
14343
14671
|
};
|
|
14344
14672
|
class A2uiTextFieldComponent {
|
|
14345
14673
|
static _idCounter = 0;
|
|
14346
14674
|
_inputId = `a2ui-text-field-${++A2uiTextFieldComponent._idCounter}`;
|
|
14347
14675
|
host = injectRenderHost();
|
|
14348
14676
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
14349
|
-
/**
|
|
14350
|
-
|
|
14351
|
-
/** Back-compat alias: value. surface-to-spec resolves DynamicString → plain string. */
|
|
14352
|
-
value = computed(() => this.text() ?? '', ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
14677
|
+
/** v0.9 prop: resolved string value. */
|
|
14678
|
+
value = input('', ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
14353
14679
|
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
14354
|
-
|
|
14680
|
+
/** v0.9 prop: input variant (default 'shortText'). */
|
|
14681
|
+
variant = input('shortText', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
14682
|
+
/** Enforced by the surface's check gate as an implicit regex rule (plus the native pattern attribute). */
|
|
14355
14683
|
validationRegexp = input('', ...(ngDevMode ? [{ debugName: "validationRegexp" }] : []));
|
|
14684
|
+
/** Live validation message written by the surface's check gate
|
|
14685
|
+
* (bound to /_a2uiChecks/<id>); empty when valid. */
|
|
14686
|
+
errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : []));
|
|
14356
14687
|
_bindings = input({}, ...(ngDevMode ? [{ debugName: "_bindings" }] : []));
|
|
14357
14688
|
// Framework inputs required by the render harness.
|
|
14358
14689
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
14359
14690
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
14360
14691
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
14361
14692
|
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
14362
|
-
htmlInputType = computed(() => TYPE_MAP[this.
|
|
14693
|
+
htmlInputType = computed(() => TYPE_MAP[this.variant()] ?? 'text', ...(ngDevMode ? [{ debugName: "htmlInputType" }] : []));
|
|
14363
14694
|
onInput(event) {
|
|
14364
14695
|
const val = event.target.value;
|
|
14365
|
-
|
|
14366
|
-
const bound = this._bindings();
|
|
14367
|
-
if (bound['text']) {
|
|
14368
|
-
emitBinding(this.host, bound, 'text', val);
|
|
14369
|
-
}
|
|
14370
|
-
else {
|
|
14371
|
-
emitBinding(this.host, bound, 'value', val);
|
|
14372
|
-
}
|
|
14696
|
+
emitBinding(this.host, this._bindings(), 'value', val);
|
|
14373
14697
|
}
|
|
14374
14698
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiTextFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14375
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiTextFieldComponent, isStandalone: true, selector: "a2ui-text-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null },
|
|
14699
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: A2uiTextFieldComponent, isStandalone: true, selector: "a2ui-text-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, validationRegexp: { classPropertyName: "validationRegexp", publicName: "validationRegexp", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, _bindings: { classPropertyName: "_bindings", publicName: "_bindings", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
14376
14700
|
<div class="a2ui-tf">
|
|
14377
14701
|
@if (label()) {
|
|
14378
14702
|
<label [htmlFor]="_inputId" class="a2ui-tf__label">{{ label() }}</label>
|
|
14379
14703
|
}
|
|
14380
|
-
@if (
|
|
14704
|
+
@if (variant() === 'longText') {
|
|
14381
14705
|
<textarea
|
|
14382
14706
|
[id]="_inputId"
|
|
14383
14707
|
[value]="value()"
|
|
@@ -14397,8 +14721,11 @@ class A2uiTextFieldComponent {
|
|
|
14397
14721
|
(input)="onInput($event)"
|
|
14398
14722
|
/>
|
|
14399
14723
|
}
|
|
14724
|
+
@if (errorText()) {
|
|
14725
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
14726
|
+
}
|
|
14400
14727
|
</div>
|
|
14401
|
-
`, isInline: true, styles: [".a2ui-tf{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-tf__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-tf__input{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard);resize:vertical}.a2ui-tf__input:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14728
|
+
`, isInline: true, styles: [".a2ui-tf{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-tf__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-tf__input{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard);resize:vertical}.a2ui-tf__input:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14402
14729
|
}
|
|
14403
14730
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiTextFieldComponent, decorators: [{
|
|
14404
14731
|
type: Component,
|
|
@@ -14407,7 +14734,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
14407
14734
|
@if (label()) {
|
|
14408
14735
|
<label [htmlFor]="_inputId" class="a2ui-tf__label">{{ label() }}</label>
|
|
14409
14736
|
}
|
|
14410
|
-
@if (
|
|
14737
|
+
@if (variant() === 'longText') {
|
|
14411
14738
|
<textarea
|
|
14412
14739
|
[id]="_inputId"
|
|
14413
14740
|
[value]="value()"
|
|
@@ -14427,16 +14754,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
14427
14754
|
(input)="onInput($event)"
|
|
14428
14755
|
/>
|
|
14429
14756
|
}
|
|
14757
|
+
@if (errorText()) {
|
|
14758
|
+
<div class="a2ui-check-error" role="alert">{{ errorText() }}</div>
|
|
14759
|
+
}
|
|
14430
14760
|
</div>
|
|
14431
|
-
`, styles: [".a2ui-tf{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-tf__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-tf__input{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard);resize:vertical}.a2ui-tf__input:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}\n"] }]
|
|
14432
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }],
|
|
14761
|
+
`, styles: [".a2ui-tf{display:flex;flex-direction:column;gap:var(--a2ui-spacing-1)}.a2ui-tf__label{font-size:var(--a2ui-typography-label-size);font-weight:var(--a2ui-typography-label-weight);color:var(--a2ui-label)}.a2ui-tf__input{padding:var(--a2ui-spacing-2) var(--a2ui-spacing-3);font-size:var(--a2ui-typography-body-size);border-radius:var(--a2ui-shape-small);background:var(--a2ui-input-bg);color:var(--a2ui-on-surface);border:1px solid var(--a2ui-outline);outline:none;transition:border-color var(--a2ui-motion-duration-short) var(--a2ui-motion-easing-standard);resize:vertical}.a2ui-tf__input:focus{outline:var(--a2ui-focus-ring-width) solid var(--a2ui-focus-ring-color);outline-offset:2px;border-color:var(--a2ui-primary)}.a2ui-check-error{font-size:var(--a2ui-typography-label-size);color:var(--a2ui-error, #d33d55)}\n"] }]
|
|
14762
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], validationRegexp: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationRegexp", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], _bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "_bindings", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
14433
14763
|
|
|
14434
14764
|
// SPDX-License-Identifier: MIT
|
|
14435
14765
|
class A2uiVideoComponent {
|
|
14436
14766
|
url = input('', ...(ngDevMode ? [{ debugName: "url" }] : []));
|
|
14437
|
-
/** v1 prop name: autoPlay (camelCase). */
|
|
14438
|
-
autoPlay = input(false, ...(ngDevMode ? [{ debugName: "autoPlay" }] : []));
|
|
14439
|
-
controls = input(true, ...(ngDevMode ? [{ debugName: "controls" }] : []));
|
|
14440
14767
|
// Framework inputs required by the render harness.
|
|
14441
14768
|
bindings = input({}, ...(ngDevMode ? [{ debugName: "bindings" }] : []));
|
|
14442
14769
|
emit = input(() => { }, ...(ngDevMode ? [{ debugName: "emit" }] : []));
|
|
@@ -14444,12 +14771,11 @@ class A2uiVideoComponent {
|
|
|
14444
14771
|
childKeys = input([], ...(ngDevMode ? [{ debugName: "childKeys" }] : []));
|
|
14445
14772
|
spec = input(undefined, ...(ngDevMode ? [{ debugName: "spec" }] : []));
|
|
14446
14773
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: A2uiVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14447
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.6", type: A2uiVideoComponent, isStandalone: true, selector: "a2ui-video", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null },
|
|
14774
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.6", type: A2uiVideoComponent, isStandalone: true, selector: "a2ui-video", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, bindings: { classPropertyName: "bindings", publicName: "bindings", isSignal: true, isRequired: false, transformFunction: null }, emit: { classPropertyName: "emit", publicName: "emit", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, childKeys: { classPropertyName: "childKeys", publicName: "childKeys", isSignal: true, isRequired: false, transformFunction: null }, spec: { classPropertyName: "spec", publicName: "spec", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
14448
14775
|
<video
|
|
14449
14776
|
class="a2ui-video"
|
|
14450
14777
|
[src]="url()"
|
|
14451
|
-
|
|
14452
|
-
[controls]="controls()"
|
|
14778
|
+
controls
|
|
14453
14779
|
></video>
|
|
14454
14780
|
`, isInline: true, styles: [".a2ui-video{display:block;width:100%;border-radius:var(--a2ui-shape-small)}\n"] });
|
|
14455
14781
|
}
|
|
@@ -14459,11 +14785,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
14459
14785
|
<video
|
|
14460
14786
|
class="a2ui-video"
|
|
14461
14787
|
[src]="url()"
|
|
14462
|
-
|
|
14463
|
-
[controls]="controls()"
|
|
14788
|
+
controls
|
|
14464
14789
|
></video>
|
|
14465
14790
|
`, styles: [".a2ui-video{display:block;width:100%;border-radius:var(--a2ui-shape-small)}\n"] }]
|
|
14466
|
-
}], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }],
|
|
14791
|
+
}], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], bindings: [{ type: i0.Input, args: [{ isSignal: true, alias: "bindings", required: false }] }], emit: [{ type: i0.Input, args: [{ isSignal: true, alias: "emit", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], childKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "childKeys", required: false }] }], spec: [{ type: i0.Input, args: [{ isSignal: true, alias: "spec", required: false }] }] } });
|
|
14467
14792
|
|
|
14468
14793
|
// SPDX-License-Identifier: MIT
|
|
14469
14794
|
/**
|
|
@@ -14484,6 +14809,7 @@ function a2uiBasicCatalog() {
|
|
|
14484
14809
|
Button: A2uiButtonComponent,
|
|
14485
14810
|
Card: A2uiCardComponent,
|
|
14486
14811
|
CheckBox: A2uiCheckBoxComponent,
|
|
14812
|
+
ChoicePicker: A2uiChoicePickerComponent,
|
|
14487
14813
|
Column: A2uiColumnComponent,
|
|
14488
14814
|
DateTimeInput: A2uiDateTimeInputComponent,
|
|
14489
14815
|
Divider: A2uiDividerComponent,
|
|
@@ -14491,7 +14817,6 @@ function a2uiBasicCatalog() {
|
|
|
14491
14817
|
Image: A2uiImageComponent,
|
|
14492
14818
|
List: A2uiListComponent,
|
|
14493
14819
|
Modal: A2uiModalComponent,
|
|
14494
|
-
MultipleChoice: A2uiMultipleChoiceComponent,
|
|
14495
14820
|
Row: A2uiRowComponent,
|
|
14496
14821
|
Slider: A2uiSliderComponent,
|
|
14497
14822
|
Tabs: A2uiTabsComponent,
|
|
@@ -14501,6 +14826,22 @@ function a2uiBasicCatalog() {
|
|
|
14501
14826
|
});
|
|
14502
14827
|
}
|
|
14503
14828
|
|
|
14829
|
+
// SPDX-License-Identifier: MIT
|
|
14830
|
+
/**
|
|
14831
|
+
* The A2UI client capabilities this renderer supports — the typed
|
|
14832
|
+
* `a2uiClientCapabilities` metadata a host attaches to agent requests so
|
|
14833
|
+
* the agent knows which component catalogs it may target
|
|
14834
|
+
* (catalog negotiation, A2UI v0.9 transport metadata).
|
|
14835
|
+
*
|
|
14836
|
+
* @example
|
|
14837
|
+
* ```ts
|
|
14838
|
+
* const metadata = { a2uiClientCapabilities: a2uiClientCapabilities() };
|
|
14839
|
+
* ```
|
|
14840
|
+
*/
|
|
14841
|
+
function a2uiClientCapabilities() {
|
|
14842
|
+
return { supportedCatalogIds: [A2UI_BASIC_CATALOG_ID] };
|
|
14843
|
+
}
|
|
14844
|
+
|
|
14504
14845
|
/**
|
|
14505
14846
|
* Declare an async function tool the model can call; its resolved return value
|
|
14506
14847
|
* becomes the tool result shipped back to the model.
|
|
@@ -14695,5 +15036,5 @@ function mockAgent(opts = {}) {
|
|
|
14695
15036
|
* Generated bundle index. Do not edit.
|
|
14696
15037
|
*/
|
|
14697
15038
|
|
|
14698
|
-
export { A2uiAudioPlayerComponent, A2uiButtonComponent, A2uiCardComponent, A2uiCheckBoxComponent, A2uiColumnComponent, A2uiDateTimeInputComponent, A2uiDividerComponent, A2uiIconComponent, A2uiImageComponent, A2uiListComponent, A2uiModalComponent,
|
|
15039
|
+
export { A2uiAudioPlayerComponent, A2uiButtonComponent, A2uiCardComponent, A2uiCheckBoxComponent, A2uiChoicePickerComponent, A2uiColumnComponent, A2uiDateTimeInputComponent, A2uiDividerComponent, A2uiIconComponent, A2uiImageComponent, A2uiListComponent, A2uiModalComponent, A2uiRowComponent, A2uiSliderComponent, A2uiSurfaceComponent, A2uiTabsComponent, A2uiTextComponent, A2uiTextFieldComponent, A2uiVideoComponent, AGENT_ERROR_MESSAGES, AgentError, CHAT_CONFIG, CHAT_LIFECYCLE, ChatApprovalCardComponent, ChatCitationCardTemplateDirective, ChatCitationPreviewComponent, ChatCitationsCardComponent, ChatCitationsComponent, ChatComponent, ChatConfirmDialogComponent, ChatConnectedOverlayDirective, ChatErrorComponent, ChatGenerativeUiComponent, ChatGenuiSkeletonComponent, ChatHistorySearchPaletteComponent, ChatInputComponent, ChatInterruptComponent, ChatInterruptPanelComponent, ChatLauncherButtonComponent, ChatMessageActionsComponent, ChatMessageComponent, ChatMessageListComponent, ChatOverflowMenuComponent, ChatOverlayOriginDirective, ChatPopupComponent, ChatProjectListComponent, ChatReasoningComponent, ChatScrollBubbleComponent, ChatSelectComponent, ChatSidebarComponent, ChatSidenavComponent, ChatSidenavScrimComponent, ChatStreamingMdComponent, ChatSubagentCardComponent, ChatSubagentsComponent, ChatSuggestionsComponent, ChatThreadListComponent, ChatTimelineComponent, ChatTimelineSliderComponent, ChatToolCallCardComponent, ChatToolCallTemplateDirective, ChatToolCallsComponent, ChatToolViewsComponent, ChatTraceComponent, ChatTypingIndicatorComponent, ChatWelcomeComponent, ChatWelcomeSuggestionComponent, ChatWindowComponent, CitationsResolverService, IS_HEADER_ROW, MARKDOWN_VIEW_REGISTRY, MarkdownAutolinkComponent, MarkdownBlockquoteComponent, MarkdownChildrenComponent, MarkdownCitationReferenceComponent, MarkdownCodeBlockComponent, MarkdownDocumentComponent, MarkdownEmphasisComponent, MarkdownHardBreakComponent, MarkdownHeadingComponent, MarkdownHtmlComponent, MarkdownImageComponent, MarkdownInlineCodeComponent, MarkdownLinkComponent, MarkdownListComponent, MarkdownListItemComponent, MarkdownMathComponent, MarkdownParagraphComponent, MarkdownSoftBreakComponent, MarkdownStrikethroughComponent, MarkdownStrongComponent, MarkdownTableCellComponent, MarkdownTableComponent, MarkdownTableRowComponent, MarkdownTextComponent, MarkdownThematicBreakComponent, MessageTemplateDirective, STREAMING_MARKDOWN_CONTRACT_VIOLATION_POLICY, a2uiBasicCatalog, a2uiClientCapabilities, action, ask, buildA2uiActionMessage, cacheplaneMarkdownViews, cancelledClientToolResult, citationSourceVisual, citationTypeLabel, citationTypeMeta, clientToolGuardFailureResult, completeDelivery, createA2uiSurfaceStore, createAgentRef, createContentClassifier, createParseTreeStore, createPartialArgsBridge, defaultInterruptedClientToolResult, deriveDomain, deriveJsonSchema, deriveMonogram, deriveSourceType, emitBinding, executeFunctionTool, extractErrorMessage, formatDuration, formatPublished, getInterrupt, getMessageType, injectThreadRouting, isAbortError, isAssistantMessage, isSystemMessage, isToolMessage, isTyping, isUserMessage, markdownDocument, messageContent, mockAgent, monogramColor, monogramHue, normalizeEnvelopeArgs, normalizeViewEntry, provideChat, renderMarkdown, selectPendingClientToolCalls, shouldClaimBeforeExecute, startClientToolExecutor, staticDelivery, statusColor, streamingDelivery, submitMessage, toAgentError, toClientToolSpecs, tools, validateArgs, view };
|
|
14699
15040
|
//# sourceMappingURL=threadplane-chat.mjs.map
|