@pyreon/coolgrid 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/lib/index.d.ts +75 -0
- package/lib/index.js +387 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present Vit Bokisch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# @pyreon/coolgrid
|
|
2
|
+
|
|
3
|
+
Responsive grid system for Pyreon.
|
|
4
|
+
|
|
5
|
+
Bootstrap-inspired Container / Row / Col grid with context-cascading configuration. Define breakpoints, column count, gaps, and gutters at any level — children inherit automatically. Every value is responsive.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Familiar mental model** — Container, Row, Col just like Bootstrap
|
|
10
|
+
- **Context cascading** — set columns, gaps, and gutters at Container level, inherited by all Rows and Cols
|
|
11
|
+
- **Responsive values** — single value, mobile-first array, or breakpoint object on every prop
|
|
12
|
+
- **Custom breakpoints** — name and size them however you want
|
|
13
|
+
- **Custom column counts** — 12, 24, 5 — any number
|
|
14
|
+
- **Custom components** — swap Container, Row, or Col underlying elements
|
|
15
|
+
- **Default Bootstrap theme** — included and ready to use
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bun add @pyreon/coolgrid
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { Container, Row, Col, Provider, theme } from '@pyreon/coolgrid'
|
|
27
|
+
|
|
28
|
+
Provider({
|
|
29
|
+
theme,
|
|
30
|
+
children: Container({
|
|
31
|
+
children: Row({
|
|
32
|
+
children: [
|
|
33
|
+
Col({ size: 8, children: 'Main content' }),
|
|
34
|
+
Col({ size: 4, children: 'Sidebar' }),
|
|
35
|
+
],
|
|
36
|
+
}),
|
|
37
|
+
}),
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Components
|
|
42
|
+
|
|
43
|
+
### Container
|
|
44
|
+
|
|
45
|
+
Outermost grid boundary. Sets max-width and provides configuration context to descendants.
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
Container({
|
|
49
|
+
columns: 12,
|
|
50
|
+
gap: 16,
|
|
51
|
+
gutter: 24,
|
|
52
|
+
padding: 16,
|
|
53
|
+
children: Row({ children: '...' }),
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| Prop | Type | Description |
|
|
58
|
+
| ---- | ---- | ----------- |
|
|
59
|
+
| columns | `number` | Number of grid columns (default: 12) |
|
|
60
|
+
| gap | `number` | Space between columns |
|
|
61
|
+
| gutter | `number` | Outer gutter (negative margin offset on Row) |
|
|
62
|
+
| padding | `number` | Column inner padding |
|
|
63
|
+
| width | `value \| function` | Override container max-width |
|
|
64
|
+
| component | `ComponentFn` | Custom root element |
|
|
65
|
+
| css | `ExtendCss` | Extend container styling |
|
|
66
|
+
| contentAlignX | `AlignX` | Horizontal alignment of columns |
|
|
67
|
+
|
|
68
|
+
All configuration props cascade to Row and Col through context.
|
|
69
|
+
|
|
70
|
+
### Row
|
|
71
|
+
|
|
72
|
+
Flex wrapper with column management. Inherits Container config and can override it.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
Row({
|
|
76
|
+
size: { xs: 12, md: 6 },
|
|
77
|
+
contentAlignX: 'center',
|
|
78
|
+
children: [
|
|
79
|
+
Col({ children: 'Column 1' }),
|
|
80
|
+
Col({ children: 'Column 2' }),
|
|
81
|
+
],
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Setting `size` on Row applies it to all Cols inside:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
// All columns are 6 of 12
|
|
89
|
+
Row({
|
|
90
|
+
size: 6,
|
|
91
|
+
children: [
|
|
92
|
+
Col({ children: 'Half' }),
|
|
93
|
+
Col({ children: 'Half' }),
|
|
94
|
+
],
|
|
95
|
+
})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
| Prop | Type | Description |
|
|
99
|
+
| ---- | ---- | ----------- |
|
|
100
|
+
| size | `number` | Default column size for all Cols inside |
|
|
101
|
+
| component | `ComponentFn` | Custom row element |
|
|
102
|
+
| css | `ExtendCss` | Extend row styling |
|
|
103
|
+
| contentAlignX | `AlignX` | Override horizontal alignment |
|
|
104
|
+
|
|
105
|
+
### Col
|
|
106
|
+
|
|
107
|
+
Individual column. Width is calculated as a fraction of total columns.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
// Fixed size
|
|
111
|
+
Col({ size: 4, children: '1/3 width' })
|
|
112
|
+
|
|
113
|
+
// Responsive size
|
|
114
|
+
Col({ size: { xs: 12, sm: 6, lg: 4 }, children: 'Responsive' })
|
|
115
|
+
|
|
116
|
+
// Hidden on mobile
|
|
117
|
+
Col({ size: { xs: 0, md: 6 }, children: 'Hidden on xs' })
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
| Prop | Type | Description |
|
|
121
|
+
| ---- | ---- | ----------- |
|
|
122
|
+
| size | `number` | Column span (e.g. 4 of 12) |
|
|
123
|
+
| padding | `number` | Override column inner padding |
|
|
124
|
+
| component | `ComponentFn` | Custom column element |
|
|
125
|
+
| css | `ExtendCss` | Extend column styling |
|
|
126
|
+
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
### Custom Breakpoints
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
Provider({
|
|
133
|
+
theme: {
|
|
134
|
+
rootSize: 16,
|
|
135
|
+
breakpoints: {
|
|
136
|
+
phone: 0,
|
|
137
|
+
tablet: 600,
|
|
138
|
+
desktop: 1024,
|
|
139
|
+
wide: 1440,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
children: [/* ... */],
|
|
143
|
+
})
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Custom Column Count
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
Container({
|
|
150
|
+
columns: 24,
|
|
151
|
+
children: Row({
|
|
152
|
+
children: [
|
|
153
|
+
Col({ size: 16, children: 'Two thirds' }),
|
|
154
|
+
Col({ size: 8, children: 'One third' }),
|
|
155
|
+
],
|
|
156
|
+
}),
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Context Cascading
|
|
161
|
+
|
|
162
|
+
Configuration flows from Container through Row to Col via Pyreon's context system (`pushContext`/`popContext`):
|
|
163
|
+
|
|
164
|
+
```text
|
|
165
|
+
Container (columns: 12, gap: 16)
|
|
166
|
+
└─ Row (inherits columns, gap)
|
|
167
|
+
└─ Col (inherits columns, gap, calculates width)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Props set on a child override the inherited value for that level and below.
|
|
171
|
+
|
|
172
|
+
## Default Theme
|
|
173
|
+
|
|
174
|
+
The included `theme` export provides Bootstrap 4 defaults:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
{
|
|
178
|
+
rootSize: 16,
|
|
179
|
+
breakpoints: { xs: 0, sm: 576, md: 768, lg: 992, xl: 1200 },
|
|
180
|
+
grid: {
|
|
181
|
+
columns: 12,
|
|
182
|
+
container: { xs: '100%', sm: 540, md: 720, lg: 960, xl: 1140 },
|
|
183
|
+
},
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Responsive Values
|
|
188
|
+
|
|
189
|
+
All numeric props support three formats:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
// Single value
|
|
193
|
+
Col({ size: 6 })
|
|
194
|
+
|
|
195
|
+
// Array (mobile-first, by breakpoint position)
|
|
196
|
+
Col({ size: [12, 6, 4] })
|
|
197
|
+
|
|
198
|
+
// Object (explicit breakpoints)
|
|
199
|
+
Col({ size: { xs: 12, md: 6, lg: 4 } })
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Peer Dependencies
|
|
203
|
+
|
|
204
|
+
| Package | Version |
|
|
205
|
+
| ------- | ------- |
|
|
206
|
+
| @pyreon/core | >= 0.0.1 |
|
|
207
|
+
| @pyreon/reactivity | >= 0.0.1 |
|
|
208
|
+
| @pyreon/ui-core | >= 0.0.1 |
|
|
209
|
+
| @pyreon/unistyle | >= 0.0.1 |
|
|
210
|
+
| @pyreon/styler | >= 0.0.1 |
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Provider, extendCss } from "@pyreon/unistyle";
|
|
2
|
+
import { ComponentFn, VNodeChild } from "@pyreon/core";
|
|
3
|
+
import { BreakpointKeys, config } from "@pyreon/ui-core";
|
|
4
|
+
|
|
5
|
+
//#region src/types.d.ts
|
|
6
|
+
type CreateValueType<T> = T | T[] | Partial<Record<BreakpointKeys, T>>;
|
|
7
|
+
type Value = string | number;
|
|
8
|
+
type Css = Parameters<typeof extendCss>[0];
|
|
9
|
+
type ExtraStyles = CreateValueType<Css>;
|
|
10
|
+
type ValueType = CreateValueType<number>;
|
|
11
|
+
type ContainerWidth = CreateValueType<Value>;
|
|
12
|
+
type ContentAlignX = "center" | "left" | "right" | "spaceAround" | "spaceBetween" | "spaceEvenly";
|
|
13
|
+
type ConfigurationProps = Partial<{
|
|
14
|
+
size: ValueType;
|
|
15
|
+
padding: ValueType;
|
|
16
|
+
gap: ValueType;
|
|
17
|
+
gutter: ValueType;
|
|
18
|
+
columns: ValueType;
|
|
19
|
+
colCss: ExtraStyles;
|
|
20
|
+
rowCss: ExtraStyles;
|
|
21
|
+
colComponent: ComponentFn<any>;
|
|
22
|
+
rowComponent: ComponentFn<any>;
|
|
23
|
+
contentAlignX: ContentAlignX;
|
|
24
|
+
containerWidth: ContainerWidth;
|
|
25
|
+
width: ContainerWidth | ((widths: Record<string, any>) => ContainerWidth);
|
|
26
|
+
}>;
|
|
27
|
+
type ComponentProps = ConfigurationProps & Partial<{
|
|
28
|
+
component: ComponentFn<any>;
|
|
29
|
+
css: ExtraStyles;
|
|
30
|
+
}>;
|
|
31
|
+
type ElementType<O extends string[]> = ComponentFn<Omit<ComponentProps, O[number]> & Record<string, unknown> & {
|
|
32
|
+
children?: VNodeChild;
|
|
33
|
+
}> & {
|
|
34
|
+
displayName: string;
|
|
35
|
+
pkgName: string;
|
|
36
|
+
PYREON__COMPONENT: string;
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/Col/component.d.ts
|
|
40
|
+
declare const Component: ElementType<["containerWidth", "width", "rowComponent", "rowCss", "colCss", "colComponent", "columns", "gap", "gutter", "contentAlignX"]>;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/Container/component.d.ts
|
|
43
|
+
declare const Component$1: ElementType<["containerWidth"]>;
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/Row/component.d.ts
|
|
46
|
+
declare const Component$2: ElementType<["containerWidth", "width", "rowComponent", "rowCss"]>;
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/theme.d.ts
|
|
49
|
+
/**
|
|
50
|
+
* Default Bootstrap-like grid configuration. Provides 5 breakpoints (xs-xl),
|
|
51
|
+
* a 12-column grid, and responsive container max-widths matching Bootstrap 4.
|
|
52
|
+
*/
|
|
53
|
+
declare const _default: {
|
|
54
|
+
readonly rootSize: 16;
|
|
55
|
+
readonly breakpoints: {
|
|
56
|
+
readonly xs: 0;
|
|
57
|
+
readonly sm: 576;
|
|
58
|
+
readonly md: 768;
|
|
59
|
+
readonly lg: 992;
|
|
60
|
+
readonly xl: 1200;
|
|
61
|
+
};
|
|
62
|
+
readonly grid: {
|
|
63
|
+
readonly columns: 12;
|
|
64
|
+
readonly container: {
|
|
65
|
+
readonly xs: "100%";
|
|
66
|
+
readonly sm: 540;
|
|
67
|
+
readonly md: 720;
|
|
68
|
+
readonly lg: 960;
|
|
69
|
+
readonly xl: 1140;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
export { Component as Col, Component$1 as Container, Provider, Component$2 as Row, _default as theme };
|
|
75
|
+
//# sourceMappingURL=index2.d.ts.map
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { ALIGN_CONTENT_MAP_X, Provider, context, extendCss, makeItResponsive, value } from "@pyreon/unistyle";
|
|
2
|
+
import { createContext, onUnmount, popContext, pushContext, useContext } from "@pyreon/core";
|
|
3
|
+
import { config, get, omit, pick } from "@pyreon/ui-core";
|
|
4
|
+
import { jsx } from "@pyreon/core/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/constants.ts
|
|
7
|
+
const PKG_NAME = "@pyreon/coolgrid";
|
|
8
|
+
/**
|
|
9
|
+
* Grid configuration keys that are passed through context
|
|
10
|
+
* from Container to Row and from Row to Col components.
|
|
11
|
+
*/
|
|
12
|
+
const CONTEXT_KEYS = [
|
|
13
|
+
"columns",
|
|
14
|
+
"size",
|
|
15
|
+
"gap",
|
|
16
|
+
"padding",
|
|
17
|
+
"gutter",
|
|
18
|
+
"colCss",
|
|
19
|
+
"colComponent",
|
|
20
|
+
"rowCss",
|
|
21
|
+
"rowComponent",
|
|
22
|
+
"contentAlignX"
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/context/ContainerContext.ts
|
|
27
|
+
/**
|
|
28
|
+
* Context for container-level grid configuration.
|
|
29
|
+
* Provided by the Container component and consumed by Row children
|
|
30
|
+
* to inherit columns, gap, gutter, and other grid settings.
|
|
31
|
+
*/
|
|
32
|
+
var ContainerContext_default = createContext({});
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/context/RowContext.ts
|
|
36
|
+
/**
|
|
37
|
+
* Context for row-level grid configuration.
|
|
38
|
+
* Provided by the Row component and consumed by Col children
|
|
39
|
+
* to inherit columns, gap, gutter, and sizing for width calculations.
|
|
40
|
+
*/
|
|
41
|
+
var RowContext_default = createContext({});
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/useContext.tsx
|
|
45
|
+
const pickThemeProps = (props, keywords) => pick(props, keywords);
|
|
46
|
+
const getGridContext = (props = {}, theme = {}) => ({
|
|
47
|
+
columns: get(props, "columns") || get(theme, "grid.columns") || get(theme, "coolgrid.columns"),
|
|
48
|
+
containerWidth: get(props, "width") || get(theme, "grid.container") || get(theme, "coolgrid.container")
|
|
49
|
+
});
|
|
50
|
+
const useGridContext = (props) => {
|
|
51
|
+
const { theme } = useContext(context);
|
|
52
|
+
const ctxProps = pickThemeProps(props, CONTEXT_KEYS);
|
|
53
|
+
return {
|
|
54
|
+
...getGridContext(ctxProps, theme),
|
|
55
|
+
...ctxProps
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/utils.ts
|
|
61
|
+
/** Checks whether a value is a finite number. */
|
|
62
|
+
const isNumber = (value) => Number.isFinite(value);
|
|
63
|
+
/** Checks whether a value is a finite number greater than zero. */
|
|
64
|
+
const hasValue = (value) => isNumber(value) && value > 0;
|
|
65
|
+
/**
|
|
66
|
+
* Determines if a column should be visible. A column is visible when its
|
|
67
|
+
* size is undefined (auto) or a non-zero number. Size 0 hides the column.
|
|
68
|
+
*/
|
|
69
|
+
const isVisible = (value) => isNumber(value) && value !== 0 || value === void 0;
|
|
70
|
+
const omitCtxKeys = (props) => omit(props, CONTEXT_KEYS);
|
|
71
|
+
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/Col/styled.ts
|
|
74
|
+
const { styled: styled$2, css: css$2, component: component$2 } = config;
|
|
75
|
+
/** Returns true when both size and columns are valid, enabling explicit width calculation. */
|
|
76
|
+
const hasWidth = (size, columns) => hasValue(size) && hasValue(columns);
|
|
77
|
+
/**
|
|
78
|
+
* Calculates column width as a percentage of total columns, subtracting
|
|
79
|
+
* the gap when present. Uses `calc(%)` for web.
|
|
80
|
+
*/
|
|
81
|
+
const widthStyles = ({ size, columns, gap }, { rootSize }) => {
|
|
82
|
+
if (!hasWidth(size, columns)) return "";
|
|
83
|
+
const s = size;
|
|
84
|
+
const c = columns;
|
|
85
|
+
const g = gap;
|
|
86
|
+
const width = s / c * 100;
|
|
87
|
+
const v = value(hasValue(gap) ? `calc(${width}% - ${g}px)` : `${width}%`, rootSize);
|
|
88
|
+
return css$2`
|
|
89
|
+
flex-grow: 0;
|
|
90
|
+
flex-shrink: 0;
|
|
91
|
+
max-width: ${v};
|
|
92
|
+
flex-basis: ${v};
|
|
93
|
+
`;
|
|
94
|
+
};
|
|
95
|
+
/** Applies half of the given value as either margin or padding (used for gap and padding distribution). */
|
|
96
|
+
const spacingStyles$1 = (type, param, rootSize) => {
|
|
97
|
+
if (!isNumber(param)) return "";
|
|
98
|
+
return css$2`
|
|
99
|
+
${`${type}: ${value(param / 2, rootSize)}`};
|
|
100
|
+
`;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Main responsive style block for Col. When the column is visible, applies
|
|
104
|
+
* width, padding, margin, and extra CSS. When hidden (size === 0), moves
|
|
105
|
+
* the element off-screen with fixed positioning.
|
|
106
|
+
*/
|
|
107
|
+
const styles$2 = ({ theme, css: cssFn, rootSize }) => {
|
|
108
|
+
const { size, columns, gap, padding, extraStyles } = theme;
|
|
109
|
+
if (isVisible(size)) return cssFn`
|
|
110
|
+
left: initial;
|
|
111
|
+
position: relative;
|
|
112
|
+
${widthStyles({
|
|
113
|
+
size,
|
|
114
|
+
columns,
|
|
115
|
+
gap
|
|
116
|
+
}, { rootSize })};
|
|
117
|
+
${spacingStyles$1("padding", padding, rootSize)};
|
|
118
|
+
${spacingStyles$1("margin", gap, rootSize)};
|
|
119
|
+
${extendCss(extraStyles)};
|
|
120
|
+
`;
|
|
121
|
+
return cssFn`
|
|
122
|
+
left: -9999px;
|
|
123
|
+
position: fixed;
|
|
124
|
+
margin: 0;
|
|
125
|
+
padding: 0;
|
|
126
|
+
`;
|
|
127
|
+
};
|
|
128
|
+
var styled_default$2 = styled$2(component$2)`
|
|
129
|
+
box-sizing: border-box;
|
|
130
|
+
justify-content: stretch;
|
|
131
|
+
|
|
132
|
+
position: relative;
|
|
133
|
+
display: flex;
|
|
134
|
+
flex-basis: 0;
|
|
135
|
+
flex-grow: 1;
|
|
136
|
+
flex-direction: column;
|
|
137
|
+
|
|
138
|
+
${makeItResponsive({
|
|
139
|
+
key: "$coolgrid",
|
|
140
|
+
styles: styles$2,
|
|
141
|
+
css: css$2,
|
|
142
|
+
normalize: true
|
|
143
|
+
})};
|
|
144
|
+
`;
|
|
145
|
+
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/Col/component.tsx
|
|
148
|
+
/**
|
|
149
|
+
* Col (column) component that reads grid settings from RowContext
|
|
150
|
+
* (columns, gap, gutter) and calculates its own width as a fraction
|
|
151
|
+
* of the total columns. Supports responsive size, padding, and visibility.
|
|
152
|
+
*/
|
|
153
|
+
const DEV_PROPS$2 = process.env.NODE_ENV !== "production" ? { "data-coolgrid": "col" } : {};
|
|
154
|
+
const Component$2 = ({ children, component, css, ...props }) => {
|
|
155
|
+
const { colCss, colComponent, columns, gap, size, padding } = useGridContext({
|
|
156
|
+
...useContext(RowContext_default),
|
|
157
|
+
...props
|
|
158
|
+
});
|
|
159
|
+
const finalProps = { $coolgrid: {
|
|
160
|
+
columns,
|
|
161
|
+
gap,
|
|
162
|
+
size,
|
|
163
|
+
padding,
|
|
164
|
+
extraStyles: css ?? colCss
|
|
165
|
+
} };
|
|
166
|
+
return /* @__PURE__ */ jsx(styled_default$2, {
|
|
167
|
+
...omitCtxKeys(props),
|
|
168
|
+
as: component ?? colComponent,
|
|
169
|
+
...finalProps,
|
|
170
|
+
...DEV_PROPS$2,
|
|
171
|
+
children
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
const name$2 = `${PKG_NAME}/Col`;
|
|
175
|
+
Component$2.displayName = name$2;
|
|
176
|
+
Component$2.pkgName = PKG_NAME;
|
|
177
|
+
Component$2.PYREON__COMPONENT = name$2;
|
|
178
|
+
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/Col/index.ts
|
|
181
|
+
var Col_default = Component$2;
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/Container/styled.ts
|
|
185
|
+
const { styled: styled$1, css: css$1, component: component$1 } = config;
|
|
186
|
+
/** Responsive styles that apply the container's max-width and any extra CSS at each breakpoint. */
|
|
187
|
+
const styles$1 = ({ theme: t, css: cssFn, rootSize }) => {
|
|
188
|
+
const w = t.width != null && typeof t.width !== "object" ? t.width : null;
|
|
189
|
+
return cssFn`
|
|
190
|
+
${w != null ? `max-width: ${value(w, rootSize)};` : ""};
|
|
191
|
+
${extendCss(t.extraStyles)};
|
|
192
|
+
`;
|
|
193
|
+
};
|
|
194
|
+
/** Styled Container element. Centered via auto margins with responsive max-width. */
|
|
195
|
+
var styled_default$1 = styled$1(component$1)`
|
|
196
|
+
display: flex;
|
|
197
|
+
flex-direction: column;
|
|
198
|
+
box-sizing: border-box;
|
|
199
|
+
width: 100%;
|
|
200
|
+
margin-right: auto;
|
|
201
|
+
margin-left: auto;
|
|
202
|
+
|
|
203
|
+
${makeItResponsive({
|
|
204
|
+
key: "$coolgrid",
|
|
205
|
+
styles: styles$1,
|
|
206
|
+
css: css$1,
|
|
207
|
+
normalize: true
|
|
208
|
+
})};
|
|
209
|
+
`;
|
|
210
|
+
|
|
211
|
+
//#endregion
|
|
212
|
+
//#region src/Container/component.tsx
|
|
213
|
+
/**
|
|
214
|
+
* Container component that establishes the outermost grid boundary.
|
|
215
|
+
* Resolves grid config from the theme, provides it to descendant Row/Col
|
|
216
|
+
* components via ContainerContext, and renders a styled wrapper with
|
|
217
|
+
* responsive max-width.
|
|
218
|
+
*/
|
|
219
|
+
const DEV_PROPS$1 = process.env.NODE_ENV !== "production" ? { "data-coolgrid": "container" } : {};
|
|
220
|
+
const Component$1 = ({ children, component, css, width, ...props }) => {
|
|
221
|
+
const { containerWidth, columns, size, gap, padding, gutter, colCss, colComponent, rowCss, rowComponent, contentAlignX } = useGridContext(props);
|
|
222
|
+
const context = {
|
|
223
|
+
columns,
|
|
224
|
+
size,
|
|
225
|
+
gap,
|
|
226
|
+
padding,
|
|
227
|
+
gutter,
|
|
228
|
+
colCss,
|
|
229
|
+
colComponent,
|
|
230
|
+
rowCss,
|
|
231
|
+
rowComponent,
|
|
232
|
+
contentAlignX
|
|
233
|
+
};
|
|
234
|
+
const finalProps = { $coolgrid: {
|
|
235
|
+
width: (() => {
|
|
236
|
+
if (!width) return containerWidth;
|
|
237
|
+
if (typeof width === "function") return width(containerWidth);
|
|
238
|
+
return width;
|
|
239
|
+
})(),
|
|
240
|
+
extraStyles: css
|
|
241
|
+
} };
|
|
242
|
+
pushContext(new Map([[ContainerContext_default.id, context]]));
|
|
243
|
+
onUnmount(() => popContext());
|
|
244
|
+
return /* @__PURE__ */ jsx(styled_default$1, {
|
|
245
|
+
...omitCtxKeys(props),
|
|
246
|
+
as: component,
|
|
247
|
+
...finalProps,
|
|
248
|
+
...DEV_PROPS$1,
|
|
249
|
+
children
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
const name$1 = `${PKG_NAME}/Container`;
|
|
253
|
+
Component$1.displayName = name$1;
|
|
254
|
+
Component$1.pkgName = PKG_NAME;
|
|
255
|
+
Component$1.PYREON__COMPONENT = name$1;
|
|
256
|
+
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/Container/index.ts
|
|
259
|
+
var Container_default = Component$1;
|
|
260
|
+
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/Row/styled.ts
|
|
263
|
+
const { styled, css, component } = config;
|
|
264
|
+
const spacingStyles = ({ gap, gutter }, { rootSize }) => {
|
|
265
|
+
if (!isNumber(gap)) return "";
|
|
266
|
+
const g = gap;
|
|
267
|
+
const getValue = (param) => value(param, rootSize);
|
|
268
|
+
const spacingX = g / 2 * -1;
|
|
269
|
+
return css`
|
|
270
|
+
margin: ${getValue(isNumber(gutter) ? gutter - g / 2 : g / 2)} ${getValue(spacingX)};
|
|
271
|
+
`;
|
|
272
|
+
};
|
|
273
|
+
/** Maps the contentAlignX prop to a CSS justify-content value. */
|
|
274
|
+
const contentAlign = (align) => {
|
|
275
|
+
if (!align) return "";
|
|
276
|
+
return css`
|
|
277
|
+
justify-content: ${ALIGN_CONTENT_MAP_X[align]};
|
|
278
|
+
`;
|
|
279
|
+
};
|
|
280
|
+
/** Composes spacing, alignment, and extra CSS into a single responsive style block for the Row. */
|
|
281
|
+
const styles = ({ theme, css: cssFn, rootSize }) => {
|
|
282
|
+
const { gap, gutter, contentAlignX, extraStyles } = theme;
|
|
283
|
+
return cssFn`
|
|
284
|
+
${spacingStyles({
|
|
285
|
+
gap,
|
|
286
|
+
gutter
|
|
287
|
+
}, { rootSize })};
|
|
288
|
+
${contentAlign(contentAlignX)};
|
|
289
|
+
${extendCss(extraStyles)};
|
|
290
|
+
`;
|
|
291
|
+
};
|
|
292
|
+
var styled_default = styled(component)`
|
|
293
|
+
box-sizing: border-box;
|
|
294
|
+
|
|
295
|
+
display: flex;
|
|
296
|
+
flex-wrap: wrap;
|
|
297
|
+
align-self: stretch;
|
|
298
|
+
flex-direction: row;
|
|
299
|
+
|
|
300
|
+
${makeItResponsive({
|
|
301
|
+
key: "$coolgrid",
|
|
302
|
+
styles,
|
|
303
|
+
css,
|
|
304
|
+
normalize: true
|
|
305
|
+
})};
|
|
306
|
+
`;
|
|
307
|
+
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/Row/component.tsx
|
|
310
|
+
/**
|
|
311
|
+
* Row component that reads inherited config from ContainerContext, merges
|
|
312
|
+
* it with its own props, and provides the resolved grid settings (columns,
|
|
313
|
+
* gap, gutter) to Col children via RowContext. Renders a flex-wrap container
|
|
314
|
+
* with negative margins to offset column gutters.
|
|
315
|
+
*/
|
|
316
|
+
const DEV_PROPS = process.env.NODE_ENV !== "production" ? { "data-coolgrid": "row" } : {};
|
|
317
|
+
const Component = ({ children, component, css, contentAlignX: rowAlignX, ...props }) => {
|
|
318
|
+
const { columns, gap, gutter, rowComponent, rowCss, contentAlignX, containerWidth, size, padding, colCss, colComponent } = useGridContext({
|
|
319
|
+
...useContext(ContainerContext_default),
|
|
320
|
+
...props
|
|
321
|
+
});
|
|
322
|
+
const context = {
|
|
323
|
+
containerWidth,
|
|
324
|
+
size,
|
|
325
|
+
padding,
|
|
326
|
+
colCss,
|
|
327
|
+
colComponent,
|
|
328
|
+
columns,
|
|
329
|
+
gap,
|
|
330
|
+
gutter
|
|
331
|
+
};
|
|
332
|
+
const finalProps = { $coolgrid: {
|
|
333
|
+
contentAlignX: rowAlignX || contentAlignX,
|
|
334
|
+
columns,
|
|
335
|
+
gap,
|
|
336
|
+
gutter,
|
|
337
|
+
extraStyles: css || rowCss
|
|
338
|
+
} };
|
|
339
|
+
pushContext(new Map([[RowContext_default.id, context]]));
|
|
340
|
+
onUnmount(() => popContext());
|
|
341
|
+
return /* @__PURE__ */ jsx(styled_default, {
|
|
342
|
+
...omitCtxKeys(props),
|
|
343
|
+
as: component || rowComponent,
|
|
344
|
+
...finalProps,
|
|
345
|
+
...DEV_PROPS,
|
|
346
|
+
children
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
const name = `${PKG_NAME}/Row`;
|
|
350
|
+
Component.displayName = name;
|
|
351
|
+
Component.pkgName = PKG_NAME;
|
|
352
|
+
Component.PYREON__COMPONENT = name;
|
|
353
|
+
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/Row/index.ts
|
|
356
|
+
var Row_default = Component;
|
|
357
|
+
|
|
358
|
+
//#endregion
|
|
359
|
+
//#region src/theme.ts
|
|
360
|
+
/**
|
|
361
|
+
* Default Bootstrap-like grid configuration. Provides 5 breakpoints (xs-xl),
|
|
362
|
+
* a 12-column grid, and responsive container max-widths matching Bootstrap 4.
|
|
363
|
+
*/
|
|
364
|
+
var theme_default = {
|
|
365
|
+
rootSize: 16,
|
|
366
|
+
breakpoints: {
|
|
367
|
+
xs: 0,
|
|
368
|
+
sm: 576,
|
|
369
|
+
md: 768,
|
|
370
|
+
lg: 992,
|
|
371
|
+
xl: 1200
|
|
372
|
+
},
|
|
373
|
+
grid: {
|
|
374
|
+
columns: 12,
|
|
375
|
+
container: {
|
|
376
|
+
xs: "100%",
|
|
377
|
+
sm: 540,
|
|
378
|
+
md: 720,
|
|
379
|
+
lg: 960,
|
|
380
|
+
xl: 1140
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
//#endregion
|
|
386
|
+
export { Col_default as Col, Container_default as Container, Provider, Row_default as Row, theme_default as theme };
|
|
387
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pyreon/coolgrid",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Responsive grid system for Pyreon",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"exports": {
|
|
9
|
+
"source": "./src/index.ts",
|
|
10
|
+
"import": "./lib/index.js",
|
|
11
|
+
"types": "./lib/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"types": "./lib/index.d.ts",
|
|
14
|
+
"main": "./lib/index.js",
|
|
15
|
+
"files": [
|
|
16
|
+
"lib",
|
|
17
|
+
"!lib/**/*.map",
|
|
18
|
+
"!lib/analysis",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">= 18"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"prepublish": "bun run build",
|
|
30
|
+
"build": "bun run vl_rolldown_build",
|
|
31
|
+
"build:watch": "bun run vl_rolldown_build-watch",
|
|
32
|
+
"lint": "biome check src/",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:coverage": "vitest run --coverage",
|
|
35
|
+
"test:watch": "vitest",
|
|
36
|
+
"typecheck": "tsc --noEmit"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@pyreon/core": ">=0.3.0",
|
|
40
|
+
"@pyreon/reactivity": ">=0.3.0",
|
|
41
|
+
"@pyreon/ui-core": "^0.0.2",
|
|
42
|
+
"@pyreon/unistyle": "^0.0.2",
|
|
43
|
+
"@pyreon/styler": "^0.0.2"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@vitus-labs/tools-rolldown": "^1.15.0",
|
|
47
|
+
"@vitus-labs/tools-typescript": "^1.15.0"
|
|
48
|
+
}
|
|
49
|
+
}
|