@uniweb/kit 0.1.5 → 0.1.6

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 (30) hide show
  1. package/package.json +3 -2
  2. package/src/components/Asset/Asset.jsx +31 -81
  3. package/src/components/Media/Media.jsx +27 -125
  4. package/src/components/SocialIcon/index.jsx +146 -0
  5. package/src/hooks/index.js +6 -0
  6. package/src/hooks/useAccordion.js +143 -0
  7. package/src/hooks/useActiveRoute.js +97 -0
  8. package/src/hooks/useGridLayout.js +71 -0
  9. package/src/hooks/useMobileMenu.js +58 -0
  10. package/src/hooks/useScrolled.js +48 -0
  11. package/src/hooks/useTheme.js +205 -0
  12. package/src/index.js +29 -10
  13. package/src/styled/Asset/Asset.jsx +161 -0
  14. package/src/styled/Asset/index.js +1 -0
  15. package/src/{components → styled}/Disclaimer/Disclaimer.jsx +1 -1
  16. package/src/styled/Media/Media.jsx +322 -0
  17. package/src/styled/Media/index.js +1 -0
  18. package/src/{components → styled}/Section/Render.jsx +4 -4
  19. package/src/{components → styled}/Section/index.js +6 -0
  20. package/src/{components → styled}/Section/renderers/Alert.jsx +1 -1
  21. package/src/{components → styled}/Section/renderers/Details.jsx +1 -1
  22. package/src/{components → styled}/Section/renderers/Table.jsx +1 -1
  23. package/src/{components → styled}/Section/renderers/index.js +1 -1
  24. package/src/styled/SidebarLayout/SidebarLayout.jsx +310 -0
  25. package/src/styled/SidebarLayout/index.js +1 -0
  26. package/src/styled/index.js +40 -0
  27. /package/src/{components → styled}/Disclaimer/index.js +0 -0
  28. /package/src/{components → styled}/Section/Section.jsx +0 -0
  29. /package/src/{components → styled}/Section/renderers/Code.jsx +0 -0
  30. /package/src/{components → styled}/Section/renderers/Divider.jsx +0 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * useAccordion Hook
