@axzydev/axzy_ui_system 1.4.1 → 1.4.3
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.
- package/README.md +2 -2
- package/dist/index.cjs +422 -259
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +169 -70
- package/dist/index.d.ts +169 -70
- package/dist/index.js +324 -162
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/App.tsx +3 -0
- package/src/components/molecules/card/card.tsx +22 -9
- package/src/components/organisms/page-header/page-header.tsx +14 -3
- package/src/components/organisms/sidebar/sidebar.doc.mdx +48 -2
- package/src/components/organisms/sidebar/sidebar.props.ts +58 -3
- package/src/components/organisms/sidebar/sidebar.stories.tsx +59 -1
- package/src/components/organisms/sidebar/sidebar.tsx +141 -25
- package/src/components/organisms/topbar/topbar.props.ts +7 -0
- package/src/components/organisms/topbar/topbar.tsx +31 -8
- package/src/components/templates/layout/layout.props.ts +8 -0
- package/src/components/templates/layout/layout.tsx +101 -54
- package/src/components/theme-provider/themeProvider.doc.mdx +1 -0
- package/src/components/theme-provider/themeProvider.props.ts +6 -0
- package/src/components/theme-provider/themeProvider.tsx +11 -1
- package/src/index.ts +6 -5
- package/src/sandbox/LandingShowcase.tsx +1 -1
- package/src/sandbox/navigation.ts +1 -0
- package/src/showcases/HelpShowcase.tsx +497 -0
- package/src/showcases/StructureShowcases.tsx +58 -5
- package/src/theme/theme-context.ts +11 -1
- package/src/theme/theme.types.ts +7 -0
|
@@ -3,6 +3,7 @@ import useClickOutside from "@/hooks/useClickOutside";
|
|
|
3
3
|
import { useRef, useState } from "react";
|
|
4
4
|
import { ITTopBarProps } from "./topbar.props";
|
|
5
5
|
import ITText from "@/components/atoms/text/text";
|
|
6
|
+
import { useITFlatAppearance } from "@/theme/theme-context";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* ITTopBar — sticky top navigation bar with logo, nav items, and user avatar dropdown.
|
|
@@ -67,7 +68,16 @@ export default function ITTopBar({
|
|
|
67
68
|
onToggleMobileMenu,
|
|
68
69
|
navItems,
|
|
69
70
|
onNavItemClick,
|
|
71
|
+
hideBrandOnDesktop = false,
|
|
70
72
|
}: ITTopBarProps) {
|
|
73
|
+
// Flat appearance: plain bar (no shadow/blur), initials avatar, name before it.
|
|
74
|
+
const flat = useITFlatAppearance();
|
|
75
|
+
const initials = (userMenu?.userName ?? "")
|
|
76
|
+
.trim()
|
|
77
|
+
.split(/\s+/)
|
|
78
|
+
.slice(0, 2)
|
|
79
|
+
.map((word) => word.charAt(0).toUpperCase())
|
|
80
|
+
.join("");
|
|
71
81
|
const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
|
|
72
82
|
const userMenuRef = useRef<HTMLDivElement>(null);
|
|
73
83
|
|
|
@@ -75,14 +85,14 @@ export default function ITTopBar({
|
|
|
75
85
|
|
|
76
86
|
return (
|
|
77
87
|
<header
|
|
78
|
-
className=
|
|
88
|
+
className={`sticky top-0 z-40 transition-all duration-300 ${flat ? "" : "backdrop-blur-md"}`}
|
|
79
89
|
style={{
|
|
80
90
|
backgroundColor: "var(--it-topbar-bg, rgba(255, 255, 255, 0.9))",
|
|
81
91
|
borderBottom: "1px solid var(--it-topbar-border, rgba(15, 23, 42, 0.06))",
|
|
82
|
-
boxShadow: "var(--shadow-xs)",
|
|
92
|
+
boxShadow: flat ? "none" : "var(--shadow-xs)",
|
|
83
93
|
}}
|
|
84
94
|
>
|
|
85
|
-
<div className=
|
|
95
|
+
<div className={`flex items-center justify-between px-6 lg:px-8 ${flat ? "h-[64px]" : "h-[72px]"}`}>
|
|
86
96
|
|
|
87
97
|
{/* LEFT AREA: Logo & Mobile Toggle */}
|
|
88
98
|
<div className="flex items-center gap-5">
|
|
@@ -103,7 +113,7 @@ export default function ITTopBar({
|
|
|
103
113
|
)}
|
|
104
114
|
|
|
105
115
|
{/* Logo */}
|
|
106
|
-
<div className=
|
|
116
|
+
<div className={`items-center gap-3 ${hideBrandOnDesktop ? "flex lg:hidden" : "flex"}`}>
|
|
107
117
|
{logo && (
|
|
108
118
|
<div className="flex-shrink-0 drop-shadow-sm">
|
|
109
119
|
{logo}
|
|
@@ -153,7 +163,7 @@ export default function ITTopBar({
|
|
|
153
163
|
`justify-between` has nothing left to distribute: the logo/nav and
|
|
154
164
|
the user menu stay flush with the row edges. */}
|
|
155
165
|
{centerContent && (
|
|
156
|
-
<div className=
|
|
166
|
+
<div className={`hidden lg:flex flex-1 min-w-0 items-center ${hideBrandOnDesktop ? "justify-start pr-4" : "justify-center px-4"}`}>
|
|
157
167
|
<div className="w-full max-w-[420px]">{centerContent}</div>
|
|
158
168
|
</div>
|
|
159
169
|
)}
|
|
@@ -169,7 +179,7 @@ export default function ITTopBar({
|
|
|
169
179
|
<div className="relative">
|
|
170
180
|
<button
|
|
171
181
|
type="button"
|
|
172
|
-
className=
|
|
182
|
+
className={`flex items-center gap-3 rounded-full py-1.5 transition-all duration-200 ease-[cubic-bezier(0.2,0,0,1)] border border-transparent hover:border-secondary-200 ${flat ? "flex-row-reverse pl-4 pr-2" : "pl-2 pr-4"}`}
|
|
173
183
|
style={{
|
|
174
184
|
backgroundColor: isUserMenuOpen ? "var(--it-topbar-user-hover, #f1f5f9)" : "transparent",
|
|
175
185
|
}}
|
|
@@ -189,17 +199,30 @@ export default function ITTopBar({
|
|
|
189
199
|
src={userMenu.userImage}
|
|
190
200
|
alt="Current user"
|
|
191
201
|
/>
|
|
202
|
+
) : flat && initials ? (
|
|
203
|
+
<div
|
|
204
|
+
aria-hidden="true"
|
|
205
|
+
className="w-9 h-9 rounded-full flex items-center justify-center text-[0.8rem] font-semibold"
|
|
206
|
+
style={{
|
|
207
|
+
backgroundColor: "color-mix(in srgb, var(--color-primary, #3b82f6) 14%, transparent)",
|
|
208
|
+
color: "var(--color-primary, #2563eb)",
|
|
209
|
+
}}
|
|
210
|
+
>
|
|
211
|
+
{initials}
|
|
212
|
+
</div>
|
|
192
213
|
) : (
|
|
193
214
|
<div className="w-9 h-9 rounded-full bg-slate-100 flex items-center justify-center ring-2 ring-white shadow-sm">
|
|
194
215
|
<FaUserCircle className="w-6 h-6" style={{ color: "var(--it-topbar-icon, #94a3b8)" }} />
|
|
195
216
|
</div>
|
|
196
217
|
)}
|
|
197
218
|
{/* Active dot indicator */}
|
|
198
|
-
|
|
219
|
+
{!flat && (
|
|
220
|
+
<div className="absolute bottom-0 right-0 w-2.5 h-2.5 bg-green-500 border-2 border-white rounded-full"></div>
|
|
221
|
+
)}
|
|
199
222
|
</div>
|
|
200
223
|
|
|
201
224
|
{/* Name Details */}
|
|
202
|
-
<div className=
|
|
225
|
+
<div className={`hidden sm:flex flex-col py-0.5 ${flat ? "text-right" : "text-left"}`}>
|
|
203
226
|
<ITText as="span"
|
|
204
227
|
className="font-semibold text-[0.85rem] leading-tight"
|
|
205
228
|
style={{ color: "var(--it-topbar-user-text, #0f172a)" }}
|
|
@@ -12,4 +12,12 @@ export interface ITLayoutProps {
|
|
|
12
12
|
className?: string;
|
|
13
13
|
/** Additional CSS classes for the content container */
|
|
14
14
|
contentClassName?: string;
|
|
15
|
+
/**
|
|
16
|
+
* App-shell arrangement. `false` (default): the top bar spans the full width
|
|
17
|
+
* and the sidebar sits below it. `true`: the sidebar spans the full viewport
|
|
18
|
+
* height and shows the brand (`topBar.logo` + `topBar.logoText`) at its top,
|
|
19
|
+
* while the top bar covers only the content column and drops the logo from
|
|
20
|
+
* the `lg` breakpoint up. Mobile is unchanged. @default false
|
|
21
|
+
*/
|
|
22
|
+
sidebarFullHeight?: boolean;
|
|
15
23
|
}
|
|
@@ -4,6 +4,7 @@ import ITTopBar from "@/components/organisms/topbar/topbar";
|
|
|
4
4
|
import ITSidebar from "@/components/organisms/sidebar/sidebar";
|
|
5
5
|
import { ITLayoutProps } from "./layout.props";
|
|
6
6
|
import { theme } from "@/theme/theme";
|
|
7
|
+
import { useITFlatAppearance } from "@/theme/theme-context";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Main application shell with sidebar, topbar, and content area.
|
|
@@ -27,6 +28,16 @@ import { theme } from "@/theme/theme";
|
|
|
27
28
|
* >
|
|
28
29
|
* <SettingsPage />
|
|
29
30
|
* </ITLayout>
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Full-height sidebar with the brand on top; the top bar covers only the content.
|
|
34
|
+
* <ITLayout
|
|
35
|
+
* sidebarFullHeight
|
|
36
|
+
* topBar={{ logo: <Logo />, logoText: "Acme", centerContent: <SearchBox /> }}
|
|
37
|
+
* sidebar={{ navigationItems, isCollapsed: false }}
|
|
38
|
+
* >
|
|
39
|
+
* <Dashboard />
|
|
40
|
+
* </ITLayout>
|
|
30
41
|
*/
|
|
31
42
|
export default function ITLayout({
|
|
32
43
|
topBar,
|
|
@@ -34,77 +45,113 @@ export default function ITLayout({
|
|
|
34
45
|
children,
|
|
35
46
|
className = "",
|
|
36
47
|
contentClassName = "",
|
|
48
|
+
sidebarFullHeight = false,
|
|
37
49
|
}: ITLayoutProps) {
|
|
38
50
|
const [internalCollapsed, setInternalCollapsed] = useState(true);
|
|
39
51
|
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
|
|
52
|
+
const flat = useITFlatAppearance();
|
|
40
53
|
|
|
41
54
|
const isControlled = sidebar.isCollapsed !== undefined;
|
|
42
55
|
const desktopCollapsed = isControlled ? sidebar.isCollapsed : internalCollapsed;
|
|
43
56
|
const handleToggleCollapse = isControlled ? (sidebar.onToggleCollapse ?? (() => {})) : () => setInternalCollapsed(v => !v);
|
|
44
57
|
|
|
45
58
|
const layoutTokens = theme.layout;
|
|
59
|
+
// Must match ITSidebar's own at-rest width (88px rail / 280px, 248px when flat).
|
|
60
|
+
const reservedWidth = desktopCollapsed ? "w-[88px]" : flat ? "w-[248px]" : "w-[280px]";
|
|
61
|
+
// With a full-height sidebar the brand moves from the top bar to the sidebar.
|
|
62
|
+
const brand = sidebarFullHeight
|
|
63
|
+
? (sidebar.brand ?? { logo: topBar.logo, text: topBar.logoText })
|
|
64
|
+
: sidebar.brand;
|
|
46
65
|
|
|
47
|
-
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
66
|
+
const topBarNode = (
|
|
67
|
+
<ITTopBar
|
|
68
|
+
{...topBar}
|
|
69
|
+
hideBrandOnDesktop={sidebarFullHeight || topBar.hideBrandOnDesktop}
|
|
70
|
+
showMobileMenuButton
|
|
71
|
+
onToggleMobileMenu={() => setMobileSidebarOpen(v => !v)}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
54
74
|
|
|
75
|
+
const desktopSidebar = (
|
|
76
|
+
// Full-height: the sidebar sits beside the top bar, so it needs to win the
|
|
77
|
+
// stacking order when the collapsed rail expands over the content on hover.
|
|
78
|
+
<div className={`hidden lg:block relative h-full ${sidebarFullHeight ? "z-50" : "z-40"}`}>
|
|
79
|
+
{/* Reserves the sidebar's at-rest width. When the sidebar is collapsed
|
|
80
|
+
(default), this is the 88px rail and hover expands over the content.
|
|
81
|
+
When controlled-expanded (`sidebar.isCollapsed === false`), it
|
|
82
|
+
reserves the full width so the sidebar never overlays content. */}
|
|
83
|
+
<div className={`${reservedWidth} h-full flex-shrink-0`} />
|
|
84
|
+
<div className="absolute top-0 left-0 h-full">
|
|
85
|
+
<ITSidebar
|
|
86
|
+
{...sidebar}
|
|
87
|
+
brand={brand}
|
|
88
|
+
isCollapsed={desktopCollapsed}
|
|
89
|
+
onToggleCollapse={handleToggleCollapse}
|
|
90
|
+
visibleOnMobile={false}
|
|
91
|
+
className={`h-full ${flat ? "" : "drop-shadow-2xl"} transition-all duration-400 ease-[cubic-bezier(0.2,0,0,1)] flex-shrink-0`}
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const mobileSidebar = mobileSidebarOpen && (
|
|
98
|
+
<div
|
|
99
|
+
className="lg:hidden fixed inset-0 z-[40] transition-opacity duration-300 backdrop-blur-sm bg-black/40"
|
|
100
|
+
onClick={() => setMobileSidebarOpen(false)}
|
|
101
|
+
>
|
|
55
102
|
<div
|
|
56
|
-
className="flex
|
|
103
|
+
className="h-full w-fit flex transform transition-transform duration-300 ease-[cubic-bezier(0.2,0,0,1)]"
|
|
104
|
+
onClick={(e) => e.stopPropagation()}
|
|
105
|
+
>
|
|
106
|
+
<ITSidebar
|
|
107
|
+
{...sidebar}
|
|
108
|
+
brand={brand}
|
|
109
|
+
isCollapsed={false}
|
|
110
|
+
visibleOnMobile={true}
|
|
111
|
+
className="h-full shadow-2xl relative z-[60]"
|
|
112
|
+
onToggleCollapse={() => setMobileSidebarOpen(false)}
|
|
113
|
+
onItemClick={() => setMobileSidebarOpen(false)}
|
|
114
|
+
onSubItemClick={() => setMobileSidebarOpen(false)}
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const main = (
|
|
121
|
+
<main className="flex-1 overflow-y-auto w-full custom-scrollbar relative z-0">
|
|
122
|
+
<div className={clsx("mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8 py-6 h-full", contentClassName)}>
|
|
123
|
+
{children}
|
|
124
|
+
</div>
|
|
125
|
+
</main>
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
if (sidebarFullHeight) {
|
|
129
|
+
return (
|
|
130
|
+
<div
|
|
131
|
+
className={`flex h-screen overflow-hidden w-full relative ${className}`}
|
|
57
132
|
style={{ backgroundColor: layoutTokens.backgroundColor }}
|
|
58
133
|
>
|
|
59
|
-
{
|
|
60
|
-
<div className="
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
When controlled-expanded (`sidebar.isCollapsed === false`), it
|
|
64
|
-
reserves the full 280px so the sidebar never overlays content. */}
|
|
65
|
-
<div
|
|
66
|
-
className={`${desktopCollapsed ? "w-[88px]" : "w-[280px]"} h-full flex-shrink-0`}
|
|
67
|
-
/>
|
|
68
|
-
<div className="absolute top-0 left-0 h-full">
|
|
69
|
-
<ITSidebar
|
|
70
|
-
{...sidebar}
|
|
71
|
-
isCollapsed={desktopCollapsed}
|
|
72
|
-
onToggleCollapse={handleToggleCollapse}
|
|
73
|
-
visibleOnMobile={false}
|
|
74
|
-
className="h-full drop-shadow-2xl transition-all duration-400 ease-[cubic-bezier(0.2,0,0,1)] flex-shrink-0"
|
|
75
|
-
/>
|
|
76
|
-
</div>
|
|
134
|
+
{desktopSidebar}
|
|
135
|
+
<div className="flex flex-col flex-1 min-w-0 overflow-hidden">
|
|
136
|
+
{topBarNode}
|
|
137
|
+
{main}
|
|
77
138
|
</div>
|
|
139
|
+
{mobileSidebar}
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
78
143
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
className="lg:hidden fixed inset-0 z-[40] transition-opacity duration-300 backdrop-blur-sm bg-black/40"
|
|
83
|
-
onClick={() => setMobileSidebarOpen(false)}
|
|
84
|
-
>
|
|
85
|
-
<div
|
|
86
|
-
className="h-full w-fit flex transform transition-transform duration-300 ease-[cubic-bezier(0.2,0,0,1)]"
|
|
87
|
-
onClick={(e) => e.stopPropagation()}
|
|
88
|
-
>
|
|
89
|
-
<ITSidebar
|
|
90
|
-
{...sidebar}
|
|
91
|
-
isCollapsed={false}
|
|
92
|
-
visibleOnMobile={true}
|
|
93
|
-
className="h-full shadow-2xl relative z-[60]"
|
|
94
|
-
onToggleCollapse={() => setMobileSidebarOpen(false)}
|
|
95
|
-
onItemClick={() => setMobileSidebarOpen(false)}
|
|
96
|
-
onSubItemClick={() => setMobileSidebarOpen(false)}
|
|
97
|
-
/>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
)}
|
|
144
|
+
return (
|
|
145
|
+
<div className={`flex flex-col h-screen overflow-hidden w-full ${className}`}>
|
|
146
|
+
{topBarNode}
|
|
101
147
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
148
|
+
<div
|
|
149
|
+
className="flex flex-1 overflow-hidden relative"
|
|
150
|
+
style={{ backgroundColor: layoutTokens.backgroundColor }}
|
|
151
|
+
>
|
|
152
|
+
{desktopSidebar}
|
|
153
|
+
{mobileSidebar}
|
|
154
|
+
{main}
|
|
108
155
|
</div>
|
|
109
156
|
</div>
|
|
110
157
|
);
|
|
@@ -17,6 +17,7 @@ Root theme context that injects CSS custom properties into the entire component
|
|
|
17
17
|
| `density` | `number` | `1` | Global density/compactness factor: values below `1` shrink base sizes (fonts, paddings, gaps), above `1` grow them. Applies by scaling the root font-size so every `rem`-based token compacts together while the layout stays fluid. Clamped to `0.5`–`1.5`. |
|
|
18
18
|
| `radius` | `number` | — | Global border radius in **px** applied to the whole rounding scale. `2` ⇒ 2px corners (near-square), `8` ⇒ 8px, `0` ⇒ square. No override when omitted (Tailwind defaults). |
|
|
19
19
|
| `shadow` | `number` | `2` | Global shadow strength level: `0` ⇒ none, `1` ⇒ subtle, `2` ⇒ default current look, `3` ⇒ pronounced. No override when omitted (keeps defaults). |
|
|
20
|
+
| `appearance` | `"soft" \| "flat"` | `"soft"` | Visual language. `"flat"` switches `ITCard`, `ITSidebar`, `ITTopBar` and `ITPageHeader` to flat surfaces (hairline borders, no shadows, no header icon tile) and sets `data-it-appearance` on `<html>`. Read it in your own components with `useITFlatAppearance()`. |
|
|
20
21
|
|
|
21
22
|
### ITThemePalette Shape
|
|
22
23
|
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type { ITThemeAppearance } from "@/theme/theme.types";
|
|
2
|
+
|
|
3
|
+
export type { ITThemeAppearance };
|
|
4
|
+
|
|
1
5
|
export interface ITThemePalette {
|
|
2
6
|
/** Main brand accent color (hex). Drives primary buttons, active nav items, focus rings, links, and the `--color-primary` CSS variable. @default "#06b6d4" */
|
|
3
7
|
primary: string;
|
|
@@ -54,4 +58,6 @@ export interface ITThemeProviderProps {
|
|
|
54
58
|
radius?: number;
|
|
55
59
|
/** Global shadow strength level. `0` ⇒ no shadows, `1` ⇒ subtle, `2` ⇒ default current look, `3` ⇒ pronounced. Shadows are injected as `--shadow-*`/`.shadow-*` overrides so cards, dropdowns and dialogs follow the level. @default 2 (keeps current default when omitted) */
|
|
56
60
|
shadow?: number;
|
|
61
|
+
/** Visual language of the whole system. `"soft"` keeps the current look (floating cards, tinted shadows, glass sidebar/top bar). `"flat"` switches the app shell and surfaces to flat ones: hairline borders instead of shadows on `ITCard`, a plain `ITSidebar` (no glow, no accent bar, narrower), a plain `ITTopBar` (no shadow, initials avatar) and a compact `ITPageHeader` without the icon tile. It also sets `data-it-appearance` on `<html>` so app CSS can follow it. Combine it with `shadow` and `radius` to finish the look. @default "soft" */
|
|
62
|
+
appearance?: ITThemeAppearance;
|
|
57
63
|
}
|
|
@@ -73,7 +73,7 @@ import { DEFAULT_PALETTE, PRESETS } from "./themePresets";
|
|
|
73
73
|
// Contexto y hooks (useITTheme / useITThemeSafe) viven en @/theme/theme-context.
|
|
74
74
|
// Re-exportados desde aquí para mantener compatibilidad de la API pública.
|
|
75
75
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
76
|
-
export { useITTheme, useITThemeSafe } from "@/theme/theme-context";
|
|
76
|
+
export { useITTheme, useITThemeSafe, useITFlatAppearance } from "@/theme/theme-context";
|
|
77
77
|
|
|
78
78
|
const getNestedValue = (obj: any, path: string) => {
|
|
79
79
|
return path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
|
@@ -143,6 +143,7 @@ export default function ITThemeProvider({
|
|
|
143
143
|
density = 1,
|
|
144
144
|
radius,
|
|
145
145
|
shadow,
|
|
146
|
+
appearance = "soft",
|
|
146
147
|
}: ITThemeProviderProps) {
|
|
147
148
|
const [palette, setPaletteState] = useState<ITThemePalette>(() => {
|
|
148
149
|
const basePalette = {
|
|
@@ -276,6 +277,14 @@ export default function ITThemeProvider({
|
|
|
276
277
|
};
|
|
277
278
|
}, [density]);
|
|
278
279
|
|
|
280
|
+
// Lenguaje visual: se publica en <html> para que el CSS de la app pueda
|
|
281
|
+
// seguirlo; los componentes lo leen del contexto (useITFlatAppearance).
|
|
282
|
+
useLayoutEffect(() => {
|
|
283
|
+
const root = document.documentElement;
|
|
284
|
+
root.setAttribute("data-it-appearance", appearance);
|
|
285
|
+
return () => root.removeAttribute("data-it-appearance");
|
|
286
|
+
}, [appearance]);
|
|
287
|
+
|
|
279
288
|
// Overrides globales de radius y sombras.
|
|
280
289
|
// Radius: en Tailwind v4 cada `rounded-*` resuelve a var(--radius-*), así que
|
|
281
290
|
// setear los vars en :root (en px) cuadra/redondea todo el sistema sin tocar
|
|
@@ -1611,6 +1620,7 @@ export default function ITThemeProvider({
|
|
|
1611
1620
|
resolvedTheme,
|
|
1612
1621
|
darkModeMode,
|
|
1613
1622
|
setDarkModeMode,
|
|
1623
|
+
appearance,
|
|
1614
1624
|
}}
|
|
1615
1625
|
>
|
|
1616
1626
|
{children}
|
package/src/index.ts
CHANGED
|
@@ -103,7 +103,7 @@ import type { ITSearchSelectProps } from "./components/molecules/search-select/s
|
|
|
103
103
|
import type { ITSelectProps } from "./components/molecules/select/select.props";
|
|
104
104
|
import type { ITSearchTableProps } from "./components/organisms/searchTable/searchTable.props";
|
|
105
105
|
import type { ITSegmentedControlProps } from "./components/atoms/segmented-control/segmented-control.props";
|
|
106
|
-
import type { ITSidebarProps, ITNavigationItem, ITNavigationSubItem, ITNavigationSubItemEntry, ITNavigationSubItemGroup } from "./components/organisms/sidebar/sidebar.props";
|
|
106
|
+
import type { ITSidebarProps, ITSidebarNotification, ITSidebarBrand, ITNavigationItem, ITNavigationSubItem, ITNavigationSubItemEntry, ITNavigationSubItemGroup } from "./components/organisms/sidebar/sidebar.props";
|
|
107
107
|
import type { ITSkeletonProps } from "./components/atoms/skeleton/skeleton.props";
|
|
108
108
|
import type { ITSlideToggleProps } from "./components/atoms/slide/slide.props";
|
|
109
109
|
import type { ITSliderProps } from "./components/atoms/slider/slider.props";
|
|
@@ -127,8 +127,8 @@ import ITLoader from "./components/atoms/loader/loader";
|
|
|
127
127
|
import type { LoaderProps as ITLoaderProps } from "./components/atoms/loader/loader.props";
|
|
128
128
|
import ITStepper from "./components/molecules/stepper/stepper";
|
|
129
129
|
import type { ITStepperProps } from "./components/molecules/stepper/stepper.props";
|
|
130
|
-
import ITThemeProvider, { useITTheme, useITThemeSafe } from "./components/theme-provider/themeProvider";
|
|
131
|
-
import type { ITThemeProviderProps, ITThemePalette } from "./components/theme-provider/themeProvider.props";
|
|
130
|
+
import ITThemeProvider, { useITTheme, useITThemeSafe, useITFlatAppearance } from "./components/theme-provider/themeProvider";
|
|
131
|
+
import type { ITThemeProviderProps, ITThemePalette, ITThemeAppearance } from "./components/theme-provider/themeProvider.props";
|
|
132
132
|
import ITTimePicker from "./components/molecules/time-picker/timePicker";
|
|
133
133
|
import type { ITTimePickerProps } from "./components/molecules/time-picker/timePicker.props";
|
|
134
134
|
import type { ITThemeConfig } from "./theme/theme.types";
|
|
@@ -153,7 +153,7 @@ export {
|
|
|
153
153
|
ITSearchTable,
|
|
154
154
|
ITSegmentedControl, ITSidebar, ITSkeleton, ITSlideToggle, ITSlider, ITStack, ITStatCard, ITStepper,
|
|
155
155
|
ITTable, ITTabs, ITText, ITTextarea, ITTripleFilter, ITThemeProvider,
|
|
156
|
-
useITTheme, useITThemeSafe, ITTimePicker, ITToast, ITWysiwyg,
|
|
156
|
+
useITTheme, useITThemeSafe, useITFlatAppearance, ITTimePicker, ITToast, ITWysiwyg,
|
|
157
157
|
UploadStatus, FileTypeEnum,
|
|
158
158
|
getContrastTextColor, isLightColor, resolveCssColor
|
|
159
159
|
};
|
|
@@ -176,6 +176,7 @@ export {
|
|
|
176
176
|
ITPageProps, ITPageHeaderProps,
|
|
177
177
|
ITNavigationItem, ITNavigationSubItem,
|
|
178
178
|
ITNavigationSubItemEntry, ITNavigationSubItemGroup,
|
|
179
|
+
ITSidebarNotification, ITSidebarBrand,
|
|
179
180
|
ITPaginationProps, ITPopoverProps, ITProgressProps,
|
|
180
181
|
ITRadioGroupProps, ITRadioOption, ITSelectProps, ITSearchSelectProps,
|
|
181
182
|
ITSearchTableProps,
|
|
@@ -183,7 +184,7 @@ export {
|
|
|
183
184
|
ITStackProps, ITStatCardProps, ITStepperProps,
|
|
184
185
|
ITTableProps, ITTabsProps, ITTabItem, ITTextProps, ITTextareaProps,
|
|
185
186
|
TableDensity,
|
|
186
|
-
ITTripleFilterProps, ITTripleFilterOption, ITThemeConfig, ITThemeProviderProps, ITThemePalette,
|
|
187
|
+
ITTripleFilterProps, ITTripleFilterOption, ITThemeConfig, ITThemeProviderProps, ITThemePalette, ITThemeAppearance,
|
|
187
188
|
ITTimePickerProps, ITToastProps,
|
|
188
189
|
ITWysiwygProps,
|
|
189
190
|
UseTableStateOptions, UseTableStateResult
|
|
@@ -72,7 +72,7 @@ const GROUP_ACCENTS = [
|
|
|
72
72
|
"from-primary-500 to-purple-500",
|
|
73
73
|
];
|
|
74
74
|
|
|
75
|
-
const GITHUB_URL = "https://github.com/
|
|
75
|
+
const GITHUB_URL = "https://github.com/maag070208/AXZY_UI_SYSTEM";
|
|
76
76
|
const INSTALL_CMD = "pnpm add @axzydev/axzy_ui_system";
|
|
77
77
|
|
|
78
78
|
/**
|