@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.
Files changed (204) hide show
  1. package/README.md +66 -0
  2. package/package.json +130 -0
  3. package/src/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +221 -0
  4. package/src/b0-app-shell/clarification-overlay/index.ts +1 -0
  5. package/src/b0-app-shell/command-bar/CommandBar.svelte +565 -0
  6. package/src/b0-app-shell/index.ts +14 -0
  7. package/src/base.css +152 -0
  8. package/src/d0-data-viz/BarChart.svelte +236 -0
  9. package/src/d0-data-viz/CheckpointBar.svelte +574 -0
  10. package/src/d0-data-viz/CheckpointPill.svelte +297 -0
  11. package/src/d0-data-viz/MetricCard.svelte +159 -0
  12. package/src/d0-data-viz/SparkLine.svelte +66 -0
  13. package/src/d0-data-viz/StorageMap.svelte +182 -0
  14. package/src/d0-data-viz/Timeline.svelte +188 -0
  15. package/src/d0-data-viz/checkpoint-types.ts +162 -0
  16. package/src/d0-data-viz/d0-tokens.css +32 -0
  17. package/src/d0-data-viz/index.ts +58 -0
  18. package/src/d0-data-viz/storage-map-types.ts +142 -0
  19. package/src/d0-data-viz/theme-integration.ts +134 -0
  20. package/src/d0-data-viz/types.ts +53 -0
  21. package/src/demos/BspSizingInfographic.svelte +386 -0
  22. package/src/demos/BspZoneDemo.svelte +255 -0
  23. package/src/demos/ControlRoomDemo.svelte +570 -0
  24. package/src/demos/NodepadBlocksShowcase.svelte +189 -0
  25. package/src/demos/index.ts +7 -0
  26. package/src/editor/CodeEditor.svelte +188 -0
  27. package/src/editor/FindReplaceDialog.svelte +516 -0
  28. package/src/editor/MarkdownEditor.svelte +660 -0
  29. package/src/editor/index.ts +2 -0
  30. package/src/entity-graph-view/WorldView.svelte +171 -0
  31. package/src/entity-graph-view/index.ts +6 -0
  32. package/src/entity-graph-view/types.ts +364 -0
  33. package/src/epistemic/index.ts +2 -0
  34. package/src/epistemic/types.ts +134 -0
  35. package/src/epistemic/utils.ts +32 -0
  36. package/src/f0-forms/checkbox/Checkbox.svelte +158 -0
  37. package/src/f0-forms/field/FormField.svelte +91 -0
  38. package/src/f0-forms/index.ts +11 -0
  39. package/src/f0-forms/radio/RadioGroup.svelte +192 -0
  40. package/src/f0-forms/search/SearchBar.svelte +99 -0
  41. package/src/f0-forms/select/Select.svelte +198 -0
  42. package/src/f0-forms/textarea/TextArea.svelte +170 -0
  43. package/src/f0-forms/toggle/FormToggle.svelte +147 -0
  44. package/src/f0-forms/validation/validate.ts +47 -0
  45. package/src/fabric/ai/ChatPanel.svelte +648 -0
  46. package/src/fabric/ai/index.ts +11 -0
  47. package/src/fabric/data/index.ts +21 -0
  48. package/src/fabric/feedback/StatusBar.svelte +274 -0
  49. package/src/fabric/feedback/ToastContainer.svelte +122 -0
  50. package/src/fabric/feedback/index.ts +14 -0
  51. package/src/fabric/index.ts +37 -0
  52. package/src/fabric/input/CommandBar.svelte +79 -0
  53. package/src/fabric/input/KeyboardShortcuts.svelte +388 -0
  54. package/src/fabric/input/index.ts +12 -0
  55. package/src/fabric/layout/GlassBox.svelte +193 -0
  56. package/src/fabric/layout/KanbanBoard.svelte +158 -0
  57. package/src/fabric/layout/KanbanCard.svelte +226 -0
  58. package/src/fabric/layout/KanbanColumn.svelte +278 -0
  59. package/src/fabric/layout/index.ts +17 -0
  60. package/src/fabric/navigation/ActivityRail.svelte +271 -0
  61. package/src/fabric/navigation/index.ts +11 -0
  62. package/src/g0-geo/SovereignMap.svelte +149 -0
  63. package/src/g0-geo/index.ts +2 -0
  64. package/src/index.ts +68 -0
  65. package/src/l0-layout/block-writer/BlockConnectionLines.svelte +98 -0
  66. package/src/l0-layout/block-writer/BlockContent.svelte +213 -0
  67. package/src/l0-layout/block-writer/BlockHeader.svelte +230 -0
  68. package/src/l0-layout/block-writer/BlockItem.svelte +177 -0
  69. package/src/l0-layout/block-writer/BlockWriter.svelte +219 -0
  70. package/src/l0-layout/block-writer/block-writer-types.ts +63 -0
  71. package/src/l0-layout/block-writer/index.ts +24 -0
  72. package/src/l0-layout/block-writer/markdown.ts +110 -0
  73. package/src/l0-layout/chat-view/ChatViewLayout.svelte +61 -0
  74. package/src/l0-layout/epistemic/AllayDetailPanel.svelte +113 -0
  75. package/src/l0-layout/epistemic/AssayDetailPanel.svelte +164 -0
  76. package/src/l0-layout/epistemic/AvenueTrace.svelte +253 -0
  77. package/src/l0-layout/epistemic/KnowledgeDetailPanel.svelte +204 -0
  78. package/src/l0-layout/epistemic/ParadigmLens.svelte +170 -0
  79. package/src/l0-layout/epistemic/ProvenanceChain.svelte +164 -0
  80. package/src/l0-layout/epistemic/TrustView.svelte +195 -0
  81. package/src/l0-layout/epistemic/index.ts +7 -0
  82. package/src/l0-layout/grove/AccordCard.svelte +156 -0
  83. package/src/l0-layout/grove/GroveCard.svelte +197 -0
  84. package/src/l0-layout/grove/MemberBadge.svelte +96 -0
  85. package/src/l0-layout/grove/MemberList.svelte +59 -0
  86. package/src/l0-layout/grove/grove-types.ts +29 -0
  87. package/src/l0-layout/grove/index.ts +14 -0
  88. package/src/l0-layout/index.ts +45 -0
  89. package/src/l0-layout/kanban/KanbanBoard.svelte +71 -0
  90. package/src/l0-layout/kanban/KanbanCard.svelte +276 -0
  91. package/src/l0-layout/kanban/KanbanColumn.svelte +198 -0
  92. package/src/l0-layout/kanban/KanbanViewLayout.svelte +61 -0
  93. package/src/l0-layout/workspace/WorkspaceLayout.svelte +93 -0
  94. package/src/n0-node-graph/GraphEditor.svelte +342 -0
  95. package/src/n0-node-graph/GraphHistory.svelte +122 -0
  96. package/src/n0-node-graph/Node.svelte +269 -0
  97. package/src/n0-node-graph/NodeCanvas.svelte +187 -0
  98. package/src/n0-node-graph/NodeEdge.svelte +152 -0
  99. package/src/n0-node-graph/NodePalette.svelte +318 -0
  100. package/src/n0-node-graph/NodePort.svelte +128 -0
  101. package/src/n0-node-graph/index.ts +33 -0
  102. package/src/n0-node-graph/n0-tokens.css +29 -0
  103. package/src/n0-node-graph/node-port-types.ts +19 -0
  104. package/src/n0-node-graph/types.ts +96 -0
  105. package/src/n0-node-graph/validate.test.ts +722 -0
  106. package/src/n0-node-graph/validate.ts +371 -0
  107. package/src/n1-flow-canvas/FlowCanvas.svelte +202 -0
  108. package/src/n1-flow-canvas/graph-state.svelte.ts +95 -0
  109. package/src/n1-flow-canvas/index.ts +21 -0
  110. package/src/n1-flow-canvas/layout.ts +118 -0
  111. package/src/n1-flow-canvas/layout.worker.ts +128 -0
  112. package/src/n1-flow-canvas/types.ts +102 -0
  113. package/src/n1-flow-canvas/utils.ts +146 -0
  114. package/src/n2-manifold-disk/ManifoldDisk.svelte +314 -0
  115. package/src/n2-manifold-disk/index.ts +6 -0
  116. package/src/n2-manifold-disk/poincare.ts +184 -0
  117. package/src/n3-force-graph/ForceGraph.svelte +180 -0
  118. package/src/n3-force-graph/GraphTooltip.svelte +99 -0
  119. package/src/n3-force-graph/animated-edge.ts +107 -0
  120. package/src/n3-force-graph/health-node.ts +128 -0
  121. package/src/n3-force-graph/index.ts +31 -0
  122. package/src/n3-force-graph/types.ts +94 -0
  123. package/src/n4-adaptive-manifold/AdaptiveManifold.svelte +1165 -0
  124. package/src/n4-adaptive-manifold/DetailCard.svelte +212 -0
  125. package/src/n4-adaptive-manifold/SuggestionIndicator.svelte +91 -0
  126. package/src/n4-adaptive-manifold/classifier.ts +139 -0
  127. package/src/n4-adaptive-manifold/index.ts +45 -0
  128. package/src/n4-adaptive-manifold/n4-tokens.css +155 -0
  129. package/src/n4-adaptive-manifold/orchestrator.ts +301 -0
  130. package/src/n4-adaptive-manifold/phase-theme.ts +92 -0
  131. package/src/n4-adaptive-manifold/pinnacle-events.ts +135 -0
  132. package/src/n4-adaptive-manifold/providers/gravitational-provider.ts +191 -0
  133. package/src/n4-adaptive-manifold/providers/manifold-provider.ts +276 -0
  134. package/src/n4-adaptive-manifold/transition.ts +90 -0
  135. package/src/n4-adaptive-manifold/types.ts +313 -0
  136. package/src/p0-primitives/index.ts +6 -0
  137. package/src/p0-primitives/tokens/control-room.css +309 -0
  138. package/src/p0-primitives/tokens/index.ts +6 -0
  139. package/src/p0-primitives/tokens/tokens.css +140 -0
  140. package/src/p0-primitives/tokens/tokens.json +132 -0
  141. package/src/p0-primitives/types/index.ts +123 -0
  142. package/src/p0-primitives/types/plugin-types.ts +74 -0
  143. package/src/p0-primitives/utils/index.ts +39 -0
  144. package/src/platform/hud-protocol.ts +20 -0
  145. package/src/platform/index.ts +3 -0
  146. package/src/s0-state/create-store.ts +84 -0
  147. package/src/s0-state/derived.ts +41 -0
  148. package/src/s0-state/index.ts +6 -0
  149. package/src/showcase/Showcase.svelte +401 -0
  150. package/src/spatial/BspTilingCanvas.svelte +232 -0
  151. package/src/spatial/ForceCanvas.svelte +289 -0
  152. package/src/spatial/LodRenderer.svelte +334 -0
  153. package/src/spatial/SnapZoomCamera.svelte +185 -0
  154. package/src/spatial/ZoneTiler.svelte +311 -0
  155. package/src/spatial/camera-types.ts +45 -0
  156. package/src/spatial/content-proportional-bsp.ts +253 -0
  157. package/src/spatial/force-canvas-types.ts +102 -0
  158. package/src/spatial/index.ts +15 -0
  159. package/src/spatial/lod-types.ts +70 -0
  160. package/src/spatial/zone-tiler-types.ts +177 -0
  161. package/src/stores/vaultStore.svelte +14 -0
  162. package/src/t0-transport/connection.ts +34 -0
  163. package/src/t0-transport/error.ts +37 -0
  164. package/src/t0-transport/events.ts +50 -0
  165. package/src/t0-transport/index.ts +6 -0
  166. package/src/t0-transport/invoke.ts +30 -0
  167. package/src/tauri/index.ts +13 -0
  168. package/src/u0-primitives/allay-gauge/AllayGauge.svelte +90 -0
  169. package/src/u0-primitives/allay-gauge/index.ts +1 -0
  170. package/src/u0-primitives/animated-icon/AnimatedIcon.svelte +273 -0
  171. package/src/u0-primitives/animated-icon/README.md +53 -0
  172. package/src/u0-primitives/animated-icon/index.ts +31 -0
  173. package/src/u0-primitives/assay-badge/AssayBadge.svelte +121 -0
  174. package/src/u0-primitives/assay-badge/AssaySignalBar.svelte +83 -0
  175. package/src/u0-primitives/assay-badge/index.ts +2 -0
  176. package/src/u0-primitives/avatar/Avatar.svelte +177 -0
  177. package/src/u0-primitives/badge/Badge.svelte +149 -0
  178. package/src/u0-primitives/button/Button.svelte +304 -0
  179. package/src/u0-primitives/card/Card.svelte +182 -0
  180. package/src/u0-primitives/dropdown/Dropdown.svelte +305 -0
  181. package/src/u0-primitives/expert-badge/ExpertBadge.svelte +89 -0
  182. package/src/u0-primitives/expert-badge/index.ts +1 -0
  183. package/src/u0-primitives/index.ts +35 -0
  184. package/src/u0-primitives/input/Input.svelte +237 -0
  185. package/src/u0-primitives/modal/Modal.svelte +331 -0
  186. package/src/u0-primitives/modal/index.ts +1 -0
  187. package/src/u0-primitives/spinner/Spinner.svelte +129 -0
  188. package/src/u0-primitives/tabs/Tabs.svelte +225 -0
  189. package/src/u0-primitives/tabs/tabs-types.ts +11 -0
  190. package/src/u0-primitives/toggle/Toggle.svelte +161 -0
  191. package/src/u0-primitives/tooltip/Tooltip.svelte +234 -0
  192. package/src/v0-diagrams/DiagramPanel.svelte +68 -0
  193. package/src/v0-diagrams/MarkmapDiagram.svelte +56 -0
  194. package/src/v0-diagrams/MermaidDiagram.svelte +53 -0
  195. package/src/v0-diagrams/index.ts +4 -0
  196. package/src/v0-diagrams/types.ts +28 -0
  197. package/src/v0-diagrams/v0-tokens.css +6 -0
  198. package/src/vite-env.d.ts +7 -0
  199. package/src/x0-enchanted-blocks/ENCHANTED_BLOCKS_SPEC.md +457 -0
  200. package/src/x0-enchanted-blocks/components/EnchantedBlock.svelte +485 -0
  201. package/src/x0-enchanted-blocks/components/NodepadBlock.svelte +262 -0
  202. package/src/x0-enchanted-blocks/core/block-layout.ts +211 -0
  203. package/src/x0-enchanted-blocks/core/block-types.ts +227 -0
  204. package/src/x0-enchanted-blocks/index.ts +46 -0
