kmcom-nuxt-layers 2.2.8 → 2.2.10
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/layers/feeds/public/feed/style.css +256 -0
- package/layers/shader/app/types/tsl.ts +41 -7
- package/package.json +3 -1
- package/types/events.ts +17 -0
- package/types/index.ts +19 -0
- package/types/motion.ts +14 -0
- package/types/runtime.ts +5 -0
- package/types/theme.ts +60 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/* XSLT feed page stylesheet
|
|
2
|
+
* Served at /feed/style.css — referenced from the RSS <?xml-stylesheet?> PI.
|
|
3
|
+
* Uses Nuxt UI v4 CSS custom property naming conventions with light/dark fallbacks.
|
|
4
|
+
* Variables are resolved from the Nuxt UI theme when the stylesheet is loaded from the same
|
|
5
|
+
* origin; otherwise the fallbacks provide sensible standalone defaults.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
*,
|
|
9
|
+
*::before,
|
|
10
|
+
*::after {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
:root {
|
|
15
|
+
--feed-bg: var(--ui-bg, #ffffff);
|
|
16
|
+
--feed-bg-elevated: var(--ui-bg-elevated, #f8fafc);
|
|
17
|
+
--feed-bg-accented: var(--ui-bg-accented, #f1f5f9);
|
|
18
|
+
--feed-border: var(--ui-border, #e2e8f0);
|
|
19
|
+
--feed-text: var(--ui-text, #0f172a);
|
|
20
|
+
--feed-text-muted: var(--ui-text-muted, #64748b);
|
|
21
|
+
--feed-text-toned: var(--ui-text-toned, #475569);
|
|
22
|
+
--feed-primary: var(--ui-color-primary-500, oklch(62.3% 0.214 259.5));
|
|
23
|
+
--feed-primary-text: var(--ui-color-primary-600, oklch(54.6% 0.214 259.5));
|
|
24
|
+
--feed-primary-bg: var(--ui-color-primary-50, oklch(97% 0.03 259.5));
|
|
25
|
+
--feed-radius: var(--ui-radius, 0.375rem);
|
|
26
|
+
--feed-font: var(--font-sans, ui-sans-serif, system-ui, -apple-system, sans-serif);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@media (prefers-color-scheme: dark) {
|
|
30
|
+
:root {
|
|
31
|
+
--feed-bg: var(--ui-bg, #020617);
|
|
32
|
+
--feed-bg-elevated: var(--ui-bg-elevated, #0f172a);
|
|
33
|
+
--feed-bg-accented: var(--ui-bg-accented, #1e293b);
|
|
34
|
+
--feed-border: var(--ui-border, #1e293b);
|
|
35
|
+
--feed-text: var(--ui-text, #f8fafc);
|
|
36
|
+
--feed-text-muted: var(--ui-text-muted, #94a3b8);
|
|
37
|
+
--feed-text-toned: var(--ui-text-toned, #cbd5e1);
|
|
38
|
+
--feed-primary: var(--ui-color-primary-400, oklch(71% 0.18 259.5));
|
|
39
|
+
--feed-primary-text: var(--ui-color-primary-400, oklch(71% 0.18 259.5));
|
|
40
|
+
--feed-primary-bg: var(--ui-color-primary-950, oklch(22% 0.06 259.5));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
html {
|
|
45
|
+
color-scheme: light dark;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
body {
|
|
49
|
+
margin: 0;
|
|
50
|
+
background-color: var(--feed-bg);
|
|
51
|
+
padding: 0;
|
|
52
|
+
color: var(--feed-text);
|
|
53
|
+
font-size: 1rem;
|
|
54
|
+
line-height: 1.6;
|
|
55
|
+
font-family: var(--feed-font);
|
|
56
|
+
-webkit-font-smoothing: antialiased;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
a {
|
|
60
|
+
color: var(--feed-primary-text);
|
|
61
|
+
text-decoration: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
a:hover {
|
|
65
|
+
text-decoration: underline;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ─── Layout ─────────────────────────────────────────────────────────────── */
|
|
69
|
+
|
|
70
|
+
.feed-container {
|
|
71
|
+
margin: 0 auto;
|
|
72
|
+
padding: 0 1.5rem 5rem;
|
|
73
|
+
max-width: 52rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ─── Header ─────────────────────────────────────────────────────────────── */
|
|
77
|
+
|
|
78
|
+
.feed-header {
|
|
79
|
+
margin-bottom: 0.5rem;
|
|
80
|
+
border-bottom: 1px solid var(--feed-border);
|
|
81
|
+
padding: 5rem 0 4.5rem;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.feed-eyebrow {
|
|
85
|
+
display: inline-flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
gap: 0.375rem;
|
|
88
|
+
margin-bottom: 1rem;
|
|
89
|
+
border-radius: 9999px;
|
|
90
|
+
background-color: var(--feed-primary-bg);
|
|
91
|
+
padding: 0.25rem 0.625rem;
|
|
92
|
+
color: var(--feed-primary-text);
|
|
93
|
+
font-weight: 600;
|
|
94
|
+
font-size: 0.6875rem;
|
|
95
|
+
letter-spacing: 0.07em;
|
|
96
|
+
text-transform: uppercase;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.feed-eyebrow svg {
|
|
100
|
+
flex-shrink: 0;
|
|
101
|
+
width: 0.875rem;
|
|
102
|
+
height: 0.875rem;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.feed-title {
|
|
106
|
+
margin: 0 0 0.5rem;
|
|
107
|
+
color: var(--feed-text);
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
font-size: 1.875rem;
|
|
110
|
+
line-height: 1.2;
|
|
111
|
+
letter-spacing: -0.025em;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.feed-title a {
|
|
115
|
+
color: inherit;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.feed-title a:hover {
|
|
119
|
+
opacity: 0.8;
|
|
120
|
+
text-decoration: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.feed-description {
|
|
124
|
+
margin: 0 0 1.25rem;
|
|
125
|
+
max-width: 38rem;
|
|
126
|
+
color: var(--feed-text-muted);
|
|
127
|
+
font-size: 1rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.feed-meta {
|
|
131
|
+
display: flex;
|
|
132
|
+
flex-wrap: wrap;
|
|
133
|
+
align-items: center;
|
|
134
|
+
gap: 1rem;
|
|
135
|
+
color: var(--feed-text-muted);
|
|
136
|
+
font-size: 0.8125rem;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.feed-meta-link {
|
|
140
|
+
color: var(--feed-primary-text);
|
|
141
|
+
font-weight: 500;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.feed-header-actions {
|
|
145
|
+
display: flex;
|
|
146
|
+
flex-wrap: wrap;
|
|
147
|
+
justify-content: space-between;
|
|
148
|
+
align-items: center;
|
|
149
|
+
gap: 1rem;
|
|
150
|
+
margin-top: 1.5rem;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.feed-subscribe {
|
|
154
|
+
display: inline-flex;
|
|
155
|
+
flex-shrink: 0;
|
|
156
|
+
align-items: center;
|
|
157
|
+
gap: 0.4375rem;
|
|
158
|
+
transition: opacity 0.15s ease;
|
|
159
|
+
cursor: pointer;
|
|
160
|
+
border-radius: var(--feed-radius);
|
|
161
|
+
background-color: var(--feed-primary);
|
|
162
|
+
padding: 0.5rem 1.125rem;
|
|
163
|
+
color: #ffffff;
|
|
164
|
+
font-weight: 600;
|
|
165
|
+
font-size: 0.875rem;
|
|
166
|
+
line-height: 1;
|
|
167
|
+
text-decoration: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.feed-subscribe:hover {
|
|
171
|
+
opacity: 0.85;
|
|
172
|
+
color: #ffffff;
|
|
173
|
+
text-decoration: none;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.feed-subscribe svg {
|
|
177
|
+
flex-shrink: 0;
|
|
178
|
+
width: 0.9375rem;
|
|
179
|
+
height: 0.9375rem;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* ─── Items ──────────────────────────────────────────────────────────────── */
|
|
183
|
+
|
|
184
|
+
.feed-items {
|
|
185
|
+
margin: 0;
|
|
186
|
+
padding: 0;
|
|
187
|
+
list-style: none;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.feed-item {
|
|
191
|
+
border-bottom: 1px solid var(--feed-border);
|
|
192
|
+
padding: 1.5rem 0;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.feed-item:last-child {
|
|
196
|
+
border-bottom: none;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.feed-item-title {
|
|
200
|
+
margin: 0 0 0.375rem;
|
|
201
|
+
font-weight: 600;
|
|
202
|
+
font-size: 1.0625rem;
|
|
203
|
+
line-height: 1.4;
|
|
204
|
+
letter-spacing: -0.01em;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.feed-item-title a {
|
|
208
|
+
color: var(--feed-text);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.feed-item-title a:hover {
|
|
212
|
+
color: var(--feed-primary-text);
|
|
213
|
+
text-decoration: none;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.feed-item-meta {
|
|
217
|
+
display: flex;
|
|
218
|
+
flex-wrap: wrap;
|
|
219
|
+
align-items: center;
|
|
220
|
+
gap: 0.4rem;
|
|
221
|
+
margin-bottom: 0.625rem;
|
|
222
|
+
color: var(--feed-text-muted);
|
|
223
|
+
font-size: 0.8125rem;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.feed-item-separator {
|
|
227
|
+
opacity: 0.4;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.feed-item-description {
|
|
231
|
+
display: -webkit-box;
|
|
232
|
+
margin: 0;
|
|
233
|
+
-webkit-line-clamp: 3;
|
|
234
|
+
color: var(--feed-text-toned);
|
|
235
|
+
font-size: 0.9375rem;
|
|
236
|
+
line-height: 1.6;
|
|
237
|
+
-webkit-box-orient: vertical;
|
|
238
|
+
overflow: hidden;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.feed-tags {
|
|
242
|
+
display: flex;
|
|
243
|
+
flex-wrap: wrap;
|
|
244
|
+
gap: 0.375rem;
|
|
245
|
+
margin-top: 0.75rem;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.feed-tag {
|
|
249
|
+
border: 1px solid var(--feed-border);
|
|
250
|
+
border-radius: 9999px;
|
|
251
|
+
background-color: var(--feed-bg-accented);
|
|
252
|
+
padding: 0.125rem 0.5rem;
|
|
253
|
+
color: var(--feed-text-muted);
|
|
254
|
+
font-weight: 500;
|
|
255
|
+
font-size: 0.75rem;
|
|
256
|
+
}
|
|
@@ -1,11 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* TSL Node types
|
|
3
|
+
*
|
|
4
|
+
* These are intentionally `any`. The Three.js TSL type system wraps every node in
|
|
5
|
+
* `ShaderNodeObject<T>` (from `three/tsl`) which adds method chaining (.add, .mul, etc.),
|
|
6
|
+
* but that type is only accessible via a deep import path and is not stable across
|
|
7
|
+
* Three.js minor versions. Components also access `.value` directly on uniform nodes
|
|
8
|
+
* (which are `UniformNode<T>`, a subclass of Node), so a simple `Node` alias would break them.
|
|
9
|
+
*
|
|
10
|
+
* TODO: Replace with `ShaderNodeObject<Node>` once three/tsl exports stabilise and
|
|
11
|
+
* uniform nodes are properly typed as `FloatUniform` at their use sites.
|
|
12
|
+
*/
|
|
2
13
|
|
|
3
|
-
|
|
4
|
-
export type
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export type
|
|
8
|
-
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
export type TSLNode = any
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
export type TSLFloat = any
|
|
19
|
+
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
export type TSLVec2 = any
|
|
22
|
+
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
export type TSLVec3 = any
|
|
25
|
+
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
export type TSLVec4 = any
|
|
28
|
+
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
export type TSLColor = any
|
|
31
|
+
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
|
+
export type TSLMat3 = any
|
|
34
|
+
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
export type TSLMat4 = any
|
|
9
37
|
|
|
10
38
|
export type GradientStop = {
|
|
11
39
|
position: number
|
|
@@ -19,3 +47,9 @@ export type FBMOptions = {
|
|
|
19
47
|
amplitude?: number
|
|
20
48
|
frequency?: number
|
|
21
49
|
}
|
|
50
|
+
|
|
51
|
+
export type VoronoiResult = {
|
|
52
|
+
distance: TSLFloat
|
|
53
|
+
cellCenter: TSLVec2
|
|
54
|
+
edgeDistance: TSLFloat
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kmcom-nuxt-layers",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.10",
|
|
5
5
|
"description": "Composable Nuxt 4 layers for building scalable Vue applications",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./layers/core": "./layers/core/nuxt.config.ts",
|
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
"layers/*/tsconfig.json",
|
|
34
34
|
"layers/*/tailwind.config.*",
|
|
35
35
|
"layers/*/app/**",
|
|
36
|
+
"layers/*/public/**",
|
|
36
37
|
"layers/*/server/**",
|
|
38
|
+
"types/**",
|
|
37
39
|
"docs/"
|
|
38
40
|
],
|
|
39
41
|
"repository": {
|
package/types/events.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** @consumers motion, core */
|
|
2
|
+
export interface ScrollLockEvent {
|
|
3
|
+
locked: boolean
|
|
4
|
+
/** Which layer/component emitted this event */
|
|
5
|
+
source: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** @consumers core */
|
|
9
|
+
export interface LoadingStateEvent {
|
|
10
|
+
loading: boolean
|
|
11
|
+
id?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** @consumers core, motion */
|
|
15
|
+
export type LayerEvent =
|
|
16
|
+
| { type: 'scroll:lock'; payload: ScrollLockEvent }
|
|
17
|
+
| { type: 'loading:state'; payload: LoadingStateEvent }
|
package/types/index.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
ColourMode,
|
|
3
|
+
ContrastLevel,
|
|
4
|
+
MotionPreference,
|
|
5
|
+
TransparencyPreference,
|
|
6
|
+
AccentColor,
|
|
7
|
+
ThemeState,
|
|
8
|
+
ThemeTokens,
|
|
9
|
+
ColorUsage,
|
|
10
|
+
UiColors,
|
|
11
|
+
UiSemanticColor,
|
|
12
|
+
UiStatusColor,
|
|
13
|
+
UiDefaultNuxtUiColors,
|
|
14
|
+
UiCustomColors,
|
|
15
|
+
UiBaseColor,
|
|
16
|
+
} from './theme'
|
|
17
|
+
export type { ScrollLockEvent, LoadingStateEvent, LayerEvent } from './events'
|
|
18
|
+
export type { MotionConfig, TransitionConfig } from './motion'
|
|
19
|
+
export type { PublicRuntimeConfig } from './runtime'
|
package/types/motion.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** @consumers motion, layout, shader */
|
|
2
|
+
export interface MotionConfig {
|
|
3
|
+
duration: number
|
|
4
|
+
ease: string
|
|
5
|
+
delay?: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** @consumers motion, layout */
|
|
9
|
+
export interface TransitionConfig extends MotionConfig {
|
|
10
|
+
enterFrom?: Record<string, string | number>
|
|
11
|
+
enterTo?: Record<string, string | number>
|
|
12
|
+
leaveFrom?: Record<string, string | number>
|
|
13
|
+
leaveTo?: Record<string, string | number>
|
|
14
|
+
}
|
package/types/runtime.ts
ADDED
package/types/theme.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** @consumers ui, layout, motion, shader, theme */
|
|
2
|
+
export type ColourMode = 'light' | 'dark' | 'system'
|
|
3
|
+
|
|
4
|
+
/** @consumers theme, ui */
|
|
5
|
+
export type ContrastLevel = 'standard' | 'high'
|
|
6
|
+
|
|
7
|
+
/** @consumers motion, layout, theme */
|
|
8
|
+
export type MotionPreference = 'full' | 'reduced' | 'none'
|
|
9
|
+
|
|
10
|
+
/** @consumers theme, ui */
|
|
11
|
+
export type TransparencyPreference = 'full' | 'reduced' | 'none'
|
|
12
|
+
|
|
13
|
+
/** @consumers theme, visual, typography */
|
|
14
|
+
export type AccentColor =
|
|
15
|
+
| 'red'
|
|
16
|
+
| 'orange'
|
|
17
|
+
| 'amber'
|
|
18
|
+
| 'yellow'
|
|
19
|
+
| 'lime'
|
|
20
|
+
| 'green'
|
|
21
|
+
| 'emerald'
|
|
22
|
+
| 'teal'
|
|
23
|
+
| 'cyan'
|
|
24
|
+
| 'sky'
|
|
25
|
+
| 'blue'
|
|
26
|
+
| 'indigo'
|
|
27
|
+
| 'violet'
|
|
28
|
+
| 'purple'
|
|
29
|
+
| 'fuchsia'
|
|
30
|
+
| 'pink'
|
|
31
|
+
| 'rose'
|
|
32
|
+
|
|
33
|
+
/** @consumers theme, visual */
|
|
34
|
+
export interface ThemeState {
|
|
35
|
+
mode: ColourMode
|
|
36
|
+
palette: string
|
|
37
|
+
contrast: ContrastLevel
|
|
38
|
+
motion: MotionPreference
|
|
39
|
+
transparency: TransparencyPreference
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** @consumers theme, ui */
|
|
43
|
+
export interface ThemeTokens {
|
|
44
|
+
[key: string]: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// UI semantic colour types (shared with typography and visual layers)
|
|
48
|
+
/** @consumers typography, visual, ui */
|
|
49
|
+
export type ColorUsage = 'text' | 'bg' | 'border'
|
|
50
|
+
export type UiSemanticColor = 'dimmed' | 'muted' | 'toned' | 'default' | 'highlighted' | 'inverted'
|
|
51
|
+
export type UiStatusColor = 'info' | 'success' | 'warning' | 'error'
|
|
52
|
+
export type UiDefaultNuxtUiColors = 'primary' | 'neutral'
|
|
53
|
+
export type UiCustomColors = 'secondary' | 'accent'
|
|
54
|
+
export type UiBaseColor = 'black' | 'white'
|
|
55
|
+
export type UiColors =
|
|
56
|
+
| UiSemanticColor
|
|
57
|
+
| UiStatusColor
|
|
58
|
+
| UiDefaultNuxtUiColors
|
|
59
|
+
| UiCustomColors
|
|
60
|
+
| UiBaseColor
|