kmcom-nuxt-layers 6.3.0 → 6.5.0

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.
Files changed (142) hide show
  1. package/docs/MIGRATION-v6.4.0.md +215 -0
  2. package/docs/MIGRATION-v6.5.0.md +87 -0
  3. package/docs/MIGRATION.md +3 -1
  4. package/docs/USAGE.md +35 -10
  5. package/docs/adr/0003-modular-step-system-replaces-fluid-clamps.md +16 -0
  6. package/docs/component-levels.md +1 -0
  7. package/docs/layout-shift-causes.md +18 -0
  8. package/layers/content/app/components/content/Figure.vue +1 -1
  9. package/layers/content/app/composables/useContentSection.ts +1 -1
  10. package/layers/core/app/app.config.ts +9 -5
  11. package/layers/core/app/app.vue +2 -1
  12. package/layers/core/app/components/LoadingScreen.vue +35 -21
  13. package/layers/core/app/composables/useCache.ts +2 -2
  14. package/layers/core/app/composables/useErrorLog.ts +5 -5
  15. package/layers/core/app/composables/useLoading.ts +19 -10
  16. package/layers/core/app/plugins/loading.client.ts +11 -3
  17. package/layers/core/app/types/loading.ts +10 -3
  18. package/layers/core/app/utils/loading.ts +7 -16
  19. package/layers/core/nuxt.config.ts +14 -14
  20. package/layers/core/server/utils/app-config.ts +17 -0
  21. package/layers/data/auth/app/middleware/auth.ts +1 -1
  22. package/layers/data/forms/app/components/Form/Contact.vue +1 -1
  23. package/layers/data/forms/server/api/contact.post.ts +16 -8
  24. package/layers/data/forms/server/api/forms/status.get.ts +3 -0
  25. package/layers/data/forms/{app → shared}/utils/contact-schema.ts +2 -1
  26. package/layers/data/metadata/server/api/metadata/search.get.ts +27 -7
  27. package/layers/data/metadata/server/api/metadata/status.get.ts +4 -1
  28. package/layers/data/metadata/server/api/metadata/sync.post.ts +13 -3
  29. package/layers/data/metadata/server/utils/metadata/resolve-record.ts +3 -3
  30. package/layers/delivery/feeds/nuxt.config.ts +6 -1
  31. package/layers/delivery/feeds/package.json +2 -2
  32. package/layers/delivery/feeds/server/routes/feed/demo.get.ts +2 -2
  33. package/layers/delivery/feeds/server/utils/content-adapter.ts +1 -1
  34. package/layers/delivery/feeds/server/utils/feed-service.ts +2 -2
  35. package/layers/design-system/theming/app/plugins/theme.client.ts +7 -0
  36. package/layers/design-system/theming/nuxt.config.ts +0 -2
  37. package/layers/design-system/typography/app/assets/css/typography.css +41 -5
  38. package/layers/design-system/visual/app/components/HoverDimGroup.vue +11 -3
  39. package/layers/motion/scroll/app/plugins/locomotive-scroll.client.ts +3 -2
  40. package/layers/render/canvas/nuxt.config.ts +0 -4
  41. package/layers/render/shader/nuxt.config.ts +0 -4
  42. package/layers/structure/navigation/app/app.config.ts +37 -14
  43. package/layers/structure/navigation/app/components/Mast/Nav.vue +14 -13
  44. package/layers/structure/navigation/app/components/Mast/NavModal.vue +83 -28
  45. package/layers/structure/navigation/app/components/Site/Logo.vue +35 -0
  46. package/layers/structure/navigation/app/components/Site/Title.vue +3 -3
  47. package/layers/structure/navigation/app/composables/mastNav.ts +38 -13
  48. package/layers/structure/navigation/app/types/nav.ts +34 -0
  49. package/layers/structure/routing/app/middleware/01.maintenance.global.ts +4 -1
  50. package/layers/structure/routing/app/middleware/02.governance.global.ts +1 -1
  51. package/layers/structure/routing/nuxt.config.ts +19 -12
  52. package/layers/structure/routing/server/api/feature-flags.get.ts +4 -2
  53. package/package.json +35 -5
  54. package/docs/FALLOW-COMPLEXITY-DUPLICATION-AUDIT.md +0 -64
  55. package/docs/IMPROVE-AUDIT-README.md +0 -29
  56. package/docs/IMPROVE-AUDIT-RESULTS.md +0 -51
  57. package/docs/IMPROVE-DEEP-AUDIT-RESULTS.md +0 -81
  58. package/docs/fallow-refactor/apps-debug.md +0 -27
  59. package/docs/fallow-refactor/apps-playground.md +0 -46
  60. package/docs/fallow-refactor/apps-visual-identity.md +0 -41
  61. package/docs/fallow-refactor/layers-animations.md +0 -34
  62. package/docs/fallow-refactor/layers-canvas.md +0 -32
  63. package/docs/fallow-refactor/layers-content.md +0 -33
  64. package/docs/fallow-refactor/layers-core.md +0 -39
  65. package/docs/fallow-refactor/layers-feeds.md +0 -39
  66. package/docs/fallow-refactor/layers-forms.md +0 -30
  67. package/docs/fallow-refactor/layers-layout.md +0 -42
  68. package/docs/fallow-refactor/layers-mailer.md +0 -32
  69. package/docs/fallow-refactor/layers-motion.md +0 -27
  70. package/docs/fallow-refactor/layers-navigation.md +0 -31
  71. package/docs/fallow-refactor/layers-page-transitions.md +0 -30
  72. package/docs/fallow-refactor/layers-routing.md +0 -33
  73. package/docs/fallow-refactor/layers-scripts.md +0 -35
  74. package/docs/fallow-refactor/layers-scroll.md +0 -38
  75. package/docs/fallow-refactor/layers-seo.md +0 -32
  76. package/docs/fallow-refactor/layers-shader.md +0 -53
  77. package/docs/fallow-refactor/layers-theme.md +0 -33
  78. package/docs/fallow-refactor/layers-transitions.md +0 -27
  79. package/docs/fallow-refactor/layers-typography.md +0 -29
  80. package/docs/fallow-refactor/layers-visual.md +0 -34
  81. package/docs/superpowers/plans/2026-09-03-layout-layer-fluid-rebuild.md +0 -1850
  82. package/docs/superpowers/plans/2026-09-03-vue-element-system.md +0 -1019
  83. package/docs/superpowers/plans/2026-09-04-grid-layer.md +0 -977
  84. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-0-1-design.md +0 -533
  85. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-2-design.md +0 -154
  86. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-3-design.md +0 -109
  87. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-4-design.md +0 -124
  88. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-5-design.md +0 -121
  89. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-6-design.md +0 -77
  90. package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-7-design.md +0 -73
  91. package/docs/superpowers/specs/2026-08-31-swiss-grid-layer-design.md +0 -190
  92. package/docs/superpowers/specs/2026-09-03-layout-layer-fluid-rebuild-design.md +0 -312
  93. package/docs/superpowers/specs/2026-09-03-vue-element-system-design.md +0 -342
  94. package/docs/superpowers/specs/2026-09-04-grid-layer-design.md +0 -236
  95. package/layers/content/app/utils/galleryImageMeta.test.ts +0 -30
  96. package/layers/core/app/components/Element.test.ts +0 -90
  97. package/layers/core/app/components/ElementTw.test.ts +0 -64
  98. package/layers/core/app/composables/useLayoutAttrs.test.ts +0 -77
  99. package/layers/core/app/utils/browserInfo.test.ts +0 -81
  100. package/layers/core/app/utils/featureClasses.test.ts +0 -101
  101. package/layers/core/app/utils/loading.test.ts +0 -48
  102. package/layers/core/app/utils/resolveElementStyle.test.ts +0 -99
  103. package/layers/core/app/utils/scrollGuardClamp.test.ts +0 -36
  104. package/layers/core/app/utils/styleToTailwindClasses.test.ts +0 -31
  105. package/layers/data/forms/app/utils/contact-schema.test.ts +0 -75
  106. package/layers/data/forms/app/utils/fieldProps.test.ts +0 -141
  107. package/layers/data/metadata/providers/comicvine/server/utils/metadata-comicvine/normalise.test.ts +0 -201
  108. package/layers/data/metadata/providers/google-books/server/utils/metadata-google-books/client.test.ts +0 -76
  109. package/layers/data/metadata/providers/google-books/server/utils/metadata-google-books/normalise.test.ts +0 -144
  110. package/layers/data/metadata/providers/openlibrary/server/utils/metadata-openlibrary/client.test.ts +0 -25
  111. package/layers/data/metadata/providers/openlibrary/server/utils/metadata-openlibrary/normalise.test.ts +0 -144
  112. package/layers/data/metadata/providers/themoviedb/server/utils/metadata-tmdb/client.test.ts +0 -29
  113. package/layers/data/metadata/providers/themoviedb/server/utils/metadata-tmdb/normalise.test.ts +0 -162
  114. package/layers/data/metadata/server/utils/metadata/cache.test.ts +0 -39
  115. package/layers/data/metadata/server/utils/metadata/provider-fetch.test.ts +0 -27
  116. package/layers/data/metadata/server/utils/metadata/provider-registry.test.ts +0 -54
  117. package/layers/data/metadata/server/utils/metadata/resolve-record.test.ts +0 -87
  118. package/layers/data/metadata/server/utils/metadata/search.test.ts +0 -204
  119. package/layers/delivery/feeds/server/utils/content-adapter.test.ts +0 -67
  120. package/layers/delivery/feeds/server/utils/feed-author.test.ts +0 -71
  121. package/layers/delivery/feeds/server/utils/feed-config.test.ts +0 -184
  122. package/layers/delivery/feeds/server/utils/formats.test.ts +0 -71
  123. package/layers/delivery/seo/app/utils/seoConfig.test.ts +0 -58
  124. package/layers/design-system/theming/server/utils/accent-css.test.ts +0 -71
  125. package/layers/design-system/theming/server/utils/fouc-config.test.ts +0 -78
  126. package/layers/design-system/typography/app/components/Typography/Headline.test.ts +0 -36
  127. package/layers/design-system/typography/app/components/Typography/index.test.ts +0 -31
  128. package/layers/design-system/typography/app/composables/color.test.ts +0 -30
  129. package/layers/design-system/typography/app/composables/typography.test.ts +0 -53
  130. package/layers/design-system/visual/app/composables/tint.test.ts +0 -22
  131. package/layers/design-system/visual/app/utils/colorTokens.test.ts +0 -51
  132. package/layers/design-system/visual/app/utils/gradientStyle.test.ts +0 -75
  133. package/layers/design-system/visual/app/utils/responsiveSizes.test.ts +0 -71
  134. package/layers/motion/animations/app/components/Motion/Staggered.test.ts +0 -40
  135. package/layers/motion/scroll/app/composables/useReducedMotion.test.ts +0 -23
  136. package/layers/motion/scroll/app/utils/parallax.test.ts +0 -24
  137. package/layers/structure/grid/app/composables/useGridTracks.test.ts +0 -94
  138. package/layers/structure/grid/app/types/tracks.test.ts +0 -32
  139. package/layers/structure/grid/app/utils/placement.test.ts +0 -19
  140. package/layers/structure/layout/app/utils/gridPlacementStyle.test.ts +0 -269
  141. package/layers/structure/navigation/app/utils/site.test.ts +0 -39
  142. package/layers/structure/routing/app/utils/resolveRoute.test.ts +0 -47
