kmcom-nuxt-layers 2.2.5 → 2.2.8
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/docs/FEEDS.md +197 -0
- package/docs/LAYERS-FIXES.md +101 -0
- package/docs/MIGRATION.md +627 -0
- package/docs/feed-layer.md +374 -0
- package/docs/patch-picture-provider-type.md +52 -0
- package/docs/shaderGuide.md +2071 -0
- package/docs/types-architecture.md +234 -0
- package/layers/animations/app/components/Motion/CountUp.vue +1 -1
- package/layers/animations/app/components/Motion/Magnetic.vue +1 -1
- package/layers/animations/app/components/Motion/Marquee.vue +3 -2
- package/layers/animations/app/components/Motion/MarqueeText.vue +3 -2
- package/layers/animations/app/components/Motion/Tilt.vue +1 -1
- package/layers/animations/app/composables/useCountUp.ts +4 -1
- package/layers/animations/app/composables/useMagneticElement.ts +2 -4
- package/layers/animations/app/composables/useMarqueeCopies.ts +4 -4
- package/layers/animations/app/composables/useTiltEffect.ts +1 -1
- package/layers/animations/app/types/animations.ts +8 -0
- package/layers/animations/app/types/index.ts +1 -0
- package/layers/animations/package.json +4 -1
- package/layers/canvas/app/components/ShaderCanvas.vue +4 -4
- package/layers/canvas/app/composables/useRendererCapabilities.ts +19 -15
- package/layers/canvas/app/types/index.ts +1 -0
- package/layers/canvas/package.json +2 -1
- package/layers/canvas/tsconfig.json +2 -1
- package/layers/content/app/components/Blog/Card.vue +5 -5
- package/layers/content/app/components/Gallery/AmbientImage.vue +3 -3
- package/layers/content/app/components/Gallery/Card.vue +3 -3
- package/layers/content/app/components/Gallery/Lightbox.vue +5 -1
- package/layers/content/app/components/NuxtContent/Detail.vue +5 -1
- package/layers/content/app/components/NuxtContent/Surround.vue +5 -3
- package/layers/content/app/components/NuxtContent/Toc.vue +1 -1
- package/layers/content/app/components/Portfolio/Card.vue +5 -5
- package/layers/content/app/components/content/Figure.vue +3 -3
- package/layers/content/app/composables/useBlogPosts.ts +2 -2
- package/layers/content/app/composables/useCollectionItem.ts +1 -3
- package/layers/content/app/composables/useGalleryItems.ts +2 -2
- package/layers/content/app/types/index.ts +1 -0
- package/layers/content/package.json +2 -1
- package/layers/core/app/composables/useCache.ts +0 -1
- package/layers/core/app/composables/useErrorLog.ts +9 -11
- package/layers/core/app/plugins/error-handler.ts +36 -36
- package/layers/core/app/plugins/feature-detection.client.ts +15 -15
- package/layers/core/app/plugins/init.ts +121 -129
- package/layers/core/app/plugins/loading.client.ts +27 -27
- package/layers/core/app/plugins/scroll-guard.client.ts +26 -26
- package/layers/core/app/utils/helpers.ts +14 -12
- package/layers/core/nuxt.config.ts +1 -0
- package/layers/feeds/app/plugins/feed-head.ts +62 -63
- package/layers/feeds/package.json +2 -1
- package/layers/feeds/server/routes/feed/discovery.get.ts +1 -2
- package/layers/feeds/server/utils/content-adapter.ts +3 -2
- package/layers/forms/app/components/Form/Field.vue +4 -4
- package/layers/forms/app/types/index.ts +1 -0
- package/layers/forms/package.json +2 -1
- package/layers/forms/server/api/contact.post.ts +1 -1
- package/layers/layout/app/components/Layout/Grid/Item.vue +33 -19
- package/layers/layout/app/components/Layout/Page/Container.vue +11 -11
- package/layers/layout/app/components/Layout/Page/Header.vue +1 -1
- package/layers/layout/app/components/Layout/Page/index.vue +1 -1
- package/layers/layout/app/components/Layout/Section/Gallery.vue +6 -1
- package/layers/layout/app/components/Layout/Section/Title.vue +1 -1
- package/layers/layout/app/types/index.ts +1 -0
- package/layers/layout/package.json +2 -1
- package/layers/mailer/app/types/index.ts +1 -0
- package/layers/mailer/app/types/mailer.ts +25 -0
- package/layers/mailer/package.json +2 -1
- package/layers/motion/package.json +2 -1
- package/layers/navigation/app/components/Links/Group.vue +1 -0
- package/layers/navigation/app/components/Links/Named.vue +2 -0
- package/layers/navigation/app/types/index.ts +1 -0
- package/layers/navigation/package.json +4 -1
- package/layers/page-transitions/app/plugins/page-transitions.client.ts +9 -9
- package/layers/page-transitions/package.json +4 -1
- package/layers/routing/app/plugins/feature-flags.client.ts +9 -9
- package/layers/routing/app/types/app-config.d.ts +3 -1
- package/layers/routing/app/types/index.ts +1 -0
- package/layers/routing/package.json +2 -1
- package/layers/scripts/app/composables/useGtm.ts +1 -1
- package/layers/scripts/app/types/index.ts +1 -0
- package/layers/scripts/app/types/scripts.ts +14 -0
- package/layers/scripts/package.json +2 -1
- package/layers/scroll/app/components/Motion/ScrollScene.vue +3 -1
- package/layers/scroll/app/composables/useScrollSteps.ts +2 -9
- package/layers/scroll/app/composables/useSectionProgress.ts +2 -1
- package/layers/scroll/app/plugins/locomotive-scroll.client.ts +54 -61
- package/layers/scroll/app/types/index.ts +1 -0
- package/layers/scroll/app/types/scroll.ts +32 -0
- package/layers/scroll/package.json +3 -0
- package/layers/seo/package.json +2 -1
- package/layers/shader/app/components/Material/Fresnel.client.vue +1 -1
- package/layers/shader/app/components/Material/Image.client.vue +1 -1
- package/layers/shader/app/components/Material/Node.client.vue +7 -7
- package/layers/shader/app/components/Material/Noise.client.vue +1 -1
- package/layers/shader/app/components/Node/Color.client.vue +17 -20
- package/layers/shader/app/components/Node/Noise.client.vue +31 -34
- package/layers/shader/app/components/Pipeline/Aurora.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/BilinearGradient.client.vue +8 -11
- package/layers/shader/app/components/Pipeline/BillowNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/BrightnessContrast.client.vue +6 -2
- package/layers/shader/app/components/Pipeline/CellularNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Checkerboard.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Circle.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/Clouds.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/ColorBurnBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/ColorDodgeBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/ColourRamp.client.vue +5 -9
- package/layers/shader/app/components/Pipeline/ConicGradient.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/Cross.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/CurlNoise.client.vue +3 -7
- package/layers/shader/app/components/Pipeline/DarkenBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/DayNightCycle.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/DiagonalGradient.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/DiamondGradient.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/DifferenceBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/DomainWarpedNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Dots.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/DuoTone.client.vue +5 -9
- package/layers/shader/app/components/Pipeline/ExclusionBlend.client.vue +3 -23
- package/layers/shader/app/components/Pipeline/ExponentialFog.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/FilmBurn.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/Flame.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/FocalGradient.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/GodRays.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/GradientNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Grid.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Halation.client.vue +3 -7
- package/layers/shader/app/components/Pipeline/HardLightBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/Haze.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/Hexagon.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/LensFlare.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/LightenBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/LinearGradient4.client.vue +2 -2
- package/layers/shader/app/components/Pipeline/Marble.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/MonochromeTint.client.vue +3 -7
- package/layers/shader/app/components/Pipeline/MultiplyBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/NoisyGradient.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/NoisyGradientBlend.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/OverlayBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/Polygon.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/RaymarchTunnel.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/Rectangle.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/RidgedNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Ring.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/ScreenBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/SkyAtmosphere.client.vue +6 -9
- package/layers/shader/app/components/Pipeline/SoftLightBlend.client.vue +2 -19
- package/layers/shader/app/components/Pipeline/SplitTone.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Star.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Stripes.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Tint.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/Triangle.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/ValueNoise.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/VoronoiEdges.client.vue +4 -8
- package/layers/shader/app/components/Pipeline/Water.client.vue +5 -8
- package/layers/shader/app/components/Pipeline/WaveBendLayer.client.vue +4 -7
- package/layers/shader/app/components/Pipeline/WaveColourLayer.client.vue +3 -7
- package/layers/shader/app/components/Pipeline/Wood.client.vue +4 -8
- package/layers/shader/app/components/Preset/Aurora.client.vue +15 -21
- package/layers/shader/app/components/Preset/Flow.client.vue +2 -1
- package/layers/shader/app/components/Preset/GradientMesh.client.vue +2 -1
- package/layers/shader/app/components/Preset/Nebula.client.vue +2 -1
- package/layers/shader/app/components/Preset/Ocean.client.vue +2 -1
- package/layers/shader/app/components/Preset/ThemeAurora.client.vue +30 -90
- package/layers/shader/app/components/Preset/ThemeBubble.client.vue +30 -91
- package/layers/shader/app/components/Preset/ThemeFlow.client.vue +30 -90
- package/layers/shader/app/components/Preset/ThemeGradient.client.vue +30 -91
- package/layers/shader/app/components/Preset/ThemeLavaLamp.client.vue +30 -90
- package/layers/shader/app/components/Preset/ThemePlasma.client.vue +30 -90
- package/layers/shader/app/components/Preset/ThemeWave.client.vue +30 -90
- package/layers/shader/app/components/Shader/Background.client.vue +4 -4
- package/layers/shader/app/components/Shader/Host.client.vue +31 -33
- package/layers/shader/app/components/Shader/Runtime.client.vue +15 -23
- package/layers/shader/app/composables/useAmbientMaterials.ts +53 -51
- package/layers/shader/app/composables/useShaderMixBlend.ts +26 -0
- package/layers/shader/app/composables/useThemePreset.ts +75 -0
- package/layers/shader/app/plugins/shader.client.ts +21 -21
- package/layers/shader/app/shaders/common/noise.ts +2 -7
- package/layers/shader/app/shaders/types.ts +6 -6
- package/layers/shader/app/types/tsl.ts +7 -25
- package/layers/shader/app/types/uniforms.ts +2 -1
- package/layers/shader/app/utils/tsl/color.ts +7 -1
- package/layers/shader/package.json +2 -1
- package/layers/theme/app/components/ThemePicker/Colors.vue +1 -3
- package/layers/theme/app/plugins/theme.client.ts +54 -51
- package/layers/theme/app/types/app-config.d.ts +4 -2
- package/layers/theme/app/types/index.ts +1 -0
- package/layers/theme/app/types/theme.ts +3 -18
- package/layers/theme/package.json +2 -1
- package/layers/theme/server/plugins/theme-fouc.ts +1 -1
- package/layers/transitions/package.json +4 -1
- package/layers/typography/app/components/Typography/CodeBlock.vue +2 -2
- package/layers/typography/app/components/Typography/Headline.vue +2 -2
- package/layers/typography/app/components/Typography/HeadlineScreen.vue +1 -1
- package/layers/typography/app/components/Typography/QuoteBlock.vue +4 -1
- package/layers/typography/app/components/Typography/TextStroke.vue +2 -0
- package/layers/typography/app/components/Typography/index.vue +36 -27
- package/layers/typography/app/composables/typography.ts +27 -21
- package/layers/typography/app/types/colors.ts +9 -29
- package/layers/typography/app/types/index.ts +2 -0
- package/layers/typography/package.json +4 -1
- package/layers/ui/package.json +2 -1
- package/layers/visual/app/app.config.ts +5 -2
- package/layers/visual/app/components/Accent/Blob.vue +20 -20
- package/layers/visual/app/components/Accent/Scene.vue +2 -2
- package/layers/visual/app/components/Base/Modal.vue +2 -2
- package/layers/visual/app/components/Gradient/Background.vue +2 -2
- package/layers/visual/app/components/Gradient/Text.vue +2 -2
- package/layers/visual/app/components/Media/Picture.vue +3 -1
- package/layers/visual/app/components/Progress/Bar.vue +6 -6
- package/layers/visual/app/components/Tint/Overlay.vue +14 -14
- package/layers/visual/app/composables/accent.ts +10 -8
- package/layers/visual/app/composables/gradient.ts +2 -3
- package/layers/visual/app/composables/tint.ts +7 -7
- package/layers/visual/app/types/index.ts +6 -0
- package/layers/visual/app/types/media.ts +4 -2
- package/layers/visual/app/types/tint.ts +2 -1
- package/layers/visual/package.json +4 -1
- package/package.json +5 -2
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Type System Architecture — `kmcom-nuxt-layers`
|
|
2
|
+
|
|
3
|
+
## Guiding Principle
|
|
4
|
+
|
|
5
|
+
Types have two distinct jobs in this monorepo:
|
|
6
|
+
|
|
7
|
+
- **Internal types** — owned by a single layer, not exported, can change freely
|
|
8
|
+
- **Cross-layer contracts** — shared between two or more layers, or exposed to consuming apps; changes here are breaking changes
|
|
9
|
+
|
|
10
|
+
The rule: **if only one layer needs it, it lives in that layer. If two or more layers need it, it lives in root `types/`.**
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Directory Structure
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
kmcom-nuxt-layers/
|
|
18
|
+
│
|
|
19
|
+
├── types/ # Cross-layer contracts & public API
|
|
20
|
+
│ ├── theme.ts # Token shapes, mode/palette/contrast enums
|
|
21
|
+
│ ├── motion.ts # Shared motion contracts (e.g. scroll lock events)
|
|
22
|
+
│ ├── events.ts # Event bus payload types (cross-layer)
|
|
23
|
+
│ ├── runtime.ts # runtimeConfig shape types
|
|
24
|
+
│ └── index.ts # Public barrel — consuming apps import from here
|
|
25
|
+
│
|
|
26
|
+
├── layers/
|
|
27
|
+
│ ├── core/
|
|
28
|
+
│ │ └── types/
|
|
29
|
+
│ │ ├── device.ts # Browser/device detection internals
|
|
30
|
+
│ │ ├── network.ts # Network status types
|
|
31
|
+
│ │ └── index.ts
|
|
32
|
+
│ │
|
|
33
|
+
│ ├── ui/
|
|
34
|
+
│ │ └── types/
|
|
35
|
+
│ │ ├── components.ts # Component prop shapes
|
|
36
|
+
│ │ ├── typography.ts # Type scale, font role types
|
|
37
|
+
│ │ └── index.ts
|
|
38
|
+
│ │
|
|
39
|
+
│ ├── layout/
|
|
40
|
+
│ │ └── types/
|
|
41
|
+
│ │ ├── grid.ts # 18-col grid config types
|
|
42
|
+
│ │ ├── sections.ts # Section/page component prop shapes
|
|
43
|
+
│ │ └── index.ts
|
|
44
|
+
│ │
|
|
45
|
+
│ ├── motion/
|
|
46
|
+
│ │ └── types/
|
|
47
|
+
│ │ ├── transitions.ts # Transition component prop shapes
|
|
48
|
+
│ │ ├── scroll.ts # Scroll composable internals
|
|
49
|
+
│ │ └── index.ts
|
|
50
|
+
│ │
|
|
51
|
+
│ ├── shader/
|
|
52
|
+
│ │ └── types/
|
|
53
|
+
│ │ ├── blocks.ts # Block category interfaces (Primitives, Generators, etc.)
|
|
54
|
+
│ │ ├── pipeline.ts # ShaderPipeline / useShaderStage internals
|
|
55
|
+
│ │ ├── colour.ts # Colour utility types (oklch, hsla, hex, rgb)
|
|
56
|
+
│ │ └── index.ts
|
|
57
|
+
│ │
|
|
58
|
+
│ └── theme/
|
|
59
|
+
│ └── types/
|
|
60
|
+
│ ├── modes.ts # dark/light/system mode internals
|
|
61
|
+
│ ├── colour.ts # Accent/palette resolution internals
|
|
62
|
+
│ └── index.ts
|
|
63
|
+
│
|
|
64
|
+
└── package.json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Root `types/` — Cross-Layer Contracts
|
|
70
|
+
|
|
71
|
+
These are the types that define how layers talk to each other. Treat them as a public API — changes here may require updates across multiple layers and in consuming apps.
|
|
72
|
+
|
|
73
|
+
### `theme.ts`
|
|
74
|
+
|
|
75
|
+
Consumed by: `ui`, `layout`, `motion`, `shader`, `theme`
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
export type ColourMode = 'light' | 'dark' | 'system'
|
|
79
|
+
export type ContrastLevel = 'standard' | 'high'
|
|
80
|
+
export type MotionPreference = 'full' | 'reduced' | 'none'
|
|
81
|
+
export type TransparencyPreference = 'full' | 'reduced' | 'none'
|
|
82
|
+
|
|
83
|
+
export interface ThemeState {
|
|
84
|
+
mode: ColourMode
|
|
85
|
+
palette: string // e.g. 'default' | 'ocean' | custom slug
|
|
86
|
+
contrast: ContrastLevel
|
|
87
|
+
motion: MotionPreference
|
|
88
|
+
transparency: TransparencyPreference
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface ThemeTokens {
|
|
92
|
+
// Add resolved CSS custom property shapes here as the system matures
|
|
93
|
+
[key: string]: string
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### `events.ts`
|
|
98
|
+
|
|
99
|
+
Consumed by: any layer using the event bus (e.g. `motion` scroll lock, `core` loading states)
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
export interface ScrollLockEvent {
|
|
103
|
+
locked: boolean
|
|
104
|
+
source: string // which layer/component emitted it
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface LoadingStateEvent {
|
|
108
|
+
loading: boolean
|
|
109
|
+
id?: string
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Extend as new cross-layer events are introduced
|
|
113
|
+
export type LayerEvent =
|
|
114
|
+
| { type: 'scroll:lock'; payload: ScrollLockEvent }
|
|
115
|
+
| { type: 'loading:state'; payload: LoadingStateEvent }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### `motion.ts`
|
|
119
|
+
|
|
120
|
+
Consumed by: `motion`, `layout` (section entry animations), `shader` (transition hooks)
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
export interface MotionConfig {
|
|
124
|
+
duration: number
|
|
125
|
+
ease: string
|
|
126
|
+
delay?: number
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface TransitionConfig extends MotionConfig {
|
|
130
|
+
enterFrom?: Record<string, string | number>
|
|
131
|
+
enterTo?: Record<string, string | number>
|
|
132
|
+
leaveFrom?: Record<string, string | number>
|
|
133
|
+
leaveTo?: Record<string, string | number>
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### `runtime.ts`
|
|
138
|
+
|
|
139
|
+
Consumed by: `core`, any layer that reads `useRuntimeConfig()`
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
export interface PublicRuntimeConfig {
|
|
143
|
+
apiBase: string
|
|
144
|
+
// Extend per project — this is the shared baseline
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### `index.ts` — Public Barrel
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
// What consuming apps are allowed to import
|
|
152
|
+
export type {
|
|
153
|
+
ColourMode,
|
|
154
|
+
ContrastLevel,
|
|
155
|
+
MotionPreference,
|
|
156
|
+
TransparencyPreference,
|
|
157
|
+
ThemeState,
|
|
158
|
+
} from './theme'
|
|
159
|
+
export type { ScrollLockEvent, LoadingStateEvent, LayerEvent } from './events'
|
|
160
|
+
export type { MotionConfig, TransitionConfig } from './motion'
|
|
161
|
+
export type { PublicRuntimeConfig } from './runtime'
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Per-Layer `types/` — Internal Types
|
|
167
|
+
|
|
168
|
+
Internal types are **not re-exported from root `types/index.ts`**. They are only accessible within their own layer. There is no rule against a layer importing from root `types/` — that's expected — but root `types/` should never import from a layer.
|
|
169
|
+
|
|
170
|
+
### Dependency direction
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
consuming app
|
|
174
|
+
↓
|
|
175
|
+
root types/ ← cross-layer contracts
|
|
176
|
+
↓
|
|
177
|
+
layer/types/ ← internal, layer-owned
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Never:** `root types/` ← `layer/types/`
|
|
181
|
+
**Never:** `layer-a/types/` ← `layer-b/types/`
|
|
182
|
+
|
|
183
|
+
If two layers both need a type that currently lives in one of them — move it to root `types/`.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Recommended Type Packages
|
|
188
|
+
|
|
189
|
+
### Add now
|
|
190
|
+
|
|
191
|
+
| Package | Rationale |
|
|
192
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
193
|
+
| `type-fest` | Utility types: `PartialDeep`, `RequireAtLeastOne`, `Simplify`, `SetOptional`. Eliminates most hand-rolled utility types. |
|
|
194
|
+
| `@types/three` | Required for shader layer — Three.js/TSL types for `ShaderNodeObject`, `MeshStandardNodeMaterial`, etc. |
|
|
195
|
+
| `csstype` | Typed CSS properties — useful in the design system and any style object work in UI/Layout layers. |
|
|
196
|
+
|
|
197
|
+
### Consider later
|
|
198
|
+
|
|
199
|
+
| Package | Rationale |
|
|
200
|
+
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
201
|
+
| `zod` | Runtime validation for `runtimeConfig` shapes and any API responses in a Data layer. Pairs with `z.infer<>` to derive TypeScript types from schemas. |
|
|
202
|
+
| `ts-pattern` | Exhaustive pattern matching — useful in event bus handlers and shader block routing logic. |
|
|
203
|
+
|
|
204
|
+
### Skip
|
|
205
|
+
|
|
206
|
+
| Package | Why |
|
|
207
|
+
| -------------------- | --------------------------------------------------------------- |
|
|
208
|
+
| `io-ts` / `runtypes` | Same space as Zod, less ecosystem momentum, more complex API. |
|
|
209
|
+
| `@types/gsap` | GSAP ships its own types — no separate `@types` package needed. |
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Migration Checklist
|
|
214
|
+
|
|
215
|
+
When moving existing types into this structure:
|
|
216
|
+
|
|
217
|
+
- [ ] Audit all `.ts` files and `.vue` `<script>` blocks for locally defined types
|
|
218
|
+
- [ ] Classify each type: internal (one layer) or cross-layer (two or more)
|
|
219
|
+
- [ ] Move cross-layer types to root `types/` and update all imports
|
|
220
|
+
- [ ] Move internal types to `layer/types/index.ts` and update local imports
|
|
221
|
+
- [ ] Add `type-fest`, `@types/three`, `csstype` to `package.json`
|
|
222
|
+
- [ ] Ensure root `types/index.ts` barrel only exports what consuming apps should see
|
|
223
|
+
- [ ] Verify no layer `types/` files are importing from another layer `types/` — any such coupling should be resolved via root `types/`
|
|
224
|
+
- [ ] Add a TSDoc comment to each type in root `types/` explaining which layers consume it
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Conventions
|
|
229
|
+
|
|
230
|
+
- **Type-only imports:** always use `import type { ... }` for type-only imports to keep the bundle clean
|
|
231
|
+
- **No circular deps:** root `types/` has zero imports from layers; layers may import from root `types/`
|
|
232
|
+
- **TSDoc all root types:** internal types can be lightly documented; root types should always have a JSDoc/TSDoc comment
|
|
233
|
+
- **Barrel per layer:** every `layer/types/` has an `index.ts` — no deep imports into layer type files from outside that layer
|
|
234
|
+
- **Naming:** prefer `interface` for object shapes (extensible), `type` for unions/aliases
|
|
@@ -52,8 +52,9 @@
|
|
|
52
52
|
const { gsap } = useGsap()
|
|
53
53
|
const { velocity: scrollVelocity, direction: scrollDirection } = useSmoothScroll()
|
|
54
54
|
|
|
55
|
-
const containerRef =
|
|
56
|
-
const contentRef =
|
|
55
|
+
const containerRef = useTemplateRef<HTMLElement>('containerRef')
|
|
56
|
+
const contentRef = useTemplateRef<HTMLElement>('contentRef')
|
|
57
|
+
|
|
57
58
|
const tweenRef = ref<gsap.core.Tween | null>(null)
|
|
58
59
|
|
|
59
60
|
const isPaused = ref(false)
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
const { gsap, ScrollTrigger } = useGsap()
|
|
36
36
|
const { velocityFactor } = useMarqueeVelocity({ damping, stiffness, velocityMapping })
|
|
37
37
|
|
|
38
|
-
const containerRef =
|
|
38
|
+
const containerRef = useTemplateRef<HTMLElement[]>('containerRef')
|
|
39
|
+
|
|
39
40
|
const copyRefs = ref<HTMLSpanElement[]>([])
|
|
40
41
|
|
|
41
42
|
const { copyWidths, calculatedCopies } = useMarqueeCopies(
|
|
@@ -130,7 +131,7 @@
|
|
|
130
131
|
:style="parallaxStyle"
|
|
131
132
|
>
|
|
132
133
|
<div
|
|
133
|
-
:class="`${scrollerClassName} font-styles-logo flex py-2 text-center font-sans text-4xl font-medium tracking-[-0.02em] whitespace-nowrap text-neutral drop-shadow md:text-[5rem] md:leading-
|
|
134
|
+
:class="`${scrollerClassName} font-styles-logo flex py-2 text-center font-sans text-4xl font-medium tracking-[-0.02em] whitespace-nowrap text-neutral drop-shadow md:text-[5rem] md:leading-20`"
|
|
134
135
|
:style="{ transform: `translateX(${scrollTransforms[index] ?? '0px'})`, ...scrollerStyle }"
|
|
135
136
|
>
|
|
136
137
|
<span
|
|
@@ -10,7 +10,10 @@ type UseCountUpOptions = {
|
|
|
10
10
|
once?: boolean
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function useCountUp(
|
|
13
|
+
export function useCountUp(
|
|
14
|
+
elementRef: MaybeRefOrGetter<HTMLElement | null>,
|
|
15
|
+
opts: UseCountUpOptions
|
|
16
|
+
) {
|
|
14
17
|
const { gsap, ScrollTrigger } = useGsap()
|
|
15
18
|
|
|
16
19
|
const displayValue = ref(String(opts.from ?? 0))
|
|
@@ -5,7 +5,7 @@ export function useMagneticElement(
|
|
|
5
5
|
radius?: number
|
|
6
6
|
damping?: number
|
|
7
7
|
stiffness?: number
|
|
8
|
-
} = {}
|
|
8
|
+
} = {}
|
|
9
9
|
) {
|
|
10
10
|
const { gsap } = useGsap()
|
|
11
11
|
const { elementX, elementY, elementWidth, elementHeight } = useMouseInElement(elementRef)
|
|
@@ -27,12 +27,10 @@ export function useMagneticElement(
|
|
|
27
27
|
let targetX = 0
|
|
28
28
|
let targetY = 0
|
|
29
29
|
|
|
30
|
+
isActive.value = dist < radius
|
|
30
31
|
if (dist < radius) {
|
|
31
|
-
isActive.value = true
|
|
32
32
|
targetX = dx * strength
|
|
33
33
|
targetY = dy * strength
|
|
34
|
-
} else {
|
|
35
|
-
isActive.value = false
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
currentX.value += (targetX - currentX.value) * stiffness
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { MaybeRef } from 'vue'
|
|
1
|
+
import type { MaybeRef, ShallowRef } from 'vue'
|
|
2
2
|
|
|
3
3
|
export function useMarqueeCopies(
|
|
4
|
-
containerRefs:
|
|
4
|
+
containerRefs: Readonly<ShallowRef<HTMLElement[] | null>>,
|
|
5
5
|
copyRefs: Ref<HTMLSpanElement[]>,
|
|
6
|
-
rowCount: MaybeRef<number
|
|
6
|
+
rowCount: MaybeRef<number>
|
|
7
7
|
) {
|
|
8
8
|
const copyWidths = ref<number[]>([])
|
|
9
9
|
const calculatedCopies = ref<number[]>([])
|
|
@@ -14,7 +14,7 @@ export function useMarqueeCopies(
|
|
|
14
14
|
const n = unref(rowCount)
|
|
15
15
|
for (let i = 0; i < n; i++) {
|
|
16
16
|
const copy = copyRefs.value[i]
|
|
17
|
-
const container = containerRefs.value[i]
|
|
17
|
+
const container = containerRefs.value?.[i]
|
|
18
18
|
if (!copy || !container) continue
|
|
19
19
|
const singleWidth = copy.offsetWidth
|
|
20
20
|
if (singleWidth === 0) continue
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type * from './animations'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { TresCanvas } from '@tresjs/core'
|
|
2
|
+
import { TresCanvas, type TresContext, type TresRendererSetupContext } from '@tresjs/core'
|
|
3
3
|
import {
|
|
4
4
|
ACESFilmicToneMapping,
|
|
5
5
|
CineonToneMapping,
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
}>()
|
|
38
38
|
|
|
39
39
|
const emit = defineEmits<{
|
|
40
|
-
ready: [context:
|
|
40
|
+
ready: [context: TresContext]
|
|
41
41
|
}>()
|
|
42
42
|
|
|
43
43
|
const config = useAppConfig()
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
|
|
70
70
|
// WebGPU renderer factory — TresJS v5 calls renderer.init() automatically
|
|
71
71
|
// when the returned object has isRenderer === true (three/webgpu Renderer base class)
|
|
72
|
-
function webgpuRendererFactory({ canvas }:
|
|
72
|
+
function webgpuRendererFactory({ canvas }: TresRendererSetupContext) {
|
|
73
73
|
const r = new WebGPURenderer({
|
|
74
74
|
canvas: unref(canvas),
|
|
75
75
|
antialias,
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
|
|
86
86
|
const rendererBinding = computed(() => (webgpu ? { renderer: webgpuRendererFactory } : {}))
|
|
87
87
|
|
|
88
|
-
function onReady(context:
|
|
88
|
+
function onReady(context: TresContext) {
|
|
89
89
|
emit('ready', context)
|
|
90
90
|
}
|
|
91
91
|
</script>
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { WebGPURenderer } from 'three/webgpu'
|
|
2
|
+
import type { WebGLRenderer } from 'three'
|
|
1
3
|
import {
|
|
2
4
|
QUALITY_PRESETS,
|
|
3
5
|
type QualityLevel,
|
|
@@ -12,7 +14,7 @@ export function useRendererCapabilities() {
|
|
|
12
14
|
const capabilities = ref<RendererCapabilities | null>(null)
|
|
13
15
|
const isReady = ref(false)
|
|
14
16
|
|
|
15
|
-
function detectFromRenderer(renderer:
|
|
17
|
+
function detectFromRenderer(renderer: WebGPURenderer | WebGLRenderer) {
|
|
16
18
|
const isWebGPU = renderer.constructor?.name === 'WebGPURenderer'
|
|
17
19
|
const glCaps = renderer.capabilities
|
|
18
20
|
|
|
@@ -29,19 +31,21 @@ export function useRendererCapabilities() {
|
|
|
29
31
|
devicePixelRatio: renderer.getPixelRatio?.() ?? 1,
|
|
30
32
|
isWebGPU: true,
|
|
31
33
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
isReady.value = true
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
capabilities.value = {
|
|
39
|
+
backend: 'webgl',
|
|
40
|
+
maxTextureSize: glCaps.maxTextureSize,
|
|
41
|
+
maxTextures: glCaps.maxTextures,
|
|
42
|
+
maxVertexUniforms: glCaps.maxVertexUniforms,
|
|
43
|
+
maxFragmentUniforms: glCaps.maxFragmentUniforms,
|
|
44
|
+
floatTextures: glCaps.isWebGL2 || false,
|
|
45
|
+
anisotropy: glCaps.getMaxAnisotropy(),
|
|
46
|
+
precision: glCaps.precision as 'lowp' | 'mediump' | 'highp',
|
|
47
|
+
devicePixelRatio: renderer.getPixelRatio(),
|
|
48
|
+
isWebGPU: false,
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
isReady.value = true
|
|
@@ -70,7 +74,7 @@ export async function checkWebGPUSupport(): Promise<boolean> {
|
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
try {
|
|
73
|
-
const adapter = await
|
|
77
|
+
const adapter = await navigator.gpu.requestAdapter()
|
|
74
78
|
return adapter !== null
|
|
75
79
|
} catch {
|
|
76
80
|
return false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './renderer'
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "nuxi dev",
|
|
8
8
|
"dev:playground": "PLAYGROUND_LAYERS=core,canvas pnpm -F playground dev",
|
|
9
|
-
"typecheck": "vue-tsc --noEmit -p ../../tsconfig.typecheck.json"
|
|
9
|
+
"typecheck": "vue-tsc --noEmit -p ../../tsconfig.typecheck.json",
|
|
10
|
+
"lint": "eslint ."
|
|
10
11
|
},
|
|
11
12
|
"dependencies": {
|
|
12
13
|
"@tresjs/cientos": "catalog:",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
const {
|
|
3
3
|
title,
|
|
4
|
-
description,
|
|
5
|
-
date,
|
|
6
|
-
image,
|
|
7
|
-
badge,
|
|
4
|
+
description = undefined,
|
|
5
|
+
date = undefined,
|
|
6
|
+
image = undefined,
|
|
7
|
+
badge = undefined,
|
|
8
8
|
authors = [],
|
|
9
|
-
to,
|
|
9
|
+
to = undefined,
|
|
10
10
|
} = defineProps<{
|
|
11
11
|
title: string
|
|
12
12
|
description?: string
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { PageCollections } from '@nuxt/content'
|
|
3
|
+
import type { ContentSurroundLink } from '@nuxt/ui'
|
|
3
4
|
|
|
4
5
|
const {
|
|
5
6
|
collection,
|
|
@@ -16,6 +17,9 @@
|
|
|
16
17
|
const { data: item, status } = await useCollectionItem(collection, slug)
|
|
17
18
|
const { data: surround } = await useCollectionSurround(collection, slug)
|
|
18
19
|
|
|
20
|
+
const surroundLinks = computed(
|
|
21
|
+
() => (surround.value ?? undefined) as ContentSurroundLink[] | undefined
|
|
22
|
+
)
|
|
19
23
|
const itemImage = computed(() => (item.value as { image?: string } | null)?.image)
|
|
20
24
|
|
|
21
25
|
useSeoMeta({
|
|
@@ -47,7 +51,7 @@
|
|
|
47
51
|
<slot name="after-content" :item />
|
|
48
52
|
|
|
49
53
|
<USeparator class="my-8" />
|
|
50
|
-
<NuxtContentSurround :surround="
|
|
54
|
+
<NuxtContentSurround :surround="surroundLinks" />
|
|
51
55
|
</UPageBody>
|
|
52
56
|
|
|
53
57
|
<template v-if="!hideToc" #right>
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type { ContentSurroundLink } from '@nuxt/ui'
|
|
3
|
+
|
|
4
|
+
const { surround = undefined } = defineProps<{
|
|
5
|
+
surround?: ContentSurroundLink[]
|
|
4
6
|
}>()
|
|
5
7
|
</script>
|
|
6
8
|
|
|
7
9
|
<template>
|
|
8
10
|
<UContentSurround
|
|
9
11
|
v-if="surround"
|
|
10
|
-
:surround
|
|
12
|
+
:surround
|
|
11
13
|
prev-icon="i-lucide-arrow-left"
|
|
12
14
|
next-icon="i-lucide-arrow-right"
|
|
13
15
|
/>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
const {
|
|
3
3
|
title,
|
|
4
|
-
description,
|
|
5
|
-
image,
|
|
4
|
+
description = undefined,
|
|
5
|
+
image = undefined,
|
|
6
6
|
tags = [],
|
|
7
|
-
client,
|
|
8
|
-
year,
|
|
9
|
-
to,
|
|
7
|
+
client = undefined,
|
|
8
|
+
year = undefined,
|
|
9
|
+
to = undefined,
|
|
10
10
|
} = defineProps<{
|
|
11
11
|
title: string
|
|
12
12
|
description?: string
|