@harmonia-core/ui 1.2.3 → 1.2.5

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.
@@ -1,9 +1,10 @@
1
+ "use client";
1
2
  'use strict';
2
3
 
3
4
  var react = require('react');
4
- var react$1 = require('motion/react');
5
- var jsxRuntime = require('react/jsx-runtime');
5
+ var ui = require('@harmonia-core/ui');
6
6
  var tokens = require('@renge-ui/tokens');
7
+ var jsxRuntime = require('react/jsx-runtime');
7
8
 
8
9
  var __defProp = Object.defineProperty;
9
10
  var __defProps = Object.defineProperties;
@@ -36,320 +37,6 @@ var __objRest = (source, exclude) => {
36
37
  }
37
38
  return target;
38
39
  };
39
- var FEEDBACK_FREQUENCIES = {
40
- low: 396,
41
- // Foundation/root elements
42
- mid: 528,
43
- // Primary interactive content
44
- high: 741
45
- // Dynamic/feedback elements
46
- };
47
- var DEFAULT_FIELD_CONFIG = {
48
- smoothing: 0.15,
49
- // Exponential smoothing factor
50
- velocityThreshold: 0.05,
51
- // Min velocity to register as trend
52
- debounceMs: 100
53
- // Debounce rapid changes
54
- };
55
- var DEFAULT_USER_CAPACITY = {
56
- cognitive: 0.7,
57
- temporal: 0.7,
58
- emotional: 0.7
59
- };
60
- var DEFAULT_EMOTIONAL_STATE = {
61
- valence: 0.3,
62
- // > 0.15 (with emotional > 0.6) triggers expressive motion mode
63
- arousal: 0.5
64
- };
65
-
66
- // lib/capacity/feedback.ts
67
- var HAPTIC_PATTERNS = {
68
- /** Short tap — confirm/select */
69
- tap: [8],
70
- /** Two pulses — toggle/switch */
71
- toggle: [8, 50, 8],
72
- /** Gentle pulse — ambient/ambient confirmation */
73
- pulse: [15, 30, 15],
74
- /** Error/warning — three quick */
75
- error: [50, 30, 50, 30, 50]
76
- };
77
- function triggerHaptic(pattern = "tap") {
78
- if (typeof navigator !== "undefined" && "vibrate" in navigator) {
79
- navigator.vibrate(HAPTIC_PATTERNS[pattern]);
80
- }
81
- }
82
- var _audioCtx = null;
83
- function getAudioContext() {
84
- if (typeof window === "undefined") return null;
85
- try {
86
- if (!_audioCtx || _audioCtx.state === "closed") {
87
- _audioCtx = new AudioContext();
88
- }
89
- if (_audioCtx.state === "suspended") {
90
- _audioCtx.resume();
91
- }
92
- return _audioCtx;
93
- } catch (e) {
94
- return null;
95
- }
96
- }
97
- function playSonicFeedback(frequency, duration = 120, volume = 0.06) {
98
- const ctx = getAudioContext();
99
- if (!ctx) return;
100
- const oscillator = ctx.createOscillator();
101
- const gainNode = ctx.createGain();
102
- oscillator.connect(gainNode);
103
- gainNode.connect(ctx.destination);
104
- oscillator.type = "sine";
105
- oscillator.frequency.setValueAtTime(frequency, ctx.currentTime);
106
- gainNode.gain.setValueAtTime(0, ctx.currentTime);
107
- gainNode.gain.linearRampToValueAtTime(volume, ctx.currentTime + 0.015);
108
- gainNode.gain.linearRampToValueAtTime(0, ctx.currentTime + duration / 1e3);
109
- oscillator.start(ctx.currentTime);
110
- oscillator.stop(ctx.currentTime + duration / 1e3 + 0.02);
111
- }
112
- function getFrequencyForPace(pace) {
113
- if (pace === "activated") return FEEDBACK_FREQUENCIES.high;
114
- if (pace === "calm") return FEEDBACK_FREQUENCIES.low;
115
- return FEEDBACK_FREQUENCIES.mid;
116
- }
117
- function playPacedSonic(pace, duration) {
118
- playSonicFeedback(getFrequencyForPace(pace), duration);
119
- }
120
-
121
- // lib/capacity/fields/field-manager.ts
122
- function deriveEnergyField(capacity) {
123
- const { cognitive, temporal, emotional } = capacity;
124
- return Math.pow(cognitive * temporal * emotional, 1 / 3);
125
- }
126
- function deriveAttentionField(capacity) {
127
- return 1 - capacity.temporal * 0.5;
128
- }
129
- function deriveEmotionalValenceField(state) {
130
- return state.valence;
131
- }
132
- function createFieldValue(value, previousValue) {
133
- var _a;
134
- const now = Date.now();
135
- const lastChange = (_a = previousValue == null ? void 0 : previousValue.lastChange) != null ? _a : now;
136
- const timeDelta = (now - lastChange) / 1e3;
137
- let trend = "stable";
138
- let velocity;
139
- if (typeof value === "number" && previousValue && typeof previousValue.value === "number") {
140
- const valueDelta = value - previousValue.value;
141
- velocity = timeDelta > 0 ? valueDelta / timeDelta : 0;
142
- if (Math.abs(velocity) > DEFAULT_FIELD_CONFIG.velocityThreshold) {
143
- trend = velocity > 0 ? "rising" : "falling";
144
- }
145
- }
146
- return {
147
- value,
148
- lastChange: now,
149
- trend,
150
- velocity
151
- };
152
- }
153
- var FieldManagerClass = class {
154
- constructor() {
155
- this.listeners = /* @__PURE__ */ new Set();
156
- this.config = DEFAULT_FIELD_CONFIG;
157
- const initialCapacity = DEFAULT_USER_CAPACITY;
158
- const initialState = DEFAULT_EMOTIONAL_STATE;
159
- this.context = {
160
- energy: createFieldValue(deriveEnergyField(initialCapacity)),
161
- attention: createFieldValue(deriveAttentionField(initialCapacity)),
162
- emotionalValence: createFieldValue(deriveEmotionalValenceField(initialState)),
163
- userCapacity: initialCapacity,
164
- emotionalState: initialState
165
- };
166
- }
167
- /**
168
- * Get current ambient context (read-only)
169
- */
170
- getContext() {
171
- return this.context;
172
- }
173
- /**
174
- * Update user capacity (Phase 1 slider system writes here)
175
- */
176
- updateCapacity(capacity) {
177
- const newCapacity = __spreadValues(__spreadValues({}, this.context.userCapacity), capacity);
178
- this.context = __spreadProps(__spreadValues({}, this.context), {
179
- userCapacity: newCapacity,
180
- energy: createFieldValue(deriveEnergyField(newCapacity), this.context.energy),
181
- attention: createFieldValue(deriveAttentionField(newCapacity), this.context.attention)
182
- });
183
- this.notifyListeners();
184
- }
185
- /**
186
- * Update emotional state (Phase 1 slider system writes here)
187
- */
188
- updateEmotionalState(state) {
189
- const newState = __spreadValues(__spreadValues({}, this.context.emotionalState), state);
190
- this.context = __spreadProps(__spreadValues({}, this.context), {
191
- emotionalState: newState,
192
- emotionalValence: createFieldValue(deriveEmotionalValenceField(newState), this.context.emotionalValence)
193
- });
194
- this.notifyListeners();
195
- }
196
- /**
197
- * Subscribe to field changes
198
- */
199
- subscribe(listener) {
200
- this.listeners.add(listener);
201
- return () => {
202
- this.listeners.delete(listener);
203
- };
204
- }
205
- /**
206
- * Notify all listeners of field changes
207
- */
208
- notifyListeners() {
209
- this.listeners.forEach((listener) => {
210
- try {
211
- listener(this.context);
212
- } catch (error) {
213
- console.error("[v0] Field listener error:", error);
214
- }
215
- });
216
- }
217
- /**
218
- * Update field configuration
219
- */
220
- updateConfig(config) {
221
- this.config = __spreadValues(__spreadValues({}, this.config), config);
222
- }
223
- /**
224
- * Get current field configuration
225
- */
226
- getConfig() {
227
- return this.config;
228
- }
229
- };
230
- new FieldManagerClass();
231
-
232
- // lib/capacity/mode.ts
233
- function deriveMode(field) {
234
- var _a;
235
- const lowCognitive = field.cognitive < 0.4;
236
- const highCognitive = field.cognitive > 0.7;
237
- const lowEmotional = field.emotional < 0.4;
238
- const highEmotional = field.emotional > 0.6;
239
- const lowTemporal = field.temporal < 0.4;
240
- const highValence = field.valence > 0.15;
241
- const negValence = field.valence < -0.15;
242
- const density = lowCognitive ? "low" : highCognitive ? "high" : "medium";
243
- const choiceLoad = lowTemporal ? "minimal" : "normal";
244
- const guidance = lowCognitive ? "high" : lowTemporal ? "medium" : "low";
245
- const veryLowEmotional = field.emotional < 0.15;
246
- const motion2 = veryLowEmotional ? "off" : lowEmotional ? "soothing" : highEmotional && highValence ? "expressive" : "subtle";
247
- const contrast = negValence ? "boosted" : "standard";
248
- const focus = motion2 === "off" ? "default" : lowCognitive ? "guided" : !highCognitive ? "gentle" : "default";
249
- const arousal = (_a = field.arousal) != null ? _a : 0.5;
250
- const pace = arousal < 0.35 ? "calm" : arousal > 0.65 ? "activated" : "neutral";
251
- return { density, guidance, motion: motion2, contrast, choiceLoad, focus, pace };
252
- }
253
- function deriveModeLabel(inputs) {
254
- const { cognitive, temporal, emotional } = inputs;
255
- if (cognitive > 0.6 && emotional > 0.6) {
256
- return "Exploratory";
257
- }
258
- if (cognitive < 0.4 && temporal < 0.4) {
259
- return "Minimal";
260
- }
261
- if (cognitive >= 0.55 && temporal >= 0.55) {
262
- return "Focused";
263
- }
264
- return "Calm";
265
- }
266
- function getModeBadgeColor(label) {
267
- switch (label) {
268
- case "Calm":
269
- return "oklch(0.65 0.15 220)";
270
- // Soft blue
271
- case "Focused":
272
- return "oklch(0.68 0.16 45)";
273
- // Primary rust
274
- case "Exploratory":
275
- return "oklch(0.65 0.2 135)";
276
- // Toxic green
277
- case "Minimal":
278
- return "oklch(0.55 0.1 280)";
279
- // Muted purple
280
- default:
281
- return "oklch(0.5 0 0)";
282
- }
283
- }
284
- var CapacityContext = react.createContext(null);
285
- function useCapacityContext() {
286
- const context = react.useContext(CapacityContext);
287
- if (!context) {
288
- throw new Error("useCapacityContext must be used within CapacityProvider");
289
- }
290
- return context;
291
- }
292
- function useEnergyField() {
293
- const { context } = useCapacityContext();
294
- return context.energy;
295
- }
296
- function useAttentionField() {
297
- const { context } = useCapacityContext();
298
- return context.attention;
299
- }
300
- function useEmotionalValenceField() {
301
- const { context } = useCapacityContext();
302
- return context.emotionalValence;
303
- }
304
- function useDerivedMode() {
305
- const { context } = useCapacityContext();
306
- const field = {
307
- cognitive: context.userCapacity.cognitive,
308
- temporal: context.userCapacity.temporal,
309
- emotional: context.userCapacity.emotional,
310
- valence: context.emotionalState.valence,
311
- arousal: context.emotionalState.arousal
312
- };
313
- const mode = deriveMode(field);
314
- return { field, mode };
315
- }
316
- function useFeedback() {
317
- const { hapticEnabled, sonicEnabled, setHapticEnabled, setSonicEnabled } = useCapacityContext();
318
- const { mode } = useDerivedMode();
319
- const fire = react.useCallback((pattern = "tap") => {
320
- if (hapticEnabled) triggerHaptic(pattern);
321
- if (sonicEnabled) playPacedSonic(mode.pace);
322
- }, [hapticEnabled, sonicEnabled, mode.pace]);
323
- return { hapticEnabled, sonicEnabled, setHapticEnabled, setSonicEnabled, fire };
324
- }
325
-
326
- // lib/capacity/animation.ts
327
- var ENTRANCE_PRESETS = {
328
- /** Liquid organic morph -> gentle scale fade -> soft bloom -> none */
329
- morph: { expressive: "morph-fade-in", subtle: "sacred-fade", soothing: "bloom", off: "" },
330
- /** Spinning vortex -> gentle scale fade -> soft bloom -> none */
331
- vortex: { expressive: "vortex-reveal", subtle: "sacred-fade", soothing: "bloom", off: "" },
332
- /** Spiral in from corner -> soft bloom -> soft bloom -> none */
333
- spiral: { expressive: "spiral-in", subtle: "bloom", soothing: "bloom", off: "" }
334
- };
335
- function entranceClass(motion2, preset, hasPlayed) {
336
- return ENTRANCE_PRESETS[preset][motion2];
337
- }
338
- function hoverClass(motion2) {
339
- if (motion2 === "expressive") return "hover-expand";
340
- if (motion2 === "subtle" || motion2 === "soothing") return "hover-lift";
341
- return "";
342
- }
343
- function ambientClass(motion2, type) {
344
- if (motion2 === "expressive") return type;
345
- if (motion2 === "soothing" && (type === "breathe" || type === "float")) return type;
346
- return "";
347
- }
348
- function listItemClass(motion2) {
349
- if (motion2 === "expressive") return "helix-rise";
350
- if (motion2 === "subtle" || motion2 === "soothing") return "sacred-fade";
351
- return "";
352
- }
353
40
  var SLIDER_STYLES = `
354
41
  [data-renge-slider] {
355
42
  -webkit-appearance: none;
@@ -995,14 +682,14 @@ var DEFAULT_CALM_STATE = {
995
682
  function CapacityControls() {
996
683
  var _a;
997
684
  const [isOpen, setIsOpen] = react.useState(false);
998
- const { updateCapacity, updateEmotionalState, isAutoMode, toggleAutoMode } = useCapacityContext();
999
- const { hapticEnabled, sonicEnabled, setHapticEnabled, setSonicEnabled, fire: fireFeedback } = useFeedback();
1000
- const { field, mode } = useDerivedMode();
1001
- const energy = useEnergyField();
1002
- const attention = useAttentionField();
1003
- const valence = useEmotionalValenceField();
1004
- const modeLabel = deriveModeLabel(field);
1005
- const modeBadgeColor = getModeBadgeColor(modeLabel);
685
+ const { updateCapacity, updateEmotionalState, isAutoMode, toggleAutoMode, conflicts } = ui.useCapacityContext();
686
+ const { hapticEnabled, sonicEnabled, setHapticEnabled, setSonicEnabled, fire: fireFeedback } = ui.useFeedback();
687
+ const { field, mode } = ui.useDerivedMode();
688
+ const energy = ui.useEnergyField();
689
+ const attention = ui.useAttentionField();
690
+ const valence = ui.useEmotionalValenceField();
691
+ const modeLabel = ui.deriveModeLabel(field);
692
+ const modeBadgeColor = ui.getModeBadgeColor(modeLabel);
1006
693
  const handleReset = () => {
1007
694
  updateCapacity({
1008
695
  cognitive: DEFAULT_CALM_STATE.cognitive,
@@ -1018,262 +705,266 @@ function CapacityControls() {
1018
705
  fireFeedback("tap");
1019
706
  }, [fireFeedback]);
1020
707
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed bottom-4 right-4 z-50", children: [
1021
- /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: !isOpen && /* @__PURE__ */ jsxRuntime.jsxs(
1022
- react$1.motion.div,
1023
- {
1024
- initial: { opacity: 0, scale: 0.8 },
1025
- animate: { opacity: 1, scale: 1 },
1026
- exit: { opacity: 0, scale: 0.8 },
1027
- className: "flex items-center gap-2",
1028
- children: [
1029
- /* @__PURE__ */ jsxRuntime.jsx(
1030
- Badge,
1031
- {
1032
- className: "shadow-lg",
1033
- style: { backgroundColor: modeBadgeColor, color: "white" },
1034
- children: modeLabel
1035
- }
1036
- ),
1037
- /* @__PURE__ */ jsxRuntime.jsxs(
1038
- Button,
1039
- {
1040
- onClick: () => setIsOpen(true),
1041
- variant: "outline",
1042
- size: "sm",
1043
- className: "shadow-lg bg-background",
1044
- children: [
1045
- /* @__PURE__ */ jsxRuntime.jsx(SettingsIcon, { className: "w-4 h-4 mr-2" }),
1046
- "Capacity"
1047
- ]
1048
- }
1049
- )
1050
- ]
1051
- }
1052
- ) }),
1053
- /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxRuntime.jsx(
1054
- react$1.motion.div,
708
+ !isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
709
+ /* @__PURE__ */ jsxRuntime.jsx(
710
+ Badge,
711
+ {
712
+ className: "shadow-lg",
713
+ style: { backgroundColor: modeBadgeColor, color: "white" },
714
+ children: modeLabel
715
+ }
716
+ ),
717
+ /* @__PURE__ */ jsxRuntime.jsxs(
718
+ Button,
719
+ {
720
+ onClick: () => setIsOpen(true),
721
+ variant: "outline",
722
+ size: "sm",
723
+ className: "shadow-lg bg-background",
724
+ children: [
725
+ /* @__PURE__ */ jsxRuntime.jsx(SettingsIcon, { className: "w-4 h-4 mr-2" }),
726
+ "Capacity"
727
+ ]
728
+ }
729
+ )
730
+ ] }),
731
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx(
732
+ "div",
1055
733
  {
1056
- initial: { opacity: 0 },
1057
- animate: { opacity: 1 },
1058
- exit: { opacity: 0 },
1059
734
  className: "fixed inset-0 bg-black/20 backdrop-blur-sm md:hidden",
1060
735
  onClick: () => setIsOpen(false),
1061
736
  "aria-hidden": "true"
1062
737
  }
1063
- ) }),
1064
- /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxRuntime.jsx(
1065
- react$1.motion.div,
1066
- {
1067
- initial: { opacity: 0, y: 20, scale: 0.95 },
1068
- animate: { opacity: 1, y: 0, scale: 1 },
1069
- exit: { opacity: 0, y: 20, scale: 0.95 },
1070
- transition: { type: "spring", damping: 20, stiffness: 300 },
1071
- className: "relative",
1072
- children: /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "w-80 shadow-xl max-h-[85vh] overflow-y-auto", children: [
1073
- /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "pb-3", children: [
1074
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
1075
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1076
- /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-sm font-semibold", children: "Capacity Controls" }),
1077
- /* @__PURE__ */ jsxRuntime.jsx(
1078
- Button,
1079
- {
1080
- variant: "ghost",
1081
- size: "icon",
1082
- className: "h-8 w-8 shrink-0",
1083
- onClick: (e) => {
1084
- e.stopPropagation();
1085
- setIsOpen(false);
1086
- },
1087
- "aria-label": "Close capacity controls",
1088
- children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "w-4 h-4" })
1089
- }
1090
- )
1091
- ] }),
1092
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1093
- /* @__PURE__ */ jsxRuntime.jsx(
1094
- Badge,
1095
- {
1096
- className: "text-xs",
1097
- style: { backgroundColor: modeBadgeColor, color: "white" },
1098
- children: modeLabel
1099
- }
1100
- ),
1101
- /* @__PURE__ */ jsxRuntime.jsx(
1102
- Button,
1103
- {
1104
- variant: isAutoMode ? "default" : "outline",
1105
- size: "sm",
1106
- className: "h-7 text-xs px-2",
1107
- onClick: toggleAutoMode,
1108
- "aria-label": isAutoMode ? "Switch to manual mode" : "Switch to auto mode",
1109
- children: isAutoMode ? "Auto" : "Manual"
1110
- }
1111
- )
1112
- ] })
1113
- ] }),
1114
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: isAutoMode ? "Signals are driving values automatically. Move any slider to take manual control." : "Adjust your state to see the UI adapt in real-time." })
1115
- ] }),
1116
- /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "space-y-6", children: [
1117
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 flex flex-col gap-2", children: [
1118
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Quick Presets" }),
1119
- /* @__PURE__ */ jsxRuntime.jsxs(
1120
- Select,
1121
- {
1122
- defaultValue: "",
1123
- onValueChange: (value) => {
1124
- if (!value) return;
1125
- const preset = CAPACITY_PRESETS[value];
1126
- updateCapacity({
1127
- cognitive: preset.cognitive,
1128
- temporal: preset.temporal,
1129
- emotional: preset.emotional
1130
- });
1131
- updateEmotionalState({ valence: preset.valence, arousal: preset.arousal });
1132
- fireInteractionFeedback();
1133
- },
1134
- children: [
1135
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select a preset..." }),
1136
- Object.entries(CAPACITY_PRESETS).map(([key, preset]) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: key, children: [
1137
- preset.label,
1138
- " \u2014 ",
1139
- preset.description
1140
- ] }, key))
1141
- ]
1142
- }
1143
- )
1144
- ] }),
1145
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-t border-border pt-4", children: [
1146
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Or adjust individually:" }),
1147
- /* @__PURE__ */ jsxRuntime.jsxs(
1148
- Button,
1149
- {
1150
- variant: "ghost",
1151
- size: "sm",
1152
- onClick: handleReset,
1153
- className: "h-7 text-xs text-muted-foreground hover:text-foreground",
1154
- children: [
1155
- /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, { className: "w-3 h-3 mr-1" }),
1156
- "Reset"
1157
- ]
1158
- }
1159
- )
1160
- ] }),
738
+ ),
739
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "w-80 shadow-xl max-h-[85vh] overflow-y-auto", children: [
740
+ /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "pb-3", children: [
741
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
742
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
743
+ /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-sm font-semibold", children: "Capacity Controls" }),
1161
744
  /* @__PURE__ */ jsxRuntime.jsx(
1162
- SliderControl,
745
+ Button,
1163
746
  {
1164
- label: "Cognitive Capacity",
1165
- description: "Controls: density, hierarchy, concurrency",
1166
- value: field.cognitive,
1167
- onChange: (v) => updateCapacity({ cognitive: v }),
1168
- lowLabel: "Fewer items",
1169
- highLabel: "More items"
747
+ variant: "ghost",
748
+ size: "icon",
749
+ className: "h-8 w-8 shrink-0",
750
+ onClick: (e) => {
751
+ e.stopPropagation();
752
+ setIsOpen(false);
753
+ },
754
+ "aria-label": "Close capacity controls",
755
+ children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "w-4 h-4" })
1170
756
  }
1171
- ),
757
+ )
758
+ ] }),
759
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1172
760
  /* @__PURE__ */ jsxRuntime.jsx(
1173
- SliderControl,
761
+ Badge,
1174
762
  {
1175
- label: "Temporal Capacity",
1176
- description: "Controls: content length, shortcuts, defaults",
1177
- value: field.temporal,
1178
- onChange: (v) => updateCapacity({ temporal: v }),
1179
- lowLabel: "Abbreviated",
1180
- highLabel: "Full detail"
763
+ className: "text-xs",
764
+ style: { backgroundColor: modeBadgeColor, color: "white" },
765
+ children: modeLabel
1181
766
  }
1182
767
  ),
1183
768
  /* @__PURE__ */ jsxRuntime.jsx(
1184
- SliderControl,
769
+ Button,
1185
770
  {
1186
- label: "Emotional Capacity",
1187
- description: "Controls: motion restraint, friction",
1188
- value: field.emotional,
1189
- onChange: (v) => updateCapacity({ emotional: v }),
1190
- lowLabel: "Calm UI",
1191
- highLabel: "Expressive"
771
+ variant: isAutoMode ? "default" : "outline",
772
+ size: "sm",
773
+ className: "h-7 text-xs px-2",
774
+ onClick: toggleAutoMode,
775
+ "aria-label": isAutoMode ? "Switch to manual mode" : "Switch to auto mode",
776
+ children: isAutoMode ? "Auto" : "Manual"
1192
777
  }
1193
- ),
1194
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-2 border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
1195
- ValenceSliderControl,
778
+ )
779
+ ] })
780
+ ] }),
781
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: isAutoMode ? "Signals are driving values automatically. Move any slider to take manual control." : "Adjust your state to see the UI adapt in real-time." })
782
+ ] }),
783
+ /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "space-y-6", children: [
784
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 flex flex-col gap-2", children: [
785
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Quick Presets" }),
786
+ /* @__PURE__ */ jsxRuntime.jsxs(
787
+ Select,
788
+ {
789
+ defaultValue: "",
790
+ onValueChange: (value) => {
791
+ if (!value) return;
792
+ const preset = CAPACITY_PRESETS[value];
793
+ updateCapacity({
794
+ cognitive: preset.cognitive,
795
+ temporal: preset.temporal,
796
+ emotional: preset.emotional
797
+ });
798
+ updateEmotionalState({ valence: preset.valence, arousal: preset.arousal });
799
+ fireInteractionFeedback();
800
+ },
801
+ children: [
802
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select a preset..." }),
803
+ Object.entries(CAPACITY_PRESETS).map(([key, preset]) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: key, children: [
804
+ preset.label,
805
+ " \u2014 ",
806
+ preset.description
807
+ ] }, key))
808
+ ]
809
+ }
810
+ )
811
+ ] }),
812
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-t border-border pt-4", children: [
813
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Or adjust individually:" }),
814
+ /* @__PURE__ */ jsxRuntime.jsxs(
815
+ Button,
816
+ {
817
+ variant: "ghost",
818
+ size: "sm",
819
+ onClick: handleReset,
820
+ className: "h-7 text-xs text-muted-foreground hover:text-foreground",
821
+ children: [
822
+ /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, { className: "w-3 h-3 mr-1" }),
823
+ "Reset"
824
+ ]
825
+ }
826
+ )
827
+ ] }),
828
+ /* @__PURE__ */ jsxRuntime.jsx(
829
+ SliderControl,
830
+ {
831
+ label: "Cognitive Capacity",
832
+ description: "Controls: density, hierarchy, concurrency",
833
+ value: field.cognitive,
834
+ onChange: (v) => updateCapacity({ cognitive: v }),
835
+ lowLabel: "Fewer items",
836
+ highLabel: "More items"
837
+ }
838
+ ),
839
+ /* @__PURE__ */ jsxRuntime.jsx(
840
+ SliderControl,
841
+ {
842
+ label: "Temporal Capacity",
843
+ description: "Controls: content length, shortcuts, defaults",
844
+ value: field.temporal,
845
+ onChange: (v) => updateCapacity({ temporal: v }),
846
+ lowLabel: "Abbreviated",
847
+ highLabel: "Full detail"
848
+ }
849
+ ),
850
+ /* @__PURE__ */ jsxRuntime.jsx(
851
+ SliderControl,
852
+ {
853
+ label: "Emotional Capacity",
854
+ description: "Controls: motion restraint, friction",
855
+ value: field.emotional,
856
+ onChange: (v) => updateCapacity({ emotional: v }),
857
+ lowLabel: "Calm UI",
858
+ highLabel: "Expressive"
859
+ }
860
+ ),
861
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-2 border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
862
+ ValenceSliderControl,
863
+ {
864
+ label: "Emotional Valence",
865
+ description: "Controls: tone, expressiveness (not info volume)",
866
+ value: field.valence,
867
+ onChange: (v) => updateEmotionalState({ valence: v })
868
+ }
869
+ ) }),
870
+ /* @__PURE__ */ jsxRuntime.jsx(
871
+ SliderControl,
872
+ {
873
+ label: "Arousal",
874
+ description: "Controls: animation pacing (calm \u2192 activated)",
875
+ value: (_a = field.arousal) != null ? _a : 0.5,
876
+ onChange: (v) => updateEmotionalState({ arousal: v }),
877
+ lowLabel: "Calm",
878
+ highLabel: "Activated"
879
+ }
880
+ ),
881
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-2 border-t border-border space-y-2", children: [
882
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs font-medium text-muted-foreground", children: [
883
+ "Feedback ",
884
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-normal opacity-60", children: "(opt-in)" })
885
+ ] }),
886
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
887
+ /* @__PURE__ */ jsxRuntime.jsx(
888
+ "button",
1196
889
  {
1197
- label: "Emotional Valence",
1198
- description: "Controls: tone, expressiveness (not info volume)",
1199
- value: field.valence,
1200
- onChange: (v) => updateEmotionalState({ valence: v })
890
+ onClick: () => setHapticEnabled((v) => !v),
891
+ className: `flex-1 py-1.5 px-2 rounded-md text-xs border transition-colors ${hapticEnabled ? "bg-primary/10 border-primary/50 text-primary" : "border-border text-muted-foreground hover:text-foreground"}`,
892
+ "aria-pressed": hapticEnabled,
893
+ children: "\u{1F4F3} Haptic"
1201
894
  }
1202
- ) }),
895
+ ),
1203
896
  /* @__PURE__ */ jsxRuntime.jsx(
1204
- SliderControl,
897
+ "button",
1205
898
  {
1206
- label: "Arousal",
1207
- description: "Controls: animation pacing (calm \u2192 activated)",
1208
- value: (_a = field.arousal) != null ? _a : 0.5,
1209
- onChange: (v) => updateEmotionalState({ arousal: v }),
1210
- lowLabel: "Calm",
1211
- highLabel: "Activated"
899
+ onClick: () => setSonicEnabled((v) => !v),
900
+ className: `flex-1 py-1.5 px-2 rounded-md text-xs border transition-colors ${sonicEnabled ? "bg-primary/10 border-primary/50 text-primary" : "border-border text-muted-foreground hover:text-foreground"}`,
901
+ "aria-pressed": sonicEnabled,
902
+ children: "\u{1F514} Sonic"
1212
903
  }
1213
- ),
1214
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-2 border-t border-border space-y-2", children: [
1215
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs font-medium text-muted-foreground", children: [
1216
- "Feedback ",
1217
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-normal opacity-60", children: "(opt-in)" })
1218
- ] }),
1219
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
1220
- /* @__PURE__ */ jsxRuntime.jsx(
1221
- "button",
1222
- {
1223
- onClick: () => setHapticEnabled((v) => !v),
1224
- className: `flex-1 py-1.5 px-2 rounded-md text-xs border transition-colors ${hapticEnabled ? "bg-primary/10 border-primary/50 text-primary" : "border-border text-muted-foreground hover:text-foreground"}`,
1225
- "aria-pressed": hapticEnabled,
1226
- children: "\u{1F4F3} Haptic"
1227
- }
1228
- ),
1229
- /* @__PURE__ */ jsxRuntime.jsx(
1230
- "button",
1231
- {
1232
- onClick: () => setSonicEnabled((v) => !v),
1233
- className: `flex-1 py-1.5 px-2 rounded-md text-xs border transition-colors ${sonicEnabled ? "bg-primary/10 border-primary/50 text-primary" : "border-border text-muted-foreground hover:text-foreground"}`,
1234
- "aria-pressed": sonicEnabled,
1235
- children: "\u{1F514} Sonic"
1236
- }
1237
- )
1238
- ] }),
1239
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[10px] text-muted-foreground opacity-60", children: [
1240
- "Pace: ",
1241
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.pace }),
1242
- " \u2192 ",
1243
- mode.pace === "calm" ? "+50% duration" : mode.pace === "activated" ? "\u221235% duration" : "standard"
1244
- ] })
1245
- ] }),
1246
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-4 border-t border-border", children: [
1247
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Derived Fields" }),
1248
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-2 text-center", children: [
1249
- /* @__PURE__ */ jsxRuntime.jsx(FieldDisplay, { label: "Energy", value: energy.value, color: "text-chart-1" }),
1250
- /* @__PURE__ */ jsxRuntime.jsx(FieldDisplay, { label: "Attention", value: attention.value, color: "text-chart-2" }),
1251
- /* @__PURE__ */ jsxRuntime.jsx(FieldDisplay, { label: "Valence", value: valence.value, color: "text-chart-3", signed: true })
1252
- ] })
1253
- ] }),
1254
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-4 border-t border-border", children: [
1255
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Interface Mode" }),
1256
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-1 text-xs", children: [
1257
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Density:" }),
1258
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.density }),
1259
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Guidance:" }),
1260
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.guidance }),
1261
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Motion:" }),
1262
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.motion }),
1263
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Contrast:" }),
1264
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.contrast }),
1265
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Choices:" }),
1266
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.choiceLoad }),
1267
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Focus:" }),
1268
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.focus }),
1269
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Pace:" }),
1270
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.pace })
1271
- ] })
904
+ )
905
+ ] }),
906
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[10px] text-muted-foreground opacity-60", children: [
907
+ "Pace: ",
908
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.pace }),
909
+ " \u2192 ",
910
+ mode.pace === "calm" ? "+50% duration" : mode.pace === "activated" ? "\u221235% duration" : "standard"
911
+ ] })
912
+ ] }),
913
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-4 border-t border-border", children: [
914
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Derived Fields" }),
915
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-2 text-center", children: [
916
+ /* @__PURE__ */ jsxRuntime.jsx(FieldDisplay, { label: "Energy", value: energy.value, color: "text-chart-1" }),
917
+ /* @__PURE__ */ jsxRuntime.jsx(FieldDisplay, { label: "Attention", value: attention.value, color: "text-chart-2" }),
918
+ /* @__PURE__ */ jsxRuntime.jsx(FieldDisplay, { label: "Valence", value: valence.value, color: "text-chart-3", signed: true })
919
+ ] })
920
+ ] }),
921
+ conflicts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-4 border-t border-border space-y-2", children: [
922
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs font-medium text-muted-foreground", children: [
923
+ "Conflicts ",
924
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-normal opacity-60", children: [
925
+ "(",
926
+ conflicts.length,
927
+ ")"
1272
928
  ] })
929
+ ] }),
930
+ conflicts.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
931
+ "div",
932
+ {
933
+ className: `rounded-md p-2 text-xs space-y-1 ${c.severity === "warning" ? "bg-warning/10 border border-warning/30 text-warning-content" : "bg-muted/60 border border-border text-muted-foreground"}`,
934
+ children: [
935
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: c.label }),
936
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "opacity-80 leading-snug", children: c.message }),
937
+ c.suggestion && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "opacity-60 italic", children: c.suggestion }),
938
+ c.affectedTokens.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "opacity-50", children: [
939
+ "Affects: ",
940
+ c.affectedTokens.join(", ")
941
+ ] })
942
+ ]
943
+ },
944
+ c.id
945
+ ))
946
+ ] }),
947
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-4 border-t border-border", children: [
948
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Interface Mode" }),
949
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-1 text-xs", children: [
950
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Density:" }),
951
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.density }),
952
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Guidance:" }),
953
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.guidance }),
954
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Motion:" }),
955
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.motion }),
956
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Contrast:" }),
957
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.contrast }),
958
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Choices:" }),
959
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.choiceLoad }),
960
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Focus:" }),
961
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.focus }),
962
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Pace:" }),
963
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: mode.pace })
1273
964
  ] })
1274
965
  ] })
1275
- }
1276
- ) })
966
+ ] })
967
+ ] }) })
1277
968
  ] });
1278
969
  }
1279
970
  function SliderControl({
@@ -1404,16 +1095,16 @@ var TONE = {
1404
1095
  }
1405
1096
  };
1406
1097
  function CapacityDemoCard() {
1407
- const { field, mode } = useDerivedMode();
1408
- const { fire } = useFeedback();
1409
- const modeLabel = deriveModeLabel(field);
1410
- const modeBadgeColor = getModeBadgeColor(modeLabel);
1098
+ const { field, mode } = ui.useDerivedMode();
1099
+ const { fire } = ui.useFeedback();
1100
+ const modeLabel = ui.deriveModeLabel(field);
1101
+ const modeBadgeColor = ui.getModeBadgeColor(modeLabel);
1411
1102
  const densityContent = DENSITY_CONTENT[mode.density];
1412
1103
  const temporalContent = field.temporal > 0.4 ? TEMPORAL_CONTENT.full : TEMPORAL_CONTENT.abbreviated;
1413
1104
  const toneKey = field.valence > 0.2 ? "positive" : field.valence < -0.2 ? "negative" : "neutral";
1414
1105
  const tone = TONE[toneKey];
1415
- const entrance = entranceClass(mode.motion, "morph");
1416
- const hover = hoverClass(mode.motion);
1106
+ const entrance = ui.entranceClass(mode.motion, "morph", false);
1107
+ const hover = ui.hoverClass(mode.motion);
1417
1108
  const visibleFeatures = temporalContent.features.slice(0, densityContent.featureCount);
1418
1109
  return /* @__PURE__ */ jsxRuntime.jsxs(
1419
1110
  Card,
@@ -1436,14 +1127,14 @@ function CapacityDemoCard() {
1436
1127
  ),
1437
1128
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs ${tone.accent}`, children: tone.greeting })
1438
1129
  ] }),
