@flusys/ng-layout 6.3.0 → 6.4.1
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 +152 -11
- package/assets/layout/base/_brand.scss +44 -0
- package/assets/layout/{_core.scss → base/_core.scss} +8 -1
- package/assets/layout/{_footer.scss → base/_footer.scss} +1 -1
- package/assets/layout/{_forms.scss → base/_forms.scss} +3 -3
- package/assets/layout/base/_menu.scss +52 -0
- package/assets/layout/base/_rtl.scss +230 -0
- package/assets/layout/base/_topbar.scss +132 -0
- package/assets/layout/base/variables/_common.scss +62 -0
- package/assets/layout/classic/_main.scss +14 -0
- package/assets/layout/classic/_menu.scss +77 -0
- package/assets/layout/classic/_responsive.scss +95 -0
- package/assets/layout/classic/_rtl.scss +26 -0
- package/assets/layout/classic/_topbar.scss +53 -0
- package/assets/layout/{_topbar_nav.scss → classic/_topbar_nav.scss} +45 -17
- package/assets/layout/classic/classic.scss +6 -0
- package/assets/layout/layout.scss +18 -16
- package/assets/layout/modern/_menu.scss +98 -0
- package/assets/layout/modern/_responsive.scss +93 -0
- package/assets/layout/modern/_rtl.scss +24 -0
- package/assets/layout/modern/_shell.scss +59 -0
- package/assets/layout/modern/_sidebar.scss +101 -0
- package/assets/layout/modern/_topbar.scss +37 -0
- package/assets/layout/modern/_variables.scss +114 -0
- package/assets/layout/modern/modern.scss +7 -0
- package/fesm2022/flusys-ng-layout.mjs +1353 -954
- package/fesm2022/flusys-ng-layout.mjs.map +1 -1
- package/package.json +4 -4
- package/types/flusys-ng-layout.d.ts +175 -65
- package/assets/layout/_main.scss +0 -13
- package/assets/layout/_menu.scss +0 -188
- package/assets/layout/_responsive.scss +0 -128
- package/assets/layout/_rtl.scss +0 -482
- package/assets/layout/_topbar.scss +0 -215
- package/assets/layout/variables/_common.scss +0 -20
- /package/assets/layout/{_mixins.scss → base/_mixins.scss} +0 -0
- /package/assets/layout/{_preloading.scss → base/_preloading.scss} +0 -0
- /package/assets/layout/{_typography.scss → base/_typography.scss} +0 -0
- /package/assets/layout/{_utils.scss → base/_utils.scss} +0 -0
- /package/assets/layout/{variables → base/variables}/_dark.scss +0 -0
- /package/assets/layout/{variables → base/variables}/_light.scss +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @flusys/ng-layout
|
|
2
2
|
|
|
3
|
-
Application shell for the FLUSYS Angular platform — topbar, sidebar, menu, and signal-based layout state management.
|
|
3
|
+
Application shell for the FLUSYS Angular platform — topbar, sidebar, menu, and signal-based layout state management. Ships two interchangeable layout skins (**classic** and **modern**) that share the same services, menu and topbar components.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@flusys/ng-layout)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -21,21 +21,21 @@ Use `AppLayout` as the parent route component. All authenticated pages become ch
|
|
|
21
21
|
|
|
22
22
|
```typescript
|
|
23
23
|
// app.routes.ts
|
|
24
|
-
import { Routes } from
|
|
25
|
-
import { AppLayout } from
|
|
24
|
+
import { Routes } from "@angular/router";
|
|
25
|
+
import { AppLayout } from "@flusys/ng-layout";
|
|
26
26
|
|
|
27
27
|
export const routes: Routes = [
|
|
28
28
|
{
|
|
29
|
-
path:
|
|
29
|
+
path: "",
|
|
30
30
|
component: AppLayout,
|
|
31
31
|
children: [
|
|
32
|
-
{ path:
|
|
33
|
-
{ path:
|
|
32
|
+
{ path: "dashboard", loadComponent: () => import("./pages/dashboard.component") },
|
|
33
|
+
{ path: "products", loadComponent: () => import("./pages/product-list.component") },
|
|
34
34
|
],
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
|
-
path:
|
|
38
|
-
loadChildren: () => import(
|
|
37
|
+
path: "auth",
|
|
38
|
+
loadChildren: () => import("./pages/auth/auth.routes"),
|
|
39
39
|
},
|
|
40
40
|
];
|
|
41
41
|
```
|
|
@@ -64,7 +64,148 @@ To push user/company profile into the topbar (done automatically by `ng-auth`'s
|
|
|
64
64
|
|
|
65
65
|
---
|
|
66
66
|
|
|
67
|
-
## 3.
|
|
67
|
+
## 3. Layout Skins
|
|
68
|
+
|
|
69
|
+
`AppLayout` renders the skin selected by `LayoutConfig.layoutTheme`. Both skins share every
|
|
70
|
+
service and topbar component — only the shell markup and styling differ, so switching costs
|
|
71
|
+
nothing but a config value.
|
|
72
|
+
|
|
73
|
+
| Skin | Shell | Menu modes |
|
|
74
|
+
| --------- | ---------------------------------------------------------------------------------- | ----------------------- |
|
|
75
|
+
| `classic` | Fixed topbar across the top, sidebar below it, page content in the remaining space | static, overlay, topbar |
|
|
76
|
+
| `modern` | Gradient canvas, transparent sidebar, page content in an elevated rounded card | static, overlay |
|
|
77
|
+
|
|
78
|
+
Set the default in `APP_CONFIG`:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
export const environment: IAppConfig = {
|
|
82
|
+
layoutConfig: {
|
|
83
|
+
layoutTheme: "modern", // 'classic' (default) | 'modern'
|
|
84
|
+
menuMode: "static",
|
|
85
|
+
},
|
|
86
|
+
// ...
|
|
87
|
+
};
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Users can switch skins at runtime from the theme configurator; the choice is persisted with the
|
|
91
|
+
rest of the layout config unless `isMemorable: false`. Read it back through the service:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
readonly theme = this.layout.layoutTheme; // Signal<'classic' | 'modern'>
|
|
95
|
+
readonly isModern = this.layout.isModernLayout; // Signal<boolean>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`menuMode: 'topbar'` renders a horizontal nav, which only the classic skin provides — the modern
|
|
99
|
+
skin falls back to its static sidebar. The nav scrolls when it outgrows the bar, with its native
|
|
100
|
+
scrollbar hidden and replaced by an overlay thumb that fades in on hover — out of the flow, so it
|
|
101
|
+
cannot take height from the row and knock the menu items off centre.
|
|
102
|
+
|
|
103
|
+
The menu toggle belongs to the sidebar modes, and `LayoutService.onMenuToggle()` decides what it
|
|
104
|
+
acts on from the current mode and viewport:
|
|
105
|
+
|
|
106
|
+
| Mode | What the toggle does |
|
|
107
|
+
| ------------------- | ------------------------------------------------------------- |
|
|
108
|
+
| any mode, mobile | Opens/closes the sidebar drawer over a mask |
|
|
109
|
+
| `static`, desktop | Collapses/restores the sidebar in place |
|
|
110
|
+
| `overlay`, desktop | Slides the sidebar in/out over the content |
|
|
111
|
+
| `topbar`, desktop | No toggle — there is no sidebar to collapse, so it is hidden |
|
|
112
|
+
|
|
113
|
+
### Source layout
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
components/
|
|
117
|
+
app.layout.ts # skin switcher — the component you route to
|
|
118
|
+
shared/ # used by every skin
|
|
119
|
+
layout-shell.base.ts # shared open/close, outside-click and body-scroll behaviour
|
|
120
|
+
app.brand-logo.ts # logo + company name home link
|
|
121
|
+
app.menu.ts # menu tree, configurator, footer
|
|
122
|
+
top-bar/
|
|
123
|
+
app.topbar-actions.ts # the whole trailing action rail (search, theme, widgets)
|
|
124
|
+
layouts/classic/ # classic shell — bar, brand block, horizontal nav, sidebar
|
|
125
|
+
layouts/modern/ # modern shell — bar, brand block, page title, sidebar
|
|
126
|
+
|
|
127
|
+
assets/layout/
|
|
128
|
+
base/ # tokens, core, typography, forms, brand, topbar, menu, footer, rtl, utils
|
|
129
|
+
classic/ # classic skin styling
|
|
130
|
+
modern/ # modern skin styling
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
A skin owns only the parts that actually differ. The brand block, the topbar action rail and
|
|
134
|
+
the menu tree are one component and one stylesheet each, shared by every skin; `base/_topbar.scss`
|
|
135
|
+
and `base/_menu.scss` hold their structure and read the tokens below, and a skin retunes them by
|
|
136
|
+
overriding a token on its own shell class rather than restating the rules.
|
|
137
|
+
|
|
138
|
+
Every colour in both skins resolves from the active `@flusys/ng-ui` theme variables, so preset,
|
|
139
|
+
primary, surface and dark-mode changes repaint the shell automatically.
|
|
140
|
+
|
|
141
|
+
### Preset-driven chrome
|
|
142
|
+
|
|
143
|
+
A `@flusys/ng-ui` preset (Aura / Lara / Nora) publishes structural tokens alongside its colours,
|
|
144
|
+
and both skins read them — so switching preset restyles the shell, not just the components inside
|
|
145
|
+
it. The classic skin uses them directly; the modern skin clamps each one into its own range with
|
|
146
|
+
`min()` / `max()`, so its card and rows stay softer than a classic sidebar's while a square preset
|
|
147
|
+
still squares them.
|
|
148
|
+
|
|
149
|
+
| Preset token | Classic | Modern |
|
|
150
|
+
| ----------------------------------- | ---------------------------------- | ----------------------------------------------------------------------- |
|
|
151
|
+
| `--f-card-border-radius` | components inside the page | `--layout-modern-radius` — the content card, its topbar and its content |
|
|
152
|
+
| `--f-menuitem-active-radius` | active menu row radius | `--layout-modern-item-radius` — capped at the skin's own `0.625rem` |
|
|
153
|
+
| `--f-menuitem-active-border-width` | accent bar on the active row | same accent bar, drawn in the row's own ink |
|
|
154
|
+
| `--f-topbar-border-width` | topbar bottom border | `--layout-modern-topbar-border-width` — floored at a hairline |
|
|
155
|
+
| `--f-topbar-shadow` | topbar shadow | topbar shadow |
|
|
156
|
+
| `--f-sidebar-border-width` | sidebar trailing border | `--layout-modern-divider-width` — the sidebar footer's divider |
|
|
157
|
+
| `--f-sidebar-radius` / `-shadow` | sidebar corner and shadow | — (this skin's sidebar is transparent on the canvas) |
|
|
158
|
+
| `--f-border-radius-lg` | components inside the page | `--layout-modern-control-radius` — the drawer's collapse button |
|
|
159
|
+
|
|
160
|
+
Every length a preset publishes carries a unit (`0px`, never `0`), because a bare `0` is a
|
|
161
|
+
`<number>` inside `min()` / `max()` / `calc()` and would invalidate the whole expression.
|
|
162
|
+
|
|
163
|
+
A neutral primary — the `noir` swatch, and Nora's signature colour — resolves the primary ramp to
|
|
164
|
+
the surface greys, which would leave the modern skin's canvas too pale for the white ink on top.
|
|
165
|
+
`applyPrimaryPalette` marks the root with `f-primary-noir` for exactly this case (CSS cannot branch
|
|
166
|
+
on a custom property's value), and the skin anchors its canvas in the dark end of the ramp instead.
|
|
167
|
+
|
|
168
|
+
### Shell geometry tokens
|
|
169
|
+
|
|
170
|
+
Both skins size themselves from one set of CSS variables declared in
|
|
171
|
+
`assets/layout/base/variables/_common.scss` — nothing hardcodes a width, height or z-index, so
|
|
172
|
+
overriding a token in your own stylesheet resizes the shell in both skins at once.
|
|
173
|
+
|
|
174
|
+
| Token | Default | Used for |
|
|
175
|
+
| ------------------------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------- |
|
|
176
|
+
| `--layout-viewport-height` | `100dvh` | Full-height shells — a fixed sidebar always fills exactly 100% |
|
|
177
|
+
| `--layout-topbar-height` | `4rem` | Topbar height, sidebar offset, content padding, dropdown top |
|
|
178
|
+
| `--layout-topbar-inline-padding` | `--layout-content-padding` | Topbar gutters, and where the compact widget menu hangs from |
|
|
179
|
+
| `--layout-topbar-actions-gap` | `1rem` | Space between the action rail's groups |
|
|
180
|
+
| `--layout-topbar-group-gap` | `1rem` | Space inside a group (theme controls, widget menu) |
|
|
181
|
+
| `--layout-topbar-action-size` | `2.5rem` | Diameter of a round topbar action button |
|
|
182
|
+
| `--layout-topbar-action-icon-size` | `1.25rem` | Icon size inside those buttons |
|
|
183
|
+
| `--layout-sidebar-width` | `19rem` | Sidebar width and the content margin that clears it |
|
|
184
|
+
| `--layout-content-padding` | `2rem` | Page gutters |
|
|
185
|
+
| `--layout-shell-topbar-bottom` | `--layout-topbar-height` | Where the topbar ends — shared widgets pin full-width overlays here (the modern skin adds its card margin) |
|
|
186
|
+
| `--layout-content-viewport-height` | `viewport − topbar-bottom` | The space left under the topbar — the classic sidebar, pinned below the topbar, fills exactly this |
|
|
187
|
+
| `--layout-topbar-z` | `997` | Stacking order: topbar under mask under sidebar |
|
|
188
|
+
| `--layout-mask-z` | `998` | |
|
|
189
|
+
| `--layout-sidebar-z` | `999` | |
|
|
190
|
+
|
|
191
|
+
```css
|
|
192
|
+
:root {
|
|
193
|
+
--layout-sidebar-width: 18rem; /* narrower sidebar, everything else follows */
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The modern skin overrides the topbar tokens on `.layout-modern` (a taller bar, tighter gaps,
|
|
198
|
+
smaller icons) and adds its own `--layout-modern-*` tokens for the pieces that have no shared
|
|
199
|
+
equivalent — gradient canvas, card radius, its narrower sidebar. Everything else it inherits.
|
|
200
|
+
|
|
201
|
+
Both skins' shells are written with CSS logical properties, so RTL needs no mirrored copy of the
|
|
202
|
+
layout rules; `classic/_rtl.scss` and `modern/_rtl.scss` only flip the drawer `transform`, which
|
|
203
|
+
has no logical equivalent, and `base/_rtl.scss` carries the component-library corrections that
|
|
204
|
+
are not tied to a skin.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## 4. Integration Tokens — Auth, Notifications, Language
|
|
68
209
|
|
|
69
210
|
Connect feature packages to the layout via injection tokens. Register them in `app.config.ts`.
|
|
70
211
|
|
|
@@ -86,10 +227,10 @@ The layout reads these tokens to render topbar slots without directly importing
|
|
|
86
227
|
|
|
87
228
|
---
|
|
88
229
|
|
|
89
|
-
##
|
|
230
|
+
## 5. Clear Persisted Layout
|
|
90
231
|
|
|
91
232
|
```typescript
|
|
92
|
-
import { LayoutPersistenceService } from
|
|
233
|
+
import { LayoutPersistenceService } from "@flusys/ng-layout";
|
|
93
234
|
|
|
94
235
|
inject(LayoutPersistenceService).clear(); // removes flusys.layout.config from localStorage
|
|
95
236
|
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
@use 'mixins' as *;
|
|
2
|
+
|
|
3
|
+
// Shared <app-brand-logo> markup. The host is `display: contents`, so the anchor
|
|
4
|
+
// below is the flex item of whichever bar renders it. Every skin gets the same
|
|
5
|
+
// treatment — a full-size mark next to a slightly oversized name, which still reads
|
|
6
|
+
// as the brand on its own when no logo is configured.
|
|
7
|
+
.layout-brand-logo {
|
|
8
|
+
display: inline-flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
gap: 0.5rem;
|
|
11
|
+
min-width: 0;
|
|
12
|
+
flex-shrink: 0;
|
|
13
|
+
color: var(--text-color);
|
|
14
|
+
border-radius: var(--content-border-radius);
|
|
15
|
+
font-size: 1.5rem;
|
|
16
|
+
font-weight: 500;
|
|
17
|
+
|
|
18
|
+
.logo-image {
|
|
19
|
+
height: 2.5rem;
|
|
20
|
+
width: auto;
|
|
21
|
+
max-width: 3rem;
|
|
22
|
+
object-fit: contain;
|
|
23
|
+
flex-shrink: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// The name is the first thing to give up room on a narrow bar; skins that keep a
|
|
27
|
+
// full-width brand row (the modern drawer) reveal it again.
|
|
28
|
+
span {
|
|
29
|
+
display: none;
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
text-overflow: ellipsis;
|
|
32
|
+
white-space: nowrap;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&:focus-visible {
|
|
36
|
+
@include focused();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@media (min-width: 640px) {
|
|
41
|
+
.layout-brand-logo span {
|
|
42
|
+
display: inline;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -20,7 +20,14 @@ a {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.layout-wrapper {
|
|
23
|
-
min-height:
|
|
23
|
+
min-height: var(--layout-viewport-height);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Set by LayoutShellBase while a mobile drawer is open — shared by every skin. */
|
|
27
|
+
@media (max-width: 991px) {
|
|
28
|
+
.blocked-scroll {
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
}
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
@keyframes scalein {
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
/* Native select element */
|
|
6
6
|
select.ui-select {
|
|
7
7
|
width: 100%;
|
|
8
|
-
padding: 0.5rem 2.5rem 0.5rem 0.75rem;
|
|
8
|
+
padding: var(--f-field-padding-y, 0.5rem) 2.5rem var(--f-field-padding-y, 0.5rem) var(--f-field-padding-x, 0.75rem);
|
|
9
9
|
font-size: 1rem;
|
|
10
10
|
font-family: inherit;
|
|
11
11
|
background: var(--f-form-field-background, #ffffff);
|
|
12
|
-
border: 1px solid var(--f-form-field-border-color, #d1d5db);
|
|
13
|
-
border-radius: var(--f-border-radius
|
|
12
|
+
border: var(--f-border-width, 1px) solid var(--f-form-field-border-color, #d1d5db);
|
|
13
|
+
border-radius: var(--f-field-border-radius, 6px);
|
|
14
14
|
color: var(--f-text-color, #374151);
|
|
15
15
|
transition: border-color 0.2s, box-shadow 0.2s;
|
|
16
16
|
appearance: none;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Structure of the shared <app-menu> markup — list reset and row layout. Every skin
|
|
2
|
+
// renders this same tree, so only the look (colours, padding, indentation) belongs in
|
|
3
|
+
// a skin file.
|
|
4
|
+
// Written with logical properties throughout, which is what keeps the menu correct
|
|
5
|
+
// in RTL without a mirrored copy of these rules.
|
|
6
|
+
.layout-menu {
|
|
7
|
+
margin: 0;
|
|
8
|
+
padding: 0;
|
|
9
|
+
list-style-type: none;
|
|
10
|
+
|
|
11
|
+
a {
|
|
12
|
+
user-select: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
ul {
|
|
16
|
+
margin: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
list-style-type: none;
|
|
19
|
+
|
|
20
|
+
a {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
position: relative;
|
|
24
|
+
outline: 0 none;
|
|
25
|
+
color: var(--text-color);
|
|
26
|
+
cursor: pointer;
|
|
27
|
+
transition:
|
|
28
|
+
background-color var(--element-transition-duration),
|
|
29
|
+
box-shadow var(--element-transition-duration);
|
|
30
|
+
|
|
31
|
+
.layout-menuitem-icon {
|
|
32
|
+
margin-inline-end: 0.5rem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.layout-submenu-toggler {
|
|
36
|
+
font-size: 75%;
|
|
37
|
+
margin-inline-start: auto;
|
|
38
|
+
transition: transform var(--element-transition-duration);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// An expanded submenu flips its chevron. Shared by every skin whose menu is a
|
|
45
|
+
// vertical list — a new skin joins the selector list. The classic horizontal nav is
|
|
46
|
+
// deliberately left out: it opens submenus on hover and its chevron points sideways.
|
|
47
|
+
.layout-sidebar .layout-menu,
|
|
48
|
+
.layout-modern-sidebar .layout-menu {
|
|
49
|
+
li.active-menuitem > a .layout-submenu-toggler {
|
|
50
|
+
transform: rotate(-180deg);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// RTL corrections that are not tied to a layout skin — component library widgets and
|
|
2
|
+
// the utility classes pages use directly. Anything the shell itself needs is written
|
|
3
|
+
// with logical properties instead, so it mirrors without a rule here.
|
|
4
|
+
html[dir='rtl'] {
|
|
5
|
+
// Flip navigation arrows
|
|
6
|
+
.pi-chevron-left::before {
|
|
7
|
+
content: '\e901'; // pi-chevron-right icon code
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.pi-chevron-right::before {
|
|
11
|
+
content: '\e900'; // pi-chevron-left icon code
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Calendar grid direction
|
|
15
|
+
.calendar-month .grid,
|
|
16
|
+
.calendar-week .grid,
|
|
17
|
+
.calendar-day {
|
|
18
|
+
direction: rtl;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Calendar day - time column should align left in RTL (visually on right side)
|
|
22
|
+
.calendar-day .pr-2 {
|
|
23
|
+
padding-right: 0 !important;
|
|
24
|
+
padding-left: 0.5rem !important;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.calendar-day .border-r {
|
|
28
|
+
border-right: none !important;
|
|
29
|
+
border-left: var(--f-border-width, 1px) solid var(--surface-border) !important;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Form labels and inputs
|
|
33
|
+
.p-float-label > label {
|
|
34
|
+
left: auto;
|
|
35
|
+
right: 0.75rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Checkbox/radio alignment
|
|
39
|
+
.p-checkbox,
|
|
40
|
+
.p-radiobutton {
|
|
41
|
+
margin-right: 0;
|
|
42
|
+
margin-left: 0.5rem;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Button icons
|
|
46
|
+
.p-button-icon-left {
|
|
47
|
+
margin-right: 0;
|
|
48
|
+
margin-left: 0.5rem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.p-button-icon-right {
|
|
52
|
+
margin-left: 0;
|
|
53
|
+
margin-right: 0.5rem;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Table - full RTL support
|
|
57
|
+
.p-datatable {
|
|
58
|
+
direction: rtl;
|
|
59
|
+
|
|
60
|
+
.p-datatable-thead > tr > th,
|
|
61
|
+
.p-datatable-tbody > tr > td {
|
|
62
|
+
text-align: right;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Actions column (usually last) should be left-aligned
|
|
66
|
+
.p-datatable-thead > tr > th:last-child,
|
|
67
|
+
.p-datatable-tbody > tr > td:last-child {
|
|
68
|
+
text-align: left;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Paginator - rotate navigation icons
|
|
72
|
+
.p-paginator {
|
|
73
|
+
.p-paginator-first,
|
|
74
|
+
.p-paginator-prev,
|
|
75
|
+
.p-paginator-next,
|
|
76
|
+
.p-paginator-last {
|
|
77
|
+
transform: rotate(180deg);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Toast positioning
|
|
83
|
+
.p-toast {
|
|
84
|
+
&.p-toast-top-right,
|
|
85
|
+
&.p-toast-bottom-right {
|
|
86
|
+
right: auto;
|
|
87
|
+
left: 20px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
&.p-toast-top-left,
|
|
91
|
+
&.p-toast-bottom-left {
|
|
92
|
+
left: auto;
|
|
93
|
+
right: 20px;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Breadcrumb separator - rotate arrow
|
|
98
|
+
.p-breadcrumb .p-menuitem-separator {
|
|
99
|
+
transform: rotate(180deg);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Steps
|
|
103
|
+
.p-steps .p-steps-item::before {
|
|
104
|
+
left: auto;
|
|
105
|
+
right: 50%;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Dialog - swap margins only
|
|
109
|
+
.p-dialog .p-dialog-header-icons {
|
|
110
|
+
margin-left: 0;
|
|
111
|
+
margin-right: auto;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Sidebar panel
|
|
115
|
+
.p-sidebar-left {
|
|
116
|
+
left: auto !important;
|
|
117
|
+
right: 0 !important;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.p-sidebar-right {
|
|
121
|
+
right: auto !important;
|
|
122
|
+
left: 0 !important;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Card actions - swap margin
|
|
126
|
+
.card-actions {
|
|
127
|
+
margin-left: 0;
|
|
128
|
+
margin-right: auto;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Tag/Badge positioning
|
|
132
|
+
.p-tag,
|
|
133
|
+
.p-badge {
|
|
134
|
+
margin-left: 0;
|
|
135
|
+
margin-right: 0.5rem;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Menu items with icons - swap icon margin for RTL
|
|
139
|
+
.p-menuitem-link .p-menuitem-icon {
|
|
140
|
+
margin-right: 0;
|
|
141
|
+
margin-left: 0.5rem;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Accordion - swap toggle icon margin
|
|
145
|
+
.p-accordion .p-accordion-toggle-icon {
|
|
146
|
+
margin-left: 0;
|
|
147
|
+
margin-right: auto;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Tree/TreeTable - swap toggler margin
|
|
151
|
+
.p-tree .p-tree-toggler,
|
|
152
|
+
.p-treetable .p-treetable-toggler {
|
|
153
|
+
margin-right: 0;
|
|
154
|
+
margin-left: 0.5rem;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Text alignment
|
|
158
|
+
.text-left {
|
|
159
|
+
text-align: right !important;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.text-right {
|
|
163
|
+
text-align: left !important;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Border utilities
|
|
167
|
+
.border-l {
|
|
168
|
+
border-left: none !important;
|
|
169
|
+
border-right: var(--f-border-width, 1px) solid var(--surface-border) !important;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.border-r {
|
|
173
|
+
border-right: none !important;
|
|
174
|
+
border-left: var(--f-border-width, 1px) solid var(--surface-border) !important;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Margin/padding utilities
|
|
178
|
+
.ml-auto {
|
|
179
|
+
margin-left: 0 !important;
|
|
180
|
+
margin-right: auto !important;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.mr-auto {
|
|
184
|
+
margin-right: 0 !important;
|
|
185
|
+
margin-left: auto !important;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.ml-2 {
|
|
189
|
+
margin-left: 0 !important;
|
|
190
|
+
margin-right: 0.5rem !important;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.mr-2 {
|
|
194
|
+
margin-right: 0 !important;
|
|
195
|
+
margin-left: 0.5rem !important;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.pl-2 {
|
|
199
|
+
padding-left: 0 !important;
|
|
200
|
+
padding-right: 0.5rem !important;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.pr-2 {
|
|
204
|
+
padding-right: 0 !important;
|
|
205
|
+
padding-left: 0.5rem !important;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Justify content
|
|
209
|
+
.justify-start {
|
|
210
|
+
justify-content: flex-end !important;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.justify-end {
|
|
214
|
+
justify-content: flex-start !important;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Items alignment in flex
|
|
218
|
+
.items-start {
|
|
219
|
+
align-items: flex-start;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Scroll container
|
|
223
|
+
.overflow-x-auto {
|
|
224
|
+
direction: rtl;
|
|
225
|
+
|
|
226
|
+
> * {
|
|
227
|
+
direction: rtl;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|