@almadar/ui 1.0.21 → 1.0.22

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,10 +1,21 @@
1
- export { DesignThemeProvider, useDesignTheme } from '../chunk-4FRUCUO5.js';
2
- export { BUILT_IN_THEMES, ThemeContext_default as ThemeContext, ThemeProvider, UISlotContext, UISlotProvider, useSlotContent, useSlotHasContent, useTheme, useUISlots } from '../chunk-I5RSZIOE.js';
1
+ export { UISlotContext, UISlotProvider, useSlotContent, useSlotHasContent, useUISlots } from '../chunk-W5YTXLXL.js';
3
2
  import '../chunk-7NEWMNNU.js';
3
+ import { ThemeProvider, useTheme } from '../chunk-4UFNDD6B.js';
4
+ export { BUILT_IN_THEMES, ThemeContext_default as ThemeContext, ThemeProvider, useTheme } from '../chunk-4UFNDD6B.js';
4
5
  import '../chunk-PKBMQBKP.js';
5
6
  import { createContext, useCallback, useMemo, useContext } from 'react';
6
7
  import { jsx } from 'react/jsx-runtime';
7
8
 
9
+ // context/DesignThemeContext.tsx
10
+ var DesignThemeProvider = ThemeProvider;
11
+ function useDesignTheme() {
12
+ const { theme, setTheme, availableThemes } = useTheme();
13
+ return {
14
+ designTheme: theme,
15
+ setDesignTheme: setTheme,
16
+ availableThemes: availableThemes.map((t) => t.name)
17
+ };
18
+ }
8
19
  var ANONYMOUS_USER = {
9
20
  id: "anonymous",
10
21
  role: "anonymous",
@@ -104,4 +115,4 @@ function useUserForEvaluation() {
104
115
  return isLoggedIn && user ? user : void 0;
105
116
  }
106
117
 
107
- export { ANONYMOUS_USER, UserContext, UserProvider, useHasPermission, useHasRole, useUser, useUserForEvaluation };
118
+ export { ANONYMOUS_USER, DesignThemeProvider, UserContext, UserProvider, useDesignTheme, useHasPermission, useHasRole, useUser, useUserForEvaluation };
@@ -2,9 +2,81 @@ import { OrbitalSchema } from '@almadar/core';
2
2
  import { E as EventBusContextType, a as EventListener } from '../event-bus-types-8-cjyMxw.js';
3
3
  export { K as KFlowEvent, U as Unsubscribe } from '../event-bus-types-8-cjyMxw.js';
4
4
  export { D as DEFAULT_SLOTS, R as RenderUIConfig, b as SlotAnimation, c as SlotChangeCallback, S as SlotContent, a as UISlot, U as UISlotManager, u as useUISlotManager } from '../useUISlots-mnggE9X9.js';
5
+ import React__default, { ReactNode } from 'react';
5
6
  import * as _tanstack_react_query from '@tanstack/react-query';
6
7
  import { Entity, getEntity, getByType, getAllEntities, getSingleton, spawnEntity, updateEntity, updateSingleton, removeEntity, clearEntities } from '../stores/index.js';
7
8
 
9
+ /**
10
+ * useEventBus Hook
11
+ *
12
+ * Provides event bus utilities for component communication.
13
+ * This connects to the EventBusProvider for real applications
14
+ * or provides a simple in-memory bus for design system / Storybook.
15
+ *
16
+ * @packageDocumentation
17
+ */
18
+
19
+ declare global {
20
+ interface Window {
21
+ __kflowEventBus?: EventBusContextType | null;
22
+ }
23
+ }
24
+ /**
25
+ * Hook for accessing the event bus.
26
+ *
27
+ * Uses EventBusProvider context if available, otherwise falls back to
28
+ * a simple in-memory event bus (for design system / Storybook).
29
+ *
30
+ * @returns Event bus instance with emit, on, once, and hasListeners methods
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * const eventBus = useEventBus();
35
+ *
36
+ * // Emit an event
37
+ * eventBus.emit('UI:CLICK', { id: '123' });
38
+ *
39
+ * // Subscribe to an event
40
+ * useEffect(() => {
41
+ * return eventBus.on('UI:CLICK', (event) => {
42
+ * console.log('Clicked:', event.payload);
43
+ * });
44
+ * }, []);
45
+ * ```
46
+ */
47
+ declare function useEventBus(): EventBusContextType;
48
+ /**
49
+ * Hook for subscribing to a specific event.
50
+ * Automatically cleans up subscription on unmount.
51
+ *
52
+ * @param event - Event name to subscribe to
53
+ * @param handler - Event handler function
54
+ *
55
+ * @example
56
+ * ```tsx
57
+ * useEventListener('UI:CLICK', (event) => {
58
+ * console.log('Clicked:', event.payload);
59
+ * });
60
+ * ```
61
+ */
62
+ declare function useEventListener(event: string, handler: EventListener): void;
63
+ /**
64
+ * Hook for emitting events.
65
+ * Returns a memoized emit function.
66
+ *
67
+ * @returns Function to emit events
68
+ *
69
+ * @example
70
+ * ```tsx
71
+ * const emit = useEmitEvent();
72
+ *
73
+ * const handleClick = () => {
74
+ * emit('UI:CLICK', { id: '123' });
75
+ * };
76
+ * ```
77
+ */
78
+ declare function useEmitEvent(): (type: string, payload?: Record<string, unknown>) => void;
79
+
8
80
  /**
9
81
  * useOrbitalHistory Hook
10
82
  *
@@ -478,77 +550,6 @@ interface UseValidationResult {
478
550
  }
479
551
  declare function useValidation(): UseValidationResult;
480
552
 
481
- /**
482
- * useEventBus Hook
483
- *
484
- * Provides event bus utilities for component communication.
485
- * This connects to the EventBusProvider for real applications
486
- * or provides a simple in-memory bus for design system / Storybook.
487
- *
488
- * @packageDocumentation
489
- */
490
-
491
- declare global {
492
- interface Window {
493
- __kflowEventBus?: EventBusContextType | null;
494
- }
495
- }
496
- /**
497
- * Hook for accessing the event bus.
498
- *
499
- * Uses EventBusProvider context if available, otherwise falls back to
500
- * a simple in-memory event bus (for design system / Storybook).
501
- *
502
- * @returns Event bus instance with emit, on, once, and hasListeners methods
503
- *
504
- * @example
505
- * ```tsx
506
- * const eventBus = useEventBus();
507
- *
508
- * // Emit an event
509
- * eventBus.emit('UI:CLICK', { id: '123' });
510
- *
511
- * // Subscribe to an event
512
- * useEffect(() => {
513
- * return eventBus.on('UI:CLICK', (event) => {
514
- * console.log('Clicked:', event.payload);
515
- * });
516
- * }, []);
517
- * ```
518
- */
519
- declare function useEventBus(): EventBusContextType;
520
- /**
521
- * Hook for subscribing to a specific event.
522
- * Automatically cleans up subscription on unmount.
523
- *
524
- * @param event - Event name to subscribe to
525
- * @param handler - Event handler function
526
- *
527
- * @example
528
- * ```tsx
529
- * useEventListener('UI:CLICK', (event) => {
530
- * console.log('Clicked:', event.payload);
531
- * });
532
- * ```
533
- */
534
- declare function useEventListener(event: string, handler: EventListener): void;
535
- /**
536
- * Hook for emitting events.
537
- * Returns a memoized emit function.
538
- *
539
- * @returns Function to emit events
540
- *
541
- * @example
542
- * ```tsx
543
- * const emit = useEmitEvent();
544
- *
545
- * const handleClick = () => {
546
- * emit('UI:CLICK', { id: '123' });
547
- * };
548
- * ```
549
- */
550
- declare function useEmitEvent(): (type: string, payload?: Record<string, unknown>) => void;
551
-
552
553
  /**
553
554
  * useUIEvents - UI Event to State Machine Bridge
554
555
  *
@@ -597,16 +598,50 @@ declare function useSelectedEntity<T>(eventBusInstance?: ReturnType<typeof useEv
597
598
  /**
598
599
  * useEntityData Hook
599
600
  *
600
- * Provides data fetching utilities for entity lists.
601
- * This is a stub implementation for the design system that returns mock data.
602
- * In a real application, this would connect to a backend API.
601
+ * Provides data fetching utilities for entity lists and details.
602
+ * Uses a pluggable EntityDataContext when available (e.g., builder runtime
603
+ * bridges FetchedDataContext). Falls back to stubs when no provider is
604
+ * present (Storybook, standalone design system).
603
605
  *
604
606
  * @packageDocumentation
605
607
  */
608
+
609
+ interface EntityDataAdapter {
610
+ /** Get all records for an entity */
611
+ getData: (entity: string) => Record<string, unknown>[];
612
+ /** Get a single record by entity name and ID */
613
+ getById: (entity: string, id: string) => Record<string, unknown> | undefined;
614
+ /** Whether data is currently loading */
615
+ isLoading: boolean;
616
+ /** Current error */
617
+ error: string | null;
618
+ }
606
619
  /**
607
- * Query key factory for entity data queries.
608
- * Used with React Query for cache invalidation.
620
+ * Provider that bridges a host app's data source to useEntityList/useEntity hooks.
621
+ *
622
+ * @example
623
+ * ```tsx
624
+ * // In builder runtime
625
+ * const fetchedData = useFetchedData();
626
+ * const adapter = {
627
+ * getData: fetchedData.getData,
628
+ * getById: fetchedData.getById,
629
+ * isLoading: fetchedData.loading,
630
+ * error: fetchedData.error,
631
+ * };
632
+ * <EntityDataProvider adapter={adapter}>
633
+ * {children}
634
+ * </EntityDataProvider>
635
+ * ```
636
+ */
637
+ declare function EntityDataProvider({ adapter, children, }: {
638
+ adapter: EntityDataAdapter;
639
+ children: ReactNode;
640
+ }): React__default.FunctionComponentElement<React__default.ProviderProps<EntityDataAdapter | null>>;
641
+ /**
642
+ * Access the entity data adapter (null if no provider).
609
643
  */
644
+ declare function useEntityDataAdapter(): EntityDataAdapter | null;
610
645
  declare const entityDataKeys: {
611
646
  all: readonly ["entities"];
612
647
  lists: () => readonly ["entities", "list"];
@@ -614,43 +649,31 @@ declare const entityDataKeys: {
614
649
  details: () => readonly ["entities", "detail"];
615
650
  detail: (entity: string, id: string) => readonly ["entities", "detail", string, string];
616
651
  };
617
- /**
618
- * Generic entity data record type
619
- */
620
652
  type EntityDataRecord = Record<string, unknown>;
621
653
  interface UseEntityListOptions {
622
654
  /** Skip fetching */
623
655
  skip?: boolean;
624
656
  }
625
657
  interface UseEntityListResult<T = Record<string, unknown>> {
626
- /** Fetched data */
627
658
  data: T[];
628
- /** Loading state */
629
659
  isLoading: boolean;
630
- /** Error state */
631
660
  error: Error | null;
632
- /** Refetch function */
661
+ refetch: () => void;
662
+ }
663
+ interface UseEntityDetailResult<T = Record<string, unknown>> {
664
+ data: T | null;
665
+ isLoading: boolean;
666
+ error: Error | null;
633
667
  refetch: () => void;
634
668
  }
635
669
  /**
636
- * Hook for fetching entity list data
637
- *
638
- * @param entity - Entity name to fetch
639
- * @param options - Fetch options
640
- * @returns Entity list data and loading states
641
- *
642
- * @example
643
- * ```tsx
644
- * const { data, isLoading, error } = useEntityList('tasks');
645
- * ```
670
+ * Hook for fetching entity list data.
671
+ * Uses EntityDataContext if available, otherwise falls back to stub.
646
672
  */
647
673
  declare function useEntityList<T = Record<string, unknown>>(entity: string | undefined, options?: UseEntityListOptions): UseEntityListResult<T>;
648
674
  /**
649
- * Hook for fetching a single entity by ID
650
- *
651
- * @param entity - Entity name
652
- * @param id - Entity ID
653
- * @returns Single entity data and loading states
675
+ * Hook for fetching a single entity by ID.
676
+ * Uses EntityDataContext if available, otherwise falls back to stub.
654
677
  */
655
678
  declare function useEntity$1<T = Record<string, unknown>>(entity: string | undefined, id: string | undefined): {
656
679
  data: T | null;
@@ -658,29 +681,8 @@ declare function useEntity$1<T = Record<string, unknown>>(entity: string | undef
658
681
  error: Error | null;
659
682
  };
660
683
  /**
661
- * Result type for useEntityDetail hook
662
- */
663
- interface UseEntityDetailResult<T = Record<string, unknown>> {
664
- /** Fetched entity data */
665
- data: T | null;
666
- /** Loading state */
667
- isLoading: boolean;
668
- /** Error state */
669
- error: Error | null;
670
- /** Refetch function */
671
- refetch: () => void;
672
- }
673
- /**
674
- * Hook for fetching entity detail by ID (alias for useEntity with refetch)
675
- *
676
- * @param entity - Entity name
677
- * @param id - Entity ID
678
- * @returns Entity detail data and loading states
679
- *
680
- * @example
681
- * ```tsx
682
- * const { data, isLoading, error, refetch } = useEntityDetail('tasks', taskId);
683
- * ```
684
+ * Hook for fetching entity detail by ID (alias for useEntity with refetch).
685
+ * Uses EntityDataContext if available, otherwise falls back to stub.
684
686
  */
685
687
  declare function useEntityDetail<T = Record<string, unknown>>(entity: string | undefined, id: string | undefined): UseEntityDetailResult<T>;
686
688
 
@@ -1072,4 +1074,4 @@ declare function useGitHubBranches(owner: string, repo: string, enabled?: boolea
1072
1074
  branches: string[];
1073
1075
  }, Error>;
1074
1076
 
1075
- export { type AuthContextValue, type AuthUser, type ChangeSummary, type CompileResult, type CompileStage, ENTITY_EVENTS, Entity, type EntityDataRecord, type EntityMutationResult, EventBusContextType, EventListener, type Extension, type ExtensionManifest, type FileSystemFile, type FileSystemStatus, type GitHubRepo, type GitHubStatus, type HistoryTimelineItem, type OpenFile, type OrbitalEventPayload, type OrbitalEventResponse, type QuerySingletonEntity, type QuerySingletonResult, type QuerySingletonState, type QueryState, type RevertResult, type SelectedFile, type UseCompileResult, type UseEntityDetailResult, type UseEntityListOptions, type UseEntityListResult, type UseEntityMutationsOptions, type UseExtensionsOptions, type UseExtensionsResult, type UseFileEditorOptions, type UseFileEditorResult, type UseFileSystemResult, type UseOrbitalHistoryOptions, type UseOrbitalHistoryResult, clearEntities, entityDataKeys, getAllEntities, getByType, getEntity, getSingleton, parseQueryBinding, removeEntity, spawnEntity, updateEntity, updateSingleton, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEmitEvent, useEntities, useEntitiesByType, useEntity$1 as useEntity, useEntity as useEntityById, useEntityDetail, useEntityList, useEntityMutations, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePlayer, usePreview, useQuerySingleton, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation };
1077
+ export { type AuthContextValue, type AuthUser, type ChangeSummary, type CompileResult, type CompileStage, ENTITY_EVENTS, Entity, type EntityDataAdapter, EntityDataProvider, type EntityDataRecord, type EntityMutationResult, EventBusContextType, EventListener, type Extension, type ExtensionManifest, type FileSystemFile, type FileSystemStatus, type GitHubRepo, type GitHubStatus, type HistoryTimelineItem, type OpenFile, type OrbitalEventPayload, type OrbitalEventResponse, type QuerySingletonEntity, type QuerySingletonResult, type QuerySingletonState, type QueryState, type RevertResult, type SelectedFile, type UseCompileResult, type UseEntityDetailResult, type UseEntityListOptions, type UseEntityListResult, type UseEntityMutationsOptions, type UseExtensionsOptions, type UseExtensionsResult, type UseFileEditorOptions, type UseFileEditorResult, type UseFileSystemResult, type UseOrbitalHistoryOptions, type UseOrbitalHistoryResult, clearEntities, entityDataKeys, getAllEntities, getByType, getEntity, getSingleton, parseQueryBinding, removeEntity, spawnEntity, updateEntity, updateSingleton, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEmitEvent, useEntities, useEntitiesByType, useEntity$1 as useEntity, useEntity as useEntityById, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityMutations, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePlayer, usePreview, useQuerySingleton, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation };
@@ -1,6 +1,6 @@
1
- export { ENTITY_EVENTS, entityDataKeys, parseQueryBinding, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEntities, useEntitiesByType, useEntity, useEntity2 as useEntityById, useEntityDetail, useEntityList, useEntityMutations, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePlayer, usePreview, useQuerySingleton, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation } from '../chunk-VE4ZELYZ.js';
2
- import '../chunk-XSEDIUM6.js';
3
- export { useEmitEvent, useEventBus, useEventListener } from '../chunk-TTXKOHDO.js';
1
+ export { ENTITY_EVENTS, parseQueryBinding, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEntities, useEntitiesByType, useEntity as useEntityById, useEntityMutations, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePlayer, usePreview, useQuerySingleton, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation } from '../chunk-ITRZURGQ.js';
4
2
  export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-7NEWMNNU.js';
3
+ import '../chunk-XSEDIUM6.js';
4
+ export { EntityDataProvider, entityDataKeys, useEmitEvent, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEventBus, useEventListener } from '../chunk-WXFQV3ZP.js';
5
5
  export { clearEntities, getAllEntities, getByType, getEntity, getSingleton, removeEntity, spawnEntity, updateEntity, updateSingleton } from '../chunk-N7MVUW4R.js';
6
6
  import '../chunk-PKBMQBKP.js';
@@ -233,7 +233,6 @@ declare function useFetchedEntity(entityName: string): {
233
233
  * Combines:
234
234
  * - ThemeProvider - Theme and color mode management
235
235
  * - EventBusProvider - Page-scoped event pub/sub
236
- * - UISlotProvider - UI slot management for render_ui effects
237
236
  * - SelectionProvider - Selected entity tracking
238
237
  * - FetchedDataProvider - Server-fetched entity data
239
238
  *
@@ -1,7 +1,6 @@
1
- import { ThemeProvider, UISlotProvider } from '../chunk-I5RSZIOE.js';
2
- import { EventBusProvider, SelectionProvider } from '../chunk-TTXKOHDO.js';
3
- export { EventBusContext, EventBusProvider, SelectionContext, SelectionProvider, useSelection, useSelectionOptional } from '../chunk-TTXKOHDO.js';
4
- import '../chunk-7NEWMNNU.js';
1
+ import { ThemeProvider } from '../chunk-4UFNDD6B.js';
2
+ import { EventBusProvider, SelectionProvider, EntityDataProvider } from '../chunk-WXFQV3ZP.js';
3
+ export { EventBusContext, EventBusProvider, SelectionContext, SelectionProvider, useSelection, useSelectionOptional } from '../chunk-WXFQV3ZP.js';
5
4
  import { useOfflineExecutor } from '../chunk-PL7MD6GF.js';
6
5
  import '../chunk-PKBMQBKP.js';
7
6
  import { createContext, useState, useCallback, useMemo, useContext } from 'react';
@@ -162,6 +161,16 @@ function useFetchedEntity(entityName) {
162
161
  error: context.error
163
162
  };
164
163
  }
164
+ function FetchedDataBridge({ children }) {
165
+ const fetchedData = useFetchedData();
166
+ const adapter = useMemo(() => ({
167
+ getData: (entity) => fetchedData.getData(entity),
168
+ getById: (entity, id) => fetchedData.getById(entity, id),
169
+ isLoading: fetchedData.loading,
170
+ error: fetchedData.error
171
+ }), [fetchedData.getData, fetchedData.getById, fetchedData.loading, fetchedData.error]);
172
+ return /* @__PURE__ */ jsx(EntityDataProvider, { adapter, children });
173
+ }
165
174
  function OrbitalProvider({
166
175
  children,
167
176
  themes,
@@ -176,7 +185,7 @@ function OrbitalProvider({
176
185
  themes,
177
186
  defaultTheme,
178
187
  defaultMode,
179
- children: /* @__PURE__ */ jsx(FetchedDataProvider, { initialData, children: /* @__PURE__ */ jsx(EventBusProvider, { debug, children: /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsx(SelectionProvider, { debug, children }) }) }) })
188
+ children: /* @__PURE__ */ jsx(FetchedDataProvider, { initialData, children: /* @__PURE__ */ jsx(FetchedDataBridge, { children: /* @__PURE__ */ jsx(EventBusProvider, { debug, children: /* @__PURE__ */ jsx(SelectionProvider, { debug, children }) }) }) })
180
189
  }
181
190
  );
182
191
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",
@@ -64,15 +64,19 @@
64
64
  "remark-gfm": "^4.0.1",
65
65
  "remark-math": "^6.0.0",
66
66
  "react-force-graph-2d": "^1.28.0",
67
- "@almadar/core": "1.0.16",
68
- "@almadar/evaluator": "1.0.13",
69
- "@almadar/patterns": "1.1.0"
67
+ "@almadar/core": "1.0.17",
68
+ "@almadar/evaluator": "1.0.14",
69
+ "@almadar/patterns": "1.1.1"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "react": "^18.0.0",
73
73
  "react-dom": "^18.0.0",
74
74
  "react-router-dom": "^7.0.0",
75
- "@tanstack/react-query": "^5.0.0"
75
+ "@tanstack/react-query": "^5.0.0",
76
+ "three": "^0.160.0",
77
+ "@react-three/fiber": "^8.15.0",
78
+ "@react-three/drei": "^9.92.0",
79
+ "zustand": "^4.4.0"
76
80
  },
77
81
  "devDependencies": {
78
82
  "react": "^18.3.1",
@@ -81,6 +85,7 @@
81
85
  "@tanstack/react-query": "^5.0.0",
82
86
  "@types/react": "^18.3.0",
83
87
  "@types/react-dom": "^18.3.0",
88
+ "@types/three": "^0.160.0",
84
89
  "@storybook/addon-links": "^10.2.6",
85
90
  "@storybook/addon-themes": "^10.2.6",
86
91
  "@storybook/react": "^10.2.6",
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Arctic Theme — "Ice Crystal"
3
+ *
4
+ * Cool ice blue with a clean, precise, crisp aesthetic inspired by frozen
5
+ * landscapes and crystalline formations. Sky blues and cyans evoke glacial
6
+ * clarity, with sharp clean shadows and precise border radii. Tighter
7
+ * letter-spacing and snappy transitions reinforce the theme's precision
8
+ * and clarity.
9
+ */
10
+
11
+ /* ==========================================================================
12
+ * LIGHT MODE
13
+ * ========================================================================== */
14
+ [data-theme="arctic-light"] {
15
+ /* Shadows - Cool blue-tinted, crisp and clean */
16
+ --shadow-main: 0 1px 2px rgba(2, 132, 199, 0.08), 0 1px 1px rgba(2, 132, 199, 0.05);
17
+ --shadow-sm: 0 1px 1px rgba(2, 132, 199, 0.05);
18
+ --shadow-lg:
19
+ 0 8px 20px -4px rgba(2, 132, 199, 0.1), 0 4px 8px -4px rgba(2, 132, 199, 0.06);
20
+ --shadow-inner: inset 0 1px 2px rgba(2, 132, 199, 0.05);
21
+ --shadow-none: none;
22
+ --shadow-hover: 0 8px 30px -8px rgba(2, 132, 199, 0.16);
23
+ --shadow-active: 0 1px 1px rgba(2, 132, 199, 0.05);
24
+
25
+ /* Border radius - Precise, clean */
26
+ --radius-none: 0px;
27
+ --radius-sm: 4px;
28
+ --radius-md: 6px;
29
+ --radius-lg: 10px;
30
+ --radius-xl: 14px;
31
+ --radius-full: 9999px;
32
+
33
+ /* Border width */
34
+ --border-width: 1px;
35
+ --border-width-thin: 1px;
36
+ --border-width-thick: 2px;
37
+
38
+ /* Colors - Ice blue, cool and clean */
39
+ --color-primary: #0284c7;
40
+ --color-primary-hover: #0369a1;
41
+ --color-primary-foreground: #ffffff;
42
+
43
+ --color-secondary: #e0f2fe;
44
+ --color-secondary-hover: #bae6fd;
45
+ --color-secondary-foreground: #0c4a6e;
46
+
47
+ --color-accent: #67e8f9;
48
+ --color-accent-foreground: #164e63;
49
+
50
+ --color-muted: #e0f2fe;
51
+ --color-muted-foreground: #64748b;
52
+
53
+ --color-background: #f0f9ff;
54
+ --color-foreground: #0c4a6e;
55
+ --color-card: #ffffff;
56
+ --color-card-foreground: #0c4a6e;
57
+ --color-surface: #e0f2fe;
58
+ --color-border: rgba(2, 132, 199, 0.2);
59
+ --color-input: rgba(2, 132, 199, 0.22);
60
+ --color-ring: #0284c7;
61
+
62
+ /* Semantic colors */
63
+ --color-error: #dc2626;
64
+ --color-error-foreground: #ffffff;
65
+ --color-success: #16a34a;
66
+ --color-success-foreground: #ffffff;
67
+ --color-warning: #ca8a04;
68
+ --color-warning-foreground: #000000;
69
+ --color-info: #2563eb;
70
+ --color-info-foreground: #ffffff;
71
+
72
+ /* Typography */
73
+ --font-family:
74
+ "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
75
+ --font-weight-normal: 400;
76
+ --font-weight-medium: 500;
77
+ --font-weight-bold: 600;
78
+ --letter-spacing: -0.01em;
79
+ --line-height: 1.55;
80
+
81
+ /* Icon styling */
82
+ --icon-stroke-width: 1.75;
83
+ --icon-color: #0284c7;
84
+
85
+ /* Transitions - Crisp, snappy */
86
+ --transition-fast: 120ms;
87
+ --transition-normal: 220ms;
88
+ --transition-slow: 350ms;
89
+ --transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
90
+
91
+ /* Hover/Active transforms */
92
+ --hover-scale: 1.01;
93
+ --hover-translate-y: -1px;
94
+ --hover-translate-x: 0;
95
+ --active-scale: 0.99;
96
+ --active-translate-y: 0;
97
+
98
+ /* Focus ring */
99
+ --focus-ring-width: 2px;
100
+ --focus-ring-offset: 2px;
101
+ --focus-ring-color: #0284c7;
102
+
103
+ /* Apply background and foreground colors */
104
+ background-color: var(--color-background);
105
+ color: var(--color-foreground);
106
+ }
107
+
108
+ /* ==========================================================================
109
+ * DARK MODE
110
+ * ========================================================================== */
111
+ [data-theme="arctic-dark"] {
112
+ /* Shadows - Cool ice-blue glow on deep dark */
113
+ --shadow-main: 0 1px 2px rgba(103, 232, 249, 0.08), 0 1px 1px rgba(0, 0, 0, 0.2);
114
+ --shadow-sm: 0 1px 1px rgba(0, 0, 0, 0.2);
115
+ --shadow-lg:
116
+ 0 8px 20px -4px rgba(0, 0, 0, 0.35), 0 4px 8px -4px rgba(103, 232, 249, 0.06);
117
+ --shadow-inner: inset 0 1px 2px rgba(0, 0, 0, 0.25);
118
+ --shadow-none: none;
119
+ --shadow-hover: 0 8px 30px -8px rgba(103, 232, 249, 0.14);
120
+ --shadow-active: 0 1px 1px rgba(0, 0, 0, 0.2);
121
+
122
+ /* Border radius - Precise, clean */
123
+ --radius-none: 0px;
124
+ --radius-sm: 4px;
125
+ --radius-md: 6px;
126
+ --radius-lg: 10px;
127
+ --radius-xl: 14px;
128
+ --radius-full: 9999px;
129
+
130
+ /* Border width */
131
+ --border-width: 1px;
132
+ --border-width-thin: 1px;
133
+ --border-width-thick: 2px;
134
+
135
+ /* Colors - Bright cyan on deep ice blue */
136
+ --color-primary: #7dd3fc;
137
+ --color-primary-hover: #bae6fd;
138
+ --color-primary-foreground: #081520;
139
+
140
+ --color-secondary: #0c2236;
141
+ --color-secondary-hover: #10304d;
142
+ --color-secondary-foreground: #e0f2fe;
143
+
144
+ --color-accent: #67e8f9;
145
+ --color-accent-foreground: #164e63;
146
+
147
+ --color-muted: #0c2236;
148
+ --color-muted-foreground: #7dd3fc;
149
+
150
+ --color-background: #081520;
151
+ --color-foreground: #e0f2fe;
152
+ --color-card: #0c2236;
153
+ --color-card-foreground: #e0f2fe;
154
+ --color-surface: #10304d;
155
+ --color-border: rgba(103, 232, 249, 0.2);
156
+ --color-input: rgba(103, 232, 249, 0.25);
157
+ --color-ring: #7dd3fc;
158
+
159
+ /* Semantic colors - Brighter for dark mode */
160
+ --color-error: #f87171;
161
+ --color-error-foreground: #000000;
162
+ --color-success: #4ade80;
163
+ --color-success-foreground: #000000;
164
+ --color-warning: #fbbf24;
165
+ --color-warning-foreground: #000000;
166
+ --color-info: #60a5fa;
167
+ --color-info-foreground: #000000;
168
+
169
+ /* Typography */
170
+ --font-family:
171
+ "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
172
+ --font-weight-normal: 400;
173
+ --font-weight-medium: 500;
174
+ --font-weight-bold: 600;
175
+ --letter-spacing: -0.01em;
176
+ --line-height: 1.55;
177
+
178
+ /* Icon styling */
179
+ --icon-stroke-width: 1.75;
180
+ --icon-color: #67e8f9;
181
+
182
+ /* Transitions - Crisp, snappy */
183
+ --transition-fast: 120ms;
184
+ --transition-normal: 220ms;
185
+ --transition-slow: 350ms;
186
+ --transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
187
+
188
+ /* Hover/Active transforms */
189
+ --hover-scale: 1.01;
190
+ --hover-translate-y: -1px;
191
+ --hover-translate-x: 0;
192
+ --active-scale: 0.99;
193
+ --active-translate-y: 0;
194
+
195
+ /* Focus ring */
196
+ --focus-ring-width: 2px;
197
+ --focus-ring-offset: 2px;
198
+ --focus-ring-color: #67e8f9;
199
+
200
+ /* Apply background and foreground colors */
201
+ background-color: var(--color-background);
202
+ color: var(--color-foreground);
203
+ }