3
+ *
4
+ * Manages expand/collapse state for accordion-style UIs.
5
+ * Used in FAQ components and collapsible navigation (LeftPanel).
6
+ *
7
+ * @example
8
+ * // Single-select accordion (only one item open at a time)
9
+ * function FAQ({ items }) {
10
+ * const { isOpen, toggle } = useAccordion()
11
+ *
12
+ * return items.map((item, i) => (
13
+ * <div key={i}>
14
+ * <button onClick={() => toggle(i)}>{item.question}</button>
15
+ * {isOpen(i) && <p>{item.answer}</p>}
16
+ * </div>
17
+ * ))
18
+ * }
19
+ *
20
+ * @example
21
+ * // Multi-select with first item open
22
+ * const { isOpen, toggle } = useAccordion({
23
+ * multiple: true,
24
+ * defaultOpen: [0]
25
+ * })
26
+ *
27
+ * @example
28
+ * // All items open by default
29
+ * const { isOpen, toggle, openAll, closeAll } = useAccordion({
30
+ * multiple: true,
31
+ * defaultOpen: 'all',
32
+ * items: faqItems // needed when using 'all'
33
+ * })
34
+ */
35
+
36
+ import { useState, useCallback } from 'react'
37
+
38
+ /**
39
+ * Hook to manage accordion expand/collapse state.
40
+ *
41
+ * @param {Object} options - Configuration options
42
+ * @param {boolean} [options.multiple=false] - Allow multiple items open at once
43
+ * @param {Array|string} [options.defaultOpen=[]] - Initially open items (indices or 'all')
44
+ * @param {Array} [options.items] - Items array (needed for defaultOpen: 'all')
45
+ * @returns {Object} Accordion state and controls
46
+ */
47
+ export function useAccordion(options = {}) {
48
+ const {
49
+ multiple = false,
50
+ defaultOpen = [],
51
+ items = [],
52
+ } = options
53
+
54
+ // Compute initial open state
55
+ const getInitialOpen = () => {
56
+ if (defaultOpen === 'all' && items.length > 0) {
57
+ return items.map((_, i) => i)
58
+ }
59
+ if (Array.isArray(defaultOpen)) {
60
+ return defaultOpen
61
+ }
62
+ return []
63
+ }
64
+
65
+ const [openItems, setOpenItems] = useState(getInitialOpen)
66
+
67
+ /**
68
+ * Check if an item is open
69
+ * @param {number|string} id - Item identifier (index or key)
70
+ * @returns {boolean}
71
+ */
72
+ const isOpen = useCallback((id) => {
73
+ return openItems.includes(id)
74
+ }, [openItems])
75
+
76
+ /**
77
+ * Toggle an item open/closed
78
+ * @param {number|string} id - Item identifier
79
+ */
80
+ const toggle = useCallback((id) => {
81
+ setOpenItems(prev => {
82
+ if (prev.includes(id)) {
83
+ // Close this item
84
+ return prev.filter(item => item !== id)
85
+ }
86
+ if (multiple) {
87
+ // Add to open items
88
+ return [...prev, id]
89
+ }
90
+ // Single select: replace open item
91
+ return [id]
92
+ })
93
+ }, [multiple])
94
+
95
+ /**
96
+ * Open a specific item
97
+ * @param {number|string} id - Item identifier
98
+ */
99
+ const open = useCallback((id) => {
100
+ setOpenItems(prev => {
101
+ if (prev.includes(id)) return prev
102
+ if (multiple) return [...prev, id]
103
+ return [id]
104
+ })
105
+ }, [multiple])
106
+
107
+ /**
108
+ * Close a specific item
109
+ * @param {number|string} id - Item identifier
110
+ */
111
+ const close = useCallback((id) => {
112
+ setOpenItems(prev => prev.filter(item => item !== id))
113
+ }, [])
114
+
115
+ /**
116
+ * Open all items (only works in multiple mode)
117
+ * @param {Array} allIds - All item identifiers
118
+ */
119
+ const openAll = useCallback((allIds) => {
120
+ if (multiple && Array.isArray(allIds)) {
121
+ setOpenItems(allIds)
122
+ }
123
+ }, [multiple])
124
+
125
+ /**
126
+ * Close all items
127
+ */
128
+ const closeAll = useCallback(() => {
129
+ setOpenItems([])
130
+ }, [])
131
+
132
+ return {
133
+ openItems,
134
+ isOpen,
135
+ toggle,
136
+ open,
137
+ close,
138
+ openAll,
139
+ closeAll,
140
+ }
141
+ }
142
+
143
+ export default useAccordion
@@ -0,0 +1,97 @@
1
+ /**
2
+ * useActiveRoute Hook
3
+ *
4
+ * SSG-safe hook for active route detection in navigation components.
5
+ * Provides utilities for checking if pages are active or ancestors of the current route.
6
+ *
7
+ * @example
8
+ * function NavItem({ page }) {
9
+ * const { isActiveOrAncestor } = useActiveRoute()
10
+ *
11
+ * return (
12
+ * <Link
13
+ * href={page.getNavigableRoute()}
14
+ * className={isActiveOrAncestor(page) ? 'active' : ''}
15
+ * >
16
+ * {page.label}
17
+ * </Link>
18
+ * )
19
+ * }
20
+ */
21
+
22
+ import { useRouting } from './useRouting.js'
23
+
24
+ /**
25
+ * Normalize a route by removing leading/trailing slashes
26
+ * @param {string} route
27
+ * @returns {string}
28
+ */
29
+ function normalizeRoute(route) {
30
+ return (route || '').replace(/^\//, '').replace(/\/$/, '')
31
+ }
32
+
33
+ /**
34
+ * Hook for active route detection with SSG-safe fallbacks.
35
+ *
36
+ * @returns {Object} Route utilities
37
+ * @property {string} route - Current normalized route (e.g., 'docs/getting-started')
38
+ * @property {string} rootSegment - First segment of route (e.g., 'docs')
39
+ * @property {function} isActive - Check if a page is the current page
40
+ * @property {function} isActiveOrAncestor - Check if a page or its descendants are active
41
+ */
42
+ export function useActiveRoute() {
43
+ const { useLocation } = useRouting()
44
+ const location = useLocation()
45
+
46
+ const route = normalizeRoute(location?.pathname)
47
+ const rootSegment = route.split('/')[0]
48
+
49
+ return {
50
+ /**
51
+ * Current normalized route (no leading/trailing slashes)
52
+ * @type {string}
53
+ */
54
+ route,
55
+
56
+ /**
57
+ * First segment of the current route
58
+ * Useful for root-level navigation highlighting
59
+ * @type {string}
60
+ */
61
+ rootSegment,
62
+
63
+ /**
64
+ * Check if a page is the current active page (exact match)
65
+ *
66
+ * @param {Object} page - Page object with getNormalizedRoute() or route property
67
+ * @returns {boolean}
68
+ */
69
+ isActive: (page) => {
70
+ if (typeof page.getNormalizedRoute === 'function') {
71
+ return page.getNormalizedRoute() === route
72
+ }
73
+ // Fallback for page info objects from getPageHierarchy
74
+ return normalizeRoute(page.route) === route
75
+ },
76
+
77
+ /**
78
+ * Check if a page or any of its descendants is active
79
+ * Useful for highlighting parent nav items when child is active
80
+ *
81
+ * @param {Object} page - Page object with isActiveOrAncestor() or route property
82
+ * @returns {boolean}
83
+ */
84
+ isActiveOrAncestor: (page) => {
85
+ if (typeof page.isActiveOrAncestor === 'function') {
86
+ return page.isActiveOrAncestor(route)
87
+ }
88
+ // Fallback for page info objects from getPageHierarchy
89
+ const pageRoute = normalizeRoute(page.route)
90
+ if (pageRoute === route) return true
91
+ if (pageRoute === '') return true // Root is ancestor of all
92
+ return route.startsWith(pageRoute + '/')
93
+ },
94
+ }
95
+ }
96
+
97
+ export default useActiveRoute
@@ -0,0 +1,71 @@
1
+ /**
2
+ * useGridLayout Hook
3
+ *
4
+ * Returns Tailwind CSS classes for responsive grid layouts.
5
+ * Standardizes the grid column patterns used across components.
6
+ *
7
+ * @example
8
+ * function Features({ items, params }) {
9
+ * const gridClass = useGridLayout(params.columns)
10
+ *
11
+ * return (
12
+ * <div className={gridClass}>
13
+ * {items.map(item => <FeatureCard key={item.id} {...item} />)}
14
+ * </div>
15
+ * )
16
+ * }
17
+ *
18
+ * @example
19
+ * // With custom gap
20
+ * const gridClass = useGridLayout(3, { gap: 12 })
21
+ * // Returns: "grid gap-12 sm:grid-cols-2 lg:grid-cols-3"
22
+ */
23
+
24
+ /**
25
+ * Standard responsive grid column configurations.
26
+ * Keys are column counts, values are Tailwind classes.
27
+ */
28
+ const GRID_CONFIGS = {
29
+ 1: '',
30
+ 2: 'sm:grid-cols-2',
31
+ 3: 'sm:grid-cols-2 lg:grid-cols-3',
32
+ 4: 'sm:grid-cols-2 lg:grid-cols-4',
33
+ 5: 'sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5',
34
+ 6: 'sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-6',
35
+ }
36
+
37
+ /**
38
+ * Hook to generate responsive grid layout classes.
39
+ *
40
+ * @param {number} columns - Number of columns (1-6)
41
+ * @param {Object} options - Configuration options
42
+ * @param {number} [options.gap=8] - Gap size (Tailwind scale: 4, 6, 8, 10, 12)
43
+ * @param {string} [options.baseClass='grid'] - Base class to include
44
+ * @returns {string} Tailwind CSS classes for the grid
45
+ */
46
+ export function useGridLayout(columns = 3, options = {}) {
47
+ const {
48
+ gap = 8,
49
+ baseClass = 'grid',
50
+ } = options
51
+
52
+ const colConfig = GRID_CONFIGS[columns] || GRID_CONFIGS[3]
53
+ const gapClass = `gap-${gap}`
54
+
55
+ return [baseClass, gapClass, colConfig].filter(Boolean).join(' ')
56
+ }
57
+
58
+ /**
59
+ * Get grid classes without the hook (for non-React contexts)
60
+ * @param {number} columns
61
+ * @param {Object} options
62
+ * @returns {string}
63
+ */
64
+ export function getGridClasses(columns = 3, options = {}) {
65
+ const { gap = 8, baseClass = 'grid' } = options
66
+ const colConfig = GRID_CONFIGS[columns] || GRID_CONFIGS[3]
67
+ const gapClass = `gap-${gap}`
68
+ return [baseClass, gapClass, colConfig].filter(Boolean).join(' ')
69
+ }
70
+
71
+ export default useGridLayout
@@ -0,0 +1,58 @@
1
+ /**
2
+ * useMobileMenu Hook
3
+ *
4
+ * Manages mobile menu state with automatic close on route change.
5
+ * Common pattern in Header/Navbar components across all templates.
6
+ *
7
+ * @example
8
+ * function Header() {
9
+ * const { isOpen, toggle, close } = useMobileMenu()
10
+ *
11
+ * return (
12
+ * <>
13
+ * <button onClick={toggle}>Menu</button>
14
+ * {isOpen && (
15
+ * <nav>
16
+ * <Link href="/about" onClick={close}>About</Link>
17
+ * </nav>
18
+ * )}
19
+ * </>
20
+ * )
21
+ * }
22
+ */
23
+
24
+ import { useState, useEffect, useCallback } from 'react'
25
+ import { useActiveRoute } from './useActiveRoute.js'
26
+
27
+ /**
28
+ * Hook to manage mobile menu state.
29
+ * Automatically closes menu on route change.
30
+ *
31
+ * @returns {Object} Menu state and controls
32
+ * @property {boolean} isOpen - Whether menu is open
33
+ * @property {function} open - Open the menu
34
+ * @property {function} close - Close the menu
35
+ * @property {function} toggle - Toggle menu open/closed
36
+ */
37
+ export function useMobileMenu() {
38
+ const [isOpen, setIsOpen] = useState(false)
39
+ const { route } = useActiveRoute()
40
+
41
+ // Close menu on route change
42
+ useEffect(() => {
43
+ setIsOpen(false)
44
+ }, [route])
45
+
46
+ const open = useCallback(() => setIsOpen(true), [])
47
+ const close = useCallback(() => setIsOpen(false), [])
48
+ const toggle = useCallback(() => setIsOpen(prev => !prev), [])
49
+
50
+ return {
51
+ isOpen,
52
+ open,
53
+ close,
54
+ toggle,
55
+ }
56
+ }
57
+
58
+ export default useMobileMenu
@@ -0,0 +1,48 @@
1
+ /**
2
+ * useScrolled Hook
3
+ *
4
+ * Detects scroll position for sticky header effects.
5
+ * Common pattern in Header components across all templates.
6
+ *
7
+ * @example
8
+ * function Header() {
9
+ * const scrolled = useScrolled()
10
+ * return (
11
+ * <header className={scrolled ? 'bg-white shadow' : 'bg-transparent'}>
12
+ * ...
13
+ * </header>
14
+ * )
15
+ * }
16
+ *
17
+ * @example
18
+ * // With custom threshold
19
+ * const scrolled = useScrolled(50) // triggers after 50px scroll
20
+ */
21
+
22
+ import { useState, useEffect } from 'react'
23
+
24
+ /**
25
+ * Hook to detect if page has scrolled past a threshold.
26
+ *
27
+ * @param {number} threshold - Scroll position threshold in pixels (default: 0)
28
+ * @returns {boolean} Whether scroll position is past threshold
29
+ */
30
+ export function useScrolled(threshold = 0) {
31
+ const [scrolled, setScrolled] = useState(false)
32
+
33
+ useEffect(() => {
34
+ const handleScroll = () => {
35
+ setScrolled(window.scrollY > threshold)
36
+ }
37
+
38
+ // Check initial state
39
+ handleScroll()
40
+
41
+ window.addEventListener('scroll', handleScroll, { passive: true })
42
+ return () => window.removeEventListener('scroll', handleScroll)
43
+ }, [threshold])
44
+
45
+ return scrolled
46
+ }
47
+
48
+ export default useScrolled
@@ -0,0 +1,205 @@
1
+ /**
2
+ * useTheme Hook
3
+ *
4
+ * Provides standardized theme classes for components.
5
+ * Eliminates duplicated theme objects across 25+ components.
6
+ *
7
+ * @example
8
+ * function Hero({ params }) {
9
+ * const t = useTheme(params.theme)
10
+ *
11
+ * return (
12
+ * <section className={t.section}>
13
+ * <h1 className={t.title}>...</h1>
14
+ * <p className={t.body}>...</p>
15
+ * </section>
16
+ * )
17
+ * }
18
+ *
19
+ * @example
20
+ * // With custom overrides
21
+ * const t = useTheme('dark', {
22
+ * card: 'bg-gray-800 rounded-xl',
23
+ * cardHover: 'hover:bg-gray-700'
24
+ * })
25
+ */
26
+
27
+ /**
28
+ * Standard theme definitions.
29
+ * Keys are standardized across all components.
30
+ */
31
+ const THEMES = {
32
+ light: {
33
+ // Section backgrounds
34
+ section: 'bg-white',
35
+ sectionAlt: 'bg-gray-50',
36
+
37
+ // Typography
38
+ title: 'text-gray-900',
39
+ subtitle: 'text-gray-700',
40
+ pretitle: 'text-primary',
41
+ body: 'text-gray-600',
42
+ muted: 'text-gray-500',
43
+
44
+ // Cards
45
+ card: 'bg-gray-50',
46
+ cardHover: 'hover:shadow-lg',
47
+ cardBorder: 'border border-gray-200',
48
+
49
+ // Interactive
50
+ link: 'text-primary hover:text-primary-dark',
51
+ linkMuted: 'text-gray-600 hover:text-gray-900',
52
+
53
+ // Borders & Dividers
54
+ border: 'border-gray-200',
55
+ divider: 'bg-gray-200',
56
+ },
57
+
58
+ gray: {
59
+ section: 'bg-gray-50',
60
+ sectionAlt: 'bg-gray-100',
61
+
62
+ title: 'text-gray-900',
63
+ subtitle: 'text-gray-700',
64
+ pretitle: 'text-primary',
65
+ body: 'text-gray-600',
66
+ muted: 'text-gray-500',
67
+
68
+ card: 'bg-white shadow-sm',
69
+ cardHover: 'hover:shadow-lg',
70
+ cardBorder: 'border border-gray-200',
71
+
72
+ link: 'text-primary hover:text-primary-dark',
73
+ linkMuted: 'text-gray-600 hover:text-gray-900',
74
+
75
+ border: 'border-gray-200',
76
+ divider: 'bg-gray-300',
77
+ },
78
+
79
+ dark: {
80
+ section: 'bg-gray-900',
81
+ sectionAlt: 'bg-gray-800',
82
+
83
+ title: 'text-white',
84
+ subtitle: 'text-gray-300',
85
+ pretitle: 'text-primary',
86
+ body: 'text-gray-400',
87
+ muted: 'text-gray-500',
88
+
89
+ card: 'bg-gray-800',
90
+ cardHover: 'hover:bg-gray-750',
91
+ cardBorder: 'border border-gray-700',
92
+
93
+ link: 'text-primary hover:text-primary-light',
94
+ linkMuted: 'text-gray-400 hover:text-white',
95
+
96
+ border: 'border-gray-700',
97
+ divider: 'bg-gray-700',
98
+ },
99
+
100
+ primary: {
101
+ section: 'bg-primary',
102
+ sectionAlt: 'bg-primary-dark',
103
+
104
+ title: 'text-white',
105
+ subtitle: 'text-white/90',
106
+ pretitle: 'text-white/80',
107
+ body: 'text-white/80',
108
+ muted: 'text-white/60',
109
+
110
+ card: 'bg-white/10',
111
+ cardHover: 'hover:bg-white/20',
112
+ cardBorder: 'border border-white/20',
113
+
114
+ link: 'text-white hover:text-white/80',
115
+ linkMuted: 'text-white/70 hover:text-white',
116
+
117
+ border: 'border-white/20',
118
+ divider: 'bg-white/20',
119
+ },
120
+
121
+ gradient: {
122
+ section: 'bg-gradient-to-br from-primary to-indigo-600',
123
+ sectionAlt: 'bg-gradient-to-br from-primary-dark to-indigo-700',
124
+
125
+ title: 'text-white',
126
+ subtitle: 'text-white/90',
127
+ pretitle: 'text-white/80',
128
+ body: 'text-white/80',
129
+ muted: 'text-white/60',
130
+
131
+ card: 'bg-white/10 backdrop-blur-sm',
132
+ cardHover: 'hover:bg-white/20',
133
+ cardBorder: 'border border-white/20',
134
+
135
+ link: 'text-white hover:text-white/80',
136
+ linkMuted: 'text-white/70 hover:text-white',
137
+
138
+ border: 'border-white/20',
139
+ divider: 'bg-white/20',
140
+ },
141
+
142
+ glass: {
143
+ section: 'bg-white/10 backdrop-blur-lg',
144
+ sectionAlt: 'bg-white/5 backdrop-blur-lg',
145
+
146
+ title: 'text-white',
147
+ subtitle: 'text-white/90',
148
+ pretitle: 'text-primary',
149
+ body: 'text-white/80',
150
+ muted: 'text-white/60',
151
+
152
+ card: 'bg-white/10 backdrop-blur-sm',
153
+ cardHover: 'hover:bg-white/20',
154
+ cardBorder: 'border border-white/20',
155
+
156
+ link: 'text-white hover:text-primary',
157
+ linkMuted: 'text-white/70 hover:text-white',
158
+
159
+ border: 'border-white/20',
160
+ divider: 'bg-white/20',
161
+ },
162
+ }
163
+
164
+ /**
165
+ * Hook to get theme classes by name.
166
+ *
167
+ * @param {string} themeName - Theme name (light, gray, dark, primary, gradient, glass)
168
+ * @param {Object} overrides - Custom class overrides
169
+ * @returns {Object} Theme classes object
170
+ */
171
+ export function useTheme(themeName = 'light', overrides = {}) {
172
+ const baseTheme = THEMES[themeName] || THEMES.light
173
+
174
+ if (Object.keys(overrides).length === 0) {
175
+ return baseTheme
176
+ }
177
+
178
+ return {
179
+ ...baseTheme,
180
+ ...overrides,
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Get theme classes without the hook (for non-React contexts)
186
+ * @param {string} themeName
187
+ * @param {Object} overrides
188
+ * @returns {Object}
189
+ */
190
+ export function getThemeClasses(themeName = 'light', overrides = {}) {
191
+ const baseTheme = THEMES[themeName] || THEMES.light
192
+ return { ...baseTheme, ...overrides }
193
+ }
194
+
195
+ /**
196
+ * All available theme names
197
+ */
198
+ export const THEME_NAMES = Object.keys(THEMES)
199
+
200
+ /**
201
+ * Export theme definitions for customization
202
+ */
203
+ export { THEMES }
204
+
205
+ export default useTheme
package/src/index.js CHANGED
@@ -3,6 +3,9 @@
3
3
  *
4
4
  * Standard component library for Uniweb foundations.
5
5
  *
6
+ * For pre-styled components (Section, SidebarLayout, Disclaimer, etc.),
7
+ * import from '@uniweb/kit/styled'.
8
+ *
6
9
  * @example
7
10
  * import { Link, Image, useWebsite } from '@uniweb/kit'
8
11
  *
@@ -18,10 +21,10 @@
18
21
  */
19
22
 
20
23
  // ============================================================================
21
- // Components
24
+ // Components (Primitives - no Tailwind dependency)
22
25
  // ============================================================================
23
26
 
24
- // Primitives
27
+ // Navigation
25
28
  export { Link } from './components/Link/index.js'
26
29
  export { Image } from './components/Image/index.js'
27
30
  export { SafeHtml } from './components/SafeHtml/index.js'
@@ -35,24 +38,40 @@ export {
35
38
  PlainText
36
39
  } from './components/Text/index.js'
37
40
 
38
- // Media
41
+ // Media (plain version - for styled facade, use @uniweb/kit/tailwind)
39
42
  export { Media } from './components/Media/index.js'
40
43
  export { FileLogo } from './components/FileLogo/index.js'
41
44
  export { MediaIcon } from './components/MediaIcon/index.js'
42
45
 
43
- // Content
44
- export { Section, Render } from './components/Section/index.js'
45
- export { Code, Alert, Warning, Table, Details, Divider } from './components/Section/renderers/index.js'
46
-
47
- // Utilities
46
+ // Files (plain version - for styled card, use @uniweb/kit/tailwind)
48
47
  export { Asset } from './components/Asset/index.js'
49
- export { Disclaimer } from './components/Disclaimer/index.js'
48
+
49
+ // Social
50
+ export {
51
+ SocialIcon,
52
+ getSocialPlatform,
53
+ isSocialLink,
54
+ filterSocialLinks
55
+ } from './components/SocialIcon/index.jsx'
50
56
 
51
57
  // ============================================================================
52
58
  // Hooks
53
59
  // ============================================================================
54
60
 
55
- export { useWebsite, useRouting } from './hooks/index.js'
61
+ export {
62
+ useWebsite,
63
+ useRouting,
64
+ useActiveRoute,
65
+ useScrolled,
66
+ useMobileMenu,
67
+ useAccordion,
68
+ useGridLayout,
69
+ getGridClasses,
70
+ useTheme,
71
+ getThemeClasses,
72
+ THEMES,
73
+ THEME_NAMES
74
+ } from './hooks/index.js'
56
75
 
57
76
  // ============================================================================
58
77
  // Utilities