@livenetworks/ashlar 1.3.2
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 +177 -0
- package/js/COMPONENTS.md +1102 -0
- package/js/index.js +41 -0
- package/js/ln-accordion/README.md +137 -0
- package/js/ln-accordion/ln-accordion.js +1 -0
- package/js/ln-accordion/src/ln-accordion.js +41 -0
- package/js/ln-ajax/README.md +91 -0
- package/js/ln-ajax/ln-ajax.js +1 -0
- package/js/ln-ajax/src/ln-ajax.js +277 -0
- package/js/ln-api-connector/README.md +150 -0
- package/js/ln-api-connector/ln-api-connector.js +1 -0
- package/js/ln-api-connector/src/ln-api-connector.js +265 -0
- package/js/ln-autoresize/README.md +80 -0
- package/js/ln-autoresize/ln-autoresize.js +1 -0
- package/js/ln-autoresize/src/ln-autoresize.js +47 -0
- package/js/ln-autosave/README.md +92 -0
- package/js/ln-autosave/ln-autosave.js +1 -0
- package/js/ln-autosave/src/ln-autosave.js +147 -0
- package/js/ln-circular-progress/README.md +161 -0
- package/js/ln-circular-progress/ln-circular-progress.js +1 -0
- package/js/ln-circular-progress/src/ln-circular-progress.js +133 -0
- package/js/ln-confirm/README.md +86 -0
- package/js/ln-confirm/_ln-confirm.scss +13 -0
- package/js/ln-confirm/ln-confirm.js +1 -0
- package/js/ln-confirm/src/ln-confirm.js +131 -0
- package/js/ln-core/crypto.js +83 -0
- package/js/ln-core/helpers.js +411 -0
- package/js/ln-core/index.js +5 -0
- package/js/ln-core/persist.js +71 -0
- package/js/ln-core/positioning.js +207 -0
- package/js/ln-core/reactive.js +74 -0
- package/js/ln-couchdb-connector/README.md +156 -0
- package/js/ln-couchdb-connector/ln-couchdb-connector.js +1 -0
- package/js/ln-couchdb-connector/src/ln-couchdb-connector.js +348 -0
- package/js/ln-data-coordinator/README.md +165 -0
- package/js/ln-data-coordinator/ln-data-coordinator.js +1 -0
- package/js/ln-data-coordinator/src/ln-data-coordinator.js +249 -0
- package/js/ln-data-store/README.md +94 -0
- package/js/ln-data-store/ln-data-store.js +1 -0
- package/js/ln-data-store/src/ln-data-store.js +699 -0
- package/js/ln-data-table/README.md +110 -0
- package/js/ln-data-table/ln-data-table.js +1 -0
- package/js/ln-data-table/ln-data-table.scss +10 -0
- package/js/ln-data-table/src/ln-data-table.js +1103 -0
- package/js/ln-date/README.md +151 -0
- package/js/ln-date/ln-date.js +1 -0
- package/js/ln-date/src/ln-date.js +442 -0
- package/js/ln-dropdown/README.md +117 -0
- package/js/ln-dropdown/ln-dropdown.js +1 -0
- package/js/ln-dropdown/ln-dropdown.scss +15 -0
- package/js/ln-dropdown/src/ln-dropdown.js +174 -0
- package/js/ln-external-links/README.md +341 -0
- package/js/ln-external-links/ln-external-links.js +1 -0
- package/js/ln-external-links/src/ln-external-links.js +116 -0
- package/js/ln-filter/README.md +99 -0
- package/js/ln-filter/ln-filter.js +1 -0
- package/js/ln-filter/ln-filter.scss +7 -0
- package/js/ln-filter/src/ln-filter.js +404 -0
- package/js/ln-form/README.md +101 -0
- package/js/ln-form/ln-form.js +1 -0
- package/js/ln-form/src/ln-form.js +199 -0
- package/js/ln-http/README.md +89 -0
- package/js/ln-http/ln-http.js +1 -0
- package/js/ln-http/src/ln-http.js +219 -0
- package/js/ln-icons/README.md +88 -0
- package/js/ln-icons/ln-icons.js +1 -0
- package/js/ln-icons/src/ln-icons.js +169 -0
- package/js/ln-link/README.md +303 -0
- package/js/ln-link/ln-link.js +1 -0
- package/js/ln-link/src/ln-link.js +196 -0
- package/js/ln-modal/README.md +154 -0
- package/js/ln-modal/ln-modal.js +1 -0
- package/js/ln-modal/ln-modal.scss +11 -0
- package/js/ln-modal/src/ln-modal.js +201 -0
- package/js/ln-nav/README.md +70 -0
- package/js/ln-nav/ln-nav.js +1 -0
- package/js/ln-nav/src/ln-nav.js +177 -0
- package/js/ln-number/README.md +122 -0
- package/js/ln-number/ln-number.js +1 -0
- package/js/ln-number/src/ln-number.js +302 -0
- package/js/ln-popover/README.md +127 -0
- package/js/ln-popover/ln-popover.js +1 -0
- package/js/ln-popover/src/ln-popover.js +288 -0
- package/js/ln-progress/README.md +442 -0
- package/js/ln-progress/ln-progress.js +1 -0
- package/js/ln-progress/src/ln-progress.js +150 -0
- package/js/ln-search/README.md +83 -0
- package/js/ln-search/ln-search.js +1 -0
- package/js/ln-search/ln-search.scss +7 -0
- package/js/ln-search/src/ln-search.js +114 -0
- package/js/ln-sortable/README.md +95 -0
- package/js/ln-sortable/ln-sortable.js +1 -0
- package/js/ln-sortable/src/ln-sortable.js +203 -0
- package/js/ln-table/README.md +101 -0
- package/js/ln-table/ln-table-sort.js +1 -0
- package/js/ln-table/ln-table.js +1 -0
- package/js/ln-table/ln-table.scss +11 -0
- package/js/ln-table/src/ln-table-sort.js +168 -0
- package/js/ln-table/src/ln-table.js +473 -0
- package/js/ln-tabs/README.md +137 -0
- package/js/ln-tabs/ln-tabs.js +1 -0
- package/js/ln-tabs/src/ln-tabs.js +171 -0
- package/js/ln-time/README.md +81 -0
- package/js/ln-time/ln-time.js +1 -0
- package/js/ln-time/src/ln-time.js +192 -0
- package/js/ln-toast/README.md +122 -0
- package/js/ln-toast/ln-toast.js +15 -0
- package/js/ln-toast/src/ln-toast.js +210 -0
- package/js/ln-toast/template.html +14 -0
- package/js/ln-toggle/README.md +137 -0
- package/js/ln-toggle/ln-toggle.js +1 -0
- package/js/ln-toggle/src/ln-toggle.js +139 -0
- package/js/ln-tooltip/README.md +58 -0
- package/js/ln-tooltip/ln-tooltip.js +1 -0
- package/js/ln-tooltip/ln-tooltip.scss +9 -0
- package/js/ln-tooltip/src/ln-tooltip.js +169 -0
- package/js/ln-translations/README.md +96 -0
- package/js/ln-translations/ln-translations.js +1 -0
- package/js/ln-translations/src/ln-translations.js +275 -0
- package/js/ln-upload/README.md +180 -0
- package/js/ln-upload/ln-upload.js +1 -0
- package/js/ln-upload/ln-upload.scss +20 -0
- package/js/ln-upload/src/ln-upload.js +407 -0
- package/js/ln-validate/README.md +108 -0
- package/js/ln-validate/ln-validate.js +1 -0
- package/js/ln-validate/src/ln-validate.js +160 -0
- package/package.json +55 -0
- package/scss/base/_global.scss +83 -0
- package/scss/base/_reset.scss +17 -0
- package/scss/base/_typography.scss +125 -0
- package/scss/components/_accordion.scss +34 -0
- package/scss/components/_ajax.scss +15 -0
- package/scss/components/_alert.scss +5 -0
- package/scss/components/_app-shell.scss +15 -0
- package/scss/components/_avatar.scss +6 -0
- package/scss/components/_breadcrumbs.scss +33 -0
- package/scss/components/_button.scss +20 -0
- package/scss/components/_card.scss +10 -0
- package/scss/components/_chip.scss +5 -0
- package/scss/components/_circular-progress.scss +29 -0
- package/scss/components/_confirm.scss +5 -0
- package/scss/components/_data-table.scss +83 -0
- package/scss/components/_dropdown.scss +25 -0
- package/scss/components/_empty-state.scss +22 -0
- package/scss/components/_form.scss +100 -0
- package/scss/components/_layout.scss +8 -0
- package/scss/components/_link.scss +11 -0
- package/scss/components/_ln-table.scss +60 -0
- package/scss/components/_loader.scss +6 -0
- package/scss/components/_modal.scss +20 -0
- package/scss/components/_nav.scss +9 -0
- package/scss/components/_page-header.scss +10 -0
- package/scss/components/_popover.scss +10 -0
- package/scss/components/_progress.scss +17 -0
- package/scss/components/_prose.scss +5 -0
- package/scss/components/_scrollbar.scss +32 -0
- package/scss/components/_sections.scss +12 -0
- package/scss/components/_sidebar.scss +5 -0
- package/scss/components/_stat-card.scss +5 -0
- package/scss/components/_status-badge.scss +4 -0
- package/scss/components/_stepper.scss +5 -0
- package/scss/components/_table.scss +19 -0
- package/scss/components/_tabs.scss +21 -0
- package/scss/components/_timeline.scss +14 -0
- package/scss/components/_toast.scss +41 -0
- package/scss/components/_toggle.scss +81 -0
- package/scss/components/_tooltip.scss +18 -0
- package/scss/components/_translations.scss +111 -0
- package/scss/components/_upload.scss +51 -0
- package/scss/config/_breakpoints.scss +72 -0
- package/scss/config/_density.scss +117 -0
- package/scss/config/_icons.scss +37 -0
- package/scss/config/_mixins.scss +13 -0
- package/scss/config/_theme.scss +216 -0
- package/scss/config/_tokens.scss +419 -0
- package/scss/config/mixins/_accordion.scss +52 -0
- package/scss/config/mixins/_ajax.scss +39 -0
- package/scss/config/mixins/_alert.scss +82 -0
- package/scss/config/mixins/_app-shell.scss +312 -0
- package/scss/config/mixins/_avatar.scss +109 -0
- package/scss/config/mixins/_borders.scss +36 -0
- package/scss/config/mixins/_breadcrumbs.scss +72 -0
- package/scss/config/mixins/_breakpoints.scss +62 -0
- package/scss/config/mixins/_btn.scss +179 -0
- package/scss/config/mixins/_card.scss +338 -0
- package/scss/config/mixins/_chip.scss +66 -0
- package/scss/config/mixins/_circular-progress.scss +71 -0
- package/scss/config/mixins/_collapsible.scss +24 -0
- package/scss/config/mixins/_colors.scss +46 -0
- package/scss/config/mixins/_confirm.scss +31 -0
- package/scss/config/mixins/_data-table.scss +346 -0
- package/scss/config/mixins/_display.scss +32 -0
- package/scss/config/mixins/_dropdown.scss +143 -0
- package/scss/config/mixins/_empty-state.scss +30 -0
- package/scss/config/mixins/_focus.scss +55 -0
- package/scss/config/mixins/_footer.scss +42 -0
- package/scss/config/mixins/_form.scss +601 -0
- package/scss/config/mixins/_index.scss +58 -0
- package/scss/config/mixins/_interaction.scss +15 -0
- package/scss/config/mixins/_kbd.scss +22 -0
- package/scss/config/mixins/_layout.scss +117 -0
- package/scss/config/mixins/_link.scss +55 -0
- package/scss/config/mixins/_ln-table.scss +420 -0
- package/scss/config/mixins/_loader.scss +26 -0
- package/scss/config/mixins/_modal.scss +66 -0
- package/scss/config/mixins/_motion.scss +19 -0
- package/scss/config/mixins/_nav.scss +273 -0
- package/scss/config/mixins/_page-header.scss +69 -0
- package/scss/config/mixins/_popover.scss +25 -0
- package/scss/config/mixins/_position.scss +32 -0
- package/scss/config/mixins/_progress.scss +56 -0
- package/scss/config/mixins/_prose.scss +127 -0
- package/scss/config/mixins/_shadows.scss +8 -0
- package/scss/config/mixins/_sidebar.scss +95 -0
- package/scss/config/mixins/_sizing.scss +6 -0
- package/scss/config/mixins/_spacing.scss +19 -0
- package/scss/config/mixins/_stat-card.scss +68 -0
- package/scss/config/mixins/_status-badge.scss +83 -0
- package/scss/config/mixins/_stepper.scss +78 -0
- package/scss/config/mixins/_table.scss +215 -0
- package/scss/config/mixins/_tabs.scss +64 -0
- package/scss/config/mixins/_timeline.scss +69 -0
- package/scss/config/mixins/_toast.scss +148 -0
- package/scss/config/mixins/_tooltip.scss +111 -0
- package/scss/config/mixins/_transitions.scss +10 -0
- package/scss/config/mixins/_translations.scss +124 -0
- package/scss/config/mixins/_typography.scss +57 -0
- package/scss/config/mixins/_upload.scss +168 -0
- package/scss/ln-ashlar.scss +62 -0
- package/scss/tabler-icons.txt +5039 -0
- package/scss/utilities/_animations.scss +83 -0
- package/scss/utilities/_utilities.scss +49 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'spacing' as *;
|
|
3
|
+
@use 'sizing' as *;
|
|
4
|
+
@use 'typography' as *;
|
|
5
|
+
@use 'colors' as *;
|
|
6
|
+
@use 'borders' as *;
|
|
7
|
+
@use 'shadows' as *;
|
|
8
|
+
@use 'position' as *;
|
|
9
|
+
@use 'transitions' as *;
|
|
10
|
+
@use 'interaction' as *;
|
|
11
|
+
@use 'motion' as *;
|
|
12
|
+
@use 'btn' as *;
|
|
13
|
+
@use 'card' as *;
|
|
14
|
+
|
|
15
|
+
// Toast notification -- side-accent card with icon, title, body, close button.
|
|
16
|
+
//
|
|
17
|
+
// Usage:
|
|
18
|
+
// [data-ln-toast] { @include toast-container; }
|
|
19
|
+
// .ln-toast__card { @include toast-card; }
|
|
20
|
+
//
|
|
21
|
+
// Color: attach .success/.error/.warning/.info utility class on the card to cascade --color-accent.
|
|
22
|
+
|
|
23
|
+
@mixin toast-container {
|
|
24
|
+
@include fixed;
|
|
25
|
+
@include z-toast;
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
// Viewport-edge offsets — toast container distance from viewport,
|
|
28
|
+
// not shell rhythm.
|
|
29
|
+
right: var(--size-lg);
|
|
30
|
+
bottom: var(--size-lg);
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column-reverse;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@mixin toast-item {
|
|
36
|
+
opacity: 0;
|
|
37
|
+
pointer-events: auto;
|
|
38
|
+
@include motion-safe {
|
|
39
|
+
transform: translateX(30px);
|
|
40
|
+
transition: all var(--transition-base) var(--easing-standard);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
& + & {
|
|
44
|
+
--margin-block: var(--size-md);
|
|
45
|
+
margin-bottom: var(--margin-block);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@mixin toast-item-in {
|
|
50
|
+
opacity: 1;
|
|
51
|
+
@include motion-safe {
|
|
52
|
+
transform: translateX(0);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@mixin toast-item-out {
|
|
57
|
+
opacity: 0 !important;
|
|
58
|
+
@include motion-safe {
|
|
59
|
+
transform: scale(0.95) !important;
|
|
60
|
+
transition: all var(--transition-fast) !important;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@mixin toast-card {
|
|
65
|
+
@include floating-panel;
|
|
66
|
+
@include flex;
|
|
67
|
+
min-width: 320px;
|
|
68
|
+
max-width: 450px;
|
|
69
|
+
@include overflow-hidden;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@mixin toast-side {
|
|
73
|
+
--color-accent: hsl(var(--color-primary));
|
|
74
|
+
--color-accent-fg: hsl(var(--color-white));
|
|
75
|
+
flex: 0 0 44px;
|
|
76
|
+
@include flex;
|
|
77
|
+
align-items: flex-start;
|
|
78
|
+
@include justify-center;
|
|
79
|
+
--padding-y: var(--size-md);
|
|
80
|
+
padding-top: var(--padding-y);
|
|
81
|
+
background: var(--color-accent);
|
|
82
|
+
color: var(--color-accent-fg);
|
|
83
|
+
|
|
84
|
+
&::before {
|
|
85
|
+
width: 2rem;
|
|
86
|
+
height: 2rem;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@mixin toast-content {
|
|
91
|
+
@include flex-1;
|
|
92
|
+
--padding-y: var(--size-md);
|
|
93
|
+
--padding-x: var(--size-md);
|
|
94
|
+
padding: var(--padding-y) var(--padding-x) var(--padding-y) var(--size-sm); // 4th arm: icon-side gutter, component-design intrinsic.
|
|
95
|
+
@include relative;
|
|
96
|
+
|
|
97
|
+
.ln-toast__close {
|
|
98
|
+
--btn-padding-y: var(--size-2xs);
|
|
99
|
+
--btn-padding-x: var(--size-2xs);
|
|
100
|
+
@include absolute;
|
|
101
|
+
// Geometric — close button positioned inside content padding.
|
|
102
|
+
top: var(--size-sm);
|
|
103
|
+
right: var(--size-sm);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ─── Header & close ────────────────────────────────────
|
|
108
|
+
|
|
109
|
+
@mixin toast-head {
|
|
110
|
+
@include flex;
|
|
111
|
+
align-items: flex-start;
|
|
112
|
+
@include justify-between;
|
|
113
|
+
--gap: var(--size-md);
|
|
114
|
+
gap: var(--gap);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@mixin toast-title {
|
|
118
|
+
@include font-bold;
|
|
119
|
+
@include text-base;
|
|
120
|
+
color: var(--color-fg);
|
|
121
|
+
line-height: 1.25;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ─── Body ──────────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
@mixin toast-body {
|
|
127
|
+
--color-fg: var(--fg-muted);
|
|
128
|
+
--margin-block: var(--size-sm);
|
|
129
|
+
margin-top: var(--margin-block);
|
|
130
|
+
font-size: var(--text-base);
|
|
131
|
+
color: var(--color-fg);
|
|
132
|
+
line-height: 1.5;
|
|
133
|
+
|
|
134
|
+
p { @include m(0); }
|
|
135
|
+
|
|
136
|
+
ul {
|
|
137
|
+
--margin-block: var(--size-sm);
|
|
138
|
+
margin: var(--margin-block) 0 0 0;
|
|
139
|
+
--padding-x: var(--size-md-up);
|
|
140
|
+
padding-left: var(--padding-x);
|
|
141
|
+
@include text-sm;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
li + li {
|
|
145
|
+
--margin-block: var(--size-xs);
|
|
146
|
+
margin-top: var(--margin-block);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
@use 'typography' as *;
|
|
2
|
+
@use 'colors' as *;
|
|
3
|
+
@use 'borders' as *;
|
|
4
|
+
@use 'shadows' as *;
|
|
5
|
+
@use 'spacing' as *;
|
|
6
|
+
@use 'motion' as *;
|
|
7
|
+
|
|
8
|
+
// Shared dark-bubble chrome for ::after pseudo-tooltips (tooltip, confirm)
|
|
9
|
+
// and JS-portal tooltip-element. Semantic token pair — in dark mode the
|
|
10
|
+
// neutral scale inversion naturally flips the bubble to light-on-dark.
|
|
11
|
+
@mixin tooltip-bubble {
|
|
12
|
+
--padding-y: var(--size-xs);
|
|
13
|
+
--padding-x: var(--size-sm);
|
|
14
|
+
padding: var(--padding-y) var(--padding-x);
|
|
15
|
+
background: var(--color-fg);
|
|
16
|
+
color: var(--color-bg);
|
|
17
|
+
@include typography(caption);
|
|
18
|
+
--radius: var(--radius-sm);
|
|
19
|
+
border-radius: var(--radius);
|
|
20
|
+
white-space: nowrap;
|
|
21
|
+
pointer-events: none;
|
|
22
|
+
z-index: var(--z-dropdown);
|
|
23
|
+
--shadow: var(--shadow-floating);
|
|
24
|
+
box-shadow: var(--shadow);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@mixin tooltip {
|
|
28
|
+
position: relative;
|
|
29
|
+
|
|
30
|
+
&::after {
|
|
31
|
+
@include tooltip-bubble;
|
|
32
|
+
content: attr(data-ln-tooltip);
|
|
33
|
+
position: absolute;
|
|
34
|
+
opacity: 0;
|
|
35
|
+
|
|
36
|
+
// Default placement: top, centered above the trigger.
|
|
37
|
+
// Position overrides below reset `bottom` / `left` to `auto` so
|
|
38
|
+
// the pseudo-element is not stretched between two coordinates.
|
|
39
|
+
--gap: var(--size-xs-up);
|
|
40
|
+
bottom: calc(100% + var(--gap));
|
|
41
|
+
left: 50%;
|
|
42
|
+
transform: translateX(-50%);
|
|
43
|
+
|
|
44
|
+
@include motion-safe {
|
|
45
|
+
transition: opacity var(--transition-fast);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Fallback: when data-ln-tooltip has no value, pull text from `title`.
|
|
50
|
+
// Enables the semantic `<abbr data-ln-tooltip title="full form">short</abbr>`
|
|
51
|
+
// pattern. Same specificity as the base rule — wins by source order.
|
|
52
|
+
&[data-ln-tooltip=""]::after {
|
|
53
|
+
content: attr(title);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
&:hover::after,
|
|
57
|
+
&:focus-visible::after {
|
|
58
|
+
opacity: 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Bottom — push below the trigger. Must reset `bottom` from the default
|
|
62
|
+
// top placement or the pseudo-element stretches vertically.
|
|
63
|
+
&[data-ln-tooltip-position="bottom"]::after {
|
|
64
|
+
--gap: var(--size-xs-up);
|
|
65
|
+
bottom: auto;
|
|
66
|
+
top: calc(100% + var(--gap));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Left — reset `bottom` + `left` from the default, position to the left
|
|
70
|
+
// of the trigger, vertical-center via top + translateY.
|
|
71
|
+
&[data-ln-tooltip-position="left"]::after {
|
|
72
|
+
--gap: var(--size-xs-up);
|
|
73
|
+
bottom: auto;
|
|
74
|
+
left: auto;
|
|
75
|
+
right: calc(100% + var(--gap));
|
|
76
|
+
top: 50%;
|
|
77
|
+
transform: translateY(-50%);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Right — reset `bottom` from the default, override `left` to the right
|
|
81
|
+
// edge, vertical-center via top + translateY.
|
|
82
|
+
&[data-ln-tooltip-position="right"]::after {
|
|
83
|
+
--gap: var(--size-xs-up);
|
|
84
|
+
bottom: auto;
|
|
85
|
+
left: calc(100% + var(--gap));
|
|
86
|
+
top: 50%;
|
|
87
|
+
transform: translateY(-50%);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── JS Portal (real DOM tooltip) ──────────────────────
|
|
92
|
+
// When JS enhance is active, tooltips render as positioned
|
|
93
|
+
// DOM elements inside #ln-tooltip-portal instead of ::after.
|
|
94
|
+
|
|
95
|
+
@mixin tooltip-portal {
|
|
96
|
+
position: fixed;
|
|
97
|
+
top: 0;
|
|
98
|
+
left: 0;
|
|
99
|
+
pointer-events: none;
|
|
100
|
+
z-index: var(--z-toast);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@mixin tooltip-element {
|
|
104
|
+
@include tooltip-bubble;
|
|
105
|
+
position: fixed;
|
|
106
|
+
max-width: 20rem;
|
|
107
|
+
|
|
108
|
+
@include motion-safe {
|
|
109
|
+
animation: ln-tooltip-fade var(--transition-fast);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Transitions — references --transition-* tokens
|
|
2
|
+
|
|
3
|
+
@mixin transition { transition: all var(--transition-base); }
|
|
4
|
+
@mixin transition-fast { transition: all var(--transition-fast); }
|
|
5
|
+
@mixin transition-slow { transition: all var(--transition-slow); }
|
|
6
|
+
@mixin transition-colors {
|
|
7
|
+
transition: color var(--transition-base),
|
|
8
|
+
background-color var(--transition-base),
|
|
9
|
+
border-color var(--transition-base);
|
|
10
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'spacing' as *;
|
|
3
|
+
@use 'sizing' as *;
|
|
4
|
+
@use 'typography' as *;
|
|
5
|
+
@use 'colors' as *;
|
|
6
|
+
@use 'borders' as *;
|
|
7
|
+
@use 'transitions' as *;
|
|
8
|
+
@use 'interaction' as *;
|
|
9
|
+
@use 'motion' as *;
|
|
10
|
+
|
|
11
|
+
// Translation management -- flag icons, badges, trigger button.
|
|
12
|
+
//
|
|
13
|
+
// Usage:
|
|
14
|
+
// [data-ln-translatable-lang] { @include translations-flag-input; }
|
|
15
|
+
// [data-ln-translations-active] { @include translations-active-list; }
|
|
16
|
+
|
|
17
|
+
// ─── Flag icon in input background ───────────────────────────────
|
|
18
|
+
|
|
19
|
+
@mixin translations-flag-input {
|
|
20
|
+
// Intrinsic flag-icon decoration math — pad-left + bg-pos + bg-size
|
|
21
|
+
// composed against the icon's own dimensions, not shell rhythm.
|
|
22
|
+
padding-left: calc(var(--size-sm-up) + var(--size-md-up) + var(--size-sm-up));
|
|
23
|
+
background-repeat: no-repeat;
|
|
24
|
+
background-size: var(--size-md-up) auto;
|
|
25
|
+
background-position: var(--size-sm-up) calc(var(--size-sm) + (var(--size-lg) - var(--size-md-up) * 3 / 4) / 2);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ─── Dropdown menu item: flag via ::before ───────────────────────
|
|
29
|
+
|
|
30
|
+
@mixin translations-dropdown-flag {
|
|
31
|
+
@include flex;
|
|
32
|
+
@include items-center;
|
|
33
|
+
gap: var(--gap);
|
|
34
|
+
|
|
35
|
+
&::before {
|
|
36
|
+
content: '';
|
|
37
|
+
@include inline-block;
|
|
38
|
+
width: 1.25rem;
|
|
39
|
+
aspect-ratio: 4 / 3;
|
|
40
|
+
background-size: contain;
|
|
41
|
+
background-repeat: no-repeat;
|
|
42
|
+
background-position: center;
|
|
43
|
+
flex-shrink: 0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ─── Header actions ──────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
@mixin translations-actions {
|
|
50
|
+
@include inline-flex;
|
|
51
|
+
@include items-center;
|
|
52
|
+
--gap: var(--size-xs);
|
|
53
|
+
gap: var(--gap);
|
|
54
|
+
margin-left: auto;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ─── Active translations list ────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
@mixin translations-active-list {
|
|
60
|
+
@include inline-flex;
|
|
61
|
+
@include items-center;
|
|
62
|
+
--gap: var(--size-xs);
|
|
63
|
+
gap: var(--gap);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ─── Badge with flag ─────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
@mixin translations-badge {
|
|
69
|
+
@include inline-flex;
|
|
70
|
+
@include items-center;
|
|
71
|
+
--gap: var(--size-xs);
|
|
72
|
+
gap: var(--gap);
|
|
73
|
+
--padding-y: var(--size-2xs);
|
|
74
|
+
--padding-x: var(--size-xs);
|
|
75
|
+
padding: var(--padding-y) var(--padding-x);
|
|
76
|
+
@include text-xs;
|
|
77
|
+
@include font-semibold;
|
|
78
|
+
@include rounded-sm;
|
|
79
|
+
@include tinted-surface(0.08);
|
|
80
|
+
@include select-none;
|
|
81
|
+
margin: 0;
|
|
82
|
+
background-repeat: no-repeat;
|
|
83
|
+
background-position: var(--size-xs) center; // Intrinsic flag-icon position, not shell rhythm.
|
|
84
|
+
background-size: 1rem auto;
|
|
85
|
+
--padding-x: var(--size-lg);
|
|
86
|
+
padding-left: var(--padding-x);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ─── Badge remove button ─────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
@mixin translations-badge-remove {
|
|
92
|
+
background: none;
|
|
93
|
+
border: none;
|
|
94
|
+
@include cursor-pointer;
|
|
95
|
+
@include text-sm;
|
|
96
|
+
@include font-bold;
|
|
97
|
+
color: inherit;
|
|
98
|
+
--btn-padding-y: 0;
|
|
99
|
+
--btn-padding-x: 0;
|
|
100
|
+
line-height: 1;
|
|
101
|
+
@include transition-fast;
|
|
102
|
+
|
|
103
|
+
&:hover {
|
|
104
|
+
@include text-error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ─── Trigger button ──────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
@mixin translations-add-button {
|
|
111
|
+
@include inline-flex;
|
|
112
|
+
@include items-center;
|
|
113
|
+
@include justify-center;
|
|
114
|
+
@include size(1.5rem);
|
|
115
|
+
@include rounded-sm;
|
|
116
|
+
@include cursor-pointer;
|
|
117
|
+
@include transition-fast;
|
|
118
|
+
@include tinted-surface(0.08);
|
|
119
|
+
border: none;
|
|
120
|
+
|
|
121
|
+
&:hover {
|
|
122
|
+
@include tinted-surface(0.15);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
@use 'sass:list';
|
|
2
|
+
|
|
3
|
+
// Typography — references --text-* and --font-* tokens
|
|
4
|
+
|
|
5
|
+
@mixin text-xs { font-size: var(--text-xs); line-height: 1rem; }
|
|
6
|
+
@mixin text-sm { font-size: var(--text-sm); line-height: 1.25rem; }
|
|
7
|
+
@mixin text-base { font-size: var(--text-base); line-height: 1.5rem; }
|
|
8
|
+
@mixin text-lg { font-size: var(--text-lg); line-height: 1.75rem; }
|
|
9
|
+
@mixin text-xl { font-size: var(--text-xl); line-height: 1.75rem; }
|
|
10
|
+
@mixin text-2xl { font-size: var(--text-2xl); line-height: 2rem; }
|
|
11
|
+
|
|
12
|
+
@mixin font-normal { font-weight: var(--font-normal); }
|
|
13
|
+
@mixin font-medium { font-weight: var(--font-medium); }
|
|
14
|
+
@mixin font-semibold { font-weight: var(--font-semibold); }
|
|
15
|
+
@mixin font-bold { font-weight: var(--font-bold); }
|
|
16
|
+
|
|
17
|
+
@mixin text-left { text-align: left; }
|
|
18
|
+
@mixin text-center { text-align: center; }
|
|
19
|
+
@mixin text-right { text-align: right; }
|
|
20
|
+
|
|
21
|
+
@mixin uppercase { text-transform: uppercase; }
|
|
22
|
+
@mixin lowercase { text-transform: lowercase; }
|
|
23
|
+
@mixin capitalize { text-transform: capitalize; }
|
|
24
|
+
@mixin normal-case { text-transform: none; }
|
|
25
|
+
|
|
26
|
+
@mixin tracking-wide { letter-spacing: var(--tracking-wide); }
|
|
27
|
+
@mixin tracking-wider { letter-spacing: 0.05em; }
|
|
28
|
+
|
|
29
|
+
@mixin truncate {
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
text-overflow: ellipsis;
|
|
32
|
+
white-space: nowrap;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@mixin whitespace-nowrap { white-space: nowrap; }
|
|
36
|
+
@mixin font-mono { font-family: var(--font-mono); }
|
|
37
|
+
@mixin font-sans { font-family: var(--font-sans); }
|
|
38
|
+
|
|
39
|
+
// Semantic role mixin — v1.1.
|
|
40
|
+
// Usage: @include typography(display-lg) / typography(body-md) / etc.
|
|
41
|
+
@mixin typography($role) {
|
|
42
|
+
$valid-roles: (display-lg, display-md, display-sm,
|
|
43
|
+
heading-lg, heading-md, heading-sm,
|
|
44
|
+
title-md, title-sm,
|
|
45
|
+
body-lg, body-md, body-sm,
|
|
46
|
+
label-md, label-sm, caption);
|
|
47
|
+
|
|
48
|
+
@if not list.index($valid-roles, $role) {
|
|
49
|
+
@error "typography(): unknown role '#{$role}'. Valid roles: #{$valid-roles}";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
font-size: var(--text-#{$role});
|
|
53
|
+
line-height: var(--lh-#{$role});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@mixin tracking-tight { letter-spacing: var(--tracking-tight); }
|
|
57
|
+
@mixin tracking-normal { letter-spacing: var(--tracking-normal); }
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'spacing' as *;
|
|
3
|
+
@use 'sizing' as *;
|
|
4
|
+
@use 'typography' as *;
|
|
5
|
+
@use 'colors' as *;
|
|
6
|
+
@use 'borders' as *;
|
|
7
|
+
@use 'position' as *;
|
|
8
|
+
@use 'transitions' as *;
|
|
9
|
+
@use 'interaction' as *;
|
|
10
|
+
@use 'motion' as *;
|
|
11
|
+
@use 'btn' as *;
|
|
12
|
+
|
|
13
|
+
// Upload component -- drag-and-drop zone, file list, progress bar.
|
|
14
|
+
//
|
|
15
|
+
// Usage:
|
|
16
|
+
// .ln-upload { @include upload; }
|
|
17
|
+
// .ln-upload__zone { @include upload-zone; }
|
|
18
|
+
|
|
19
|
+
@mixin upload {
|
|
20
|
+
width: 100%;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@mixin upload-zone {
|
|
24
|
+
--color-bg: var(--bg-sunken);
|
|
25
|
+
border: 2px dashed var(--color-border);
|
|
26
|
+
border-radius: var(--radius);
|
|
27
|
+
--padding-y: var(--size-lg);
|
|
28
|
+
--padding-x: var(--size-lg);
|
|
29
|
+
padding: var(--padding-y) var(--padding-x);
|
|
30
|
+
text-align: center;
|
|
31
|
+
@include cursor-pointer;
|
|
32
|
+
@include motion-safe {
|
|
33
|
+
transition: border-color var(--transition),
|
|
34
|
+
background-color var(--transition);
|
|
35
|
+
}
|
|
36
|
+
background-color: var(--color-bg);
|
|
37
|
+
|
|
38
|
+
&:hover {
|
|
39
|
+
border-color: var(--color-accent);
|
|
40
|
+
background-color: var(--color-accent-tint);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
span {
|
|
44
|
+
--color-fg: var(--fg-muted);
|
|
45
|
+
display: block;
|
|
46
|
+
color: var(--color-fg);
|
|
47
|
+
font-size: var(--text-sm);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
small {
|
|
51
|
+
--color-fg: var(--fg-subtle);
|
|
52
|
+
display: block;
|
|
53
|
+
color: var(--color-fg);
|
|
54
|
+
font-size: var(--text-xs);
|
|
55
|
+
--margin-block: var(--size-xs);
|
|
56
|
+
margin-top: var(--margin-block);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@mixin upload-zone-dragover {
|
|
61
|
+
border-color: var(--color-accent);
|
|
62
|
+
background-color: var(--color-accent-tint-strong);
|
|
63
|
+
border-style: solid;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@mixin upload-list {
|
|
67
|
+
--margin-block: var(--size-sm);
|
|
68
|
+
margin-top: var(--margin-block);
|
|
69
|
+
|
|
70
|
+
&:empty {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@mixin upload-item {
|
|
76
|
+
--color-bg: var(--bg-sunken);
|
|
77
|
+
@include relative;
|
|
78
|
+
@include flex;
|
|
79
|
+
@include items-center;
|
|
80
|
+
flex-wrap: wrap;
|
|
81
|
+
--padding-y: var(--size-sm);
|
|
82
|
+
--padding-x: var(--size-md);
|
|
83
|
+
padding: var(--padding-y) var(--padding-x);
|
|
84
|
+
background-color: var(--color-bg);
|
|
85
|
+
border: var(--border-width) solid var(--color-border);
|
|
86
|
+
border-radius: var(--radius-sm);
|
|
87
|
+
--margin-block: var(--size-sm);
|
|
88
|
+
margin-bottom: var(--margin-block);
|
|
89
|
+
font-size: var(--text-sm);
|
|
90
|
+
@include overflow-hidden;
|
|
91
|
+
|
|
92
|
+
&:last-child {
|
|
93
|
+
margin-bottom: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
> svg.ln-icon {
|
|
97
|
+
--margin-inline: var(--size-sm);
|
|
98
|
+
margin-right: var(--margin-inline);
|
|
99
|
+
flex-shrink: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
> .ln-upload__remove {
|
|
103
|
+
--btn-padding-y: var(--size-2xs);
|
|
104
|
+
--btn-padding-x: var(--size-2xs);
|
|
105
|
+
--margin-inline: var(--size-sm);
|
|
106
|
+
margin-left: var(--margin-inline);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@mixin upload-name {
|
|
111
|
+
flex: 1;
|
|
112
|
+
@include truncate;
|
|
113
|
+
color: var(--color-fg);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@mixin upload-size {
|
|
117
|
+
--color-fg: var(--fg-subtle);
|
|
118
|
+
color: var(--color-fg);
|
|
119
|
+
font-size: var(--text-xs);
|
|
120
|
+
--margin-inline: var(--size-md);
|
|
121
|
+
margin-left: var(--margin-inline);
|
|
122
|
+
flex-shrink: 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@mixin upload-progress {
|
|
126
|
+
@include absolute;
|
|
127
|
+
bottom: 0;
|
|
128
|
+
left: 0;
|
|
129
|
+
right: 0;
|
|
130
|
+
height: 3px;
|
|
131
|
+
background-color: var(--color-border);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@mixin upload-progress-bar {
|
|
135
|
+
height: 100%;
|
|
136
|
+
width: 0;
|
|
137
|
+
background-color: var(--color-accent);
|
|
138
|
+
@include motion-safe {
|
|
139
|
+
transition: width 0.15s ease-out;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@mixin upload-item-error {
|
|
144
|
+
border-color: hsl(var(--color-error));
|
|
145
|
+
background-color: hsl(var(--color-error) / 0.1);
|
|
146
|
+
|
|
147
|
+
.ln-upload__progress-bar {
|
|
148
|
+
background-color: hsl(var(--color-error));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@mixin upload-item-deleting-spinner {
|
|
153
|
+
content: '';
|
|
154
|
+
box-sizing: border-box;
|
|
155
|
+
display: inline-block;
|
|
156
|
+
width: 1.25rem;
|
|
157
|
+
height: 1.25rem;
|
|
158
|
+
--margin-inline: var(--size-sm);
|
|
159
|
+
margin-right: var(--margin-inline);
|
|
160
|
+
border: 2px solid var(--color-border);
|
|
161
|
+
border-radius: 50%;
|
|
162
|
+
border-top-color: var(--color-accent);
|
|
163
|
+
background-image: none !important;
|
|
164
|
+
@include motion-safe {
|
|
165
|
+
animation: ln-upload-spin 0.6s linear infinite;
|
|
166
|
+
}
|
|
167
|
+
flex-shrink: 0;
|
|
168
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
@use 'config/tokens';
|
|
2
|
+
@use 'config/breakpoints';
|
|
3
|
+
@use 'config/density';
|
|
4
|
+
@use 'config/theme';
|
|
5
|
+
@use 'config/icons';
|
|
6
|
+
|
|
7
|
+
@use 'base/reset';
|
|
8
|
+
@use 'base/global';
|
|
9
|
+
@use 'base/typography';
|
|
10
|
+
|
|
11
|
+
@use 'components/button';
|
|
12
|
+
@use 'components/form';
|
|
13
|
+
@use 'components/layout';
|
|
14
|
+
@use 'components/table';
|
|
15
|
+
@use 'components/tabs';
|
|
16
|
+
@use 'components/toggle';
|
|
17
|
+
@use 'components/accordion';
|
|
18
|
+
@use 'components/card';
|
|
19
|
+
@use 'components/sections';
|
|
20
|
+
@use 'components/nav';
|
|
21
|
+
@use 'components/sidebar';
|
|
22
|
+
@use 'components/app-shell';
|
|
23
|
+
@use 'components/breadcrumbs';
|
|
24
|
+
@use 'components/avatar';
|
|
25
|
+
@use 'components/status-badge';
|
|
26
|
+
@use 'components/alert';
|
|
27
|
+
@use 'components/empty-state';
|
|
28
|
+
@use 'components/page-header';
|
|
29
|
+
@use 'components/stepper';
|
|
30
|
+
@use 'components/timeline';
|
|
31
|
+
@use 'components/stat-card';
|
|
32
|
+
@use 'components/prose';
|
|
33
|
+
@use 'components/scrollbar';
|
|
34
|
+
@use 'components/tooltip';
|
|
35
|
+
@use 'components/popover';
|
|
36
|
+
@use 'components/chip';
|
|
37
|
+
@use 'components/loader';
|
|
38
|
+
@use 'components/progress';
|
|
39
|
+
@use 'components/link';
|
|
40
|
+
@use 'components/confirm';
|
|
41
|
+
@use 'components/circular-progress';
|
|
42
|
+
@use 'components/modal';
|
|
43
|
+
@use 'components/dropdown';
|
|
44
|
+
@use 'components/toast';
|
|
45
|
+
@use 'components/upload';
|
|
46
|
+
@use 'components/translations';
|
|
47
|
+
@use 'components/data-table';
|
|
48
|
+
@use 'components/ln-table';
|
|
49
|
+
@use 'components/ajax';
|
|
50
|
+
|
|
51
|
+
@use 'utilities/utilities';
|
|
52
|
+
@use 'utilities/animations';
|
|
53
|
+
|
|
54
|
+
// JS component co-located styles
|
|
55
|
+
@use '../js/ln-modal/ln-modal';
|
|
56
|
+
@use '../js/ln-dropdown/ln-dropdown';
|
|
57
|
+
@use '../js/ln-tooltip/ln-tooltip';
|
|
58
|
+
@use '../js/ln-upload/ln-upload';
|
|
59
|
+
@use '../js/ln-filter/ln-filter';
|
|
60
|
+
@use '../js/ln-search/ln-search';
|
|
61
|
+
@use '../js/ln-table/ln-table' as ln-table-state;
|
|
62
|
+
@use '../js/ln-data-table/ln-data-table';
|