@kala-ui/react-app 0.1.0-beta.1 → 0.1.0-beta.11

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 (102) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/dist/components/app-shell/app-shell.d.ts +8 -46
  3. package/dist/components/app-shell/app-shell.js +41 -42
  4. package/dist/components/app-shell/app-shell.types.d.ts +45 -0
  5. package/dist/components/app-shell/app-shell.types.js +2 -0
  6. package/dist/components/app-shell/index.d.ts +1 -0
  7. package/dist/components/charts/area-chart.d.ts +1 -1
  8. package/dist/components/charts/area-chart.js +4 -3
  9. package/dist/components/charts/bar-chart.d.ts +1 -1
  10. package/dist/components/charts/bar-chart.js +4 -3
  11. package/dist/components/charts/chart-skeleton.d.ts +0 -21
  12. package/dist/components/charts/chart-skeleton.js +2 -1
  13. package/dist/components/charts/chart-utils.d.ts +56 -0
  14. package/dist/components/charts/chart-utils.js +135 -0
  15. package/dist/components/charts/chart.d.ts +3 -1
  16. package/dist/components/charts/chart.js +13 -3
  17. package/dist/components/charts/chart.types.d.ts +3 -0
  18. package/dist/components/charts/donut-chart.d.ts +1 -1
  19. package/dist/components/charts/donut-chart.js +4 -3
  20. package/dist/components/charts/index.d.ts +1 -1
  21. package/dist/components/charts/index.js +1 -1
  22. package/dist/components/charts/line-chart.d.ts +1 -1
  23. package/dist/components/charts/line-chart.js +4 -3
  24. package/dist/components/charts/radial-bar-chart.d.ts +1 -1
  25. package/dist/components/charts/radial-bar-chart.js +4 -3
  26. package/dist/components/data-table/data-table.js +4 -2
  27. package/dist/components/data-table/data-table.types.d.ts +2 -0
  28. package/dist/components/data-table/index.d.ts +1 -1
  29. package/dist/components/data-table/index.js +1 -1
  30. package/dist/components/data-table/use-table-state.d.ts +29 -0
  31. package/dist/components/data-table/use-table-state.js +312 -0
  32. package/dist/components/dnd/dnd.d.ts +16 -98
  33. package/dist/components/dnd/dnd.js +30 -2
  34. package/dist/components/dnd/dnd.types.d.ts +92 -0
  35. package/dist/components/dnd/dnd.types.js +7 -0
  36. package/dist/components/dnd/index.d.ts +2 -1
  37. package/dist/components/dnd/index.js +1 -1
  38. package/dist/components/footer/footer.d.ts +2 -37
  39. package/dist/components/footer/footer.js +18 -2
  40. package/dist/components/footer/footer.types.d.ts +25 -0
  41. package/dist/components/footer/footer.types.js +2 -0
  42. package/dist/components/footer/index.d.ts +1 -1
  43. package/dist/components/header/header.js +5 -11
  44. package/dist/components/metric-card/index.d.ts +2 -1
  45. package/dist/components/metric-card/metric-card-skeleton.js +2 -1
  46. package/dist/components/metric-card/metric-card.d.ts +2 -14
  47. package/dist/components/metric-card/metric-card.js +32 -28
  48. package/dist/components/metric-card/metric-card.types.d.ts +3 -0
  49. package/dist/components/nav-link/index.d.ts +2 -1
  50. package/dist/components/nav-link/index.js +1 -1
  51. package/dist/components/nav-link/nav-link.d.ts +2 -25
  52. package/dist/components/nav-link/nav-link.js +43 -5
  53. package/dist/components/nav-link/nav-link.types.d.ts +23 -0
  54. package/dist/components/nav-link/nav-link.types.js +2 -0
  55. package/dist/components/navigation/index.d.ts +1 -1
  56. package/dist/components/navigation/navigation.d.ts +1 -24
  57. package/dist/components/navigation/navigation.js +7 -17
  58. package/dist/components/navigation/navigation.types.d.ts +15 -0
  59. package/dist/components/navigation/navigation.types.js +2 -0
  60. package/dist/components/session-card/index.d.ts +2 -1
  61. package/dist/components/session-card/index.js +1 -1
  62. package/dist/components/session-card/session-card-skeleton.d.ts +3 -1
  63. package/dist/components/session-card/session-card-skeleton.js +3 -2
  64. package/dist/components/session-card/session-card.d.ts +3 -26
  65. package/dist/components/session-card/session-card.js +23 -8
  66. package/dist/components/session-card/session-card.types.d.ts +26 -0
  67. package/dist/components/session-card/session-card.types.js +2 -0
  68. package/dist/components/sidebar/sidebar.js +5 -11
  69. package/dist/components/social-login-button/index.d.ts +3 -1
  70. package/dist/components/social-login-button/index.js +2 -1
  71. package/dist/components/social-login-button/social-login-button.d.ts +2 -20
  72. package/dist/components/social-login-button/social-login-button.js +9 -11
  73. package/dist/components/social-login-button/social-login-button.types.d.ts +28 -0
  74. package/dist/components/social-login-button/social-login-button.types.js +2 -0
  75. package/dist/components/social-login-button/social-login-buttons.d.ts +4 -0
  76. package/dist/components/social-login-button/social-login-buttons.js +18 -0
  77. package/dist/components/user-menu-dropdown/index.d.ts +2 -1
  78. package/dist/components/user-menu-dropdown/index.js +1 -1
  79. package/dist/components/user-menu-dropdown/user-menu-dropdown.d.ts +2 -31
  80. package/dist/components/user-menu-dropdown/user-menu-dropdown.js +14 -2
  81. package/dist/components/user-menu-dropdown/user-menu-dropdown.types.d.ts +16 -0
  82. package/dist/components/user-menu-dropdown/user-menu-dropdown.types.js +2 -0
  83. package/dist/config/app-shell.d.ts +13 -0
  84. package/dist/config/app-shell.js +20 -0
  85. package/dist/config/charts.d.ts +23 -0
  86. package/dist/config/charts.js +23 -0
  87. package/dist/config/footer.d.ts +16 -0
  88. package/dist/config/footer.js +16 -0
  89. package/dist/config/index.d.ts +7 -0
  90. package/dist/config/index.js +7 -0
  91. package/dist/config/metric-card.d.ts +36 -0
  92. package/dist/config/metric-card.js +44 -0
  93. package/dist/config/session-card.d.ts +32 -0
  94. package/dist/config/session-card.js +32 -0
  95. package/dist/config/social-login-button.d.ts +15 -0
  96. package/dist/config/social-login-button.js +15 -0
  97. package/dist/config/user-menu-dropdown.d.ts +10 -0
  98. package/dist/config/user-menu-dropdown.js +10 -0
  99. package/dist/index.d.ts +0 -1
  100. package/dist/index.js +0 -1
  101. package/dist/styles/app.css +18 -53
  102. package/package.json +24 -28