@@ -1,94 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
-
3
- import type { GridPreset, TrackConfig } from '../types/tracks'
4
- import { resolve, toColumnsCss } from './useGridTracks'
5
-
6
- describe('toColumnsCss', () => {
7
- it('renders equal segments with no line names', () => {
8
- const config: TrackConfig = { columns: [{ size: 1 }, { size: 1 }, { size: 1 }] }
9
- expect(toColumnsCss(config)).toBe(
10
- 'minmax(var(--measure-min), 1fr) minmax(var(--measure-min), 1fr) ' +
11
- 'minmax(var(--measure-min), 1fr)'
12
- )
13
- })
14
-
15
- it('renders mixed sizes (8 equal + double + triple)', () => {
16
- const config: TrackConfig = {
17
- columns: [
18
- { size: 1 },
19
- { size: 1 },
20
- { size: 1 },
21
- { size: 1 },
22
- { size: 1 },
23
- { size: 1 },
24
- { size: 1 },
25
- { size: 2 },
26
- { size: 3 },
27
- ],
28
- }
29
- const css = toColumnsCss(config)
30
- expect(css.split(' ').filter((s) => s.startsWith('minmax'))).toHaveLength(9)
31
- expect(css).toContain('minmax(var(--measure-min), 2fr)')
32
- expect(css).toContain('minmax(var(--measure-min), 3fr)')
33
- })
34
-
35
- it('brackets a leading lineStart and trailing lineEnd', () => {
36
- const config: TrackConfig = {
37
- columns: [{ size: 1, lineStart: 'a-start', lineEnd: 'a-end' }],
38
- }
39
- expect(toColumnsCss(config)).toBe('[a-start] minmax(var(--measure-min), 1fr) [a-end]')
40
- })
41
-
42
- it('merges an adjacent lineEnd and lineStart into one bracket', () => {
43
- const config: TrackConfig = {
44
- columns: [
45
- { size: 2, lineStart: 'feature-start', lineEnd: 'feature-end' },
46
- { size: 1, lineStart: 'aside-start', lineEnd: 'aside-end' },
47
- ],
48
- }
49
- expect(toColumnsCss(config)).toBe(
50
- '[feature-start] minmax(var(--measure-min), 2fr) ' +
51
- '[feature-end aside-start] minmax(var(--measure-min), 1fr) [aside-end]'
52
- )
53
- })
54
-
55
- it('supports a segment with only lineStart set', () => {
56
- const config: TrackConfig = {
57
- columns: [{ size: 1, lineStart: 'only-start' }, { size: 1 }],
58
- }
59
- expect(toColumnsCss(config)).toBe(
60
- '[only-start] minmax(var(--measure-min), 1fr) minmax(var(--measure-min), 1fr)'
61
- )
62
- })
63
-
64
- it('accepts an array of line names', () => {
65
- const config: TrackConfig = {
66
- columns: [{ size: 1, lineStart: ['a', 'b'] }],
67
- }
68
- expect(toColumnsCss(config)).toBe('[a b] minmax(var(--measure-min), 1fr)')
69
- })
70
-
71
- it('uses minTrackWidth override instead of the --measure-min default', () => {
72
- const config: TrackConfig = { columns: [{ size: 1 }], minTrackWidth: '20rem' }
73
- expect(toColumnsCss(config)).toBe('minmax(20rem, 1fr)')
74
- })
75
- })
76
-
77
- describe('resolve', () => {
78
- const presets: Record<string, GridPreset> = {
79
- swiss: { name: 'swiss', columns: [{ size: 1 }] },
80
- }
81
-
82
- it('looks up a named preset from the registry', () => {
83
- expect(resolve('swiss', presets)).toBe(presets.swiss)
84
- })
85
-
86
- it('throws for an unknown preset name', () => {
87
- expect(() => resolve('nope', presets)).toThrow('Unknown grid preset: "nope"')
88
- })
89
-
90
- it('passes a TrackConfig object through unchanged', () => {
91
- const custom: TrackConfig = { columns: [{ size: 1 }, { size: 2 }] }
92
- expect(resolve(custom, presets)).toBe(custom)
93
- })
94
- })
@@ -1,32 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
-
3
- import type { GridPreset, TrackConfig, TrackSegment } from './tracks'
4
-
5
- describe('track types', () => {
6
- it('accepts a minimal equal-width segment', () => {
7
- const segment: TrackSegment = { size: 1 }
8
- expect(segment.size).toBe(1)
9
- })
10
-
11
- it('accepts a segment with named lines', () => {
12
- const segment: TrackSegment = {
13
- size: 2,
14
- lineStart: 'feature-start',
15
- lineEnd: ['feature-end', 'aside-start'],
16
- }
17
- expect(segment.lineEnd).toEqual(['feature-end', 'aside-start'])
18
- })
19
-
20
- it('accepts a TrackConfig with optional minTrackWidth', () => {
21
- const config: TrackConfig = {
22
- columns: [{ size: 1 }, { size: 2 }],
23
- minTrackWidth: '20rem',
24
- }
25
- expect(config.columns).toHaveLength(2)
26
- })
27
-
28
- it('a GridPreset is a named TrackConfig', () => {
29
- const preset: GridPreset = { name: 'swiss', columns: [{ size: 1 }] }
30
- expect(preset.name).toBe('swiss')
31
- })
32
- })
@@ -1,19 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
-
3
- import { placementFromIndex, placementFromLines } from './placement'
4
-
5
- describe('placementFromLines', () => {
6
- it('joins two named lines with a slash', () => {
7
- expect(placementFromLines('feature-start', 'aside-end')).toBe('feature-start / aside-end')
8
- })
9
- })
10
-
11
- describe('placementFromIndex', () => {
12
- it('builds a numeric span from colStart and colSpan', () => {
13
- expect(placementFromIndex(2, 3)).toBe('2 / span 3')
14
- })
15
-
16
- it('spans to the last line when colSpan is "full"', () => {
17
- expect(placementFromIndex(4, 'full')).toBe('4 / -1')
18
- })
19
- })
@@ -1,269 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
-
3
- import {
4
- buildGridPlacementClasses,
5
- buildGridPlacementStyle,
6
- layerZIndex,
7
- resolveAlignmentStyles,
8
- resolveBleedStyles,
9
- resolveDefaultPlacement,
10
- resolveLayerStyles,
11
- resolveResponsivePlacementVars,
12
- resolveRhythmStyles,
13
- } from './gridPlacementStyle'
14
-
15
- describe('layerZIndex map', () => {
16
- it('assigns ascending z-index values', () => {
17
- expect(layerZIndex).toEqual({ back: 0, mid: 10, front: 20, top: 30 })
18
- })
19
- })
20
-
21
- describe('resolveDefaultPlacement', () => {
22
- it('returns the fallback when value is undefined', () => {
23
- expect(resolveDefaultPlacement(undefined, 'full')).toBe('full')
24
- expect(resolveDefaultPlacement<number>(undefined, undefined)).toBeUndefined()
25
- })
26
-
27
- it('returns the plain value unchanged', () => {
28
- expect(resolveDefaultPlacement(3, undefined)).toBe(3)
29
- expect(resolveDefaultPlacement<string>('full', 'other')).toBe('full')
30
- })
31
-
32
- it('unwraps a responsive value default', () => {
33
- expect(resolveDefaultPlacement({ default: 2, md: 4 }, undefined)).toBe(2)
34
- })
35
- })
36
-
37
- describe('resolveResponsivePlacementVars', () => {
38
- it('returns no vars for a plain value', () => {
39
- expect(resolveResponsivePlacementVars(3, 'cs')).toEqual({})
40
- })
41
-
42
- it('returns no vars when value is undefined', () => {
43
- expect(resolveResponsivePlacementVars(undefined, 'cs')).toEqual({})
44
- })
45
-
46
- it('sets only the md var when only md is provided', () => {
47
- expect(resolveResponsivePlacementVars({ default: 1, md: 2 }, 'cs')).toEqual({
48
- '--_md-cs': '2',
49
- })
50
- })
51
-
52
- it('sets only the lg var when only lg is provided', () => {
53
- expect(resolveResponsivePlacementVars({ default: 1, lg: 5 }, 're')).toEqual({
54
- '--_lg-re': '5',
55
- })
56
- })
57
-
58
- it('sets both md and lg vars when both are provided', () => {
59
- expect(resolveResponsivePlacementVars({ default: 1, md: 2, lg: 5 }, 'ce')).toEqual({
60
- '--_md-ce': '2',
61
- '--_lg-ce': '5',
62
- })
63
- })
64
- })
65
-
66
- describe('resolveBleedStyles', () => {
67
- it('returns no styles when bleed is not set', () => {
68
- expect(resolveBleedStyles({})).toEqual({})
69
- })
70
-
71
- it('handles "both" bleed direction', () => {
72
- expect(resolveBleedStyles({ bleed: 'both', rowStart: 1, rowSpan: 3 })).toEqual({
73
- gridColumn: '1 / -1',
74
- marginInline: 'calc(-1 * var(--grid-padding))',
75
- gridRow: '1 / span 3',
76
- })
77
- })
78
-
79
- it('handles "left" bleed direction with a numeric colSpan', () => {
80
- expect(resolveBleedStyles({ bleed: 'left', colSpan: 4, rowStart: 2, rowSpan: 1 })).toEqual({
81
- gridColumn: '1 / span 4',
82
- marginInlineStart: 'calc(-1 * var(--grid-padding))',
83
- gridRow: '2 / span 1',
84
- })
85
- })
86
-
87
- it('handles "left" bleed direction without a numeric colSpan', () => {
88
- expect(resolveBleedStyles({ bleed: 'left', colSpan: 'full', rowSpan: 1 })).toEqual({
89
- gridColumn: '1 / -1',
90
- marginInlineStart: 'calc(-1 * var(--grid-padding))',
91
- gridRow: 'auto / span 1',
92
- })
93
- })
94
-
95
- it('handles "right" bleed direction', () => {
96
- expect(resolveBleedStyles({ bleed: 'right', colStart: 3, rowSpan: 2 })).toEqual({
97
- gridColumn: '3 / -1',
98
- marginInlineEnd: 'calc(-1 * var(--grid-padding))',
99
- gridRow: 'auto / span 2',
100
- })
101
- })
102
-
103
- it('defaults gridRow parts to "auto" when start/span are missing', () => {
104
- expect(resolveBleedStyles({ bleed: 'right' })).toEqual({
105
- gridColumn: 'auto / -1',
106
- marginInlineEnd: 'calc(-1 * var(--grid-padding))',
107
- gridRow: 'auto / span undefined',
108
- })
109
- })
110
- })
111
-
112
- describe('resolveAlignmentStyles', () => {
113
- it('returns no styles when neither align nor justify is set', () => {
114
- expect(resolveAlignmentStyles()).toEqual({})
115
- })
116
-
117
- it('defaults the missing axis to stretch', () => {
118
- expect(resolveAlignmentStyles('center')).toEqual({
119
- display: 'grid',
120
- width: '100%',
121
- height: '100%',
122
- placeItems: 'center stretch',
123
- })
124
- expect(resolveAlignmentStyles(undefined, 'end')).toEqual({
125
- display: 'grid',
126
- width: '100%',
127
- height: '100%',
128
- placeItems: 'stretch end',
129
- })
130
- })
131
-
132
- it('combines align and justify', () => {
133
- expect(resolveAlignmentStyles('start', 'end')).toEqual({
134
- display: 'grid',
135
- width: '100%',
136
- height: '100%',
137
- placeItems: 'start end',
138
- })
139
- })
140
- })
141
-
142
- describe('resolveRhythmStyles', () => {
143
- it('returns no styles when density is undefined', () => {
144
- expect(resolveRhythmStyles()).toEqual({})
145
- })
146
-
147
- it.each([
148
- ['compact', '0.125rem'],
149
- ['normal', '0.25rem'],
150
- ['relaxed', '0.5rem'],
151
- ] as const)('maps %s density to the expected rhythm value', (density, value) => {
152
- expect(resolveRhythmStyles(density)).toEqual({ '--rhythm': value })
153
- })
154
- })
155
-
156
- describe('resolveLayerStyles', () => {
157
- it('returns no styles when layer is not set', () => {
158
- expect(resolveLayerStyles()).toEqual({})
159
- })
160
-
161
- it('looks up the z-index for the given layer', () => {
162
- expect(resolveLayerStyles('front')).toEqual({ zIndex: '20' })
163
- })
164
- })
165
-
166
- describe('buildGridPlacementStyle', () => {
167
- it('applies defaults for an empty input', () => {
168
- expect(buildGridPlacementStyle({})).toEqual({
169
- gridColumn: '1 / -1',
170
- '--_rs': 'auto',
171
- '--_re': '1',
172
- })
173
- })
174
-
175
- it('returns early for a full colSpan and skips alignment/rhythm/layer/gap', () => {
176
- const style = buildGridPlacementStyle({
177
- colSpan: 'full',
178
- align: 'center',
179
- density: 'compact',
180
- layer: 'front',
181
- gap: '1rem',
182
- })
183
-
184
- expect(style).toEqual({
185
- gridColumn: '1 / -1',
186
- '--_rs': 'auto',
187
- '--_re': '1',
188
- })
189
- expect(style).not.toHaveProperty('zIndex')
190
- expect(style).not.toHaveProperty('--rhythm')
191
- expect(style).not.toHaveProperty('--grid-gap')
192
- })
193
-
194
- it('builds explicit column/row vars for a non-full colSpan and applies alignment/rhythm/layer/gap', () => {
195
- const style = buildGridPlacementStyle({
196
- colStart: 2,
197
- colSpan: 3,
198
- rowStart: 1,
199
- rowSpan: 2,
200
- align: 'center',
201
- justify: 'end',
202
- density: 'relaxed',
203
- layer: 'front',
204
- gap: '2rem',
205
- })
206
-
207
- expect(style).toEqual({
208
- '--_cs': '2',
209
- '--_ce': '3',
210
- '--_rs': '1',
211
- '--_re': '2',
212
- display: 'grid',
213
- width: '100%',
214
- height: '100%',
215
- placeItems: 'center end',
216
- '--rhythm': '0.5rem',
217
- zIndex: '20',
218
- '--grid-gap': '2rem',
219
- })
220
- })
221
-
222
- it('includes responsive vars for responsive-value inputs on a non-full colSpan', () => {
223
- const style = buildGridPlacementStyle({
224
- colStart: { default: 1, md: 2 },
225
- colSpan: { default: 3, lg: 6 },
226
- })
227
-
228
- expect(style['--_md-cs']).toBe('2')
229
- expect(style['--_lg-ce']).toBe('6')
230
- })
231
-
232
- it('applies bleed styles and skips the column/row var block entirely', () => {
233
- const style = buildGridPlacementStyle({
234
- bleed: 'both',
235
- rowStart: 1,
236
- rowSpan: 3,
237
- align: 'start',
238
- })
239
-
240
- expect(style).toEqual({
241
- gridColumn: '1 / -1',
242
- marginInline: 'calc(-1 * var(--grid-padding))',
243
- gridRow: '1 / span 3',
244
- display: 'grid',
245
- width: '100%',
246
- height: '100%',
247
- placeItems: 'start stretch',
248
- })
249
- expect(style).not.toHaveProperty('--_cs')
250
- expect(style).not.toHaveProperty('--_rs')
251
- })
252
-
253
- it('omits --grid-gap when gap is not provided', () => {
254
- const style = buildGridPlacementStyle({ colStart: 1, colSpan: 2 })
255
- expect(style).not.toHaveProperty('--grid-gap')
256
- })
257
- })
258
-
259
- describe('buildGridPlacementClasses', () => {
260
- it('returns the base classes when no container is set', () => {
261
- expect(buildGridPlacementClasses({})).toBe('gi-placed @container @container/item')
262
- })
263
-
264
- it('appends the container class when container is set', () => {
265
- expect(buildGridPlacementClasses({ container: 'wide' })).toBe(
266
- 'gi-placed @container @container/item layout-container-wide'
267
- )
268
- })
269
- })
@@ -1,39 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
-
3
- import { resolveSiteConfig } from './site'
4
-
5
- describe('resolveSiteConfig', () => {
6
- it('defaults title, subtitle, and description to empty values when omitted', () => {
7
- expect(resolveSiteConfig({})).toEqual({
8
- title: '',
9
- titleWords: [''],
10
- subtitle: '',
11
- subtitleWords: [''],
12
- description: '',
13
- })
14
- })
15
-
16
- it('splits the title and subtitle into words', () => {
17
- expect(resolveSiteConfig({ title: 'Nuxt Layers', subtitle: 'Composable Vue apps' })).toEqual({
18
- title: 'Nuxt Layers',
19
- titleWords: ['Nuxt', 'Layers'],
20
- subtitle: 'Composable Vue apps',
21
- subtitleWords: ['Composable', 'Vue', 'apps'],
22
- description: '',
23
- })
24
- })
25
-
26
- it('passes description through unchanged when provided', () => {
27
- expect(resolveSiteConfig({ description: 'A monorepo of Nuxt layers' })).toEqual({
28
- title: '',
29
- titleWords: [''],
30
- subtitle: '',
31
- subtitleWords: [''],
32
- description: 'A monorepo of Nuxt layers',
33
- })
34
- })
35
-
36
- it('handles a single-word title with no spaces', () => {
37
- expect(resolveSiteConfig({ title: 'Solo' }).titleWords).toEqual(['Solo'])
38
- })
39
- })
@@ -1,47 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
-
3
- import type { FeatureValue, RouteResolution, RoutingLayerConfig } from '../types/routing'
4
- import { resolveRoute } from './resolveRoute'
5
-
6
- function createConfig(overrides: Partial<RoutingLayerConfig> = {}): RoutingLayerConfig {
7
- return {
8
- preset: 'marketing',
9
- strictDefaultDeny: false,
10
- layerDefaultDeny: false,
11
- betaRedirect: '/coming-soon',
12
- runtimeFlags: false,
13
- debug: false,
14
- maintenance: { enabled: false, allowRoutes: ['/maintenance'] },
15
- scrollRouting: { enabled: false, mode: 'replace' },
16
- features: {},
17
- ...overrides,
18
- }
19
- }
20
-
21
- describe('resolveRoute', () => {
22
- it('allows routes without a feature by default', () => {
23
- expect(resolveRoute({}, createConfig(), () => 'enabled')).toEqual({ outcome: 'allow' })
24
- })
25
-
26
- it('denies routes when strict default deny is enabled', () => {
27
- expect(resolveRoute({}, createConfig({ strictDefaultDeny: true }), () => 'enabled')).toEqual({
28
- outcome: 'deny',
29
- })
30
- })
31
-
32
- it('denies layer-owned routes without a feature when layer default deny is enabled', () => {
33
- expect(
34
- resolveRoute({ __fromLayer: true }, createConfig({ layerDefaultDeny: true }), () => 'enabled')
35
- ).toEqual({ outcome: 'deny' })
36
- })
37
-
38
- const featureCases: Array<[FeatureValue, RouteResolution]> = [
39
- ['disabled', { outcome: 'deny' }],
40
- ['beta', { outcome: 'redirect', to: '/coming-soon' }],
41
- ['coming-soon', { outcome: 'redirect', to: '/coming-soon' }],
42
- ]
43
-
44
- it.each(featureCases)('handles %s feature variants', (variant, expected) => {
45
- expect(resolveRoute({ feature: 'feature-x' }, createConfig(), () => variant)).toEqual(expected)
46
- })
47
- })