@genesislcap/ai-assistant 15.19.0 → 15.19.1
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/package.json +17 -18
- package/api-extractor.json +0 -11
- package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts.map +0 -1
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts +0 -2
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts.map +0 -1
- package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts +0 -2
- package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts.map +0 -1
- package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts +0 -2
- package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts.map +0 -1
- package/dist/dts/config/define-stateful-agent.test.d.ts +0 -2
- package/dist/dts/config/define-stateful-agent.test.d.ts.map +0 -1
- package/dist/dts/config/validate-providers.test.d.ts +0 -2
- package/dist/dts/config/validate-providers.test.d.ts.map +0 -1
- package/dist/dts/main/blocked-state.test.d.ts +0 -2
- package/dist/dts/main/blocked-state.test.d.ts.map +0 -1
- package/dist/dts/main/budget-meter.test.d.ts +0 -2
- package/dist/dts/main/budget-meter.test.d.ts.map +0 -1
- package/dist/dts/main/cost-session-banking.test.d.ts +0 -2
- package/dist/dts/main/cost-session-banking.test.d.ts.map +0 -1
- package/dist/dts/main/file-attachments.test.d.ts +0 -2
- package/dist/dts/main/file-attachments.test.d.ts.map +0 -1
- package/dist/dts/main/interaction-cost.test.d.ts +0 -2
- package/dist/dts/main/interaction-cost.test.d.ts.map +0 -1
- package/dist/dts/main/main.styles.test.d.ts +0 -2
- package/dist/dts/main/main.styles.test.d.ts.map +0 -1
- package/dist/dts/main/persistence-broken-sources.test.d.ts +0 -2
- package/dist/dts/main/persistence-broken-sources.test.d.ts.map +0 -1
- package/dist/dts/main/popout-interaction-gate.test.d.ts +0 -2
- package/dist/dts/main/popout-interaction-gate.test.d.ts.map +0 -1
- package/dist/dts/state/ai-assistant-slice.test.d.ts +0 -2
- package/dist/dts/state/ai-assistant-slice.test.d.ts.map +0 -1
- package/dist/dts/state/debug-event-log.test.d.ts +0 -2
- package/dist/dts/state/debug-event-log.test.d.ts.map +0 -1
- package/dist/dts/state/driver-registry.test.d.ts +0 -2
- package/dist/dts/state/driver-registry.test.d.ts.map +0 -1
- package/dist/dts/state/interaction-context.test.d.ts +0 -2
- package/dist/dts/state/interaction-context.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts +0 -2
- package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/diagnostics.test.d.ts +0 -2
- package/dist/dts/state/persistence/diagnostics.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persistence-provider.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persistence-provider.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persistence.integration.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persistence.integration.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persister.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persister.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-snapshot.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-snapshot.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts +0 -2
- package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts.map +0 -1
- package/dist/dts/utils/animation-exclusivity.test.d.ts +0 -2
- package/dist/dts/utils/animation-exclusivity.test.d.ts.map +0 -1
- package/dist/dts/utils/collect-session-models.test.d.ts +0 -2
- package/dist/dts/utils/collect-session-models.test.d.ts.map +0 -1
- package/dist/dts/utils/condense-history.test.d.ts +0 -2
- package/dist/dts/utils/condense-history.test.d.ts.map +0 -1
- package/dist/dts/utils/cost-session-history.test.d.ts +0 -2
- package/dist/dts/utils/cost-session-history.test.d.ts.map +0 -1
- package/dist/dts/utils/derive-cost-session-title.test.d.ts +0 -2
- package/dist/dts/utils/derive-cost-session-title.test.d.ts.map +0 -1
- package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts +0 -2
- package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts.map +0 -1
- package/dist/dts/utils/history-transform.test.d.ts +0 -2
- package/dist/dts/utils/history-transform.test.d.ts.map +0 -1
- package/dist/dts/utils/message-partition.test.d.ts +0 -2
- package/dist/dts/utils/message-partition.test.d.ts.map +0 -1
- package/dist/dts/utils/resolve-cost-history-config.test.d.ts +0 -2
- package/dist/dts/utils/resolve-cost-history-config.test.d.ts.map +0 -1
- package/dist/dts/utils/resolve-preference-baseline.test.d.ts +0 -2
- package/dist/dts/utils/resolve-preference-baseline.test.d.ts.map +0 -1
- package/dist/dts/utils/strip-agent-handlers.test.d.ts +0 -2
- package/dist/dts/utils/strip-agent-handlers.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-costs.test.d.ts +0 -2
- package/dist/dts/utils/sum-costs.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-tokens.test.d.ts +0 -2
- package/dist/dts/utils/sum-tokens.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-usage.test.d.ts +0 -2
- package/dist/dts/utils/sum-usage.test.d.ts.map +0 -1
- package/dist/dts/utils/usage-rows.test.d.ts +0 -2
- package/dist/dts/utils/usage-rows.test.d.ts.map +0 -1
- package/dist/esm/components/chat-driver/chat-driver.compact.test.js +0 -93
- package/dist/esm/components/chat-driver/chat-driver.invocation-scope.test.js +0 -238
- package/dist/esm/components/chat-driver/chat-driver.test.js +0 -2770
- package/dist/esm/components/chat-driver/chat-driver.thinking-policy.test.js +0 -137
- package/dist/esm/components/chat-driver/chat-driver.trace-capture.test.js +0 -200
- package/dist/esm/components/chat-driver/chat-driver.turn-usage.test.js +0 -268
- package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.test.js +0 -104
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.budget.test.js +0 -312
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.cost.test.js +0 -76
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.pin.test.js +0 -61
- package/dist/esm/components/settings-modal/settings-modal.styles.test.js +0 -80
- package/dist/esm/components/settings-modal/settings-modal.template.test.js +0 -91
- package/dist/esm/config/define-stateful-agent.test.js +0 -53
- package/dist/esm/config/validate-providers.test.js +0 -100
- package/dist/esm/main/blocked-state.test.js +0 -1065
- package/dist/esm/main/budget-meter.test.js +0 -359
- package/dist/esm/main/cost-session-banking.test.js +0 -538
- package/dist/esm/main/file-attachments.test.js +0 -164
- package/dist/esm/main/interaction-cost.test.js +0 -107
- package/dist/esm/main/main.styles.test.js +0 -161
- package/dist/esm/main/persistence-broken-sources.test.js +0 -180
- package/dist/esm/main/popout-interaction-gate.test.js +0 -54
- package/dist/esm/state/ai-assistant-slice.test.js +0 -229
- package/dist/esm/state/debug-event-log.test.js +0 -117
- package/dist/esm/state/driver-registry.test.js +0 -55
- package/dist/esm/state/interaction-context.test.js +0 -78
- package/dist/esm/state/persistence/diagnostics-cursors.test.js +0 -30
- package/dist/esm/state/persistence/diagnostics.test.js +0 -280
- package/dist/esm/state/persistence/session-persistence-provider.test.js +0 -110
- package/dist/esm/state/persistence/session-persistence.integration.test.js +0 -113
- package/dist/esm/state/persistence/session-persister.test.js +0 -613
- package/dist/esm/state/persistence/session-snapshot.test.js +0 -256
- package/dist/esm/state/persistence/stateful-restore.e2e.test.js +0 -158
- package/dist/esm/utils/animation-exclusivity.test.js +0 -52
- package/dist/esm/utils/collect-session-models.test.js +0 -53
- package/dist/esm/utils/condense-history.test.js +0 -547
- package/dist/esm/utils/cost-session-history.test.js +0 -174
- package/dist/esm/utils/derive-cost-session-title.test.js +0 -37
- package/dist/esm/utils/flatten-sub-agent-messages.test.js +0 -139
- package/dist/esm/utils/history-transform.test.js +0 -158
- package/dist/esm/utils/message-partition.test.js +0 -90
- package/dist/esm/utils/resolve-cost-history-config.test.js +0 -32
- package/dist/esm/utils/resolve-preference-baseline.test.js +0 -69
- package/dist/esm/utils/strip-agent-handlers.test.js +0 -81
- package/dist/esm/utils/sum-costs.test.js +0 -114
- package/dist/esm/utils/sum-tokens.test.js +0 -51
- package/dist/esm/utils/sum-usage.test.js +0 -164
- package/dist/esm/utils/usage-rows.test.js +0 -189
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/license.txt +0 -46
- package/sandbox/tsconfig.json +0 -8
- package/src/channel/ai-activity-bus.ts +0 -209
- package/src/channel/ai-activity-channel.ts +0 -146
- package/src/chat-driver-node.ts +0 -159
- package/src/components/activity-halo/activity-halo.ts +0 -106
- package/src/components/agent-picker/agent-picker.constants.ts +0 -2
- package/src/components/agent-picker/agent-picker.styles.ts +0 -24
- package/src/components/agent-picker/agent-picker.template.ts +0 -54
- package/src/components/agent-picker/agent-picker.ts +0 -99
- package/src/components/agent-picker/index.ts +0 -1
- package/src/components/ai-driver/ai-driver.ts +0 -166
- package/src/components/ai-driver/index.ts +0 -1
- package/src/components/chat-bubble/chat-bubble.styles.ts +0 -194
- package/src/components/chat-bubble/chat-bubble.template.ts +0 -67
- package/src/components/chat-bubble/chat-bubble.ts +0 -436
- package/src/components/chat-bubble/index.ts +0 -1
- package/src/components/chat-driver/align-event-globals.ts +0 -23
- package/src/components/chat-driver/chat-driver.compact.test.ts +0 -131
- package/src/components/chat-driver/chat-driver.invocation-scope.test.ts +0 -285
- package/src/components/chat-driver/chat-driver.test.ts +0 -3679
- package/src/components/chat-driver/chat-driver.thinking-policy.test.ts +0 -185
- package/src/components/chat-driver/chat-driver.trace-capture.test.ts +0 -251
- package/src/components/chat-driver/chat-driver.ts +0 -3925
- package/src/components/chat-driver/chat-driver.turn-usage.test.ts +0 -362
- package/src/components/chat-driver/index.ts +0 -1
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts +0 -7
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts +0 -6
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.test.ts +0 -144
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +0 -243
- package/src/components/chat-interaction-wrapper/index.ts +0 -3
- package/src/components/chat-markdown/chat-markdown.ts +0 -89
- package/src/components/chat-markdown/index.ts +0 -1
- package/src/components/flowing-waves-indicator.ts +0 -286
- package/src/components/halo-overlay.ts +0 -184
- package/src/components/orchestrating-driver/index.ts +0 -1
- package/src/components/orchestrating-driver/orchestrating-driver.budget.test.ts +0 -438
- package/src/components/orchestrating-driver/orchestrating-driver.cost.test.ts +0 -107
- package/src/components/orchestrating-driver/orchestrating-driver.pin.test.ts +0 -96
- package/src/components/orchestrating-driver/orchestrating-driver.ts +0 -813
- package/src/components/plasma-orb-indicator.ts +0 -281
- package/src/components/popout-manager/index.ts +0 -1
- package/src/components/popout-manager/popout-manager.ts +0 -212
- package/src/components/settings-modal/index.ts +0 -2
- package/src/components/settings-modal/settings-modal.styles.test.ts +0 -94
- package/src/components/settings-modal/settings-modal.styles.ts +0 -853
- package/src/components/settings-modal/settings-modal.template.test.ts +0 -124
- package/src/components/settings-modal/settings-modal.template.ts +0 -943
- package/src/components/waves-indicator.ts +0 -241
- package/src/config/config.ts +0 -608
- package/src/config/define-stateful-agent.test.ts +0 -64
- package/src/config/define-stateful-agent.ts +0 -642
- package/src/config/fallback-agents.ts +0 -29
- package/src/config/index.ts +0 -2
- package/src/config/validate-providers.test.ts +0 -148
- package/src/config/validate-providers.ts +0 -58
- package/src/index.ts +0 -29
- package/src/main/blocked-state.test.ts +0 -1444
- package/src/main/budget-meter.test.ts +0 -477
- package/src/main/cost-session-banking.test.ts +0 -679
- package/src/main/file-attachments.test.ts +0 -215
- package/src/main/index.ts +0 -3
- package/src/main/interaction-cost.test.ts +0 -140
- package/src/main/main.styles.test.ts +0 -216
- package/src/main/main.styles.ts +0 -995
- package/src/main/main.template.ts +0 -1119
- package/src/main/main.ts +0 -5432
- package/src/main/main.types.ts +0 -225
- package/src/main/persistence-broken-sources.test.ts +0 -219
- package/src/main/popout-interaction-gate.test.ts +0 -87
- package/src/provider/ai-provider-switcher.ts +0 -40
- package/src/provider/assistant-app-settings.ts +0 -84
- package/src/state/ai-assistant-slice.test.ts +0 -336
- package/src/state/ai-assistant-slice.ts +0 -604
- package/src/state/debug-event-log.test.ts +0 -154
- package/src/state/debug-event-log.ts +0 -358
- package/src/state/driver-registry.test.ts +0 -70
- package/src/state/driver-registry.ts +0 -79
- package/src/state/interaction-context.test.ts +0 -90
- package/src/state/interaction-context.ts +0 -101
- package/src/state/persistence/build-timeline-entries.ts +0 -66
- package/src/state/persistence/diagnostics-cursors.test.ts +0 -53
- package/src/state/persistence/diagnostics-cursors.ts +0 -80
- package/src/state/persistence/diagnostics.test.ts +0 -346
- package/src/state/persistence/diagnostics.ts +0 -220
- package/src/state/persistence/index.ts +0 -10
- package/src/state/persistence/persister-registry.ts +0 -55
- package/src/state/persistence/session-persistence-provider.test.ts +0 -136
- package/src/state/persistence/session-persistence-provider.ts +0 -226
- package/src/state/persistence/session-persistence.integration.test.ts +0 -141
- package/src/state/persistence/session-persister.test.ts +0 -787
- package/src/state/persistence/session-persister.ts +0 -917
- package/src/state/persistence/session-snapshot.test.ts +0 -352
- package/src/state/persistence/session-snapshot.ts +0 -344
- package/src/state/persistence/stateful-restore.e2e.test.ts +0 -229
- package/src/state/session-store.ts +0 -56
- package/src/styles/ai-colours.ts +0 -30
- package/src/styles/menu.ts +0 -187
- package/src/styles/settings-section.ts +0 -40
- package/src/suggestions/chat-suggestions.ts +0 -186
- package/src/tags/index.ts +0 -1
- package/src/types/ai-chat-widget.ts +0 -67
- package/src/types/interaction-context.ts +0 -82
- package/src/utils/animated-panel-toggle.ts +0 -62
- package/src/utils/animation-exclusivity.test.ts +0 -72
- package/src/utils/animation-exclusivity.ts +0 -40
- package/src/utils/banked-usage-baselines.ts +0 -90
- package/src/utils/collect-session-models.test.ts +0 -82
- package/src/utils/collect-session-models.ts +0 -65
- package/src/utils/condense-history.test.ts +0 -746
- package/src/utils/condense-history.ts +0 -448
- package/src/utils/cost-session-history.test.ts +0 -226
- package/src/utils/cost-session-history.ts +0 -218
- package/src/utils/derive-cost-session-title.test.ts +0 -63
- package/src/utils/derive-cost-session-title.ts +0 -76
- package/src/utils/flatten-sub-agent-messages.test.ts +0 -163
- package/src/utils/flatten-sub-agent-messages.ts +0 -88
- package/src/utils/format-usd.ts +0 -26
- package/src/utils/history-transform.test.ts +0 -228
- package/src/utils/history-transform.ts +0 -163
- package/src/utils/index.ts +0 -3
- package/src/utils/logger.ts +0 -3
- package/src/utils/message-partition.test.ts +0 -129
- package/src/utils/message-partition.ts +0 -115
- package/src/utils/resolve-cost-history-config.test.ts +0 -38
- package/src/utils/resolve-cost-history-config.ts +0 -38
- package/src/utils/resolve-preference-baseline.test.ts +0 -84
- package/src/utils/resolve-preference-baseline.ts +0 -80
- package/src/utils/strip-agent-handlers.test.ts +0 -99
- package/src/utils/strip-agent-handlers.ts +0 -53
- package/src/utils/sum-costs.test.ts +0 -136
- package/src/utils/sum-costs.ts +0 -18
- package/src/utils/sum-tokens.test.ts +0 -93
- package/src/utils/sum-tokens.ts +0 -68
- package/src/utils/sum-usage.test.ts +0 -191
- package/src/utils/sum-usage.ts +0 -208
- package/src/utils/tool-fold.ts +0 -181
- package/src/utils/usage-rows.test.ts +0 -237
- package/src/utils/usage-rows.ts +0 -187
- package/src/utils/with-timeout.ts +0 -24
- package/tsconfig.json +0 -9
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
import { css, customElement, GenesisElement, html } from '@genesislcap/web-core';
|
|
2
|
-
import {
|
|
3
|
-
AI_COLOUR_AMBER,
|
|
4
|
-
AI_COLOUR_CYAN,
|
|
5
|
-
AI_COLOUR_PINK,
|
|
6
|
-
AI_COLOUR_VIOLET,
|
|
7
|
-
} from '../styles/ai-colours';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Animated "plasma orb" loading indicator — a fixed glowing energy sphere whose
|
|
11
|
-
* luminous filaments and swirls drift and rotate inside it, like a plasma ball.
|
|
12
|
-
* The globe never resizes; only the energy moves.
|
|
13
|
-
*
|
|
14
|
-
* Brand-coloured: a violet energy core, a slow cyan/pink tint wash, and a warm
|
|
15
|
-
* amber hot-spot — covering all four brand colours.
|
|
16
|
-
*
|
|
17
|
-
* Visual sibling of the dots loading indicator; interchangeable with the other
|
|
18
|
-
* loading styles for the "assistant is working" state.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```html
|
|
22
|
-
* <ai-plasma-orb-indicator></ai-plasma-orb-indicator>
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* @beta
|
|
26
|
-
*/
|
|
27
|
-
@customElement({
|
|
28
|
-
name: 'ai-plasma-orb-indicator',
|
|
29
|
-
template: html<AiPlasmaOrbIndicator>`
|
|
30
|
-
<div class="pulse" role="img" aria-label="Assistant is working">
|
|
31
|
-
<div class="plasma">
|
|
32
|
-
<div class="swirl1"></div>
|
|
33
|
-
<div class="swirl2"></div>
|
|
34
|
-
<svg class="filaments" viewBox="0 0 100 100">
|
|
35
|
-
<g>
|
|
36
|
-
<path d="M8 50 Q50 18 92 50" />
|
|
37
|
-
<path d="M50 8 Q82 50 50 92" />
|
|
38
|
-
<path d="M18 22 Q52 54 82 80" />
|
|
39
|
-
<path d="M82 20 Q48 46 20 82" />
|
|
40
|
-
<path d="M12 64 Q50 38 88 34" />
|
|
41
|
-
<path d="M30 12 Q55 50 72 88" />
|
|
42
|
-
<path d="M14 38 Q50 60 86 62" />
|
|
43
|
-
<path d="M66 10 Q44 48 24 90" />
|
|
44
|
-
<path d="M10 28 Q56 44 90 72" />
|
|
45
|
-
<path d="M88 44 Q46 52 16 76" />
|
|
46
|
-
<path d="M40 6 Q58 50 88 86" />
|
|
47
|
-
<path d="M22 86 Q46 44 60 8" />
|
|
48
|
-
</g>
|
|
49
|
-
</svg>
|
|
50
|
-
<div class="tint"></div>
|
|
51
|
-
<div class="hot"></div>
|
|
52
|
-
</div>
|
|
53
|
-
<div class="ring-emit"></div>
|
|
54
|
-
<div class="ring-emit r2"></div>
|
|
55
|
-
</div>
|
|
56
|
-
`,
|
|
57
|
-
styles: css`
|
|
58
|
-
:host {
|
|
59
|
-
position: relative;
|
|
60
|
-
display: inline-block;
|
|
61
|
-
width: 56px;
|
|
62
|
-
height: 56px;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/* Authored at the gallery's native 100px size and scaled down so the px
|
|
66
|
-
glow/filament geometry keeps its proportions. Absolutely centred so the
|
|
67
|
-
overflowing glow/rings don't affect the host's layout box. */
|
|
68
|
-
.pulse {
|
|
69
|
-
position: absolute;
|
|
70
|
-
top: 50%;
|
|
71
|
-
left: 50%;
|
|
72
|
-
width: 100px;
|
|
73
|
-
height: 100px;
|
|
74
|
-
transform: translate(-50%, -50%) scale(0.56);
|
|
75
|
-
display: flex;
|
|
76
|
-
align-items: center;
|
|
77
|
-
justify-content: center;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.plasma {
|
|
81
|
-
position: relative;
|
|
82
|
-
width: 86px;
|
|
83
|
-
height: 86px;
|
|
84
|
-
border-radius: 50%;
|
|
85
|
-
overflow: hidden;
|
|
86
|
-
isolation: isolate;
|
|
87
|
-
background: radial-gradient(
|
|
88
|
-
circle at 50% 40%,
|
|
89
|
-
#fdf2ff 0%,
|
|
90
|
-
#f3c7fd 14%,
|
|
91
|
-
#e362ff 38%,
|
|
92
|
-
${AI_COLOUR_VIOLET} 62%,
|
|
93
|
-
#8a0a9c 84%,
|
|
94
|
-
#3a0044 100%
|
|
95
|
-
);
|
|
96
|
-
box-shadow:
|
|
97
|
-
0 0 20px 5px color-mix(in srgb, ${AI_COLOUR_VIOLET}, transparent 20%),
|
|
98
|
-
0 0 48px 12px color-mix(in srgb, ${AI_COLOUR_VIOLET}, transparent 58%),
|
|
99
|
-
inset 0 0 22px rgb(255 255 255 / 22%),
|
|
100
|
-
inset 0 0 8px rgb(255 255 255 / 50%);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/* bright rim light */
|
|
104
|
-
.plasma::after {
|
|
105
|
-
content: '';
|
|
106
|
-
position: absolute;
|
|
107
|
-
inset: 0;
|
|
108
|
-
border-radius: 50%;
|
|
109
|
-
z-index: 5;
|
|
110
|
-
pointer-events: none;
|
|
111
|
-
box-shadow:
|
|
112
|
-
inset 0 0 6px 1px rgb(245 220 255 / 90%),
|
|
113
|
-
inset 0 0 16px color-mix(in srgb, ${AI_COLOUR_VIOLET}, transparent 35%);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/* slow colour shift: washes the orb toward cyan/pink and back */
|
|
117
|
-
.tint {
|
|
118
|
-
position: absolute;
|
|
119
|
-
inset: 0;
|
|
120
|
-
border-radius: 50%;
|
|
121
|
-
z-index: 4;
|
|
122
|
-
pointer-events: none;
|
|
123
|
-
background: radial-gradient(
|
|
124
|
-
circle at 50% 40%,
|
|
125
|
-
color-mix(in srgb, ${AI_COLOUR_CYAN}, white 35%) 0%,
|
|
126
|
-
${AI_COLOUR_CYAN} 45%,
|
|
127
|
-
${AI_COLOUR_PINK} 100%
|
|
128
|
-
);
|
|
129
|
-
mix-blend-mode: color;
|
|
130
|
-
opacity: 0;
|
|
131
|
-
animation: plasma-tint 9s ease-in-out infinite;
|
|
132
|
-
}
|
|
133
|
-
@keyframes plasma-tint {
|
|
134
|
-
0%,
|
|
135
|
-
100% {
|
|
136
|
-
opacity: 0;
|
|
137
|
-
}
|
|
138
|
-
50% {
|
|
139
|
-
opacity: 0.85;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/* warm white-hot core highlight (shifts, never resizes the orb) */
|
|
144
|
-
.hot {
|
|
145
|
-
position: absolute;
|
|
146
|
-
left: 50%;
|
|
147
|
-
top: 38%;
|
|
148
|
-
width: 42px;
|
|
149
|
-
height: 36px;
|
|
150
|
-
z-index: 4;
|
|
151
|
-
border-radius: 50%;
|
|
152
|
-
pointer-events: none;
|
|
153
|
-
filter: blur(3px);
|
|
154
|
-
background: radial-gradient(
|
|
155
|
-
circle,
|
|
156
|
-
rgb(255 255 255 / 90%) 0%,
|
|
157
|
-
color-mix(in srgb, ${AI_COLOUR_AMBER}, white 30%) 42%,
|
|
158
|
-
rgb(255 255 255 / 0%) 70%
|
|
159
|
-
);
|
|
160
|
-
animation: plasma-hot 5s ease-in-out infinite;
|
|
161
|
-
}
|
|
162
|
-
@keyframes plasma-hot {
|
|
163
|
-
0%,
|
|
164
|
-
100% {
|
|
165
|
-
opacity: 0.65;
|
|
166
|
-
transform: translate(-50%, -50%) translate(-2px, 1px);
|
|
167
|
-
}
|
|
168
|
-
50% {
|
|
169
|
-
opacity: 1;
|
|
170
|
-
transform: translate(-50%, -50%) translate(3px, -2px);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/* swirling radial filaments */
|
|
175
|
-
.swirl1,
|
|
176
|
-
.swirl2 {
|
|
177
|
-
position: absolute;
|
|
178
|
-
inset: -25%;
|
|
179
|
-
border-radius: 50%;
|
|
180
|
-
z-index: 2;
|
|
181
|
-
mix-blend-mode: screen;
|
|
182
|
-
}
|
|
183
|
-
.swirl1 {
|
|
184
|
-
background: conic-gradient(
|
|
185
|
-
from 0deg,
|
|
186
|
-
transparent 0 4deg,
|
|
187
|
-
rgb(225 240 255 / 55%) 7deg,
|
|
188
|
-
transparent 11deg 58deg,
|
|
189
|
-
rgb(190 225 255 / 45%) 64deg,
|
|
190
|
-
transparent 70deg 138deg,
|
|
191
|
-
rgb(255 255 255 / 50%) 144deg,
|
|
192
|
-
transparent 150deg 220deg,
|
|
193
|
-
rgb(200 230 255 / 45%) 226deg,
|
|
194
|
-
transparent 232deg 300deg,
|
|
195
|
-
rgb(255 255 255 / 45%) 306deg,
|
|
196
|
-
transparent 312deg 360deg
|
|
197
|
-
);
|
|
198
|
-
filter: blur(3px);
|
|
199
|
-
animation: plasma-spin-cw 9s linear infinite;
|
|
200
|
-
}
|
|
201
|
-
.swirl2 {
|
|
202
|
-
background: conic-gradient(
|
|
203
|
-
from 40deg,
|
|
204
|
-
transparent 0 30deg,
|
|
205
|
-
rgb(180 215 255 / 40%) 36deg,
|
|
206
|
-
transparent 42deg 110deg,
|
|
207
|
-
rgb(255 255 255 / 40%) 116deg,
|
|
208
|
-
transparent 122deg 190deg,
|
|
209
|
-
rgb(190 225 255 / 40%) 196deg,
|
|
210
|
-
transparent 202deg 280deg,
|
|
211
|
-
rgb(255 255 255 / 40%) 286deg,
|
|
212
|
-
transparent 292deg 360deg
|
|
213
|
-
);
|
|
214
|
-
filter: blur(5px);
|
|
215
|
-
animation: plasma-spin-ccw 13s linear infinite;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/* curved web filaments */
|
|
219
|
-
.filaments {
|
|
220
|
-
position: absolute;
|
|
221
|
-
inset: 0;
|
|
222
|
-
width: 100%;
|
|
223
|
-
height: 100%;
|
|
224
|
-
z-index: 3;
|
|
225
|
-
overflow: visible;
|
|
226
|
-
mix-blend-mode: screen;
|
|
227
|
-
filter: blur(0.5px);
|
|
228
|
-
}
|
|
229
|
-
.filaments g {
|
|
230
|
-
transform-box: fill-box;
|
|
231
|
-
transform-origin: center;
|
|
232
|
-
animation: plasma-spin-ccw 18s linear infinite;
|
|
233
|
-
}
|
|
234
|
-
.filaments path {
|
|
235
|
-
fill: none;
|
|
236
|
-
stroke: rgb(230 245 255 / 50%);
|
|
237
|
-
stroke-width: 0.7;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/* soft light rings emitting outward from the orb */
|
|
241
|
-
.ring-emit {
|
|
242
|
-
position: absolute;
|
|
243
|
-
left: 50%;
|
|
244
|
-
top: 50%;
|
|
245
|
-
width: 86px;
|
|
246
|
-
height: 86px;
|
|
247
|
-
transform: translate(-50%, -50%);
|
|
248
|
-
border-radius: 50%;
|
|
249
|
-
border: 2px solid color-mix(in srgb, ${AI_COLOUR_VIOLET}, transparent 25%);
|
|
250
|
-
box-shadow: 0 0 8px color-mix(in srgb, ${AI_COLOUR_VIOLET}, transparent 35%);
|
|
251
|
-
pointer-events: none;
|
|
252
|
-
z-index: 0;
|
|
253
|
-
animation: plasma-emit 2.8s ease-out infinite;
|
|
254
|
-
}
|
|
255
|
-
.ring-emit.r2 {
|
|
256
|
-
animation-delay: 1.4s;
|
|
257
|
-
}
|
|
258
|
-
@keyframes plasma-emit {
|
|
259
|
-
0% {
|
|
260
|
-
transform: translate(-50%, -50%) scale(1);
|
|
261
|
-
opacity: 0.7;
|
|
262
|
-
}
|
|
263
|
-
100% {
|
|
264
|
-
transform: translate(-50%, -50%) scale(1.45);
|
|
265
|
-
opacity: 0;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
@keyframes plasma-spin-cw {
|
|
270
|
-
to {
|
|
271
|
-
transform: rotate(360deg);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
@keyframes plasma-spin-ccw {
|
|
275
|
-
to {
|
|
276
|
-
transform: rotate(-360deg);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
`,
|
|
280
|
-
})
|
|
281
|
-
export class AiPlasmaOrbIndicator extends GenesisElement {}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './popout-manager';
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { customElement, GenesisElement, html, observable } from '@genesislcap/web-core';
|
|
2
|
-
import { agenticActivityBus } from '../../channel/ai-activity-bus';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Contract for pages that support docking the AI assistant.
|
|
6
|
-
* Register an implementation with {@link getAiPopoutManager} on mount and deregister on unmount.
|
|
7
|
-
*
|
|
8
|
-
* @beta
|
|
9
|
-
*/
|
|
10
|
-
export interface AiDockProvider {
|
|
11
|
-
/**
|
|
12
|
-
* Called when the user expands the bubble. The provider **moves the given
|
|
13
|
-
* element** into its layout — e.g. via a layout factory that re-parents it into
|
|
14
|
-
* a pane. It is the ONE live assistant element, so it must be moved by reference,
|
|
15
|
-
* **not cloned** (a clone would be a second, dead instance). Session state
|
|
16
|
-
* survives the move because it lives in module-level registries, not the element.
|
|
17
|
-
*/
|
|
18
|
-
onDock(element: HTMLElement): Promise<void>;
|
|
19
|
-
/**
|
|
20
|
-
* Called when the user collapses the panel or before navigation. By the time
|
|
21
|
-
* this runs the manager has already moved the assistant element back into the
|
|
22
|
-
* bubble, so the provider only needs to tear down its now-empty layout slot.
|
|
23
|
-
*/
|
|
24
|
-
onUndock(): Promise<void>;
|
|
25
|
-
/**
|
|
26
|
-
* Called by `collapseIfDocked` before navigation. The provider is responsible for
|
|
27
|
-
* finding the docked assistant element and calling `handlePopout()` on it, which
|
|
28
|
-
* publishes `chat-popin` and returns the assistant to the bubble.
|
|
29
|
-
*/
|
|
30
|
-
initiateCollapse(): void;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* App-shell component that owns the pop-out/pop-in lifecycle for the AI assistant bubble.
|
|
35
|
-
*
|
|
36
|
-
* @remarks
|
|
37
|
-
* Place this in the persistent app shell, wrapping a `foundation-ai-chat-bubble` that
|
|
38
|
-
* contains an AI assistant element in the `dialog-content` slot.
|
|
39
|
-
*
|
|
40
|
-
* GENC-1351 (Option A — single element): rather than cloning a second assistant to
|
|
41
|
-
* dock, this manager **moves the one real element** between the bubble and the page
|
|
42
|
-
* layout. One connected instance means no dual-view coordination (no shared-driver
|
|
43
|
-
* unwire/rewire, host election, or duplicated side-effects); the session survives the
|
|
44
|
-
* move because the driver/store/persister live in module-level registries keyed by the
|
|
45
|
-
* element's identity.
|
|
46
|
-
*
|
|
47
|
-
* Pages that support docking call `aiPopoutManager.registerDockProvider()` on mount
|
|
48
|
-
* and `aiPopoutManager.deregisterDockProvider()` on unmount.
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* ```html
|
|
52
|
-
* <foundation-ai-popout-manager>
|
|
53
|
-
* <foundation-ai-chat-bubble title="My Assistant">
|
|
54
|
-
* <my-assistant slot="dialog-content"></my-assistant>
|
|
55
|
-
* </foundation-ai-chat-bubble>
|
|
56
|
-
* </foundation-ai-popout-manager>
|
|
57
|
-
* ```
|
|
58
|
-
*
|
|
59
|
-
* @beta
|
|
60
|
-
*/
|
|
61
|
-
@customElement({
|
|
62
|
-
name: 'foundation-ai-popout-manager',
|
|
63
|
-
template: html`
|
|
64
|
-
<slot></slot>
|
|
65
|
-
`,
|
|
66
|
-
})
|
|
67
|
-
export class FoundationAiPopoutManager extends GenesisElement {
|
|
68
|
-
/** True when a dock provider is registered — controls expand button visibility. */
|
|
69
|
-
@observable canDock = false;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* The single assistant element. Captured while it's in the bubble slot and held
|
|
73
|
-
* across the move (it's the same instance whether docked or in the bubble), so
|
|
74
|
-
* pop-in can re-home it even though it's no longer a child of this manager.
|
|
75
|
-
*/
|
|
76
|
-
private assistantEl: HTMLElement | null = null;
|
|
77
|
-
private dockProvider: AiDockProvider | null = null;
|
|
78
|
-
private isDocked = false;
|
|
79
|
-
private unsubBus?: () => void;
|
|
80
|
-
|
|
81
|
-
connectedCallback() {
|
|
82
|
-
super.connectedCallback();
|
|
83
|
-
// oxlint-disable-next-line typescript/no-this-alias -- module-level singleton, not a local alias
|
|
84
|
-
_aiPopoutManager = this;
|
|
85
|
-
|
|
86
|
-
this.assistantEl = this.findAssistant();
|
|
87
|
-
|
|
88
|
-
const unsubPopout = agenticActivityBus.subscribe('chat-popout', async () => {
|
|
89
|
-
if (this.isDocked || !this.dockProvider) return;
|
|
90
|
-
const el = (this.assistantEl ??= this.findAssistant());
|
|
91
|
-
if (!el) return;
|
|
92
|
-
this.isDocked = true;
|
|
93
|
-
_aiAssistantDocked = true;
|
|
94
|
-
this.syncBubbleVisibility();
|
|
95
|
-
// Reflect the new location on the assistant so its header shows the "collapse"
|
|
96
|
-
// affordance. This is now purely cosmetic — the element stays wired across the
|
|
97
|
-
// move, so an async mode-forward by a wrapper element can't break it.
|
|
98
|
-
el.setAttribute('popout-mode', 'collapse');
|
|
99
|
-
// Hand the ONE real element to the page; the provider moves it into its layout.
|
|
100
|
-
await this.dockProvider.onDock(el);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const unsubPopin = agenticActivityBus.subscribe('chat-popin', async () => {
|
|
104
|
-
if (!this.isDocked) return;
|
|
105
|
-
this.isDocked = false;
|
|
106
|
-
_aiAssistantDocked = false;
|
|
107
|
-
// Re-home the assistant into the bubble BEFORE the provider tears down its
|
|
108
|
-
// layout slot — its removeItems (or equivalent) would otherwise destroy the
|
|
109
|
-
// moved element.
|
|
110
|
-
const bubble = this.querySelector('foundation-ai-chat-bubble');
|
|
111
|
-
if (this.assistantEl && bubble) {
|
|
112
|
-
this.assistantEl.setAttribute('popout-mode', 'expand');
|
|
113
|
-
this.assistantEl.setAttribute('slot', 'dialog-content');
|
|
114
|
-
bubble.appendChild(this.assistantEl);
|
|
115
|
-
}
|
|
116
|
-
this.syncBubbleVisibility();
|
|
117
|
-
await this.dockProvider?.onUndock();
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
this.unsubBus = () => {
|
|
121
|
-
unsubPopout();
|
|
122
|
-
unsubPopin();
|
|
123
|
-
};
|
|
124
|
-
this.syncBubbleVisibility();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
disconnectedCallback() {
|
|
128
|
-
super.disconnectedCallback();
|
|
129
|
-
this.unsubBus?.();
|
|
130
|
-
this.unsubBus = undefined;
|
|
131
|
-
_aiPopoutManager = undefined;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** Locate the assistant element currently slotted into the bubble. */
|
|
135
|
-
private findAssistant(): HTMLElement | null {
|
|
136
|
-
const bubble = this.querySelector('foundation-ai-chat-bubble');
|
|
137
|
-
return (bubble?.querySelector('[slot="dialog-content"]') as HTMLElement | null) ?? null;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Register an externally-created assistant element and its docked state. For
|
|
142
|
-
* single-element hosts that create the assistant directly in a layout pane (rather
|
|
143
|
-
* than statically in the bubble), so the manager tracks the one element, whether it's
|
|
144
|
-
* currently docked (for pop-in re-homing), reflects the right `popout-mode` on it
|
|
145
|
-
* (drives the header button), and hides the empty bubble.
|
|
146
|
-
*/
|
|
147
|
-
adoptAssistant(el: HTMLElement, docked: boolean): void {
|
|
148
|
-
this.assistantEl = el;
|
|
149
|
-
this.isDocked = docked;
|
|
150
|
-
_aiAssistantDocked = docked;
|
|
151
|
-
el.setAttribute('popout-mode', docked ? 'collapse' : 'expand');
|
|
152
|
-
this.syncBubbleVisibility();
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/** Hide the floating bubble unless it currently contains the assistant. */
|
|
156
|
-
private syncBubbleVisibility(): void {
|
|
157
|
-
const bubble = this.querySelector('foundation-ai-chat-bubble') as HTMLElement | null;
|
|
158
|
-
if (!bubble) return;
|
|
159
|
-
const hasAssistant = !!bubble.querySelector('[slot="dialog-content"]');
|
|
160
|
-
bubble.style.display = this.isDocked || !hasAssistant ? 'none' : '';
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
canDockChanged() {
|
|
164
|
-
const el = (this.assistantEl ??= this.findAssistant());
|
|
165
|
-
if (this.canDock) {
|
|
166
|
-
el?.setAttribute('popout-mode', this.isDocked ? 'collapse' : 'expand');
|
|
167
|
-
} else {
|
|
168
|
-
el?.removeAttribute('popout-mode');
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
registerDockProvider(provider: AiDockProvider): void {
|
|
173
|
-
this.dockProvider = provider;
|
|
174
|
-
this.canDock = true;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
deregisterDockProvider(): void {
|
|
178
|
-
this.isDocked = false;
|
|
179
|
-
_aiAssistantDocked = false;
|
|
180
|
-
this.dockProvider = null;
|
|
181
|
-
this.canDock = false;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* If the assistant is currently docked, collapses it back into the bubble.
|
|
186
|
-
* Await this in `onBeforeNavButtonClick` to ensure cleanup before navigation.
|
|
187
|
-
*/
|
|
188
|
-
collapseIfDocked(): Promise<void> {
|
|
189
|
-
if (!this.isDocked || !this.dockProvider) return Promise.resolve();
|
|
190
|
-
this.dockProvider.initiateCollapse();
|
|
191
|
-
return Promise.resolve();
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
let _aiPopoutManager: FoundationAiPopoutManager | undefined;
|
|
196
|
-
/** Whether the assistant is currently docked in the layout panel (vs bubble-only). */
|
|
197
|
-
let _aiAssistantDocked = false;
|
|
198
|
-
|
|
199
|
-
/** True when the assistant is active in the layout panel (docked) rather than the bubble. */
|
|
200
|
-
export function isAiAssistantDocked(): boolean {
|
|
201
|
-
return _aiAssistantDocked;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Returns the active `FoundationAiPopoutManager` instance, or `undefined` if none is mounted.
|
|
206
|
-
* Import this in pages to call `registerDockProvider` / `deregisterDockProvider`.
|
|
207
|
-
*
|
|
208
|
-
* @beta
|
|
209
|
-
*/
|
|
210
|
-
export function getAiPopoutManager(): FoundationAiPopoutManager | undefined {
|
|
211
|
-
return _aiPopoutManager;
|
|
212
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
2
|
-
import { settingsModalStyles } from './settings-modal.styles';
|
|
3
|
-
|
|
4
|
-
// GENC-1464 budget meter — the styling invariants a reviewer would otherwise
|
|
5
|
-
// have to catch by eye, following main.styles.test.ts (see there for why CSS
|
|
6
|
-
// gets asserted from the generated text at all, and for the scoping lesson:
|
|
7
|
-
// these assertions are about the BUDGET rules only, not a global style policy).
|
|
8
|
-
//
|
|
9
|
-
// 1. Design-system tokens are consumed UNFALLBACKED — the #2411/#2436 review
|
|
10
|
-
// rule. Every token the meter reads ships a DS default, so a
|
|
11
|
-
// `var(--token, fallback)` is dead code at best and a silently-broken
|
|
12
|
-
// token name at worst.
|
|
13
|
-
// 2. The meter's row anatomy is SHARED with the context indicator via grouped
|
|
14
|
-
// selectors, not copied. The two indicators are siblings by design;
|
|
15
|
-
// copied declarations would let them drift apart one edit at a time, which
|
|
16
|
-
// is exactly what the grouping was chosen to make impossible.
|
|
17
|
-
|
|
18
|
-
const suite = createLogicSuite('settings-modal.styles budget-meter rules');
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The generated stylesheet text, flattened recursively — `css` composes nested
|
|
22
|
-
* `ElementStyles`, and a shallow read can return almost nothing, making every
|
|
23
|
-
* negative assertion below pass vacuously. The first test guards that.
|
|
24
|
-
*/
|
|
25
|
-
const flatten = (value: unknown): string => {
|
|
26
|
-
if (typeof value === 'string') return value;
|
|
27
|
-
if (Array.isArray(value)) return value.map(flatten).join('\n');
|
|
28
|
-
const nested = (value as { styles?: unknown } | null | undefined)?.styles;
|
|
29
|
-
return nested ? flatten(nested) : '';
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Comments stripped before matching: the assertions below are about
|
|
34
|
-
* DECLARATIONS, and the sheet's own prose legitimately mentions the very
|
|
35
|
-
* pattern (`var(--x, y)`) the negative assertion hunts for.
|
|
36
|
-
*/
|
|
37
|
-
const cssText = flatten(settingsModalStyles).replace(/\/\*[\s\S]*?\*\//g, '');
|
|
38
|
-
|
|
39
|
-
/** Every declaration block whose selector mentions `.settings-budget-`, joined. */
|
|
40
|
-
const budgetRules = (cssText.match(/[^{}]*\.settings-budget-[^{}]*\{[^}]*\}/g) ?? []).join('\n');
|
|
41
|
-
|
|
42
|
-
suite('the budget rules were extracted as text (guards the assertions below)', () => {
|
|
43
|
-
assert.ok(cssText.includes('.settings-budget-usage'), 'the meter container rule is in the sheet');
|
|
44
|
-
assert.ok(budgetRules.length > 0, 'the extraction found the budget rules');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
suite('the meter consumes design-system tokens without dead fallbacks', () => {
|
|
48
|
-
// One structural probe rather than a per-token list: ANY `var(--x,` inside a
|
|
49
|
-
// budget rule is a fallback, and the meter reads only tokens that ship DS
|
|
50
|
-
// defaults (--design-unit, --neutral-foreground-*), so there is no legitimate
|
|
51
|
-
// fallback for this scope. Scoped to the budget rules on purpose — see
|
|
52
|
-
// main.styles.test.ts for why a whole-sheet grep is the wrong test.
|
|
53
|
-
assert.not.ok(/var\(--[a-z-]+\s*,/.test(budgetRules), 'no var(--token, fallback) in the meter');
|
|
54
|
-
assert.ok(budgetRules.includes('var(--design-unit)'), 'and it does consume tokens');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
suite('every meter row sits on one shared rhythm', () => {
|
|
58
|
-
// The 4/2/2 fix. `.settings-modal-section-body` gaps at 4 units and the
|
|
59
|
-
// budget meter at 2, so an unwrapped context indicator sat 4 units above the
|
|
60
|
-
// FIRST vendor row while the vendor rows sat 2 apart — three visually
|
|
61
|
-
// identical meter rows, unevenly spaced. Both meters now live in
|
|
62
|
-
// `.settings-usage-meters`, which must carry the SAME gap as the meter it
|
|
63
|
-
// wraps: asserted as ONE grouped rule, so the two cannot drift to different
|
|
64
|
-
// rhythms. (settings-modal.template.test.ts pins the other half — that the
|
|
65
|
-
// wrapper is conditional, so a host with no meters pays no stray gap for it.)
|
|
66
|
-
const shared = /\.settings-usage-meters\s*,\s*\.settings-budget-usage\s*\{([^}]*)\}/.exec(
|
|
67
|
-
cssText,
|
|
68
|
-
);
|
|
69
|
-
assert.ok(shared, '.settings-usage-meters is grouped with .settings-budget-usage');
|
|
70
|
-
assert.ok(shared![1].includes('flex-direction: column'), 'the shared container is a column');
|
|
71
|
-
assert.ok(
|
|
72
|
-
shared![1].includes('gap: calc(var(--design-unit) * 2px)'),
|
|
73
|
-
'gapped at the meter rhythm (2 units), not the section body 4',
|
|
74
|
-
);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
suite("the meter shares the context indicator's row anatomy by grouped selector", () => {
|
|
78
|
-
// The invariant is the SHARING, not the shape: each budget class must sit in
|
|
79
|
-
// the same selector list as its context sibling, so restyling one restyles
|
|
80
|
-
// both and the two indicators cannot drift apart.
|
|
81
|
-
const sharedPairs: Array<[string, string]> = [
|
|
82
|
-
['.settings-context-header', '.settings-budget-header'],
|
|
83
|
-
['.settings-context-label', '.settings-budget-label'],
|
|
84
|
-
['.settings-context-tokens', '.settings-budget-figures'],
|
|
85
|
-
];
|
|
86
|
-
for (const [contextClass, budgetClass] of sharedPairs) {
|
|
87
|
-
const grouped = new RegExp(
|
|
88
|
-
`${contextClass.replace(/\./g, '\\.')}\\s*,\\s*${budgetClass.replace(/\./g, '\\.')}\\s*\\{`,
|
|
89
|
-
);
|
|
90
|
-
assert.ok(grouped.test(cssText), `${budgetClass} is grouped with ${contextClass}`);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
suite.run();
|