@stephen-netu/design-system 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -0
- package/package.json +130 -0
- package/src/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +221 -0
- package/src/b0-app-shell/clarification-overlay/index.ts +1 -0
- package/src/b0-app-shell/command-bar/CommandBar.svelte +565 -0
- package/src/b0-app-shell/index.ts +14 -0
- package/src/base.css +152 -0
- package/src/d0-data-viz/BarChart.svelte +236 -0
- package/src/d0-data-viz/CheckpointBar.svelte +574 -0
- package/src/d0-data-viz/CheckpointPill.svelte +297 -0
- package/src/d0-data-viz/MetricCard.svelte +159 -0
- package/src/d0-data-viz/SparkLine.svelte +66 -0
- package/src/d0-data-viz/StorageMap.svelte +182 -0
- package/src/d0-data-viz/Timeline.svelte +188 -0
- package/src/d0-data-viz/checkpoint-types.ts +162 -0
- package/src/d0-data-viz/d0-tokens.css +32 -0
- package/src/d0-data-viz/index.ts +58 -0
- package/src/d0-data-viz/storage-map-types.ts +142 -0
- package/src/d0-data-viz/theme-integration.ts +134 -0
- package/src/d0-data-viz/types.ts +53 -0
- package/src/demos/BspSizingInfographic.svelte +386 -0
- package/src/demos/BspZoneDemo.svelte +255 -0
- package/src/demos/ControlRoomDemo.svelte +570 -0
- package/src/demos/NodepadBlocksShowcase.svelte +189 -0
- package/src/demos/index.ts +7 -0
- package/src/editor/CodeEditor.svelte +188 -0
- package/src/editor/FindReplaceDialog.svelte +516 -0
- package/src/editor/MarkdownEditor.svelte +660 -0
- package/src/editor/index.ts +2 -0
- package/src/entity-graph-view/WorldView.svelte +171 -0
- package/src/entity-graph-view/index.ts +6 -0
- package/src/entity-graph-view/types.ts +364 -0
- package/src/epistemic/index.ts +2 -0
- package/src/epistemic/types.ts +134 -0
- package/src/epistemic/utils.ts +32 -0
- package/src/f0-forms/checkbox/Checkbox.svelte +158 -0
- package/src/f0-forms/field/FormField.svelte +91 -0
- package/src/f0-forms/index.ts +11 -0
- package/src/f0-forms/radio/RadioGroup.svelte +192 -0
- package/src/f0-forms/search/SearchBar.svelte +99 -0
- package/src/f0-forms/select/Select.svelte +198 -0
- package/src/f0-forms/textarea/TextArea.svelte +170 -0
- package/src/f0-forms/toggle/FormToggle.svelte +147 -0
- package/src/f0-forms/validation/validate.ts +47 -0
- package/src/fabric/ai/ChatPanel.svelte +648 -0
- package/src/fabric/ai/index.ts +11 -0
- package/src/fabric/data/index.ts +21 -0
- package/src/fabric/feedback/StatusBar.svelte +274 -0
- package/src/fabric/feedback/ToastContainer.svelte +122 -0
- package/src/fabric/feedback/index.ts +14 -0
- package/src/fabric/index.ts +37 -0
- package/src/fabric/input/CommandBar.svelte +79 -0
- package/src/fabric/input/KeyboardShortcuts.svelte +388 -0
- package/src/fabric/input/index.ts +12 -0
- package/src/fabric/layout/GlassBox.svelte +193 -0
- package/src/fabric/layout/KanbanBoard.svelte +158 -0
- package/src/fabric/layout/KanbanCard.svelte +226 -0
- package/src/fabric/layout/KanbanColumn.svelte +278 -0
- package/src/fabric/layout/index.ts +17 -0
- package/src/fabric/navigation/ActivityRail.svelte +271 -0
- package/src/fabric/navigation/index.ts +11 -0
- package/src/g0-geo/SovereignMap.svelte +149 -0
- package/src/g0-geo/index.ts +2 -0
- package/src/index.ts +68 -0
- package/src/l0-layout/block-writer/BlockConnectionLines.svelte +98 -0
- package/src/l0-layout/block-writer/BlockContent.svelte +213 -0
- package/src/l0-layout/block-writer/BlockHeader.svelte +230 -0
- package/src/l0-layout/block-writer/BlockItem.svelte +177 -0
- package/src/l0-layout/block-writer/BlockWriter.svelte +219 -0
- package/src/l0-layout/block-writer/block-writer-types.ts +63 -0
- package/src/l0-layout/block-writer/index.ts +24 -0
- package/src/l0-layout/block-writer/markdown.ts +110 -0
- package/src/l0-layout/chat-view/ChatViewLayout.svelte +61 -0
- package/src/l0-layout/epistemic/AllayDetailPanel.svelte +113 -0
- package/src/l0-layout/epistemic/AssayDetailPanel.svelte +164 -0
- package/src/l0-layout/epistemic/AvenueTrace.svelte +253 -0
- package/src/l0-layout/epistemic/KnowledgeDetailPanel.svelte +204 -0
- package/src/l0-layout/epistemic/ParadigmLens.svelte +170 -0
- package/src/l0-layout/epistemic/ProvenanceChain.svelte +164 -0
- package/src/l0-layout/epistemic/TrustView.svelte +195 -0
- package/src/l0-layout/epistemic/index.ts +7 -0
- package/src/l0-layout/grove/AccordCard.svelte +156 -0
- package/src/l0-layout/grove/GroveCard.svelte +197 -0
- package/src/l0-layout/grove/MemberBadge.svelte +96 -0
- package/src/l0-layout/grove/MemberList.svelte +59 -0
- package/src/l0-layout/grove/grove-types.ts +29 -0
- package/src/l0-layout/grove/index.ts +14 -0
- package/src/l0-layout/index.ts +45 -0
- package/src/l0-layout/kanban/KanbanBoard.svelte +71 -0
- package/src/l0-layout/kanban/KanbanCard.svelte +276 -0
- package/src/l0-layout/kanban/KanbanColumn.svelte +198 -0
- package/src/l0-layout/kanban/KanbanViewLayout.svelte +61 -0
- package/src/l0-layout/workspace/WorkspaceLayout.svelte +93 -0
- package/src/n0-node-graph/GraphEditor.svelte +342 -0
- package/src/n0-node-graph/GraphHistory.svelte +122 -0
- package/src/n0-node-graph/Node.svelte +269 -0
- package/src/n0-node-graph/NodeCanvas.svelte +187 -0
- package/src/n0-node-graph/NodeEdge.svelte +152 -0
- package/src/n0-node-graph/NodePalette.svelte +318 -0
- package/src/n0-node-graph/NodePort.svelte +128 -0
- package/src/n0-node-graph/index.ts +33 -0
- package/src/n0-node-graph/n0-tokens.css +29 -0
- package/src/n0-node-graph/node-port-types.ts +19 -0
- package/src/n0-node-graph/types.ts +96 -0
- package/src/n0-node-graph/validate.test.ts +722 -0
- package/src/n0-node-graph/validate.ts +371 -0
- package/src/n1-flow-canvas/FlowCanvas.svelte +202 -0
- package/src/n1-flow-canvas/graph-state.svelte.ts +95 -0
- package/src/n1-flow-canvas/index.ts +21 -0
- package/src/n1-flow-canvas/layout.ts +118 -0
- package/src/n1-flow-canvas/layout.worker.ts +128 -0
- package/src/n1-flow-canvas/types.ts +102 -0
- package/src/n1-flow-canvas/utils.ts +146 -0
- package/src/n2-manifold-disk/ManifoldDisk.svelte +314 -0
- package/src/n2-manifold-disk/index.ts +6 -0
- package/src/n2-manifold-disk/poincare.ts +184 -0
- package/src/n3-force-graph/ForceGraph.svelte +180 -0
- package/src/n3-force-graph/GraphTooltip.svelte +99 -0
- package/src/n3-force-graph/animated-edge.ts +107 -0
- package/src/n3-force-graph/health-node.ts +128 -0
- package/src/n3-force-graph/index.ts +31 -0
- package/src/n3-force-graph/types.ts +94 -0
- package/src/n4-adaptive-manifold/AdaptiveManifold.svelte +1165 -0
- package/src/n4-adaptive-manifold/DetailCard.svelte +212 -0
- package/src/n4-adaptive-manifold/SuggestionIndicator.svelte +91 -0
- package/src/n4-adaptive-manifold/classifier.ts +139 -0
- package/src/n4-adaptive-manifold/index.ts +45 -0
- package/src/n4-adaptive-manifold/n4-tokens.css +155 -0
- package/src/n4-adaptive-manifold/orchestrator.ts +301 -0
- package/src/n4-adaptive-manifold/phase-theme.ts +92 -0
- package/src/n4-adaptive-manifold/pinnacle-events.ts +135 -0
- package/src/n4-adaptive-manifold/providers/gravitational-provider.ts +191 -0
- package/src/n4-adaptive-manifold/providers/manifold-provider.ts +276 -0
- package/src/n4-adaptive-manifold/transition.ts +90 -0
- package/src/n4-adaptive-manifold/types.ts +313 -0
- package/src/p0-primitives/index.ts +6 -0
- package/src/p0-primitives/tokens/control-room.css +309 -0
- package/src/p0-primitives/tokens/index.ts +6 -0
- package/src/p0-primitives/tokens/tokens.css +140 -0
- package/src/p0-primitives/tokens/tokens.json +132 -0
- package/src/p0-primitives/types/index.ts +123 -0
- package/src/p0-primitives/types/plugin-types.ts +74 -0
- package/src/p0-primitives/utils/index.ts +39 -0
- package/src/platform/hud-protocol.ts +20 -0
- package/src/platform/index.ts +3 -0
- package/src/s0-state/create-store.ts +84 -0
- package/src/s0-state/derived.ts +41 -0
- package/src/s0-state/index.ts +6 -0
- package/src/showcase/Showcase.svelte +401 -0
- package/src/spatial/BspTilingCanvas.svelte +232 -0
- package/src/spatial/ForceCanvas.svelte +289 -0
- package/src/spatial/LodRenderer.svelte +334 -0
- package/src/spatial/SnapZoomCamera.svelte +185 -0
- package/src/spatial/ZoneTiler.svelte +311 -0
- package/src/spatial/camera-types.ts +45 -0
- package/src/spatial/content-proportional-bsp.ts +253 -0
- package/src/spatial/force-canvas-types.ts +102 -0
- package/src/spatial/index.ts +15 -0
- package/src/spatial/lod-types.ts +70 -0
- package/src/spatial/zone-tiler-types.ts +177 -0
- package/src/stores/vaultStore.svelte +14 -0
- package/src/t0-transport/connection.ts +34 -0
- package/src/t0-transport/error.ts +37 -0
- package/src/t0-transport/events.ts +50 -0
- package/src/t0-transport/index.ts +6 -0
- package/src/t0-transport/invoke.ts +30 -0
- package/src/tauri/index.ts +13 -0
- package/src/u0-primitives/allay-gauge/AllayGauge.svelte +90 -0
- package/src/u0-primitives/allay-gauge/index.ts +1 -0
- package/src/u0-primitives/animated-icon/AnimatedIcon.svelte +273 -0
- package/src/u0-primitives/animated-icon/README.md +53 -0
- package/src/u0-primitives/animated-icon/index.ts +31 -0
- package/src/u0-primitives/assay-badge/AssayBadge.svelte +121 -0
- package/src/u0-primitives/assay-badge/AssaySignalBar.svelte +83 -0
- package/src/u0-primitives/assay-badge/index.ts +2 -0
- package/src/u0-primitives/avatar/Avatar.svelte +177 -0
- package/src/u0-primitives/badge/Badge.svelte +149 -0
- package/src/u0-primitives/button/Button.svelte +304 -0
- package/src/u0-primitives/card/Card.svelte +182 -0
- package/src/u0-primitives/dropdown/Dropdown.svelte +305 -0
- package/src/u0-primitives/expert-badge/ExpertBadge.svelte +89 -0
- package/src/u0-primitives/expert-badge/index.ts +1 -0
- package/src/u0-primitives/index.ts +35 -0
- package/src/u0-primitives/input/Input.svelte +237 -0
- package/src/u0-primitives/modal/Modal.svelte +331 -0
- package/src/u0-primitives/modal/index.ts +1 -0
- package/src/u0-primitives/spinner/Spinner.svelte +129 -0
- package/src/u0-primitives/tabs/Tabs.svelte +225 -0
- package/src/u0-primitives/tabs/tabs-types.ts +11 -0
- package/src/u0-primitives/toggle/Toggle.svelte +161 -0
- package/src/u0-primitives/tooltip/Tooltip.svelte +234 -0
- package/src/v0-diagrams/DiagramPanel.svelte +68 -0
- package/src/v0-diagrams/MarkmapDiagram.svelte +56 -0
- package/src/v0-diagrams/MermaidDiagram.svelte +53 -0
- package/src/v0-diagrams/index.ts +4 -0
- package/src/v0-diagrams/types.ts +28 -0
- package/src/v0-diagrams/v0-tokens.css +6 -0
- package/src/vite-env.d.ts +7 -0
- package/src/x0-enchanted-blocks/ENCHANTED_BLOCKS_SPEC.md +457 -0
- package/src/x0-enchanted-blocks/components/EnchantedBlock.svelte +485 -0
- package/src/x0-enchanted-blocks/components/NodepadBlock.svelte +262 -0
- package/src/x0-enchanted-blocks/core/block-layout.ts +211 -0
- package/src/x0-enchanted-blocks/core/block-types.ts +227 -0
- package/src/x0-enchanted-blocks/index.ts +46 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Transport error types
|
|
2
|
+
|
|
3
|
+
export enum TransportErrorCode {
|
|
4
|
+
InvokeFailed = 'INVOKE_FAILED',
|
|
5
|
+
ConnectionLost = 'CONNECTION_LOST',
|
|
6
|
+
Timeout = 'TIMEOUT',
|
|
7
|
+
NotAvailable = 'NOT_AVAILABLE',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class TransportError extends Error {
|
|
11
|
+
constructor(
|
|
12
|
+
public code: TransportErrorCode,
|
|
13
|
+
message: string,
|
|
14
|
+
public original?: unknown
|
|
15
|
+
) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = 'TransportError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function toTransportError(error: unknown): TransportError {
|
|
22
|
+
if (error instanceof TransportError) {
|
|
23
|
+
return error;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
27
|
+
|
|
28
|
+
if (message.includes('timeout') || message.includes('Timeout')) {
|
|
29
|
+
return new TransportError(TransportErrorCode.Timeout, message, error);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (message.includes('connection') || message.includes('Connection')) {
|
|
33
|
+
return new TransportError(TransportErrorCode.ConnectionLost, message, error);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return new TransportError(TransportErrorCode.InvokeFailed, message, error);
|
|
37
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Event bus utilities for Tauri event streams
|
|
2
|
+
|
|
3
|
+
import { listen, emit as tauriEmit, type UnlistenFn } from '@tauri-apps/api/event';
|
|
4
|
+
|
|
5
|
+
export interface EventBusOptions {
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface EventBus {
|
|
10
|
+
on<T>(event: string, handler: (payload: T) => void): Promise<() => void>;
|
|
11
|
+
once<T>(event: string, handler: (payload: T) => void): Promise<() => void>;
|
|
12
|
+
emit<T>(event: string, payload?: T): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create an event bus for Tauri events
|
|
17
|
+
*/
|
|
18
|
+
export function createEventBus(options?: EventBusOptions): EventBus {
|
|
19
|
+
const debug = options?.debug ?? false;
|
|
20
|
+
|
|
21
|
+
async function on<T>(
|
|
22
|
+
event: string,
|
|
23
|
+
handler: (payload: T) => void
|
|
24
|
+
): Promise<() => void> {
|
|
25
|
+
const unlisten = await listen<T>(event, (e) => {
|
|
26
|
+
if (debug) console.log(`[event] ${event}:`, e.payload);
|
|
27
|
+
handler(e.payload);
|
|
28
|
+
});
|
|
29
|
+
return unlisten;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function once<T>(
|
|
33
|
+
event: string,
|
|
34
|
+
handler: (payload: T) => void
|
|
35
|
+
): Promise<() => void> {
|
|
36
|
+
const unlisten = await listen<T>(event, (e) => {
|
|
37
|
+
if (debug) console.log(`[event] ${event} (once):`, e.payload);
|
|
38
|
+
handler(e.payload);
|
|
39
|
+
unlisten();
|
|
40
|
+
});
|
|
41
|
+
return unlisten;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function emit<T>(event: string, payload?: T): Promise<void> {
|
|
45
|
+
if (debug) console.log('[event] emit %s:', event, payload);
|
|
46
|
+
await tauriEmit(event, payload);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return { on, once, emit };
|
|
50
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// T0 Transport — Tauri IPC primitives
|
|
2
|
+
|
|
3
|
+
export { invoke } from './invoke';
|
|
4
|
+
export { createEventBus, type EventBus } from './events';
|
|
5
|
+
export { TransportError, TransportErrorCode } from './error';
|
|
6
|
+
export { createConnectionTracker, type ConnectionState } from './connection';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Type-safe invoke wrapper for Tauri commands
|
|
2
|
+
|
|
3
|
+
import { invoke as tauriInvoke } from '@tauri-apps/api/core';
|
|
4
|
+
|
|
5
|
+
export interface CommandDefinition<T = unknown, R = unknown> {
|
|
6
|
+
name: string;
|
|
7
|
+
payload?: T;
|
|
8
|
+
response?: R;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Invoke a Tauri command with type safety
|
|
13
|
+
*/
|
|
14
|
+
export async function invoke<R, T extends Record<string, unknown> = Record<string, unknown>>(
|
|
15
|
+
command: string,
|
|
16
|
+
payload?: T
|
|
17
|
+
): Promise<R> {
|
|
18
|
+
try {
|
|
19
|
+
return await tauriInvoke<R>(command, payload ? { ...payload } : undefined);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
throw new Error(`Invoke failed: ${command} — ${error}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Check if running in Tauri environment
|
|
27
|
+
*/
|
|
28
|
+
export function isTauri(): boolean {
|
|
29
|
+
return typeof window !== 'undefined' && '__TAURI__' in window;
|
|
30
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Stub implementations for Tauri file operations
|
|
2
|
+
// In a real Tauri environment, these would use @tauri-apps/api/fs
|
|
3
|
+
|
|
4
|
+
export async function readFile(path: string): Promise<string> {
|
|
5
|
+
// Stub: In real implementation, use Tauri fs.readTextFile
|
|
6
|
+
console.warn('readFile stub called for', path);
|
|
7
|
+
return '';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function writeFile(path: string, content: string): Promise<void> {
|
|
11
|
+
// Stub: In real implementation, use Tauri fs.writeTextFile
|
|
12
|
+
console.warn('writeFile stub called for', path);
|
|
13
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { AllayStageView } from '../../epistemic/types.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
stage: 0 | 1 | 2 | 3 | 4 | 5;
|
|
6
|
+
confidence: number; // 0.0–1.0, shown as % on hover
|
|
7
|
+
showLabel?: boolean;
|
|
8
|
+
size?: 'sm' | 'md' | 'lg';
|
|
9
|
+
class?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
stage,
|
|
14
|
+
confidence,
|
|
15
|
+
showLabel = false,
|
|
16
|
+
size = 'md',
|
|
17
|
+
class: className = '',
|
|
18
|
+
}: Props = $props();
|
|
19
|
+
|
|
20
|
+
// Stage metadata
|
|
21
|
+
const STAGE_NAMES = ['Propose', 'Parse', 'Authorize', 'Execute', 'Trace', 'Replicate'];
|
|
22
|
+
const STAGE_VARS = [
|
|
23
|
+
'var(--epistemic-stage-0)',
|
|
24
|
+
'var(--epistemic-stage-1)',
|
|
25
|
+
'var(--epistemic-stage-2)',
|
|
26
|
+
'var(--epistemic-stage-3)',
|
|
27
|
+
'var(--epistemic-stage-4)',
|
|
28
|
+
'var(--epistemic-stage-5)',
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const stageName = $derived(STAGE_NAMES[stage] ?? 'Unknown');
|
|
32
|
+
const stageColor = $derived(stage > 0 ? STAGE_VARS[stage] : STAGE_VARS[0]);
|
|
33
|
+
const confidencePct = $derived(`${Math.round(confidence * 100)}%`);
|
|
34
|
+
const tooltipText = $derived(`${stageName} (${confidencePct})`);
|
|
35
|
+
|
|
36
|
+
// 5 segments, indices 0-4; segment i is filled when stage > i
|
|
37
|
+
const segments = [0, 1, 2, 3, 4];
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<div
|
|
41
|
+
class="ds-allay-gauge size-{size} {className}"
|
|
42
|
+
title={tooltipText}
|
|
43
|
+
aria-label="Allay verification: {stageName}, {confidencePct}"
|
|
44
|
+
role="img"
|
|
45
|
+
>
|
|
46
|
+
<div class="segments">
|
|
47
|
+
{#each segments as i}
|
|
48
|
+
<div
|
|
49
|
+
class="segment"
|
|
50
|
+
class:filled={stage > i}
|
|
51
|
+
style={stage > i ? `background-color: ${stageColor};` + (stage === 5 ? ` box-shadow: 0 0 3px var(--epistemic-stage-5-glow);` : '') : ''}
|
|
52
|
+
></div>
|
|
53
|
+
{/each}
|
|
54
|
+
</div>
|
|
55
|
+
{#if showLabel}
|
|
56
|
+
<span class="stage-label">{stageName}</span>
|
|
57
|
+
{/if}
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
.ds-allay-gauge {
|
|
62
|
+
display: inline-flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
gap: var(--space-2);
|
|
65
|
+
cursor: default;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.segments {
|
|
69
|
+
display: flex;
|
|
70
|
+
gap: 2px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.segment {
|
|
74
|
+
border-radius: var(--radius-xs, 2px);
|
|
75
|
+
background-color: var(--color-bg-panel-elevated, #2a2a2a);
|
|
76
|
+
border: 1px solid var(--border-subtle);
|
|
77
|
+
transition: background-color 200ms;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Size variants */
|
|
81
|
+
.size-sm .segment { width: 6px; height: 10px; }
|
|
82
|
+
.size-md .segment { width: 8px; height: 14px; }
|
|
83
|
+
.size-lg .segment { width: 12px; height: 20px; }
|
|
84
|
+
|
|
85
|
+
.stage-label {
|
|
86
|
+
font-family: var(--font-sans);
|
|
87
|
+
font-size: var(--text-xs);
|
|
88
|
+
color: var(--color-text-secondary);
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as AllayGauge } from './AllayGauge.svelte';
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* AnimatedIcon - U0 Primitive
|
|
4
|
+
*
|
|
5
|
+
* SMIL-based animated SVG icons. Zero JS overhead, GPU-accelerated.
|
|
6
|
+
* Aligns with x0-enchanted-blocks "enchanted" philosophy via declarative animation.
|
|
7
|
+
*
|
|
8
|
+
* @package @kos/design-system/u0-primitives
|
|
9
|
+
* @adr 2026-04-17-smil-animated-icons
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
type AnimationType = 'pulse' | 'orbit' | 'wave' | 'breathe' | 'spin' | 'steam' | 'energy-arcs';
|
|
13
|
+
type IconName = 'power-node' | 'activity' | 'connection' | 'status-ring' | 'power-plant' | 'orbital-ring' | 'steam-tower' | 'energy-pulse';
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
name: IconName;
|
|
17
|
+
size?: number;
|
|
18
|
+
color?: string;
|
|
19
|
+
animation?: AnimationType;
|
|
20
|
+
speed?: number; // 0.5 = half speed, 2 = double speed
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
name,
|
|
25
|
+
size = 40,
|
|
26
|
+
color = 'var(--color-accent)',
|
|
27
|
+
animation = 'pulse',
|
|
28
|
+
speed = 1
|
|
29
|
+
}: Props = $props();
|
|
30
|
+
|
|
31
|
+
function calcDuration(baseMs: number): string {
|
|
32
|
+
return `${baseMs / speed}ms`;
|
|
33
|
+
}
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<svg
|
|
37
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
38
|
+
viewBox="0 0 40 40"
|
|
39
|
+
style="width: {size}px; height: {size}px; color: {color};"
|
|
40
|
+
class="ds-animated-icon"
|
|
41
|
+
aria-hidden="true"
|
|
42
|
+
>
|
|
43
|
+
{#if name === 'power-node'}
|
|
44
|
+
<!-- Outer ring -->
|
|
45
|
+
<circle cx="20" cy="20" r="18" fill="none" stroke="currentColor" stroke-width="1" opacity="0.3"/>
|
|
46
|
+
|
|
47
|
+
{#if animation === 'pulse'}
|
|
48
|
+
<!-- Pulsing ring -->
|
|
49
|
+
<circle cx="20" cy="20" r="18" fill="none" stroke="currentColor" stroke-width="2" opacity="0.6">
|
|
50
|
+
<animate attributeName="r" values="12;18;12" dur={calcDuration(2000)} repeatCount="indefinite"/>
|
|
51
|
+
<animate attributeName="opacity" values="0.8;0;0.8" dur={calcDuration(2000)} repeatCount="indefinite"/>
|
|
52
|
+
</circle>
|
|
53
|
+
{:else if animation === 'orbit'}
|
|
54
|
+
<!-- Orbiting dot -->
|
|
55
|
+
<circle cx="20" cy="2" r="3" fill="currentColor">
|
|
56
|
+
<animateTransform attributeName="transform" type="rotate" from="0 20 20" to="360 20 20" dur={calcDuration(3000)} repeatCount="indefinite"/>
|
|
57
|
+
</circle>
|
|
58
|
+
{/if}
|
|
59
|
+
|
|
60
|
+
<!-- Core -->
|
|
61
|
+
<circle cx="20" cy="20" r="8" fill="currentColor"/>
|
|
62
|
+
<circle cx="17" cy="17" r="3" fill="white" opacity="0.3"/>
|
|
63
|
+
|
|
64
|
+
{:else if name === 'activity'}
|
|
65
|
+
<!-- Activity bars -->
|
|
66
|
+
<rect x="6" y="20" width="4" height="10" rx="2" fill="currentColor">
|
|
67
|
+
<animate attributeName="height" values="10;20;10" dur={calcDuration(1200)} repeatCount="indefinite"/>
|
|
68
|
+
<animate attributeName="y" values="20;15;20" dur={calcDuration(1200)} repeatCount="indefinite"/>
|
|
69
|
+
</rect>
|
|
70
|
+
<rect x="14" y="15" width="4" height="15" rx="2" fill="currentColor">
|
|
71
|
+
<animate attributeName="height" values="15;25;15" dur={calcDuration(1000)} repeatCount="indefinite" begin="0.2s"/>
|
|
72
|
+
<animate attributeName="y" values="15;10;15" dur={calcDuration(1000)} repeatCount="indefinite" begin="0.2s"/>
|
|
73
|
+
</rect>
|
|
74
|
+
<rect x="22" y="18" width="4" height="12" rx="2" fill="currentColor">
|
|
75
|
+
<animate attributeName="height" values="12;22;12" dur={calcDuration(1400)} repeatCount="indefinite" begin="0.4s"/>
|
|
76
|
+
<animate attributeName="y" values="18;13;18" dur={calcDuration(1400)} repeatCount="indefinite" begin="0.4s"/>
|
|
77
|
+
</rect>
|
|
78
|
+
<rect x="30" y="22" width="4" height="8" rx="2" fill="currentColor">
|
|
79
|
+
<animate attributeName="height" values="8;18;8" dur={calcDuration(1100)} repeatCount="indefinite" begin="0.6s"/>
|
|
80
|
+
<animate attributeName="y" values="22;12;22" dur={calcDuration(1100)} repeatCount="indefinite" begin="0.6s"/>
|
|
81
|
+
</rect>
|
|
82
|
+
|
|
83
|
+
{:else if name === 'connection'}
|
|
84
|
+
<!-- Connection nodes -->
|
|
85
|
+
<circle cx="8" cy="20" r="4" fill="currentColor"/>
|
|
86
|
+
<circle cx="32" cy="20" r="4" fill="currentColor"/>
|
|
87
|
+
|
|
88
|
+
<!-- Animated connection line -->
|
|
89
|
+
<line x1="12" y1="20" x2="28" y2="20" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
|
90
|
+
<animate attributeName="stroke-dasharray" values="0,16;16,0;0,16" dur={calcDuration(1500)} repeatCount="indefinite"/>
|
|
91
|
+
</line>
|
|
92
|
+
|
|
93
|
+
<!-- Data packet -->
|
|
94
|
+
<circle cx="12" cy="20" r="2" fill="white">
|
|
95
|
+
<animate attributeName="cx" values="12;28;12" dur={calcDuration(1500)} repeatCount="indefinite"/>
|
|
96
|
+
</circle>
|
|
97
|
+
|
|
98
|
+
{:else if name === 'status-ring'}
|
|
99
|
+
<!-- Status ring with rotating segments -->
|
|
100
|
+
<circle cx="20" cy="20" r="16" fill="none" stroke="currentColor" stroke-width="3" opacity="0.2"/>
|
|
101
|
+
|
|
102
|
+
<path d="M20 4 A16 16 0 0 1 36 20" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round">
|
|
103
|
+
{#if animation === 'spin'}
|
|
104
|
+
<animateTransform attributeName="transform" type="rotate" from="0 20 20" to="360 20 20" dur={calcDuration(2000)} repeatCount="indefinite"/>
|
|
105
|
+
{:else if animation === 'breathe'}
|
|
106
|
+
<animate attributeName="opacity" values="1;0.3;1" dur={calcDuration(2000)} repeatCount="indefinite"/>
|
|
107
|
+
{/if}
|
|
108
|
+
</path>
|
|
109
|
+
|
|
110
|
+
<path d="M4 20 A16 16 0 0 1 20 4" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.6">
|
|
111
|
+
{#if animation === 'spin'}
|
|
112
|
+
<animateTransform attributeName="transform" type="rotate" from="180 20 20" to="540 20 20" dur={calcDuration(2000)} repeatCount="indefinite"/>
|
|
113
|
+
{/if}
|
|
114
|
+
</path>
|
|
115
|
+
|
|
116
|
+
{:else if name === 'power-plant'}
|
|
117
|
+
<!-- Power plant silhouette with cooling tower -->
|
|
118
|
+
<defs>
|
|
119
|
+
<linearGradient id="brassGrad-{size}" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
120
|
+
<stop offset="0%" stop-color="#d4956a"/>
|
|
121
|
+
<stop offset="50%" stop-color="#b87333"/>
|
|
122
|
+
<stop offset="100%" stop-color="#8a5626"/>
|
|
123
|
+
</linearGradient>
|
|
124
|
+
</defs>
|
|
125
|
+
|
|
126
|
+
<!-- Cooling tower -->
|
|
127
|
+
<path d="M8 35 Q4 25 12 15 L14 5 Q20 2 26 5 L28 15 Q36 25 32 35 Z"
|
|
128
|
+
fill="url(#brassGrad-{size})" opacity="0.8"/>
|
|
129
|
+
|
|
130
|
+
<!-- Inner detail -->
|
|
131
|
+
<path d="M12 32 Q8 24 15 15 L17 8 Q20 6 23 8 L25 15 Q32 24 28 32"
|
|
132
|
+
fill="none" stroke="currentColor" stroke-width="1" opacity="0.4"/>
|
|
133
|
+
|
|
134
|
+
{#if animation === 'steam'}
|
|
135
|
+
<!-- Steam plumes -->
|
|
136
|
+
<g stroke="#d4956a" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.6">
|
|
137
|
+
<path d="M14 5 Q10 -5 15 -12">
|
|
138
|
+
<animate attributeName="d"
|
|
139
|
+
values="M14 5 Q10 -5 15 -12;M14 5 Q20 -5 10 -12;M14 5 Q10 -5 15 -12"
|
|
140
|
+
dur={calcDuration(4000)} repeatCount="indefinite"/>
|
|
141
|
+
</path>
|
|
142
|
+
<path d="M20 2 Q24 -8 18 -15">
|
|
143
|
+
<animate attributeName="d"
|
|
144
|
+
values="M20 2 Q24 -8 18 -15;M20 2 Q14 -8 22 -15;M20 2 Q24 -8 18 -15"
|
|
145
|
+
dur={calcDuration(3500)} repeatCount="indefinite"/>
|
|
146
|
+
</path>
|
|
147
|
+
<path d="M26 5 Q30 -5 25 -12">
|
|
148
|
+
<animate attributeName="d"
|
|
149
|
+
values="M26 5 Q30 -5 25 -12;M26 5 Q18 -5 28 -12;M26 5 Q30 -5 25 -12"
|
|
150
|
+
dur={calcDuration(4500)} repeatCount="indefinite"/>
|
|
151
|
+
</path>
|
|
152
|
+
</g>
|
|
153
|
+
{:else if animation === 'pulse'}
|
|
154
|
+
<!-- Pulsing glow ring -->
|
|
155
|
+
<circle cx="20" cy="20" r="25" fill="none" stroke="currentColor" stroke-width="1" opacity="0">
|
|
156
|
+
<animate attributeName="r" values="15;28;15" dur={calcDuration(3000)} repeatCount="indefinite"/>
|
|
157
|
+
<animate attributeName="opacity" values="0.6;0;0.6" dur={calcDuration(3000)} repeatCount="indefinite"/>
|
|
158
|
+
</circle>
|
|
159
|
+
{/if}
|
|
160
|
+
|
|
161
|
+
<!-- Base ring -->
|
|
162
|
+
<ellipse cx="20" cy="35" rx="16" ry="3" fill="none" stroke="currentColor" stroke-width="1.5" opacity="0.5"/>
|
|
163
|
+
|
|
164
|
+
{:else if name === 'orbital-ring'}
|
|
165
|
+
<!-- Orbital ring with rotating elements -->
|
|
166
|
+
<circle cx="20" cy="20" r="16" fill="none" stroke="currentColor" stroke-width="1" opacity="0.2"/>
|
|
167
|
+
|
|
168
|
+
<!-- Rotating dashed ring -->
|
|
169
|
+
<circle cx="20" cy="20" r="16" fill="none" stroke="currentColor" stroke-width="1.5"
|
|
170
|
+
stroke-dasharray="8 4" opacity="0.6">
|
|
171
|
+
<animateTransform attributeName="transform" type="rotate" from="0 20 20" to="360 20 20"
|
|
172
|
+
dur={calcDuration(60000)} repeatCount="indefinite"/>
|
|
173
|
+
</circle>
|
|
174
|
+
|
|
175
|
+
<!-- Orbiting nodes -->
|
|
176
|
+
<g>
|
|
177
|
+
<circle cx="20" cy="4" r="3" fill="currentColor">
|
|
178
|
+
<animateTransform attributeName="transform" type="rotate" from="0 20 20" to="360 20 20"
|
|
179
|
+
dur={calcDuration(8000)} repeatCount="indefinite"/>
|
|
180
|
+
</circle>
|
|
181
|
+
<circle cx="20" cy="4" r="3" fill="currentColor" opacity="0.5">
|
|
182
|
+
<animateTransform attributeName="transform" type="rotate" from="180 20 20" to="540 20 20"
|
|
183
|
+
dur={calcDuration(8000)} repeatCount="indefinite"/>
|
|
184
|
+
</circle>
|
|
185
|
+
</g>
|
|
186
|
+
|
|
187
|
+
<!-- Core -->
|
|
188
|
+
<circle cx="20" cy="20" r="6" fill="currentColor"/>
|
|
189
|
+
|
|
190
|
+
{#if animation === 'pulse'}
|
|
191
|
+
<!-- Pulsing arcs -->
|
|
192
|
+
<path d="M20 4 A16 16 0 0 1 36 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
|
193
|
+
<animate attributeName="opacity" values="0.2;1;0.2" dur={calcDuration(2000)} repeatCount="indefinite"/>
|
|
194
|
+
</path>
|
|
195
|
+
<path d="M20 36 A16 16 0 0 1 4 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
|
196
|
+
<animate attributeName="opacity" values="0.2;1;0.2" dur={calcDuration(2000)} begin="1s" repeatCount="indefinite"/>
|
|
197
|
+
</path>
|
|
198
|
+
{/if}
|
|
199
|
+
|
|
200
|
+
{:else if name === 'steam-tower'}
|
|
201
|
+
<!-- Minimal steam tower with rising particles -->
|
|
202
|
+
<path d="M12 38 L16 12 L24 12 L28 38 Z" fill="currentColor" opacity="0.3"/>
|
|
203
|
+
<path d="M14 38 L17 14 L23 14 L26 38 Z" fill="url(#brassGrad-{size})" opacity="0.7"/>
|
|
204
|
+
|
|
205
|
+
{#if animation === 'steam'}
|
|
206
|
+
<!-- Rising particles -->
|
|
207
|
+
<g fill="#d4956a">
|
|
208
|
+
<circle cx="17" cy="10" r="1.5" opacity="0">
|
|
209
|
+
<animate attributeName="cy" values="12;-8" dur={calcDuration(2500)} repeatCount="indefinite"/>
|
|
210
|
+
<animate attributeName="opacity" values="0;0.8;0" dur={calcDuration(2500)} repeatCount="indefinite"/>
|
|
211
|
+
</circle>
|
|
212
|
+
<circle cx="20" cy="8" r="2" opacity="0">
|
|
213
|
+
<animate attributeName="cy" values="10;-12" dur={calcDuration(3000)} begin="0.5s" repeatCount="indefinite"/>
|
|
214
|
+
<animate attributeName="opacity" values="0;0.6;0" dur={calcDuration(3000)} begin="0.5s" repeatCount="indefinite"/>
|
|
215
|
+
</circle>
|
|
216
|
+
<circle cx="23" cy="12" r="1.5" opacity="0">
|
|
217
|
+
<animate attributeName="cy" values="12;-8" dur={calcDuration(2800)} begin="1s" repeatCount="indefinite"/>
|
|
218
|
+
<animate attributeName="opacity" values="0;0.7;0" dur={calcDuration(2800)} begin="1s" repeatCount="indefinite"/>
|
|
219
|
+
</circle>
|
|
220
|
+
</g>
|
|
221
|
+
{/if}
|
|
222
|
+
|
|
223
|
+
<!-- Hexagonal base -->
|
|
224
|
+
<path d="M20 40 L32 33 L32 25 L20 18 L8 25 L8 33 Z" fill="none" stroke="currentColor" stroke-width="1" opacity="0.4"/>
|
|
225
|
+
|
|
226
|
+
{:else if name === 'energy-pulse'}
|
|
227
|
+
<!-- Energy pulse with radiating arcs -->
|
|
228
|
+
<circle cx="20" cy="20" r="4" fill="currentColor"/>
|
|
229
|
+
|
|
230
|
+
{#if animation === 'pulse'}
|
|
231
|
+
<!-- Radiating rings -->
|
|
232
|
+
<circle cx="20" cy="20" r="8" fill="none" stroke="currentColor" stroke-width="1.5" opacity="0">
|
|
233
|
+
<animate attributeName="r" values="6;20;6" dur={calcDuration(2500)} repeatCount="indefinite"/>
|
|
234
|
+
<animate attributeName="opacity" values="0.8;0;0.8" dur={calcDuration(2500)} repeatCount="indefinite"/>
|
|
235
|
+
</circle>
|
|
236
|
+
<circle cx="20" cy="20" r="8" fill="none" stroke="currentColor" stroke-width="1" opacity="0">
|
|
237
|
+
<animate attributeName="r" values="6;20;6" dur={calcDuration(2500)} begin="0.8s" repeatCount="indefinite"/>
|
|
238
|
+
<animate attributeName="opacity" values="0.6;0;0.6" dur={calcDuration(2500)} begin="0.8s" repeatCount="indefinite"/>
|
|
239
|
+
</circle>
|
|
240
|
+
<circle cx="20" cy="20" r="8" fill="none" stroke="currentColor" stroke-width="0.5" opacity="0">
|
|
241
|
+
<animate attributeName="r" values="6;20;6" dur={calcDuration(2500)} begin="1.6s" repeatCount="indefinite"/>
|
|
242
|
+
<animate attributeName="opacity" values="0.4;0;0.4" dur={calcDuration(2500)} begin="1.6s" repeatCount="indefinite"/>
|
|
243
|
+
</circle>
|
|
244
|
+
{:else if animation === 'energy-arcs'}
|
|
245
|
+
<!-- Pulsing energy arcs outward -->
|
|
246
|
+
<g stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.8">
|
|
247
|
+
<line x1="20" y1="20" x2="5" y2="20">
|
|
248
|
+
<animate attributeName="opacity" values="0;1;0" dur={calcDuration(1500)} repeatCount="indefinite"/>
|
|
249
|
+
<animate attributeName="x2" values="20;2;20" dur={calcDuration(1500)} repeatCount="indefinite"/>
|
|
250
|
+
</line>
|
|
251
|
+
<line x1="20" y1="20" x2="35" y2="20">
|
|
252
|
+
<animate attributeName="opacity" values="0;1;0" dur={calcDuration(1500)} begin="0.75s" repeatCount="indefinite"/>
|
|
253
|
+
<animate attributeName="x2" values="20;38;20" dur={calcDuration(1500)} begin="0.75s" repeatCount="indefinite"/>
|
|
254
|
+
</line>
|
|
255
|
+
<line x1="20" y1="20" x2="20" y2="5">
|
|
256
|
+
<animate attributeName="opacity" values="0;1;0" dur={calcDuration(1500)} begin="0.375s" repeatCount="indefinite"/>
|
|
257
|
+
<animate attributeName="y2" values="20;2;20" dur={calcDuration(1500)} begin="0.375s" repeatCount="indefinite"/>
|
|
258
|
+
</line>
|
|
259
|
+
<line x1="20" y1="20" x2="20" y2="35">
|
|
260
|
+
<animate attributeName="opacity" values="0;1;0" dur={calcDuration(1500)} begin="1.125s" repeatCount="indefinite"/>
|
|
261
|
+
<animate attributeName="y2" values="20;38;20" dur={calcDuration(1500)} begin="1.125s" repeatCount="indefinite"/>
|
|
262
|
+
</line>
|
|
263
|
+
</g>
|
|
264
|
+
{/if}
|
|
265
|
+
{/if}
|
|
266
|
+
</svg>
|
|
267
|
+
|
|
268
|
+
<style>
|
|
269
|
+
.ds-animated-icon {
|
|
270
|
+
display: inline-block;
|
|
271
|
+
flex-shrink: 0;
|
|
272
|
+
}
|
|
273
|
+
</style>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# AnimatedIcon
|
|
2
|
+
|
|
3
|
+
SMIL-based animated SVG icons. Zero JavaScript overhead, GPU-accelerated via browser-native SVG animation.
|
|
4
|
+
|
|
5
|
+
## Philosophy
|
|
6
|
+
|
|
7
|
+
Aligns with LEAP's "enchanted" component philosophy from x0-enchanted-blocks:
|
|
8
|
+
- **Declarative**: Animations defined in markup, not JavaScript
|
|
9
|
+
- **Performant**: SMIL runs on the browser's compositor thread
|
|
10
|
+
- **Accessible**: Respects `prefers-reduced-motion` automatically
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```svelte
|
|
15
|
+
<script>
|
|
16
|
+
import { AnimatedIcon } from '@kos/design-system/u0-primitives/animated-icon';
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<AnimatedIcon name="power-node" animation="pulse" size={40} />
|
|
20
|
+
<AnimatedIcon name="activity" animation="wave" speed={0.5} />
|
|
21
|
+
<AnimatedIcon name="connection" color="#27ae60" />
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Icons
|
|
25
|
+
|
|
26
|
+
| Name | Description | Animations |
|
|
27
|
+
|------|-------------|------------|
|
|
28
|
+
| `power-node` | Energy/data center node | `pulse`, `orbit` |
|
|
29
|
+
| `activity` | Audio/video activity bars | `wave` (default) |
|
|
30
|
+
| `connection` | Network/data flow | `pulse` |
|
|
31
|
+
| `status-ring` | Loading/progress ring | `spin`, `breathe` |
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
| Prop | Type | Default | Description |
|
|
36
|
+
|------|------|---------|-------------|
|
|
37
|
+
| `name` | `IconName` | required | Icon identifier |
|
|
38
|
+
| `size` | `number` | `40` | ViewBox size (px) |
|
|
39
|
+
| `color` | `string` | `var(--color-accent)` | CSS color value |
|
|
40
|
+
| `animation` | `AnimationType` | varies | Animation style |
|
|
41
|
+
| `speed` | `number` | `1` | Multiplier (0.5 = slower, 2 = faster) |
|
|
42
|
+
|
|
43
|
+
## Design Tokens
|
|
44
|
+
|
|
45
|
+
Uses standard LEAP accent colors:
|
|
46
|
+
- `--color-accent` (primary)
|
|
47
|
+
- `--color-accent-hover`
|
|
48
|
+
- `--epistemic-live` (success states)
|
|
49
|
+
- `--epistemic-pending` (warning states)
|
|
50
|
+
|
|
51
|
+
## Browser Support
|
|
52
|
+
|
|
53
|
+
SMIL is supported in all modern browsers. For legacy environments, icons degrade gracefully to static SVG.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// AnimatedIcon - SMIL-based animated SVG icons
|
|
2
|
+
// Zero JS overhead, GPU-accelerated declarative animations
|
|
3
|
+
|
|
4
|
+
export { default as AnimatedIcon } from './AnimatedIcon.svelte';
|
|
5
|
+
|
|
6
|
+
// Type exports for consumers
|
|
7
|
+
export type AnimatedIconName =
|
|
8
|
+
| 'power-node'
|
|
9
|
+
| 'activity'
|
|
10
|
+
| 'connection'
|
|
11
|
+
| 'status-ring'
|
|
12
|
+
| 'power-plant'
|
|
13
|
+
| 'orbital-ring'
|
|
14
|
+
| 'steam-tower'
|
|
15
|
+
| 'energy-pulse';
|
|
16
|
+
|
|
17
|
+
export type AnimationType =
|
|
18
|
+
| 'pulse'
|
|
19
|
+
| 'orbit'
|
|
20
|
+
| 'wave'
|
|
21
|
+
| 'breathe'
|
|
22
|
+
| 'spin'
|
|
23
|
+
| 'steam'
|
|
24
|
+
| 'energy-arcs';
|
|
25
|
+
|
|
26
|
+
// Animation duration presets (ms)
|
|
27
|
+
export const ANIMATION_SPEEDS = {
|
|
28
|
+
slow: 0.5, // 2x duration
|
|
29
|
+
normal: 1, // base duration
|
|
30
|
+
fast: 2, // 0.5x duration
|
|
31
|
+
} as const;
|