@@ -2,117 +2,35 @@
2
2
  * DnD Component - Drag and Drop primitives for @dnd-kit
3
3
  * Provides consistent wrappers with animations, sortable support, and drag overlays
4
4
  */
5
- import type { Active, Collision, CollisionDetection, DndContextProps as DndKitContextProps, DragEndEvent, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent, DragStartEvent, Modifier, Over, PointerActivationConstraint, UniqueIdentifier } from "@dnd-kit/core";
5
+ import type { DragDropContextProps, DragOverlayComponentProps, DraggableProps, DroppableProps, SortableContextProps, SortableHandleProps, SortableItemProps, UseDragDropSensorsOptions } from "./dnd.types";
6
6
  import { KeyboardSensor, PointerSensor, TouchSensor, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
7
- import { type SortingStrategy, sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable";
8
- import type { Transform } from "@dnd-kit/utilities";
7
+ import { sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable";
9
8
  import * as React from "react";
10
- type SyntheticListenerMap = DraggableSyntheticListeners;
11
- export type DragDropModifier = Modifier;
12
- export type DragDropCollisionDetection = CollisionDetection;
13
- export type DragDropSortingStrategy = SortingStrategy;
14
- export type DragDropPointerConstraint = PointerActivationConstraint;
15
9
  export declare const collisionDetectionAlgorithms: {
16
- readonly closestCenter: CollisionDetection;
17
- readonly closestCorners: CollisionDetection;
18
- readonly rectIntersection: CollisionDetection;
19
- readonly pointerWithin: CollisionDetection;
10
+ readonly closestCenter: import("@dnd-kit/core").CollisionDetection;
11
+ readonly closestCorners: import("@dnd-kit/core").CollisionDetection;
12
+ readonly rectIntersection: import("@dnd-kit/core").CollisionDetection;
13
+ readonly pointerWithin: import("@dnd-kit/core").CollisionDetection;
20
14
  };
21
15
  export declare const modifiers: {
22
- readonly restrictToHorizontalAxis: Modifier;
23
- readonly restrictToVerticalAxis: Modifier;
24
- readonly restrictToWindowEdges: Modifier;
25
- readonly restrictToParentElement: Modifier;
26
- readonly restrictToFirstScrollableAncestor: Modifier;
16
+ readonly restrictToHorizontalAxis: import("@dnd-kit/core").Modifier;
17
+ readonly restrictToVerticalAxis: import("@dnd-kit/core").Modifier;
18
+ readonly restrictToWindowEdges: import("@dnd-kit/core").Modifier;
19
+ readonly restrictToParentElement: import("@dnd-kit/core").Modifier;
20
+ readonly restrictToFirstScrollableAncestor: import("@dnd-kit/core").Modifier;
27
21
  };
28
22
  export declare const sortingStrategies: {
29
- readonly vertical: SortingStrategy;
30
- readonly horizontal: SortingStrategy;
31
- readonly rect: SortingStrategy;
32
- readonly rectSwapping: SortingStrategy;
23
+ readonly vertical: import("@dnd-kit/sortable").SortingStrategy;
24
+ readonly horizontal: import("@dnd-kit/sortable").SortingStrategy;
25
+ readonly rect: import("@dnd-kit/sortable").SortingStrategy;
26
+ readonly rectSwapping: import("@dnd-kit/sortable").SortingStrategy;
33
27
  };
34
- export interface UseDragDropSensorsOptions {
35
- activationConstraint?: PointerActivationConstraint;
36
- keyboardCoordinateGetter?: typeof sortableKeyboardCoordinates;
37
- }
38
28
  declare function createDragDropSensors(options?: UseDragDropSensorsOptions): import("@dnd-kit/core").SensorDescriptor<import("@dnd-kit/core").SensorOptions>[];
39
- export interface DragDropContextProps extends Omit<DndKitContextProps, "sensors"> {
40
- children: React.ReactNode;
41
- sensors?: ReturnType<typeof createDragDropSensors>;
42
- useSensors?: UseDragDropSensorsOptions;
43
- }
44
29
  declare function DragDropContext({ children, sensors: sensorsProp, useSensors: useSensorsOptions, ...props }: DragDropContextProps): React.JSX.Element;
45
- export interface DroppableProps {
46
- ref?: React.Ref<HTMLDivElement>;
47
- id: UniqueIdentifier;
48
- children: React.ReactNode | ((args: {
49
- isOver: boolean;
50
- setNodeRef: (node: HTMLElement | null) => void;
51
- }) => React.ReactNode);
52
- className?: string;
53
- disabled?: boolean;
54
- }
55
30
  declare function Droppable({ ref, children, className, id, disabled, ...props }: DroppableProps): React.JSX.Element;
56
- export interface DraggableProps {
57
- ref?: React.Ref<HTMLDivElement>;
58
- id: UniqueIdentifier;
59
- children: React.ReactNode | ((args: {
60
- attributes: DraggableAttributes;
61
- listeners: SyntheticListenerMap | undefined;
62
- setNodeRef: (node: HTMLElement | null) => void;
63
- transform: {
64
- x: number;
65
- y: number;
66
- scaleX: number;
67
- scaleY: number;
68
- } | null;
69
- isDragging: boolean;
70
- }) => React.ReactNode);
71
- className?: string;
72
- disabled?: boolean;
73
- }
74
31
  declare function Draggable({ ref, children, className, id, disabled, ...props }: DraggableProps): React.JSX.Element;
75
- export interface SortableContextProps {
76
- id?: UniqueIdentifier;
77
- items: UniqueIdentifier[] | {
78
- id: UniqueIdentifier;
79
- }[];
80
- strategy?: SortingStrategy;
81
- children: React.ReactNode;
82
- }
83
32
  declare function SortableContext({ children, items, strategy, }: SortableContextProps): React.JSX.Element;
84
- export interface SortableItemProps {
85
- ref?: React.Ref<HTMLDivElement>;
86
- id: UniqueIdentifier;
87
- children: React.ReactNode | ((args: {
88
- attributes: DraggableAttributes;
89
- listeners: SyntheticListenerMap | undefined;
90
- setNodeRef: (node: HTMLElement | null) => void;
91
- transform: Transform | null;
92
- transition: string | undefined;
93
- isDragging: boolean;
94
- isSorting: boolean;
95
- isOver: boolean;
96
- }) => React.ReactNode);
97
- className?: string;
98
- disabled?: boolean;
99
- handle?: boolean;
100
- }
101
- declare function SortableItem({ ref, children, className, id, disabled, handle, ...props }: SortableItemProps): React.JSX.Element;
102
- export interface SortableHandleProps {
103
- ref?: React.Ref<HTMLDivElement>;
104
- children: React.ReactNode | ((listeners: SyntheticListenerMap | undefined) => React.ReactNode);
105
- className?: string;
106
- }
33
+ declare function SortableItem({ ref, children, className, id, disabled, handle, slotStyles: slotStylesRaw, ...props }: SortableItemProps): React.JSX.Element;
107
34
  declare function SortableHandle({ ref, children, className, ...props }: SortableHandleProps): React.JSX.Element;
108
- export interface DragOverlayComponentProps {
109
- children: React.ReactNode;
110
- className?: string;
111
- dropAnimation?: {
112
- duration?: number;
113
- easing?: string;
114
- } | null;
115
- }
116
35
  declare function DragOverlayComponent({ children, className, dropAnimation, ...props }: DragOverlayComponentProps): React.JSX.Element;
117
- export type { Active, Collision, DragEndEvent as DropResult, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent as DragUpdate, DragOverEvent, DragStartEvent as DragStart, Over, SortingStrategy, Transform, UniqueIdentifier, };
118
36
  export { createDragDropSensors as useDragDropSensors, DragDropContext, Draggable, DragOverlayComponent, Droppable, KeyboardSensor, PointerSensor, SortableContext, SortableHandle, SortableItem, sortableKeyboardCoordinates, TouchSensor, useDraggable, useDroppable, useSensor, useSensors, useSortable, };
@@ -10,6 +10,8 @@ import { restrictToFirstScrollableAncestor, restrictToHorizontalAxis, restrictTo
10
10
  import { horizontalListSortingStrategy, rectSortingStrategy, rectSwappingStrategy, SortableContext as SortableContextKit, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable";
11
11
  import { CSS } from "@dnd-kit/utilities";
12
12
  import { cn } from "@kala-ui/react/lib/utils";
13
+ import { useSlotStyles } from "@kala-ui/react/kala-provider";
14
+ import { applySlot } from "@kala-ui/react/lib/slot-styles";
13
15
  import { useMergedRef } from "@kala-ui/react-hooks";
14
16
  import * as React from "react";
15
17
  // ============================================================================
@@ -40,6 +42,9 @@ export const sortingStrategies = {
40
42
  rect: rectSortingStrategy,
41
43
  rectSwapping: rectSwappingStrategy,
42
44
  };
45
+ // ============================================================================
46
+ // Sensors Hook
47
+ // ============================================================================
43
48
  function createDragDropSensors(options = {}) {
44
49
  const { activationConstraint, keyboardCoordinateGetter = sortableKeyboardCoordinates, } = options;
45
50
  const sensors = useSensors(useSensor(PointerSensor, {
@@ -51,11 +56,17 @@ function createDragDropSensors(options = {}) {
51
56
  }));
52
57
  return sensors;
53
58
  }
59
+ // ============================================================================
60
+ // DndContext
61
+ // ============================================================================
54
62
  function DragDropContext({ children, sensors: sensorsProp, useSensors: useSensorsOptions, ...props }) {
55
63
  const defaultSensors = createDragDropSensors(useSensorsOptions);
56
64
  const sensors = sensorsProp ?? defaultSensors;
57
65
  return (_jsx(DndKitContext, { "data-kala-component": "dnd-drag-drop-context", sensors: sensors, ...props, children: children }));
58
66
  }
67
+ // ============================================================================
68
+ // Droppable
69
+ // ============================================================================
59
70
  function Droppable({ ref, children, className, id, disabled = false, ...props }) {
60
71
  const { isOver, setNodeRef } = useDroppable({
61
72
  id,
@@ -66,6 +77,9 @@ function Droppable({ ref, children, className, id, disabled = false, ...props })
66
77
  : children;
67
78
  return (_jsx("div", { "data-kala-component": "dnd-droppable", ref: useMergedRef(ref, setNodeRef), className: cn(className), ...props, children: content }));
68
79
  }
80
+ // ============================================================================
81
+ // Draggable
82
+ // ============================================================================
69
83
  function Draggable({ ref, children, className, id, disabled = false, ...props }) {
70
84
  const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({
71
85
  id,
@@ -81,12 +95,17 @@ function Draggable({ ref, children, className, id, disabled = false, ...props })
81
95
  : undefined;
82
96
  return (_jsx("div", { "data-kala-component": "dnd-draggable", ref: useMergedRef(ref, setNodeRef), style: style, className: cn(className), ...attributes, ...listeners, ...props, children: content }));
83
97
  }
98
+ // ============================================================================
99
+ // Sortable Context
100
+ // ============================================================================
84
101
  function SortableContext({ children, items, strategy = verticalListSortingStrategy, }) {
85
102
  const itemIds = React.useMemo(() => items.map((item) => typeof item === "object" && "id" in item ? item.id : item), [items]);
86
103
  return (_jsx(SortableContextKit, { "data-kala-component": "dnd-sortable-context", items: itemIds, strategy: strategy, children: children }));
87
104
  }
88
105
  const SortableHandleContext = React.createContext(null);
89
- function SortableItem({ ref, children, className, id, disabled = false, handle = false, ...props }) {
106
+ function SortableItem({ ref, children, className, id, disabled = false, handle = false, slotStyles: slotStylesRaw, ...props }) {
107
+ const slotStyles = useSlotStyles("dnd", slotStylesRaw);
108
+ const itemRoot = applySlot(cn(className), slotStyles?.root);
90
109
  const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging, isSorting, isOver, } = useSortable({
91
110
  id,
92
111
  disabled,
@@ -108,8 +127,11 @@ function SortableItem({ ref, children, className, id, disabled = false, handle =
108
127
  transition,
109
128
  zIndex: isDragging ? 9999 : undefined,
110
129
  };
111
- return (_jsx(SortableHandleContext.Provider, { "data-kala-component": "dnd-sortable-item", value: { attributes, listeners, setActivatorNodeRef }, children: _jsx("div", { ref: useMergedRef(ref, setNodeRef), style: style, className: cn(className), ...attributes, ...(handle ? {} : listeners), ...props, children: content }) }));
130
+ return (_jsx(SortableHandleContext.Provider, { value: { attributes, listeners, setActivatorNodeRef }, children: _jsx("div", { "data-kala-component": "dnd-sortable-item", ref: useMergedRef(ref, setNodeRef), style: style, className: itemRoot.className, ...attributes, ...(handle ? {} : listeners), ...props, children: content }) }));
112
131
  }
132
+ // ============================================================================
133
+ // Sortable Handle
134
+ // ============================================================================
113
135
  function SortableHandle({ ref, children, className, ...props }) {
114
136
  const sortable = React.useContext(SortableHandleContext);
115
137
  if (!sortable && process.env.NODE_ENV !== "production") {
@@ -118,9 +140,15 @@ function SortableHandle({ ref, children, className, ...props }) {
118
140
  const content = typeof children === "function" ? children(sortable?.listeners) : children;
119
141
  return (_jsx("div", { "data-kala-component": "dnd-sortable-handle", ref: useMergedRef(ref, sortable?.setActivatorNodeRef), className: cn("cursor-grab active:cursor-grabbing", className), ...(sortable?.attributes ?? {}), ...(sortable?.listeners ?? {}), ...props, children: content }));
120
142
  }
143
+ // ============================================================================
144
+ // Drag Overlay Component
145
+ // ============================================================================
121
146
  function DragOverlayComponent({ children, className, dropAnimation, ...props }) {
122
147
  return (_jsx(DragOverlay, { "data-kala-component": "dnd-drag-overlay-component", dropAnimation: dropAnimation, ...props, children: children ? _jsx("div", { className: cn(className), children: children }) : null }));
123
148
  }
149
+ // ============================================================================
150
+ // Exports
151
+ // ============================================================================
124
152
  export { createDragDropSensors as useDragDropSensors, DragDropContext, Draggable, DragOverlayComponent, Droppable,
125
153
  // Re-export sensors
126
154
  KeyboardSensor, PointerSensor, SortableContext, SortableHandle, SortableItem, sortableKeyboardCoordinates, TouchSensor,
@@ -0,0 +1,92 @@
1
+ /**
2
+ * DnD family types — the Kala-named surface over @dnd-kit plus the wrapper
3
+ * component prop shapes. Kept free of runtime code so it doubles as the
4
+ * @dnd-kit type re-export point for the family barrel.
5
+ */
6
+ import type { Active, Collision, CollisionDetection, DndContextProps as DndKitContextProps, DragEndEvent, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent, DragStartEvent, Modifier, Over, PointerActivationConstraint, UniqueIdentifier, useSensors } from "@dnd-kit/core";
7
+ import type { sortableKeyboardCoordinates, SortingStrategy } from "@dnd-kit/sortable";
8
+ import type { Transform } from "@dnd-kit/utilities";
9
+ import type { SlotStyles } from "@kala-ui/react/lib/slot-styles";
10
+ import type * as React from "react";
11
+ export type SyntheticListenerMap = DraggableSyntheticListeners;
12
+ export type DragDropModifier = Modifier;
13
+ export type DragDropCollisionDetection = CollisionDetection;
14
+ export type DragDropSortingStrategy = SortingStrategy;
15
+ export type DragDropPointerConstraint = PointerActivationConstraint;
16
+ export interface UseDragDropSensorsOptions {
17
+ activationConstraint?: PointerActivationConstraint;
18
+ keyboardCoordinateGetter?: typeof sortableKeyboardCoordinates;
19
+ }
20
+ export interface DragDropContextProps extends Omit<DndKitContextProps, "sensors"> {
21
+ children: React.ReactNode;
22
+ sensors?: ReturnType<typeof useSensors>;
23
+ useSensors?: UseDragDropSensorsOptions;
24
+ }
25
+ export interface DroppableProps {
26
+ ref?: React.Ref<HTMLDivElement>;
27
+ id: UniqueIdentifier;
28
+ children: React.ReactNode | ((args: {
29
+ isOver: boolean;
30
+ setNodeRef: (node: HTMLElement | null) => void;
31
+ }) => React.ReactNode);
32
+ className?: string;
33
+ disabled?: boolean;
34
+ }
35
+ export interface DraggableProps {
36
+ ref?: React.Ref<HTMLDivElement>;
37
+ id: UniqueIdentifier;
38
+ children: React.ReactNode | ((args: {
39
+ attributes: DraggableAttributes;
40
+ listeners: SyntheticListenerMap | undefined;
41
+ setNodeRef: (node: HTMLElement | null) => void;
42
+ transform: {
43
+ x: number;
44
+ y: number;
45
+ scaleX: number;
46
+ scaleY: number;
47
+ } | null;
48
+ isDragging: boolean;
49
+ }) => React.ReactNode);
50
+ className?: string;
51
+ disabled?: boolean;
52
+ }
53
+ export interface SortableContextProps {
54
+ id?: UniqueIdentifier;
55
+ items: UniqueIdentifier[] | {
56
+ id: UniqueIdentifier;
57
+ }[];
58
+ strategy?: SortingStrategy;
59
+ children: React.ReactNode;
60
+ }
61
+ export interface SortableItemProps {
62
+ ref?: React.Ref<HTMLDivElement>;
63
+ id: UniqueIdentifier;
64
+ children: React.ReactNode | ((args: {
65
+ attributes: DraggableAttributes;
66
+ listeners: SyntheticListenerMap | undefined;
67
+ setNodeRef: (node: HTMLElement | null) => void;
68
+ transform: Transform | null;
69
+ transition: string | undefined;
70
+ isDragging: boolean;
71
+ isSorting: boolean;
72
+ isOver: boolean;
73
+ }) => React.ReactNode);
74
+ className?: string;
75
+ disabled?: boolean;
76
+ handle?: boolean;
77
+ slotStyles?: SlotStyles;
78
+ }
79
+ export interface SortableHandleProps {
80
+ ref?: React.Ref<HTMLDivElement>;
81
+ children: React.ReactNode | ((listeners: SyntheticListenerMap | undefined) => React.ReactNode);
82
+ className?: string;
83
+ }
84
+ export interface DragOverlayComponentProps {
85
+ children: React.ReactNode;
86
+ className?: string;
87
+ dropAnimation?: {
88
+ duration?: number;
89
+ easing?: string;
90
+ } | null;
91
+ }
92
+ export type { Active, Collision, DragEndEvent as DropResult, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent as DragUpdate, DragOverEvent, DragStartEvent as DragStart, Over, SortingStrategy, Transform, UniqueIdentifier, };
@@ -0,0 +1,7 @@
1
+ "use client";
2
+ /**
3
+ * DnD family types — the Kala-named surface over @dnd-kit plus the wrapper
4
+ * component prop shapes. Kept free of runtime code so it doubles as the
5
+ * @dnd-kit type re-export point for the family barrel.
6
+ */
7
+ export {};
@@ -1 +1,2 @@
1
- export { DragDropContext, type DragDropContextProps, Draggable, type DraggableAttributes, type DraggableProps, type DragStart, type DragUpdate, Droppable, type DroppableProps, type DropResult, type UniqueIdentifier, } from "./dnd";
1
+ export { DragDropContext, Draggable, Droppable } from "./dnd";
2
+ export type { DragDropContextProps, DraggableAttributes, DraggableProps, DragStart, DragUpdate, DroppableProps, DropResult, UniqueIdentifier, } from "./dnd.types";
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- export { DragDropContext, Draggable, Droppable, } from "./dnd.js";
2
+ export { DragDropContext, Draggable, Droppable } from "./dnd.js";
@@ -1,37 +1,2 @@
1
- import type * as React from "react";
2
- export interface FooterLink {
3
- label: string;
4
- href: string;
5
- }
6
- export interface FooterLinkSection {
7
- title: string;
8
- links: FooterLink[];
9
- }
10
- export interface SocialLink {
11
- name: string;
12
- href: string;
13
- icon: React.ReactNode;
14
- }
15
- export interface FooterProps extends React.HTMLAttributes<HTMLElement>, React.RefAttributes<HTMLElement> {
16
- /**
17
- * Sections of links to display in columns
18
- */
19
- linkSections?: FooterLinkSection[];
20
- /**
21
- * Social media links with icons
22
- */
23
- socialLinks?: SocialLink[];
24
- /**
25
- * Copyright text
26
- */
27
- copyright?: string;
28
- /**
29
- * Additional content to display in footer (e.g., newsletter signup)
30
- */
31
- children?: React.ReactNode;
32
- /**
33
- * Center align all content
34
- */
35
- centered?: boolean;
36
- }
37
- export declare function Footer({ ref, className, linkSections, socialLinks, copyright, children, centered, ...props }: FooterProps): React.JSX.Element;
1
+ import type { FooterProps } from "./footer.types";
2
+ export declare function Footer({ ref, className, style, slotStyles: slotStylesRaw, linkSections, socialLinks, copyright, children, centered, ...props }: FooterProps): import("react").JSX.Element;
@@ -1,8 +1,24 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useSlotStyles } from "@kala-ui/react/kala-provider";
4
+ import { applySlot } from "@kala-ui/react/lib/slot-styles";
3
5
  import { cn } from "@kala-ui/react/lib/utils";
4
- export function Footer({ ref, className, linkSections = [], socialLinks = [], copyright, children, centered = false, ...props }) {
6
+ import { footerStyles } from "../../config/footer.js";
7
+ export function Footer({ ref, className, style, slotStyles: slotStylesRaw, linkSections = [], socialLinks = [], copyright, children, centered = false, ...props }) {
8
+ const slotStyles = useSlotStyles("footer", slotStylesRaw);
5
9
  const currentYear = new Date().getFullYear();
6
10
  const copyrightText = copyright || `© ${currentYear} All rights reserved.`;
7
- return (_jsx("footer", { "data-kala-component": "footer", ref: ref, className: cn("w-full bg-muted text-muted-foreground border-t", className), ...props, children: _jsxs("div", { className: "container mx-auto px-4 py-8 md:py-12", children: [centered && children && (_jsx("div", { className: "mb-12 flex flex-col items-center text-center", children: children })), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-8", children: [linkSections.map((section) => (_jsxs("nav", { "aria-label": `${section.title} links`, children: [_jsx("h3", { className: "text-foreground font-semibold text-sm uppercase tracking-wider mb-4", children: section.title }), _jsx("ul", { className: "space-y-2", children: section.links.map((link) => (_jsx("li", { children: _jsx("a", { href: link.href, className: "text-muted-foreground hover:text-primary transition-colors text-sm", children: link.label }) }, `${link.href}-${link.label}`))) })] }, section.title))), !centered && children && (_jsx("div", { className: "md:col-span-2 lg:col-span-1", children: children }))] }), _jsxs("div", { className: cn("border-t pt-8 flex flex-col gap-4", !centered && "md:flex-row md:justify-between md:items-center", centered && "items-center"), children: [_jsx("div", { className: "text-sm text-muted-foreground order-2 md:order-1", children: copyrightText }), socialLinks.length > 0 && (_jsx("div", { className: "flex items-center gap-4 order-1 md:order-2", children: socialLinks.map((social) => (_jsx("a", { href: social.href, target: "_blank", rel: "noopener noreferrer", className: "text-muted-foreground hover:text-primary transition-colors", "aria-label": social.name, children: social.icon }, social.href))) }))] })] }) }));
11
+ const root = applySlot(cn(footerStyles.root, className), slotStyles?.root);
12
+ const inner = applySlot(footerStyles.inner, slotStyles?.inner);
13
+ const centeredContent = applySlot(footerStyles.centeredContent, slotStyles?.centeredContent);
14
+ const grid = applySlot(footerStyles.grid, slotStyles?.grid);
15
+ const sectionTitle = applySlot(footerStyles.sectionTitle, slotStyles?.sectionTitle);
16
+ const sectionList = applySlot(footerStyles.sectionList, slotStyles?.sectionList);
17
+ const sectionLink = applySlot(footerStyles.sectionLink, slotStyles?.sectionLink);
18
+ const customContent = applySlot(footerStyles.customContent, slotStyles?.customContent);
19
+ const bottomRow = applySlot(footerStyles.bottomRow, slotStyles?.bottomRow);
20
+ const copyrightPart = applySlot(footerStyles.copyright, slotStyles?.copyright);
21
+ const socialList = applySlot(footerStyles.socialList, slotStyles?.socialList);
22
+ const socialLink = applySlot(footerStyles.socialLink, slotStyles?.socialLink);
23
+ return (_jsx("footer", { "data-kala-component": "footer", ref: ref, className: root.className, style: root.style, ...props, children: _jsxs("div", { className: inner.className, children: [centered && children && (_jsx("div", { className: centeredContent.className, children: children })), _jsxs("div", { className: grid.className, children: [linkSections.map((section) => (_jsxs("nav", { "aria-label": `${section.title} links`, children: [_jsx("h3", { className: sectionTitle.className, children: section.title }), _jsx("ul", { className: sectionList.className, children: section.links.map((link) => (_jsx("li", { children: _jsx("a", { href: link.href, className: sectionLink.className, children: link.label }) }, `${link.href}-${link.label}`))) })] }, section.title))), !centered && children && (_jsx("div", { className: customContent.className, children: children }))] }), _jsxs("div", { className: cn(bottomRow.className, !centered && footerStyles.bottomRowSide, centered && footerStyles.bottomRowCentered), children: [_jsx("div", { className: copyrightPart.className, children: copyrightText }), socialLinks.length > 0 && (_jsx("div", { className: socialList.className, children: socialLinks.map((social) => (_jsx("a", { href: social.href, target: "_blank", rel: "noopener noreferrer", className: socialLink.className, "aria-label": social.name, children: social.icon }, social.href))) }))] })] }) }));
8
24
  }
@@ -0,0 +1,25 @@
1
+ import type { SlotStyles } from "@kala-ui/react/lib/slot-styles";
2
+ import type * as React from "react";
3
+ export interface FooterLink {
4
+ label: string;
5
+ href: string;
6
+ }
7
+ export interface FooterLinkSection {
8
+ title: string;
9
+ links: FooterLink[];
10
+ }
11
+ export interface SocialLink {
12
+ name: string;
13
+ href: string;
14
+ icon: React.ReactNode;
15
+ }
16
+ export interface FooterProps extends React.HTMLAttributes<HTMLElement>, React.RefAttributes<HTMLElement> {
17
+ linkSections?: FooterLinkSection[];
18
+ socialLinks?: SocialLink[];
19
+ copyright?: string;
20
+ children?: React.ReactNode;
21
+ centered?: boolean;
22
+ /** Per-part overrides: root, inner, centeredContent, grid, sectionTitle,
23
+ * sectionList, sectionLink, customContent, bottomRow, copyright, socialList, socialLink. */
24
+ slotStyles?: SlotStyles;
25
+ }
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ export {};
@@ -1,2 +1,2 @@
1
- export type { FooterLink, FooterLinkSection, FooterProps, SocialLink, } from "./footer";
2
1
  export { Footer } from "./footer";
2
+ export type { FooterLink, FooterLinkSection, FooterProps, SocialLink, } from "./footer.types";
@@ -9,7 +9,7 @@ import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMe
9
9
  import { Stack } from "@kala-ui/react/stack";
10
10
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "@kala-ui/react/tabs";
11
11
  import { Text } from "@kala-ui/react/text";
12
- import { useFocusTrap, useMounted, useScrollLock } from "@kala-ui/react-hooks";
12
+ import { useFocusTrap, useMounted, useScrollLock, useWindowEvent, } from "@kala-ui/react-hooks";
13
13
  import { Bell, ChevronDown, Menu, Settings, X } from "lucide-react";
14
14
  import * as React from "react";
15
15
  import { createPortal } from "react-dom";
@@ -22,16 +22,10 @@ export function Header({ ref, className, logo, navLinks = [], userMenu, userProf
22
22
  }, [isMobileMenuOpen, setScrollLocked]);
23
23
  // Fullscreen mobile menu: trap focus, close on Escape.
24
24
  const mobileNavRef = useFocusTrap(!!isMobileMenuOpen);
25
- React.useEffect(() => {
26
- if (!isMobileMenuOpen)
27
- return;
28
- const handleKeyDown = (event) => {
29
- if (event.key === "Escape")
30
- onMobileMenuToggle?.();
31
- };
32
- window.addEventListener("keydown", handleKeyDown);
33
- return () => window.removeEventListener("keydown", handleKeyDown);
34
- }, [isMobileMenuOpen, onMobileMenuToggle]);
25
+ useWindowEvent("keydown", (event) => {
26
+ if (event.key === "Escape" && isMobileMenuOpen)
27
+ onMobileMenuToggle?.();
28
+ });
35
29
  const mounted = useMounted();
36
30
  // Track expanded mobile menu items
37
31
  const [expandedItems, setExpandedItems] = React.useState(new Set());
@@ -1,2 +1,3 @@
1
- export { MetricCard, type MetricCardProps } from "./metric-card";
1
+ export { MetricCard } from "./metric-card";
2
+ export type { MetricCardProps } from "./metric-card.types";
2
3
  export { MetricCardSkeleton } from "./metric-card-skeleton";
@@ -10,6 +10,7 @@ import { Card } from "@kala-ui/react/card";
10
10
  import { cn } from "@kala-ui/react/lib/utils";
11
11
  import { Skeleton, SkeletonCircle } from "@kala-ui/react/skeleton";
12
12
  import * as React from "react";
13
+ import { metricCardSkeletonStyles } from "../../config/metric-card.js";
13
14
  /**
14
15
  * Metric Card skeleton component with multiple variants
15
16
  *
@@ -21,7 +22,7 @@ import * as React from "react";
21
22
  * ```
22
23
  */
23
24
  export function MetricCardSkeleton({ variant = "default", showIcon = false, showChange = true, className, "data-testid": dataTestId, }) {
24
- return (_jsx(Card, { "data-kala-component": "metric-card-skeleton", ref: React.createRef(), "data-testid": dataTestId || "metric-card-skeleton", className: cn(className), children: _jsxs("div", { className: "p-6", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsx(Skeleton, { className: "h-4 w-24" }), variant === "withIcon" || showIcon ? (_jsx(SkeletonCircle, { size: "1.5rem", className: "rounded-md" })) : null] }), _jsx("div", { className: "mb-3", children: _jsx(Skeleton, { className: "h-10 w-32" }) }), (variant === "default" || showChange) && (_jsx("div", { className: "text-sm", children: _jsx(Skeleton, { className: "h-4 w-32" }) }))] }) }));
25
+ return (_jsx(Card, { "data-kala-component": "metric-card-skeleton", ref: React.createRef(), "data-testid": dataTestId || "metric-card-skeleton", className: cn(className), children: _jsxs("div", { className: metricCardSkeletonStyles.body, children: [_jsxs("div", { className: metricCardSkeletonStyles.head, children: [_jsx(Skeleton, { className: metricCardSkeletonStyles.title }), variant === "withIcon" || showIcon ? (_jsx(SkeletonCircle, { size: "1.5rem", className: metricCardSkeletonStyles.icon })) : null] }), _jsx("div", { className: metricCardSkeletonStyles.valueBlock, children: _jsx(Skeleton, { className: metricCardSkeletonStyles.value }) }), (variant === "default" || showChange) && (_jsx("div", { className: metricCardSkeletonStyles.meta, children: _jsx(Skeleton, { className: metricCardSkeletonStyles.metaLine }) }))] }) }));
25
26
  }
26
27
  /**
27
28
  * Compound component: MetricCard.Skeleton
@@ -1,16 +1,4 @@
1
- import type { MetricCardSkeletonConfig } from "@kala-ui/react/skeleton";
2
1
  import type * as React from "react";
3
- export interface MetricCardProps extends Omit<React.ComponentProps<"div">, "title"> {
4
- title: string;
5
- value: number | string;
6
- icon?: React.ReactNode;
7
- change?: number;
8
- changeLabel?: string;
9
- subtitle?: string;
10
- color?: "primary" | "secondary" | "destructive" | "success" | "warning" | "info" | "muted";
11
- isLoading?: boolean;
12
- skeletonConfig?: MetricCardSkeletonConfig;
13
- skeleton?: React.ReactNode;
14
- }
15
- declare function MetricCard({ ref, title, value, icon, change, changeLabel, subtitle, className, color, isLoading, skeletonConfig, skeleton, ...props }: MetricCardProps): React.JSX.Element;
2
+ import type { MetricCardProps } from "./metric-card.types";
3
+ declare function MetricCard({ ref, title, value, icon, change, changeLabel, subtitle, className, style, slotStyles: slotStylesRaw, color, isLoading, skeletonConfig, skeleton, ...props }: MetricCardProps): React.JSX.Element;
16
4
  export { MetricCard };
@@ -1,22 +1,25 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Card } from "@kala-ui/react/card";
4
+ import { useSlotStyles } from "@kala-ui/react/kala-provider";
5
+ import { applySlot } from "@kala-ui/react/lib/slot-styles";
4
6
  import { cn } from "@kala-ui/react/lib/utils";
7
+ import { metricCardChangeColors, metricCardColorStyles, metricCardStyles, } from "../../config/metric-card.js";
5
8
  import { MetricCardSkeleton } from "./metric-card-skeleton.js";
6
- function MetricCard({ ref, title, value, icon, change, changeLabel, subtitle, className, color = "muted", isLoading = false, skeletonConfig, skeleton, ...props }) {
9
+ function MetricCard({ ref, title, value, icon, change, changeLabel, subtitle, className, style, slotStyles: slotStylesRaw, color = "muted", isLoading = false, skeletonConfig, skeleton, ...props }) {
10
+ const slotStyles = useSlotStyles("metric-card", slotStylesRaw);
7
11
  if (isLoading) {
8
12
  if (skeleton) {
9
- return (_jsx(Card, { "data-kala-component": "metric-card", ref: ref, className: cn(className), ...props, children: skeleton }));
13
+ const loadingRoot = applySlot(cn(className), slotStyles?.root);
14
+ return (_jsx(Card, { "data-kala-component": "metric-card", ref: ref, className: loadingRoot.className, style: loadingRoot.style, ...props, children: skeleton }));
10
15
  }
11
16
  return (_jsx(MetricCardSkeleton, { "data-kala-component": "metric-card", className: className, ...skeletonConfig }));
12
17
  }
13
- const getChangeColor = (changeValue) => {
14
- if (changeValue > 0)
15
- return "text-success";
16
- if (changeValue < 0)
17
- return "text-destructive";
18
- return "text-muted-foreground";
19
- };
18
+ const getChangeColor = (changeValue) => changeValue > 0
19
+ ? metricCardChangeColors.up
20
+ : changeValue < 0
21
+ ? metricCardChangeColors.down
22
+ : metricCardChangeColors.flat;
20
23
  const getChangeIcon = (changeValue) => {
21
24
  if (changeValue > 0)
22
25
  return "↑";
@@ -31,25 +34,26 @@ function MetricCard({ ref, title, value, icon, change, changeLabel, subtitle, cl
31
34
  : "No change";
32
35
  return changeLabel || defaultLabel;
33
36
  };
34
- const getColorStyles = () => {
35
- switch (color) {
36
- case "primary":
37
- return "bg-gradient-to-br from-primary to-primary/90 text-primary-foreground";
38
- case "secondary":
39
- return "bg-gradient-to-br from-secondary to-secondary/90 text-secondary-foreground";
40
- case "destructive":
41
- return "bg-gradient-to-br from-destructive to-destructive/90 text-destructive-foreground";
42
- case "success":
43
- return "bg-gradient-to-br from-success to-success/90 text-success-foreground";
44
- case "warning":
45
- return "bg-gradient-to-br from-warning to-warning/90 text-warning-foreground";
46
- case "info":
47
- return "bg-gradient-to-br from-info to-info/90 text-info-foreground";
48
- default:
49
- return "bg-card border text-card-foreground";
50
- }
51
- };
52
37
  const isColorful = color !== "muted" || className?.includes("bg-");
53
- return (_jsx(Card, { "data-kala-component": "metric-card", ref: ref, className: cn(getColorStyles(), className), ...props, children: _jsxs("div", { className: "p-6", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsx("h6", { className: cn("text-xs font-semibold uppercase tracking-wide", isColorful ? "opacity-90" : "text-muted-foreground"), children: title }), icon && (_jsx("div", { className: isColorful ? "opacity-70" : "text-muted-foreground", "aria-hidden": "true", children: icon }))] }), _jsx("div", { className: "mb-3", children: _jsxs("div", { className: cn("text-4xl font-bold leading-none", isColorful ? "" : "text-card-foreground"), children: [_jsxs("span", { className: "sr-only", children: [title, ":", " ", typeof value === "number" ? value.toLocaleString() : value] }), typeof value === "number" ? value.toLocaleString() : value] }) }), (change !== undefined || subtitle) && (_jsx("div", { className: "text-sm", children: change !== undefined ? (_jsxs("div", { className: cn("flex items-center gap-1", isColorful ? "opacity-90" : getChangeColor(change)), children: [_jsxs("span", { className: "sr-only", children: ["Change: ", getChangeText(change)] }), _jsx("span", { className: "inline-block", "aria-hidden": "true", children: getChangeIcon(change) }), _jsx("span", { children: getChangeText(change) })] })) : subtitle ? (_jsx("div", { className: cn(isColorful ? "opacity-80" : "text-muted-foreground"), children: subtitle })) : null }))] }) }));
38
+ const root = applySlot(cn(metricCardColorStyles[color], className), slotStyles?.root);
39
+ const body = applySlot(metricCardStyles.body, slotStyles?.body);
40
+ const head = applySlot(metricCardStyles.head, slotStyles?.head);
41
+ const titleLabel = applySlot(metricCardStyles.title, slotStyles?.title);
42
+ const iconSlot = applySlot(metricCardStyles.icon, slotStyles?.icon);
43
+ const valueSlot = applySlot(metricCardStyles.value, slotStyles?.value);
44
+ const meta = applySlot(metricCardStyles.meta, slotStyles?.meta);
45
+ const changeSlot = applySlot(metricCardStyles.change, slotStyles?.change);
46
+ const subtitleSlot = applySlot(metricCardStyles.subtitle, slotStyles?.subtitle);
47
+ return (_jsx(Card, { "data-kala-component": "metric-card", ref: ref, className: root.className, style: root.style, ...props, children: _jsxs("div", { className: body.className, children: [_jsxs("div", { className: head.className, children: [_jsx("h6", { className: cn(titleLabel.className, isColorful
48
+ ? metricCardStyles.titleOnColor
49
+ : metricCardStyles.titleMuted), children: title }), icon && (_jsx("div", { className: cn(iconSlot.className, isColorful
50
+ ? metricCardStyles.iconOnColor
51
+ : metricCardStyles.iconMuted), "aria-hidden": "true", children: icon }))] }), _jsx("div", { className: metricCardStyles.valueBlock, children: _jsxs("div", { className: cn(valueSlot.className, isColorful
52
+ ? metricCardStyles.valueOnColor
53
+ : metricCardStyles.valueMuted), children: [_jsxs("span", { className: "sr-only", children: [title, ":", " ", typeof value === "number" ? value.toLocaleString() : value] }), typeof value === "number" ? value.toLocaleString() : value] }) }), (change !== undefined || subtitle) && (_jsx("div", { className: meta.className, children: change !== undefined ? (_jsxs("div", { className: cn(changeSlot.className, isColorful
54
+ ? metricCardStyles.changeOnColor
55
+ : getChangeColor(change)), children: [_jsxs("span", { className: "sr-only", children: ["Change: ", getChangeText(change)] }), _jsx("span", { className: "inline-block", "aria-hidden": "true", children: getChangeIcon(change) }), _jsx("span", { children: getChangeText(change) })] })) : subtitle ? (_jsx("div", { className: cn(subtitleSlot.className, isColorful
56
+ ? metricCardStyles.subtitleOnColor
57
+ : metricCardStyles.subtitleMuted), children: subtitle })) : null }))] }) }));
54
58
  }
55
59
  export { MetricCard };
@@ -1,3 +1,4 @@
1
+ import type { SlotStyles } from "@kala-ui/react/lib/slot-styles";
1
2
  import type { MetricCardSkeletonConfig } from "@kala-ui/react/skeleton";
2
3
  import type * as React from "react";
3
4
  export interface MetricCardProps extends Omit<React.ComponentProps<"div">, "title"> {
@@ -11,4 +12,6 @@ export interface MetricCardProps extends Omit<React.ComponentProps<"div">, "titl
11
12
  isLoading?: boolean;
12
13
  skeletonConfig?: MetricCardSkeletonConfig;
13
14
  skeleton?: React.ReactNode;
15
+ /** Per-part overrides: root, body, head, title, icon, value, meta, change, subtitle. */
16
+ slotStyles?: SlotStyles;
14
17
  }
@@ -1 +1,2 @@
1
- export * from "./nav-link";
1
+ export { NavLink } from "./nav-link";
2
+ export type { NavLinkProps } from "./nav-link.types";
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- export * from "./nav-link.js";
2
+ export { NavLink } from "./nav-link.js";