1439
- /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: ambientClass(mode.motion, "float"), children: densityContent.title }),
1130
+ /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: ui.ambientClass(mode.motion, "float"), children: densityContent.title }),
1440
1131
  mode.density !== "low" && /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: temporalContent.description })
1441
1132
  ] }),
1442
1133
  /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "space-y-4", children: [
1443
1134
  visibleFeatures.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-2", children: visibleFeatures.map((feature, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
1444
1135
  "li",
1445
1136
  {
1446
- className: `flex items-start gap-2 text-sm text-muted-foreground ${listItemClass(mode.motion)}`,
1137
+ className: `flex items-start gap-2 text-sm text-muted-foreground ${ui.listItemClass(mode.motion)}`,
1447
1138
  style: { animationDelay: `${idx * 0.15}s` },
1448
1139
  children: [
1449
1140
  /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "w-4 h-4 text-primary shrink-0 mt-0.5" }),
@@ -1457,7 +1148,7 @@ function CapacityDemoCard() {
1457
1148
  /* @__PURE__ */ jsxRuntime.jsx(
1458
1149
  "button",
1459
1150
  {
1460
- className: `${mode.choiceLoad === "normal" ? "flex-1" : "w-full"} py-2 px-4 rounded-md bg-primary text-primary-foreground font-medium text-sm transition-transform ${hover} ${ambientClass(mode.motion, "breathe")}`,
1151
+ className: `${mode.choiceLoad === "normal" ? "flex-1" : "w-full"} py-2 px-4 rounded-md bg-primary text-primary-foreground font-medium text-sm transition-transform ${hover} ${ui.ambientClass(mode.motion, "breathe")}`,
1461
1152
  onClick: () => fire("tap"),
1462
1153
  children: densityContent.cta
1463
1154
  }
@@ -1529,9 +1220,9 @@ function AmbientFieldMonitor() {
1529
1220
  ] });
1530
1221
  }
1531
1222
  function InputsToModeFlow() {
1532
- const { field, mode } = useDerivedMode();
1533
- const label = deriveModeLabel(field);
1534
- const badgeColor = getModeBadgeColor(label);
1223
+ const { field, mode } = ui.useDerivedMode();
1224
+ const label = ui.deriveModeLabel(field);
1225
+ const badgeColor = ui.getModeBadgeColor(label);
1535
1226
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "overflow-hidden border-border/50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid lg:grid-cols-3 divide-y lg:divide-y-0 lg:divide-x divide-border/50", children: [
1536
1227
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-4", children: [
1537
1228
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: [