@@ -0,0 +1,121 @@
1
+ <script lang="ts">
2
+ import type { AssayClearanceView } from '../../epistemic/types.js';
3
+
4
+ interface Props {
5
+ clearance: AssayClearanceView | null;
6
+ size?: 'sm' | 'md';
7
+ interactive?: boolean;
8
+ onclick?: () => void;
9
+ class?: string;
10
+ }
11
+
12
+ let {
13
+ clearance,
14
+ size = 'md',
15
+ interactive = false,
16
+ onclick,
17
+ class: className = '',
18
+ }: Props = $props();
19
+
20
+ // Derive display state from clearance
21
+ const state = $derived(
22
+ clearance === null ? 'pending' :
23
+ clearance.isDegraded ? 'degraded' :
24
+ clearance.gate === 'Cleared' ? 'cleared' : 'blocked'
25
+ );
26
+
27
+ const dotColor = $derived(
28
+ state === 'cleared' ? 'var(--epistemic-cleared)' :
29
+ state === 'blocked' ? 'var(--epistemic-blocked)' :
30
+ state === 'degraded' ? 'var(--epistemic-degraded)' :
31
+ /* pending */ 'var(--epistemic-pending)'
32
+ );
33
+
34
+ const label = $derived(
35
+ state === 'cleared' ? 'Cleared' :
36
+ state === 'blocked' ? 'Blocked' :
37
+ state === 'degraded' ? 'Degraded' :
38
+ 'Pending'
39
+ );
40
+
41
+ const title = $derived(
42
+ clearance === null ? 'ASSAY: Not yet evaluated' :
43
+ `ASSAY ${label} at ${clearance.checkpoint} — weighted: ${clearance.weightedSum.toFixed(2)}`
44
+ );
45
+
46
+ function handleClick() {
47
+ if (interactive && onclick) onclick();
48
+ }
49
+ </script>
50
+
51
+ <button
52
+ class="ds-assay-badge size-{size} state-{state} {className}"
53
+ class:interactive
54
+ {title}
55
+ onclick={handleClick}
56
+ type="button"
57
+ aria-label="ASSAY clearance: {label}"
58
+ tabindex={interactive ? 0 : -1}
59
+ >
60
+ <span class="dot" style="background-color: {dotColor}; box-shadow: 0 0 4px {dotColor};"></span>
61
+ {#if size === 'md'}
62
+ <span class="label">{label}</span>
63
+ {/if}
64
+ </button>
65
+
66
+ <style>
67
+ .ds-assay-badge {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ gap: var(--space-1);
71
+ padding: var(--space-1) var(--space-2);
72
+ border-radius: var(--radius-full);
73
+ border: 1px solid var(--border-subtle);
74
+ background: transparent;
75
+ cursor: default;
76
+ font-family: var(--font-sans);
77
+ font-size: var(--text-xs);
78
+ font-weight: 500;
79
+ color: var(--color-text-secondary);
80
+ white-space: nowrap;
81
+ transition: background var(--transition-fast, 120ms), border-color var(--transition-fast, 120ms);
82
+ }
83
+
84
+ .ds-assay-badge.interactive {
85
+ cursor: pointer;
86
+ }
87
+
88
+ .ds-assay-badge.interactive:hover {
89
+ background: var(--color-bg-panel-elevated);
90
+ border-color: var(--border-hover);
91
+ }
92
+
93
+ .ds-assay-badge.size-sm {
94
+ padding: 2px;
95
+ border: none;
96
+ background: transparent;
97
+ }
98
+
99
+ .dot {
100
+ width: 8px;
101
+ height: 8px;
102
+ border-radius: 50%;
103
+ flex-shrink: 0;
104
+ }
105
+
106
+ .size-sm .dot {
107
+ width: 6px;
108
+ height: 6px;
109
+ }
110
+
111
+ .label {
112
+ font-size: var(--text-xs);
113
+ color: var(--color-text-secondary);
114
+ }
115
+
116
+ /* State-specific label colors */
117
+ .state-cleared .label { color: var(--epistemic-cleared); }
118
+ .state-blocked .label { color: var(--epistemic-blocked); }
119
+ .state-pending .label { color: var(--epistemic-pending); }
120
+ .state-degraded .label { color: var(--epistemic-degraded); }
121
+ </style>
@@ -0,0 +1,83 @@
1
+ <script lang="ts">
2
+ import type { AssaySignalView } from '../../epistemic/types.js';
3
+
4
+ interface Props {
5
+ signal: AssaySignalView;
6
+ class?: string;
7
+ }
8
+
9
+ let { signal, class: className = '' }: Props = $props();
10
+
11
+ const resultColor = $derived(
12
+ signal.result === 'Pass' ? 'var(--epistemic-cleared)' :
13
+ signal.result === 'Fail' ? 'var(--epistemic-blocked)' :
14
+ 'var(--epistemic-degraded)'
15
+ );
16
+
17
+ const confidenceStr = $derived(
18
+ signal.confidence !== null ? `${Math.round(signal.confidence * 100)}%` : '—'
19
+ );
20
+ </script>
21
+
22
+ <div class="signal-bar {className}" class:hard-gate={signal.isHardGate}>
23
+ <span class="signal-indicator" style="color: {resultColor}">
24
+ {signal.isHardGate ? '■' : '□'}
25
+ </span>
26
+ <span class="signal-id">{signal.id}</span>
27
+ <span class="signal-result" style="color: {resultColor}">
28
+ {signal.result === 'Unavailable' ? 'unavail' : signal.result}
29
+ </span>
30
+ <span class="signal-confidence">{confidenceStr}</span>
31
+ {#if signal.result === 'Fail' && signal.reason}
32
+ <span class="signal-reason">{signal.reason}</span>
33
+ {/if}
34
+ </div>
35
+
36
+ <style>
37
+ .signal-bar {
38
+ display: grid;
39
+ grid-template-columns: 1.2rem 1fr auto auto;
40
+ align-items: center;
41
+ gap: var(--space-2);
42
+ padding: var(--space-1) 0;
43
+ font-family: var(--font-mono);
44
+ font-size: var(--text-xs);
45
+ color: var(--color-text-secondary);
46
+ }
47
+
48
+ .signal-bar:not(:last-child) {
49
+ border-bottom: 1px solid var(--border-subtle);
50
+ }
51
+
52
+ .signal-indicator {
53
+ font-size: var(--text-sm);
54
+ flex-shrink: 0;
55
+ }
56
+
57
+ .signal-id {
58
+ color: var(--color-text-primary);
59
+ font-size: var(--text-xs);
60
+ }
61
+
62
+ .signal-result {
63
+ font-weight: 600;
64
+ font-size: var(--text-xs);
65
+ text-transform: uppercase;
66
+ letter-spacing: 0.05em;
67
+ }
68
+
69
+ .signal-confidence {
70
+ color: var(--color-text-tertiary);
71
+ font-size: var(--text-xs);
72
+ min-width: 3rem;
73
+ text-align: right;
74
+ }
75
+
76
+ .signal-reason {
77
+ grid-column: 2 / -1;
78
+ color: var(--epistemic-blocked);
79
+ font-size: var(--text-xs);
80
+ font-style: italic;
81
+ padding-top: var(--space-1);
82
+ }
83
+ </style>
@@ -0,0 +1,2 @@
1
+ export { default as AssayBadge } from './AssayBadge.svelte';
2
+ export { default as AssaySignalBar } from './AssaySignalBar.svelte';
@@ -0,0 +1,177 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ src?: string;
6
+ name?: string;
7
+ size?: 'sm' | 'md' | 'lg' | 'xl';
8
+ status?: 'online' | 'offline' | 'away' | 'busy' | 'typing' | null;
9
+ class?: string;
10
+ }
11
+
12
+ let {
13
+ src,
14
+ name = '',
15
+ size = 'md',
16
+ status = null,
17
+ class: className = ''
18
+ }: Props = $props();
19
+
20
+ let hasError = $state(false);
21
+
22
+ let fallbackInitials = $derived(
23
+ name
24
+ .split(' ')
25
+ .map(n => n[0])
26
+ .slice(0, 2)
27
+ .join('')
28
+ .toUpperCase()
29
+ );
30
+
31
+ function handleError() {
32
+ hasError = true;
33
+ }
34
+ </script>
35
+
36
+ <div class="ds-avatar-wrapper size-{size} {className}">
37
+ <div class="ds-avatar-inner" aria-label={name}>
38
+ {#if src && !hasError}
39
+ <img
40
+ class="ds-avatar-image"
41
+ {src}
42
+ alt={name}
43
+ onerror={handleError}
44
+ />
45
+ {:else}
46
+ <div class="ds-avatar-fallback">
47
+ <span class="ds-avatar-initials">{fallbackInitials || '?'}</span>
48
+ </div>
49
+ {/if}
50
+ </div>
51
+
52
+ {#if status}
53
+ <div class="ds-avatar-status status-{status}" title={status}>
54
+ {#if status === 'typing'}
55
+ <span class="typing-dot"></span>
56
+ <span class="typing-dot"></span>
57
+ <span class="typing-dot"></span>
58
+ {/if}
59
+ </div>
60
+ {/if}
61
+ </div>
62
+
63
+ <style>
64
+ .ds-avatar-wrapper {
65
+ position: relative;
66
+ display: inline-flex;
67
+ flex-shrink: 0;
68
+ align-items: center;
69
+ justify-content: center;
70
+ border-radius: var(--radius-full);
71
+ }
72
+
73
+ .ds-avatar-inner {
74
+ position: relative;
75
+ width: 100%;
76
+ height: 100%;
77
+ border-radius: var(--radius-full);
78
+ overflow: hidden;
79
+ background: var(--color-bg-panel-elevated);
80
+ border: 1px solid var(--border-subtle);
81
+ box-shadow: var(--shadow-sm);
82
+ }
83
+
84
+ .ds-avatar-image {
85
+ width: 100%;
86
+ height: 100%;
87
+ object-fit: cover;
88
+ }
89
+
90
+ .ds-avatar-fallback {
91
+ width: 100%;
92
+ height: 100%;
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ background: linear-gradient(135deg, var(--color-bg-panel-elevated), var(--color-bg-panel));
97
+ color: var(--color-text-secondary);
98
+ }
99
+
100
+ .ds-avatar-initials {
101
+ font-family: var(--font-sans);
102
+ font-weight: 600;
103
+ }
104
+
105
+ /* --- Sizes --- */
106
+ .size-sm {
107
+ width: 1.5rem;
108
+ height: 1.5rem;
109
+ }
110
+ .size-sm .ds-avatar-initials { font-size: var(--text-xs); }
111
+
112
+ .size-md {
113
+ width: 2.25rem;
114
+ height: 2.25rem;
115
+ }
116
+ .size-md .ds-avatar-initials { font-size: var(--text-sm); }
117
+
118
+ .size-lg {
119
+ width: 3rem;
120
+ height: 3rem;
121
+ }
122
+ .size-lg .ds-avatar-initials { font-size: var(--text-lg); }
123
+
124
+ .size-xl {
125
+ width: 4rem;
126
+ height: 4rem;
127
+ }
128
+ .size-xl .ds-avatar-initials { font-size: var(--text-xl); }
129
+
130
+ /* --- Status Dot --- */
131
+ .ds-avatar-status {
132
+ position: absolute;
133
+ bottom: -2px;
134
+ right: -2px;
135
+ width: 25%;
136
+ height: 25%;
137
+ min-width: 10px;
138
+ min-height: 10px;
139
+ border-radius: var(--radius-full);
140
+ background-color: var(--color-offline);
141
+ border: 2px solid var(--color-bg-app); /* Cuts a ring out of the avatar */
142
+ z-index: 10;
143
+ }
144
+
145
+ .status-online { background-color: var(--color-online); box-shadow: 0 0 6px rgba(74, 222, 128, 0.4); }
146
+ .status-away { background-color: var(--color-away); }
147
+ .status-busy { background-color: var(--color-busy); }
148
+ .status-offline { background-color: var(--color-offline); }
149
+
150
+ .status-typing {
151
+ background-color: var(--color-typing);
152
+ display: flex;
153
+ align-items: center;
154
+ justify-content: space-evenly;
155
+ width: auto;
156
+ padding: 0 4px;
157
+ min-width: 16px;
158
+ border-radius: var(--radius-full);
159
+ box-shadow: var(--shadow-glow);
160
+ }
161
+
162
+ .typing-dot {
163
+ width: 3px;
164
+ height: 3px;
165
+ background-color: #111;
166
+ border-radius: var(--radius-full);
167
+ animation: typing-bounce 1.4s infinite ease-in-out both;
168
+ }
169
+
170
+ .typing-dot:nth-child(1) { animation-delay: -0.32s; }
171
+ .typing-dot:nth-child(2) { animation-delay: -0.16s; }
172
+
173
+ @keyframes typing-bounce {
174
+ 0%, 80%, 100% { transform: scale(0); }
175
+ 40% { transform: scale(1); }
176
+ }
177
+ </style>
@@ -0,0 +1,149 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ variant?: 'status' | 'count' | 'dot' | 'outline';
6
+ color?: 'accent' | 'success' | 'warning' | 'error' | 'info' | 'neutral';
7
+ size?: 'sm' | 'md' | 'lg';
8
+ class?: string;
9
+ children?: Snippet;
10
+ }
11
+
12
+ let {
13
+ variant = 'status',
14
+ color = 'accent',
15
+ size = 'md',
16
+ class: className = '',
17
+ children
18
+ }: Props = $props();
19
+ </script>
20
+
21
+ <div
22
+ class="ds-badge variant-{variant} color-{color} size-{size} {className}"
23
+ role="status"
24
+ >
25
+ {#if variant === 'dot'}
26
+ <!-- Empty dot badge -->
27
+ {:else if children}
28
+ <span class="ds-badge-content">
29
+ {@render children()}
30
+ </span>
31
+ {/if}
32
+ </div>
33
+
34
+ <style>
35
+ .ds-badge {
36
+ display: inline-flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ font-family: var(--font-sans);
40
+ font-weight: 600;
41
+ white-space: nowrap;
42
+ border-radius: var(--radius-full);
43
+ transition: all var(--transition-fast);
44
+ }
45
+
46
+ /* --- Variants --- */
47
+
48
+ /* Status (Subtle background, colored text) */
49
+ .variant-status {
50
+ border: 1px solid transparent;
51
+ }
52
+
53
+ .variant-status.color-accent {
54
+ background: var(--color-accent-subtle);
55
+ color: var(--color-accent-hover);
56
+ border-color: rgba(184, 115, 51, 0.2);
57
+ }
58
+
59
+ .variant-status.color-success {
60
+ background: color-mix(in srgb, var(--color-success) 15%, transparent);
61
+ color: color-mix(in srgb, var(--color-success) 70%, var(--color-text-primary));
62
+ border-color: color-mix(in srgb, var(--color-success) 30%, transparent);
63
+ }
64
+
65
+ .variant-status.color-warning {
66
+ background: color-mix(in srgb, var(--color-warning) 15%, transparent);
67
+ color: color-mix(in srgb, var(--color-warning) 70%, var(--color-text-primary));
68
+ border-color: color-mix(in srgb, var(--color-warning) 30%, transparent);
69
+ }
70
+
71
+ .variant-status.color-error {
72
+ background: color-mix(in srgb, var(--color-error) 15%, transparent);
73
+ color: color-mix(in srgb, var(--color-error) 70%, var(--color-text-primary));
74
+ border-color: color-mix(in srgb, var(--color-error) 30%, transparent);
75
+ }
76
+
77
+ .variant-status.color-info {
78
+ background: color-mix(in srgb, var(--color-info) 15%, transparent);
79
+ color: color-mix(in srgb, var(--color-info) 70%, var(--color-text-primary));
80
+ border-color: color-mix(in srgb, var(--color-info) 30%, transparent);
81
+ }
82
+
83
+ .variant-status.color-neutral {
84
+ background: var(--color-bg-panel-elevated);
85
+ color: var(--color-text-secondary);
86
+ border-color: var(--border-default);
87
+ }
88
+
89
+ /* Count (Solid background, white/dark text) */
90
+ .variant-count {
91
+ box-shadow: 0 1px 2px rgba(0,0,0,0.2);
92
+ }
93
+
94
+ .variant-count.color-accent { background: var(--color-accent); color: #111; }
95
+ .variant-count.color-success { background: var(--color-success); color: #fff; }
96
+ .variant-count.color-warning { background: var(--color-warning); color: #111; }
97
+ .variant-count.color-error { background: var(--color-error); color: #fff; }
98
+ .variant-count.color-info { background: var(--color-info); color: #fff; }
99
+ .variant-count.color-neutral { background: var(--color-text-tertiary); color: #fff; }
100
+
101
+ /* Outline */
102
+ .variant-outline {
103
+ background: transparent;
104
+ border: 1px solid currentColor;
105
+ }
106
+
107
+ .variant-outline.color-accent { color: var(--color-accent-hover); }
108
+ .variant-outline.color-success { color: var(--color-success); }
109
+ .variant-outline.color-warning { color: var(--color-warning); }
110
+ .variant-outline.color-error { color: var(--color-error); }
111
+ .variant-outline.color-info { color: var(--color-info); }
112
+ .variant-outline.color-neutral { color: var(--color-text-secondary); }
113
+
114
+ /* Dot (Small pulsing indicator) */
115
+ .variant-dot {
116
+ width: 0.5rem;
117
+ height: 0.5rem;
118
+ padding: 0;
119
+ border-radius: var(--radius-full);
120
+ box-shadow: 0 0 0 2px var(--color-bg-app);
121
+ }
122
+
123
+ .variant-dot.color-accent { background: var(--color-accent); }
124
+ .variant-dot.color-success { background: var(--color-success); }
125
+ .variant-dot.color-warning { background: var(--color-warning); }
126
+ .variant-dot.color-error { background: var(--color-error); }
127
+ .variant-dot.color-info { background: var(--color-info); }
128
+ .variant-dot.color-neutral { background: var(--color-text-tertiary); }
129
+
130
+ /* --- Sizes --- */
131
+
132
+ .size-sm:not(.variant-dot) {
133
+ padding: 0.1rem 0.35rem;
134
+ font-size: 0.65rem;
135
+ line-height: 1;
136
+ }
137
+
138
+ .size-md:not(.variant-dot) {
139
+ padding: 0.15rem 0.5rem;
140
+ font-size: var(--text-xs);
141
+ line-height: 1.2;
142
+ }
143
+
144
+ .size-lg:not(.variant-dot) {
145
+ padding: 0.25rem 0.75rem;
146
+ font-size: var(--text-sm);
147
+ line-height: 1.4;
148
+ }
149
+ </style>