@pyreon/coolgrid 0.24.5 → 0.25.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.
- package/package.json +10 -12
- package/src/Col/component.tsx +0 -61
- package/src/Col/index.ts +0 -3
- package/src/Col/styled.ts +0 -107
- package/src/Container/component.tsx +0 -80
- package/src/Container/index.ts +0 -3
- package/src/Container/styled.ts +0 -37
- package/src/Container/utils.ts +0 -13
- package/src/Row/component.tsx +0 -78
- package/src/Row/index.ts +0 -3
- package/src/Row/styled.ts +0 -70
- package/src/__tests__/Col.test.ts +0 -138
- package/src/__tests__/Container.styled.test.ts +0 -49
- package/src/__tests__/Container.test.ts +0 -152
- package/src/__tests__/Row.test.ts +0 -142
- package/src/__tests__/config.test.ts +0 -120
- package/src/__tests__/contextCascading.test.ts +0 -114
- package/src/__tests__/coolgrid.browser.test.tsx +0 -181
- package/src/__tests__/index.test.ts +0 -35
- package/src/__tests__/native-markers.test.ts +0 -13
- package/src/__tests__/useContext.test.ts +0 -92
- package/src/__tests__/utils.test.ts +0 -144
- package/src/constants.ts +0 -26
- package/src/context/ContainerContext.ts +0 -9
- package/src/context/RowContext.ts +0 -9
- package/src/context/index.ts +0 -4
- package/src/env.d.ts +0 -6
- package/src/index.ts +0 -7
- package/src/theme.ts +0 -40
- package/src/types.ts +0 -72
- package/src/useContext.tsx +0 -52
- package/src/utils.ts +0 -23
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
/** @jsxImportSource @pyreon/core */
|
|
2
|
-
import { h } from '@pyreon/core'
|
|
3
|
-
import { sheet } from '@pyreon/styler'
|
|
4
|
-
import { mountInBrowser } from '@pyreon/test-utils/browser'
|
|
5
|
-
import { PyreonUI } from '@pyreon/ui-core'
|
|
6
|
-
import { afterEach, describe, expect, it } from 'vitest'
|
|
7
|
-
import { Col, Container, Row } from '../index'
|
|
8
|
-
import gridTheme from '../theme'
|
|
9
|
-
|
|
10
|
-
// Real-Chromium smoke for @pyreon/coolgrid.
|
|
11
|
-
//
|
|
12
|
-
// Vitest browser mode runs at a small viewport (≈414px), so we assert
|
|
13
|
-
// RATIOS against the actual rendered Row width rather than pegging
|
|
14
|
-
// absolute pixels to a Container max-width that gets capped by the
|
|
15
|
-
// viewport.
|
|
16
|
-
//
|
|
17
|
-
// Wraps in `PyreonUI` (the unified provider that replaces the
|
|
18
|
-
// deprecated `<Provider>` from @pyreon/unistyle), matching production
|
|
19
|
-
// usage.
|
|
20
|
-
|
|
21
|
-
describe('@pyreon/coolgrid in real browser', () => {
|
|
22
|
-
afterEach(() => {
|
|
23
|
-
sheet.clearCache()
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('Container mounts and Chromium computes flex layout', () => {
|
|
27
|
-
const { container, unmount } = mountInBrowser(
|
|
28
|
-
h(PyreonUI, { theme: gridTheme }, h(Container, { id: 'c' }, 'hello')),
|
|
29
|
-
)
|
|
30
|
-
const el = container.querySelector<HTMLElement>('#c')!
|
|
31
|
-
const cs = getComputedStyle(el)
|
|
32
|
-
expect(cs.display).toBe('flex')
|
|
33
|
-
expect(cs.flexDirection).toBe('column')
|
|
34
|
-
expect(el.textContent).toContain('hello')
|
|
35
|
-
unmount()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('Col size=6 in a 12-col grid yields 50% width of its Row', () => {
|
|
39
|
-
const { container, unmount } = mountInBrowser(
|
|
40
|
-
h(
|
|
41
|
-
PyreonUI,
|
|
42
|
-
{ theme: gridTheme },
|
|
43
|
-
h(Container, null, h(Row, { id: 'row' }, h(Col, { id: 'half', size: 6 }, 'half'))),
|
|
44
|
-
),
|
|
45
|
-
)
|
|
46
|
-
const row = container.querySelector<HTMLElement>('#row')!
|
|
47
|
-
const half = container.querySelector<HTMLElement>('#half')!
|
|
48
|
-
const ratio = half.getBoundingClientRect().width / row.getBoundingClientRect().width
|
|
49
|
-
expect(ratio).toBeGreaterThan(0.495)
|
|
50
|
-
expect(ratio).toBeLessThan(0.505)
|
|
51
|
-
unmount()
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('Col size=2 in a 6-col grid yields ~33% — grid columns aren\'t hardcoded to 12', () => {
|
|
55
|
-
// Explicitly overrides `grid.columns` to 6 to prove the math is
|
|
56
|
-
// `size / columns`, not `size / 12`.
|
|
57
|
-
const theme = { ...gridTheme, grid: { ...gridTheme.grid, columns: 6 } }
|
|
58
|
-
const { container, unmount } = mountInBrowser(
|
|
59
|
-
h(
|
|
60
|
-
PyreonUI,
|
|
61
|
-
{ theme },
|
|
62
|
-
h(Container, null, h(Row, { id: 'row' }, h(Col, { id: 'third', size: 2 }, 't'))),
|
|
63
|
-
),
|
|
64
|
-
)
|
|
65
|
-
const row = container.querySelector<HTMLElement>('#row')!
|
|
66
|
-
const third = container.querySelector<HTMLElement>('#third')!
|
|
67
|
-
const ratio = third.getBoundingClientRect().width / row.getBoundingClientRect().width
|
|
68
|
-
expect(ratio).toBeGreaterThan(0.33)
|
|
69
|
-
expect(ratio).toBeLessThan(0.34)
|
|
70
|
-
// flex-basis emitted from size/columns
|
|
71
|
-
expect(getComputedStyle(third).flexBasis).toBe('33.3333%')
|
|
72
|
-
unmount()
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('two Cols of size 6 each lay out side-by-side (sum ≈ 100% of Row)', () => {
|
|
76
|
-
const { container, unmount } = mountInBrowser(
|
|
77
|
-
h(
|
|
78
|
-
PyreonUI,
|
|
79
|
-
{ theme: gridTheme },
|
|
80
|
-
h(
|
|
81
|
-
Container,
|
|
82
|
-
null,
|
|
83
|
-
h(
|
|
84
|
-
Row,
|
|
85
|
-
{ id: 'row' },
|
|
86
|
-
h(Col, { id: 'a', size: 6 }, 'A'),
|
|
87
|
-
h(Col, { id: 'b', size: 6 }, 'B'),
|
|
88
|
-
),
|
|
89
|
-
),
|
|
90
|
-
),
|
|
91
|
-
)
|
|
92
|
-
const row = container.querySelector<HTMLElement>('#row')!
|
|
93
|
-
const a = container.querySelector<HTMLElement>('#a')!
|
|
94
|
-
const b = container.querySelector<HTMLElement>('#b')!
|
|
95
|
-
const ar = a.getBoundingClientRect()
|
|
96
|
-
const br = b.getBoundingClientRect()
|
|
97
|
-
expect(br.left).toBeGreaterThanOrEqual(ar.right - 1)
|
|
98
|
-
const sum = ar.width + br.width
|
|
99
|
-
const rowW = row.getBoundingClientRect().width
|
|
100
|
-
expect(sum / rowW).toBeGreaterThan(0.99)
|
|
101
|
-
expect(sum / rowW).toBeLessThan(1.01)
|
|
102
|
-
unmount()
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('flex-basis on Col is the literal percentage authored from size/columns', () => {
|
|
106
|
-
const { container, unmount } = mountInBrowser(
|
|
107
|
-
h(
|
|
108
|
-
PyreonUI,
|
|
109
|
-
{ theme: gridTheme },
|
|
110
|
-
h(Container, null, h(Row, null, h(Col, { id: 'c', size: 3 }, 'q'))),
|
|
111
|
-
),
|
|
112
|
-
)
|
|
113
|
-
const el = container.querySelector<HTMLElement>('#c')!
|
|
114
|
-
expect(getComputedStyle(el).flexBasis).toBe('25%')
|
|
115
|
-
unmount()
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('`gap` subtracts from Col flex-basis via calc() — different emit path', () => {
|
|
119
|
-
// With gap set on Row, Col's widthStyles takes the
|
|
120
|
-
// `calc(${width}% - ${g}px)` branch (see Col/styled.ts:37).
|
|
121
|
-
// Chromium resolves the calc() and produces a width strictly less
|
|
122
|
-
// than the gap-less 50% value, which is the load-bearing behavior.
|
|
123
|
-
const { container, unmount } = mountInBrowser(
|
|
124
|
-
h(
|
|
125
|
-
PyreonUI,
|
|
126
|
-
{ theme: gridTheme },
|
|
127
|
-
h(
|
|
128
|
-
Container,
|
|
129
|
-
null,
|
|
130
|
-
h(
|
|
131
|
-
Row,
|
|
132
|
-
{ id: 'row', gap: 24 },
|
|
133
|
-
h(Col, { id: 'g', size: 6 }, 'G'),
|
|
134
|
-
),
|
|
135
|
-
),
|
|
136
|
-
),
|
|
137
|
-
)
|
|
138
|
-
const row = container.querySelector<HTMLElement>('#row')!
|
|
139
|
-
const col = container.querySelector<HTMLElement>('#g')!
|
|
140
|
-
const cs = getComputedStyle(col)
|
|
141
|
-
// Chromium preserves the `calc(... - 24px)` literal in computed style.
|
|
142
|
-
expect(cs.flexBasis).toMatch(/calc\([^)]+- 24px\)/)
|
|
143
|
-
const colW = col.getBoundingClientRect().width
|
|
144
|
-
const rowW = row.getBoundingClientRect().width
|
|
145
|
-
// Gap subtraction: col width should be less than exactly 50%
|
|
146
|
-
expect(colW).toBeLessThan(rowW * 0.5)
|
|
147
|
-
// …but not dramatically so — confirms it's a subtraction, not a failure
|
|
148
|
-
expect(colW).toBeGreaterThan(rowW * 0.4)
|
|
149
|
-
unmount()
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
it('responsive `size` array applies a per-breakpoint width at the current viewport', () => {
|
|
153
|
-
// The responsive-per-breakpoint feature: `size={[12, 6, 4]}`
|
|
154
|
-
// means "size 12 on xs, 6 on sm, 4 on md+". At the vitest browser
|
|
155
|
-
// viewport (~414px), xs is the only applicable breakpoint, so
|
|
156
|
-
// size=12 should apply (100% width of Row).
|
|
157
|
-
const { container, unmount } = mountInBrowser(
|
|
158
|
-
h(
|
|
159
|
-
PyreonUI,
|
|
160
|
-
{ theme: gridTheme },
|
|
161
|
-
h(
|
|
162
|
-
Container,
|
|
163
|
-
null,
|
|
164
|
-
h(
|
|
165
|
-
Row,
|
|
166
|
-
{ id: 'row' },
|
|
167
|
-
h(Col, { id: 'r', size: [12, 6, 4] } as any, 'x'),
|
|
168
|
-
),
|
|
169
|
-
),
|
|
170
|
-
),
|
|
171
|
-
)
|
|
172
|
-
const row = container.querySelector<HTMLElement>('#row')!
|
|
173
|
-
const col = container.querySelector<HTMLElement>('#r')!
|
|
174
|
-
expect(window.innerWidth).toBeLessThan(576) // below the `sm` breakpoint
|
|
175
|
-
const ratio = col.getBoundingClientRect().width / row.getBoundingClientRect().width
|
|
176
|
-
// xs size=12 on 12-column grid → 100% of Row
|
|
177
|
-
expect(ratio).toBeGreaterThan(0.99)
|
|
178
|
-
expect(ratio).toBeLessThan(1.01)
|
|
179
|
-
unmount()
|
|
180
|
-
})
|
|
181
|
-
})
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
|
|
3
|
-
describe('index exports', () => {
|
|
4
|
-
it('exports Container', async () => {
|
|
5
|
-
const mod = await import('../index')
|
|
6
|
-
expect(mod.Container).toBeDefined()
|
|
7
|
-
expect(typeof mod.Container).toBe('function')
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
it('exports Row', async () => {
|
|
11
|
-
const mod = await import('../index')
|
|
12
|
-
expect(mod.Row).toBeDefined()
|
|
13
|
-
expect(typeof mod.Row).toBe('function')
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('exports Col', async () => {
|
|
17
|
-
const mod = await import('../index')
|
|
18
|
-
expect(mod.Col).toBeDefined()
|
|
19
|
-
expect(typeof mod.Col).toBe('function')
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('exports Provider', async () => {
|
|
23
|
-
const mod = await import('../index')
|
|
24
|
-
expect(mod.Provider).toBeDefined()
|
|
25
|
-
expect(typeof mod.Provider).toBe('function')
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it('exports theme', async () => {
|
|
29
|
-
const mod = await import('../index')
|
|
30
|
-
expect(mod.theme).toBeDefined()
|
|
31
|
-
expect(mod.theme).toHaveProperty('rootSize')
|
|
32
|
-
expect(mod.theme).toHaveProperty('breakpoints')
|
|
33
|
-
expect(mod.theme).toHaveProperty('grid')
|
|
34
|
-
})
|
|
35
|
-
})
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { isNativeCompat } from '@pyreon/core'
|
|
2
|
-
import { describe, expect, it } from 'vitest'
|
|
3
|
-
import Container from '../Container/component'
|
|
4
|
-
import Row from '../Row/component'
|
|
5
|
-
|
|
6
|
-
describe('native-compat markers — @pyreon/coolgrid', () => {
|
|
7
|
-
it('Container is marked native', () => {
|
|
8
|
-
expect(isNativeCompat(Container)).toBe(true)
|
|
9
|
-
})
|
|
10
|
-
it('Row is marked native', () => {
|
|
11
|
-
expect(isNativeCompat(Row)).toBe(true)
|
|
12
|
-
})
|
|
13
|
-
})
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
-
|
|
3
|
-
const mockUseContext = vi.fn()
|
|
4
|
-
|
|
5
|
-
vi.mock('@pyreon/core', async (importOriginal) => {
|
|
6
|
-
const original = await importOriginal<typeof import('@pyreon/core')>()
|
|
7
|
-
return {
|
|
8
|
-
...original,
|
|
9
|
-
useContext: mockUseContext,
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
describe('useGridContext', () => {
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
vi.clearAllMocks()
|
|
16
|
-
// Default: coreContext is ReactiveContext — mock returns () => value
|
|
17
|
-
mockUseContext.mockReturnValue(() => ({ theme: {} }))
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('returns props merged with theme grid context', async () => {
|
|
21
|
-
mockUseContext.mockReturnValue(() => ({
|
|
22
|
-
theme: {
|
|
23
|
-
grid: {
|
|
24
|
-
columns: 12,
|
|
25
|
-
container: { xs: '100%', md: 720 },
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
}))
|
|
29
|
-
const useGridContext = (await import('../useContext')).default
|
|
30
|
-
const result = useGridContext({ gap: 16 })
|
|
31
|
-
expect(result.gap).toBe(16)
|
|
32
|
-
expect(result.columns).toBe(12)
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it('props override theme values', async () => {
|
|
36
|
-
mockUseContext.mockReturnValue(() => ({
|
|
37
|
-
theme: {
|
|
38
|
-
grid: { columns: 12 },
|
|
39
|
-
},
|
|
40
|
-
}))
|
|
41
|
-
const useGridContext = (await import('../useContext')).default
|
|
42
|
-
const result = useGridContext({ columns: 24 })
|
|
43
|
-
expect(result.columns).toBe(24)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('falls back to coolgrid namespace in theme', async () => {
|
|
47
|
-
mockUseContext.mockReturnValue(() => ({
|
|
48
|
-
theme: {
|
|
49
|
-
coolgrid: {
|
|
50
|
-
columns: 16,
|
|
51
|
-
container: { xs: '100%' },
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
}))
|
|
55
|
-
const useGridContext = (await import('../useContext')).default
|
|
56
|
-
const result = useGridContext({})
|
|
57
|
-
expect(result.columns).toBe(16)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('returns empty context when no theme or props', async () => {
|
|
61
|
-
mockUseContext.mockReturnValue(() => ({ theme: {} }))
|
|
62
|
-
const useGridContext = (await import('../useContext')).default
|
|
63
|
-
const result = useGridContext({})
|
|
64
|
-
expect(result).toBeDefined()
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
describe('getGridContext', () => {
|
|
69
|
-
it('resolves columns from props first', async () => {
|
|
70
|
-
const { getGridContext } = await import('../useContext')
|
|
71
|
-
const result = getGridContext({ columns: 24 }, { grid: { columns: 12 } })
|
|
72
|
-
expect(result.columns).toBe(24)
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('resolves columns from theme.grid', async () => {
|
|
76
|
-
const { getGridContext } = await import('../useContext')
|
|
77
|
-
const result = getGridContext({}, { grid: { columns: 12 } })
|
|
78
|
-
expect(result.columns).toBe(12)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it('resolves columns from theme.coolgrid', async () => {
|
|
82
|
-
const { getGridContext } = await import('../useContext')
|
|
83
|
-
const result = getGridContext({}, { coolgrid: { columns: 16 } })
|
|
84
|
-
expect(result.columns).toBe(16)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('resolves containerWidth from theme.grid.container', async () => {
|
|
88
|
-
const { getGridContext } = await import('../useContext')
|
|
89
|
-
const result = getGridContext({}, { grid: { container: { xs: '100%' } } })
|
|
90
|
-
expect(result.containerWidth).toEqual({ xs: '100%' })
|
|
91
|
-
})
|
|
92
|
-
})
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { getContainerWidth } from '../Container/utils'
|
|
3
|
-
import { hasValue, hasWidth, isNumber, isVisible, omitCtxKeys } from '../utils'
|
|
4
|
-
|
|
5
|
-
describe('isNumber', () => {
|
|
6
|
-
it('returns true for finite numbers', () => {
|
|
7
|
-
expect(isNumber(0)).toBe(true)
|
|
8
|
-
expect(isNumber(1)).toBe(true)
|
|
9
|
-
expect(isNumber(-1)).toBe(true)
|
|
10
|
-
expect(isNumber(3.14)).toBe(true)
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('returns false for non-finite values', () => {
|
|
14
|
-
expect(isNumber(Infinity)).toBe(false)
|
|
15
|
-
expect(isNumber(-Infinity)).toBe(false)
|
|
16
|
-
expect(isNumber(NaN)).toBe(false)
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('returns false for non-number types', () => {
|
|
20
|
-
expect(isNumber(null)).toBe(false)
|
|
21
|
-
expect(isNumber(undefined)).toBe(false)
|
|
22
|
-
expect(isNumber('5')).toBe(false)
|
|
23
|
-
expect(isNumber(true)).toBe(false)
|
|
24
|
-
})
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
describe('hasValue', () => {
|
|
28
|
-
it('returns true for positive finite numbers', () => {
|
|
29
|
-
expect(hasValue(1)).toBe(true)
|
|
30
|
-
expect(hasValue(12)).toBe(true)
|
|
31
|
-
expect(hasValue(0.5)).toBe(true)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('returns false for zero', () => {
|
|
35
|
-
expect(hasValue(0)).toBe(false)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('returns false for negative numbers', () => {
|
|
39
|
-
expect(hasValue(-1)).toBe(false)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('returns false for non-numbers', () => {
|
|
43
|
-
expect(hasValue(null)).toBe(false)
|
|
44
|
-
expect(hasValue(undefined)).toBe(false)
|
|
45
|
-
expect(hasValue('5')).toBe(false)
|
|
46
|
-
})
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
describe('isVisible', () => {
|
|
50
|
-
it('returns true for positive numbers', () => {
|
|
51
|
-
expect(isVisible(1)).toBe(true)
|
|
52
|
-
expect(isVisible(12)).toBe(true)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('returns true for negative numbers', () => {
|
|
56
|
-
expect(isVisible(-1)).toBe(true)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it('returns false for zero', () => {
|
|
60
|
-
expect(isVisible(0)).toBe(false)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('returns true for undefined (default visibility)', () => {
|
|
64
|
-
expect(isVisible(undefined)).toBe(true)
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
it('returns false for non-number truthy values', () => {
|
|
68
|
-
expect(isVisible('5')).toBe(false)
|
|
69
|
-
expect(isVisible(null)).toBe(false)
|
|
70
|
-
})
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
describe('hasWidth', () => {
|
|
74
|
-
it('returns true when both size and columns are positive numbers', () => {
|
|
75
|
-
expect(hasWidth(6, 12)).toBe(true)
|
|
76
|
-
expect(hasWidth(1, 1)).toBe(true)
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('returns false when size is 0', () => {
|
|
80
|
-
expect(hasWidth(0, 12)).toBe(false)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('returns false when columns is 0', () => {
|
|
84
|
-
expect(hasWidth(6, 0)).toBe(false)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('returns false when either is not a number', () => {
|
|
88
|
-
expect(hasWidth(null, 12)).toBe(false)
|
|
89
|
-
expect(hasWidth(6, null)).toBe(false)
|
|
90
|
-
expect(hasWidth(undefined, undefined)).toBe(false)
|
|
91
|
-
})
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
describe('omitCtxKeys', () => {
|
|
95
|
-
it('strips context keys from props', () => {
|
|
96
|
-
const props = {
|
|
97
|
-
columns: 12,
|
|
98
|
-
size: 6,
|
|
99
|
-
gap: 16,
|
|
100
|
-
padding: 4,
|
|
101
|
-
gutter: 8,
|
|
102
|
-
colCss: 'color: red;',
|
|
103
|
-
colComponent: () => null,
|
|
104
|
-
rowCss: 'color: blue;',
|
|
105
|
-
rowComponent: () => null,
|
|
106
|
-
contentAlignX: 'center',
|
|
107
|
-
className: 'my-class',
|
|
108
|
-
id: 'my-id',
|
|
109
|
-
}
|
|
110
|
-
const result = omitCtxKeys(props)
|
|
111
|
-
expect(result).toEqual({
|
|
112
|
-
className: 'my-class',
|
|
113
|
-
id: 'my-id',
|
|
114
|
-
})
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it('returns all props when no context keys present', () => {
|
|
118
|
-
const props = { className: 'test', style: 'color: red;' }
|
|
119
|
-
const result = omitCtxKeys(props)
|
|
120
|
-
expect(result).toEqual(props)
|
|
121
|
-
})
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
describe('getContainerWidth', () => {
|
|
125
|
-
it('returns width from props', () => {
|
|
126
|
-
const result = getContainerWidth({ width: { xs: 600 } }, {})
|
|
127
|
-
expect(result).toEqual({ xs: 600 })
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('falls back to theme.grid.container', () => {
|
|
131
|
-
const result = getContainerWidth({}, { grid: { container: { xs: '100%' } } })
|
|
132
|
-
expect(result).toEqual({ xs: '100%' })
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
it('falls back to theme.coolgrid.container', () => {
|
|
136
|
-
const result = getContainerWidth({}, { coolgrid: { container: { md: 720 } } })
|
|
137
|
-
expect(result).toEqual({ md: 720 })
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('returns undefined when nothing matches', () => {
|
|
141
|
-
const result = getContainerWidth({}, {})
|
|
142
|
-
expect(result).toBeFalsy()
|
|
143
|
-
})
|
|
144
|
-
})
|
package/src/constants.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export const PKG_NAME = '@pyreon/coolgrid'
|
|
2
|
-
|
|
3
|
-
// Dev-mode gate. `import.meta.env.DEV` is literal-replaced by Vite at build
|
|
4
|
-
// time and tree-shakes to zero bytes in prod. The previous
|
|
5
|
-
// `process.env.NODE_ENV !== 'production'` form was dead code in real Vite
|
|
6
|
-
// browser bundles (Vite does not polyfill `process`).
|
|
7
|
-
export const __DEV__ = process.env.NODE_ENV !== 'production'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Grid configuration keys that are passed through context
|
|
11
|
-
* from Container to Row and from Row to Col components.
|
|
12
|
-
*/
|
|
13
|
-
export const CONTEXT_KEYS = [
|
|
14
|
-
// 'breakpoints',
|
|
15
|
-
// 'rootSize',
|
|
16
|
-
'columns',
|
|
17
|
-
'size',
|
|
18
|
-
'gap',
|
|
19
|
-
'padding',
|
|
20
|
-
'gutter',
|
|
21
|
-
'colCss',
|
|
22
|
-
'colComponent',
|
|
23
|
-
'rowCss',
|
|
24
|
-
'rowComponent',
|
|
25
|
-
'contentAlignX',
|
|
26
|
-
]
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { createContext } from '@pyreon/core'
|
|
2
|
-
import type { Context as ContextType } from '../types'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Context for container-level grid configuration.
|
|
6
|
-
* Provided by the Container component and consumed by Row children
|
|
7
|
-
* to inherit columns, gap, gutter, and other grid settings.
|
|
8
|
-
*/
|
|
9
|
-
export default createContext<ContextType>({})
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { createContext } from '@pyreon/core'
|
|
2
|
-
import type { Context as ContextType } from '../types'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Context for row-level grid configuration.
|
|
6
|
-
* Provided by the Row component and consumed by Col children
|
|
7
|
-
* to inherit columns, gap, gutter, and sizing for width calculations.
|
|
8
|
-
*/
|
|
9
|
-
export default createContext<ContextType>({})
|
package/src/context/index.ts
DELETED
package/src/env.d.ts
DELETED
package/src/index.ts
DELETED
package/src/theme.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default Bootstrap-like grid configuration. Provides 5 breakpoints (xs-xl),
|
|
3
|
-
* a 12-column grid, and responsive container max-widths matching Bootstrap 4.
|
|
4
|
-
*/
|
|
5
|
-
export default {
|
|
6
|
-
rootSize: 16,
|
|
7
|
-
breakpoints: {
|
|
8
|
-
xs: 0,
|
|
9
|
-
sm: 576,
|
|
10
|
-
md: 768,
|
|
11
|
-
lg: 992,
|
|
12
|
-
xl: 1200,
|
|
13
|
-
},
|
|
14
|
-
grid: {
|
|
15
|
-
columns: 12,
|
|
16
|
-
container: {
|
|
17
|
-
xs: '100%',
|
|
18
|
-
sm: 540,
|
|
19
|
-
md: 720,
|
|
20
|
-
lg: 960,
|
|
21
|
-
xl: 1140,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
} as const
|
|
25
|
-
|
|
26
|
-
export const defaultBreakpoints: Record<string, number> = {
|
|
27
|
-
xs: 0,
|
|
28
|
-
sm: 576,
|
|
29
|
-
md: 768,
|
|
30
|
-
lg: 992,
|
|
31
|
-
xl: 1200,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export const defaultContainerWidths: Record<string, string | number> = {
|
|
35
|
-
xs: '100%',
|
|
36
|
-
sm: 540,
|
|
37
|
-
md: 720,
|
|
38
|
-
lg: 960,
|
|
39
|
-
xl: 1140,
|
|
40
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type definitions for the coolgrid layout system.
|
|
3
|
-
* Supports responsive values as single values, arrays (mobile-first),
|
|
4
|
-
* or breakpoint-keyed objects. Defines config props for Container/Row/Col
|
|
5
|
-
* and the resolved styled-component prop types.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { ComponentFn, VNodeChild } from '@pyreon/core'
|
|
9
|
-
import type { BreakpointKeys, config } from '@pyreon/ui-core'
|
|
10
|
-
import type { AlignContentAlignXKeys, extendCss } from '@pyreon/unistyle'
|
|
11
|
-
|
|
12
|
-
type CreateValueType<T> = T | T[] | Partial<Record<BreakpointKeys, T>>
|
|
13
|
-
|
|
14
|
-
export type Obj = Record<string, unknown>
|
|
15
|
-
export type Value = string | number
|
|
16
|
-
export type Css = Parameters<typeof extendCss>[0]
|
|
17
|
-
export type ExtraStyles = CreateValueType<Css>
|
|
18
|
-
|
|
19
|
-
export type CssOutput = ReturnType<typeof config.css> | string
|
|
20
|
-
|
|
21
|
-
export type ValueType = CreateValueType<number>
|
|
22
|
-
export type ContainerWidth = CreateValueType<Value>
|
|
23
|
-
|
|
24
|
-
export type ContentAlignX =
|
|
25
|
-
| 'center'
|
|
26
|
-
| 'left'
|
|
27
|
-
| 'right'
|
|
28
|
-
| 'spaceAround'
|
|
29
|
-
| 'spaceBetween'
|
|
30
|
-
| 'spaceEvenly'
|
|
31
|
-
|
|
32
|
-
export type ConfigurationProps = Partial<{
|
|
33
|
-
size: ValueType
|
|
34
|
-
padding: ValueType
|
|
35
|
-
gap: ValueType
|
|
36
|
-
gutter: ValueType
|
|
37
|
-
columns: ValueType
|
|
38
|
-
colCss: ExtraStyles
|
|
39
|
-
rowCss: ExtraStyles
|
|
40
|
-
colComponent: ComponentFn<any>
|
|
41
|
-
rowComponent: ComponentFn<any>
|
|
42
|
-
contentAlignX: ContentAlignX
|
|
43
|
-
containerWidth: ContainerWidth
|
|
44
|
-
width: ContainerWidth | ((widths: Record<string, any>) => ContainerWidth)
|
|
45
|
-
}>
|
|
46
|
-
|
|
47
|
-
export type ComponentProps = ConfigurationProps &
|
|
48
|
-
Partial<{
|
|
49
|
-
component: ComponentFn<any>
|
|
50
|
-
css: ExtraStyles
|
|
51
|
-
}>
|
|
52
|
-
|
|
53
|
-
export type StyledTypes = Partial<{
|
|
54
|
-
size: number | undefined
|
|
55
|
-
padding: number | undefined
|
|
56
|
-
gap: number | undefined
|
|
57
|
-
gutter: number | undefined
|
|
58
|
-
columns: number | undefined
|
|
59
|
-
extraStyles: Css
|
|
60
|
-
contentAlignX: AlignContentAlignXKeys
|
|
61
|
-
width: Value
|
|
62
|
-
}>
|
|
63
|
-
|
|
64
|
-
export type ElementType<O extends string[]> = ComponentFn<
|
|
65
|
-
Omit<ComponentProps, O[number]> & Record<string, unknown> & { children?: VNodeChild }
|
|
66
|
-
> & {
|
|
67
|
-
displayName: string
|
|
68
|
-
pkgName: string
|
|
69
|
-
PYREON__COMPONENT: string
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export type Context = { [K in keyof ConfigurationProps]?: ConfigurationProps[K] | undefined }
|