@pyreon/unistyle 0.24.5 → 0.24.6
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 +7 -9
- package/src/__tests__/alignContent.test.ts +0 -121
- package/src/__tests__/borderRadius.test.ts +0 -125
- package/src/__tests__/camelToKebab.test.ts +0 -44
- package/src/__tests__/context.test.ts +0 -147
- package/src/__tests__/createMediaQueries.test.ts +0 -98
- package/src/__tests__/edge.test.ts +0 -164
- package/src/__tests__/enrichTheme.test.ts +0 -56
- package/src/__tests__/extendCss.test.ts +0 -45
- package/src/__tests__/index.test.ts +0 -79
- package/src/__tests__/makeItResponsive.test.ts +0 -431
- package/src/__tests__/manifest-snapshot.test.ts +0 -34
- package/src/__tests__/native-marker.test.ts +0 -9
- package/src/__tests__/optimizeBreakpointDeltas.test.ts +0 -124
- package/src/__tests__/processDescriptor.test.ts +0 -322
- package/src/__tests__/responsive.test.ts +0 -221
- package/src/__tests__/special-keys.test.ts +0 -120
- package/src/__tests__/styles.test.ts +0 -273
- package/src/__tests__/unistyle.browser.test.tsx +0 -169
- package/src/__tests__/units.test.ts +0 -134
- package/src/context.tsx +0 -44
- package/src/enrichTheme.ts +0 -42
- package/src/env.d.ts +0 -6
- package/src/index.ts +0 -91
- package/src/manifest.ts +0 -197
- package/src/responsive/breakpoints.ts +0 -15
- package/src/responsive/createMediaQueries.ts +0 -43
- package/src/responsive/index.ts +0 -15
- package/src/responsive/makeItResponsive.ts +0 -223
- package/src/responsive/normalizeTheme.ts +0 -79
- package/src/responsive/optimizeBreakpointDeltas.ts +0 -190
- package/src/responsive/optimizeTheme.ts +0 -60
- package/src/responsive/sortBreakpoints.ts +0 -10
- package/src/responsive/transformTheme.ts +0 -54
- package/src/styles/alignContent.ts +0 -62
- package/src/styles/extendCss.ts +0 -26
- package/src/styles/index.ts +0 -16
- package/src/styles/shorthands/borderRadius.ts +0 -89
- package/src/styles/shorthands/edge.ts +0 -108
- package/src/styles/shorthands/index.ts +0 -4
- package/src/styles/styles/camelToKebab.ts +0 -3
- package/src/styles/styles/index.ts +0 -132
- package/src/styles/styles/processDescriptor.ts +0 -136
- package/src/styles/styles/propertyMap.ts +0 -438
- package/src/styles/styles/types.ts +0 -368
- package/src/types.ts +0 -175
- package/src/units/index.ts +0 -6
- package/src/units/stripUnit.ts +0 -25
- package/src/units/value.ts +0 -47
- package/src/units/values.ts +0 -40
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mobile-first cascade optimizer.
|
|
3
|
-
*
|
|
4
|
-
* Given an ordered array of CSS strings (one per breakpoint, smallest first),
|
|
5
|
-
* returns a parallel array where each non-base breakpoint contains only the
|
|
6
|
-
* declarations that DIFFER from the cumulative cascade so far. This relies on
|
|
7
|
-
* mobile-first `@media (min-width: …)` semantics: properties set at smaller
|
|
8
|
-
* breakpoints inherit at larger ones, so re-emitting an unchanged property is
|
|
9
|
-
* pure byte waste.
|
|
10
|
-
*
|
|
11
|
-
* Example:
|
|
12
|
-
* ["color: red; padding: 0;", "color: red; padding: 1rem;"]
|
|
13
|
-
* → ["color: red; padding: 0;", "padding: 1rem;"]
|
|
14
|
-
*
|
|
15
|
-
* Top-level declarations are diffed by `prop:value`. Selector blocks
|
|
16
|
-
* (`&:hover { … }`, `@supports { … }`) are treated as opaque and deduped by
|
|
17
|
-
* exact text. Anything inside parens or quoted strings is skipped over so
|
|
18
|
-
* `linear-gradient(red 0%, blue 100%)` and `content: ";"` parse correctly.
|
|
19
|
-
*
|
|
20
|
-
* Limitations:
|
|
21
|
-
* - shorthand/longhand interaction is not modeled. If breakpoint A sets
|
|
22
|
-
* `padding: 1rem` and breakpoint B sets `padding-top: 0`, both are kept
|
|
23
|
-
* (they have different `prop` keys). If A sets `padding-top: 1rem` and B
|
|
24
|
-
* sets `padding: 1rem`, B's `padding` is emitted because the cascade map
|
|
25
|
-
* has no entry for `padding`. This is correct: B's shorthand RESETS sides
|
|
26
|
-
* A didn't touch, so dropping it would change behaviour.
|
|
27
|
-
* - Nested blocks are deduped only by exact textual match. Two equivalent
|
|
28
|
-
* blocks with different whitespace would both be emitted.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
interface DeclEntry {
|
|
32
|
-
kind: 'decl'
|
|
33
|
-
prop: string
|
|
34
|
-
value: string
|
|
35
|
-
raw: string // canonical "prop: value;" form
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface BlockEntry {
|
|
39
|
-
kind: 'block'
|
|
40
|
-
raw: string // entire "selector { body }" or stray block
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
type Entry = DeclEntry | BlockEntry
|
|
44
|
-
|
|
45
|
-
/** Parse a CSS string into top-level declarations and opaque blocks. */
|
|
46
|
-
const parse = (css: string): Entry[] => {
|
|
47
|
-
const entries: Entry[] = []
|
|
48
|
-
const len = css.length
|
|
49
|
-
|
|
50
|
-
let depth = 0
|
|
51
|
-
let parenDepth = 0
|
|
52
|
-
let quote = 0 // charCode of active quote (0 if none)
|
|
53
|
-
let segmentStart = 0
|
|
54
|
-
|
|
55
|
-
const pushSegment = (rawSegment: string) => {
|
|
56
|
-
const trimmed = rawSegment.trim()
|
|
57
|
-
if (!trimmed) return
|
|
58
|
-
// pushSegment is only reached for segments that ended with a top-level
|
|
59
|
-
// ";" — full "selector { ... }" blocks are captured separately by the
|
|
60
|
-
// brace walker, so this path always sees declarations (or malformed
|
|
61
|
-
// declaration-shaped fragments).
|
|
62
|
-
const text = trimmed.endsWith(';') ? trimmed.slice(0, -1) : trimmed
|
|
63
|
-
const colonIdx = text.indexOf(':')
|
|
64
|
-
if (colonIdx <= 0) {
|
|
65
|
-
// No ":" or starts with ":" → not a parseable declaration; keep raw
|
|
66
|
-
entries.push({ kind: 'block', raw: `${text};` })
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
const prop = text.slice(0, colonIdx).trim()
|
|
70
|
-
const value = text.slice(colonIdx + 1).trim()
|
|
71
|
-
if (!prop || !value) {
|
|
72
|
-
entries.push({ kind: 'block', raw: `${text};` })
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
entries.push({
|
|
76
|
-
kind: 'decl',
|
|
77
|
-
prop,
|
|
78
|
-
value,
|
|
79
|
-
raw: `${prop}: ${value};`,
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
for (let i = 0; i < len; i++) {
|
|
84
|
-
const code = css.charCodeAt(i)
|
|
85
|
-
|
|
86
|
-
// Inside a quoted string — skip until matching quote (ignoring escapes)
|
|
87
|
-
if (quote !== 0) {
|
|
88
|
-
if (code === 92 /* \ */) {
|
|
89
|
-
i++ // skip the next character
|
|
90
|
-
} else if (code === quote) {
|
|
91
|
-
quote = 0
|
|
92
|
-
}
|
|
93
|
-
continue
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Quote start
|
|
97
|
-
if (code === 34 /* " */ || code === 39 /* ' */) {
|
|
98
|
-
quote = code
|
|
99
|
-
continue
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Parens — content (e.g. linear-gradient args) shouldn't be interpreted
|
|
103
|
-
if (code === 40 /* ( */) {
|
|
104
|
-
parenDepth++
|
|
105
|
-
continue
|
|
106
|
-
}
|
|
107
|
-
if (code === 41 /* ) */) {
|
|
108
|
-
if (parenDepth > 0) parenDepth--
|
|
109
|
-
continue
|
|
110
|
-
}
|
|
111
|
-
if (parenDepth > 0) continue
|
|
112
|
-
|
|
113
|
-
if (code === 123 /* { */) {
|
|
114
|
-
depth++
|
|
115
|
-
continue
|
|
116
|
-
}
|
|
117
|
-
if (code === 125 /* } */) {
|
|
118
|
-
depth--
|
|
119
|
-
if (depth === 0) {
|
|
120
|
-
// End of a top-level block — capture from segmentStart..i (inclusive)
|
|
121
|
-
const raw = css.slice(segmentStart, i + 1).trim()
|
|
122
|
-
if (raw) entries.push({ kind: 'block', raw })
|
|
123
|
-
segmentStart = i + 1
|
|
124
|
-
}
|
|
125
|
-
continue
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (depth === 0 && code === 59 /* ; */) {
|
|
129
|
-
pushSegment(css.slice(segmentStart, i))
|
|
130
|
-
segmentStart = i + 1
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Trailing segment (no terminating semicolon)
|
|
135
|
-
if (segmentStart < len) {
|
|
136
|
-
const trailing = css.slice(segmentStart).trim()
|
|
137
|
-
if (trailing) {
|
|
138
|
-
if (depth > 0) {
|
|
139
|
-
// Unbalanced braces — keep the rest as opaque so output isn't lossy
|
|
140
|
-
entries.push({ kind: 'block', raw: trailing })
|
|
141
|
-
} else {
|
|
142
|
-
pushSegment(trailing)
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return entries
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Apply the mobile-first cascade diff. The first entry passes through
|
|
152
|
-
* unchanged; subsequent entries are pruned to the delta vs. the running
|
|
153
|
-
* cascade (declarations by prop, blocks by exact text match).
|
|
154
|
-
*/
|
|
155
|
-
export const optimizeBreakpointDeltas = (cssStrings: string[]): string[] => {
|
|
156
|
-
if (cssStrings.length <= 1) return cssStrings
|
|
157
|
-
|
|
158
|
-
const cascadeDecl = new Map<string, string>()
|
|
159
|
-
const cascadeBlocks = new Set<string>()
|
|
160
|
-
const out: string[] = new Array(cssStrings.length)
|
|
161
|
-
|
|
162
|
-
for (let i = 0; i < cssStrings.length; i++) {
|
|
163
|
-
const css = cssStrings[i]
|
|
164
|
-
if (!css) {
|
|
165
|
-
out[i] = ''
|
|
166
|
-
continue
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const entries = parse(css)
|
|
170
|
-
const kept: string[] = []
|
|
171
|
-
|
|
172
|
-
for (const e of entries) {
|
|
173
|
-
if (e.kind === 'decl') {
|
|
174
|
-
if (cascadeDecl.get(e.prop) !== e.value) {
|
|
175
|
-
kept.push(e.raw)
|
|
176
|
-
cascadeDecl.set(e.prop, e.value)
|
|
177
|
-
}
|
|
178
|
-
} else if (!cascadeBlocks.has(e.raw)) {
|
|
179
|
-
kept.push(e.raw)
|
|
180
|
-
cascadeBlocks.add(e.raw)
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
out[i] = kept.join(' ')
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return out
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export default optimizeBreakpointDeltas
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
export type OptimizeTheme = ({
|
|
2
|
-
theme,
|
|
3
|
-
breakpoints,
|
|
4
|
-
}: {
|
|
5
|
-
theme: Record<string, Record<string, unknown>>
|
|
6
|
-
breakpoints: string[]
|
|
7
|
-
}) => Record<string, Record<string, unknown>>
|
|
8
|
-
|
|
9
|
-
const shallowEqual = (
|
|
10
|
-
a: Record<string, unknown> | undefined,
|
|
11
|
-
b: Record<string, unknown> | undefined,
|
|
12
|
-
): boolean => {
|
|
13
|
-
if (a === b) return true
|
|
14
|
-
if (!a || !b) return false
|
|
15
|
-
// for-in + counting avoids the two `Object.keys` array allocations the
|
|
16
|
-
// prior implementation paid on every breakpoint optimization step.
|
|
17
|
-
// Ported from vitus-labs `e573e6c4`; measured upstream: +4.0% on the
|
|
18
|
-
// EQUAL hot path (the common case in steady-state renders).
|
|
19
|
-
let aCount = 0
|
|
20
|
-
for (const key in a) {
|
|
21
|
-
aCount++
|
|
22
|
-
if (a[key] !== b[key]) return false
|
|
23
|
-
}
|
|
24
|
-
let bCount = 0
|
|
25
|
-
for (const _ in b) bCount++
|
|
26
|
-
return aCount === bCount
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Removes breakpoints whose full-object styles are identical to the
|
|
31
|
-
* previous one. Simple all-or-nothing: if ANY property differs from
|
|
32
|
-
* the previous breakpoint, emit the ENTIRE current breakpoint.
|
|
33
|
-
*
|
|
34
|
-
* This matches the reference implementation (vitus-labs/ui-system) and
|
|
35
|
-
* the original monorepo-migration version (commit 2b7c5876). Previous
|
|
36
|
-
* "optimizations" (PRs #159, #208) that tried per-property diffing
|
|
37
|
-
* broke responsive styles in subtle ways — shorthand/longhand CSS
|
|
38
|
-
* property interactions, properties that depend on each other,
|
|
39
|
-
* properties that need to be emitted together to cascade correctly.
|
|
40
|
-
*
|
|
41
|
-
* The all-or-nothing approach is the correct level of deduplication —
|
|
42
|
-
* we skip the breakpoint when it's entirely redundant, and let the
|
|
43
|
-
* browser's CSS cascade handle the rest.
|
|
44
|
-
*/
|
|
45
|
-
const optimizeTheme: OptimizeTheme = ({ theme, breakpoints }) => {
|
|
46
|
-
const result: Record<string, Record<string, unknown>> = {}
|
|
47
|
-
|
|
48
|
-
for (let i = 0; i < breakpoints.length; i++) {
|
|
49
|
-
const key = breakpoints[i] as string
|
|
50
|
-
const previousBreakpoint = breakpoints[i - 1] as string
|
|
51
|
-
const current = theme[key]
|
|
52
|
-
if (current && (i === 0 || !shallowEqual(theme[previousBreakpoint], current))) {
|
|
53
|
-
result[key] = current
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return result
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export default optimizeTheme
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export type SortBreakpoints = <T extends Record<string, number>>(breakpoints: T) => (keyof T)[]
|
|
2
|
-
|
|
3
|
-
const sortBreakpoints: SortBreakpoints = (breakpoints) => {
|
|
4
|
-
const result = Object.keys(breakpoints).sort(
|
|
5
|
-
(a, b) => (breakpoints[a] ?? 0) - (breakpoints[b] ?? 0),
|
|
6
|
-
)
|
|
7
|
-
return result
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default sortBreakpoints
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { isEmpty, set } from '@pyreon/ui-core'
|
|
2
|
-
|
|
3
|
-
const removeUnexpectedKeys = (obj: Record<string, unknown>, keys: string[]) => {
|
|
4
|
-
const result: Record<string, unknown> = {}
|
|
5
|
-
keys.forEach((bp) => {
|
|
6
|
-
const value = obj[bp]
|
|
7
|
-
if (value) {
|
|
8
|
-
result[bp] = value
|
|
9
|
-
}
|
|
10
|
-
})
|
|
11
|
-
return result
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type TransformTheme = ({
|
|
15
|
-
theme,
|
|
16
|
-
breakpoints,
|
|
17
|
-
}: {
|
|
18
|
-
theme: Record<string, unknown>
|
|
19
|
-
breakpoints: string[]
|
|
20
|
-
}) => any
|
|
21
|
-
|
|
22
|
-
const transformTheme: TransformTheme = ({ theme, breakpoints }) => {
|
|
23
|
-
const result = {}
|
|
24
|
-
|
|
25
|
-
if (isEmpty(theme) || isEmpty(breakpoints)) return result
|
|
26
|
-
|
|
27
|
-
// for-in + nested for-in avoids the two `Object.entries(...)` array
|
|
28
|
-
// allocations (outer + inner per object value) the prior forEach paid.
|
|
29
|
-
// Same for `value.forEach((child, i) => ...)` → indexed for-loop.
|
|
30
|
-
// Ported from vitus-labs `e573e6c4`.
|
|
31
|
-
for (const key in theme) {
|
|
32
|
-
const value = theme[key]
|
|
33
|
-
if (Array.isArray(value) && value.length > 0) {
|
|
34
|
-
for (let i = 0; i < value.length; i++) {
|
|
35
|
-
const indexBreakpoint = breakpoints[i]
|
|
36
|
-
if (indexBreakpoint == null) continue
|
|
37
|
-
set(result, [indexBreakpoint, key], value[i])
|
|
38
|
-
}
|
|
39
|
-
} else if (typeof value === 'object' && value !== null) {
|
|
40
|
-
const obj = value as Record<string, unknown>
|
|
41
|
-
for (const childKey in obj) {
|
|
42
|
-
set(result, [childKey, key], obj[childKey])
|
|
43
|
-
}
|
|
44
|
-
} else if (value != null) {
|
|
45
|
-
const firstBreakpoint = breakpoints[0]
|
|
46
|
-
if (firstBreakpoint == null) continue
|
|
47
|
-
set(result, [firstBreakpoint, key], value)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return removeUnexpectedKeys(result, breakpoints)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export default transformTheme
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { isEmpty } from '@pyreon/ui-core'
|
|
2
|
-
|
|
3
|
-
export type AlignContentDirectionKeys = keyof typeof ALIGN_CONTENT_DIRECTION
|
|
4
|
-
export type AlignContentAlignXKeys = keyof typeof ALIGN_CONTENT_MAP_X
|
|
5
|
-
export type AlignContentAlignYKeys = keyof typeof ALIGN_CONTENT_MAP_Y
|
|
6
|
-
|
|
7
|
-
const ALIGN_CONTENT_MAP_SHARED = {
|
|
8
|
-
center: 'center',
|
|
9
|
-
spaceBetween: 'space-between',
|
|
10
|
-
spaceAround: 'space-around',
|
|
11
|
-
block: 'stretch',
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const ALIGN_CONTENT_MAP_X = {
|
|
15
|
-
left: 'flex-start',
|
|
16
|
-
right: 'flex-end',
|
|
17
|
-
...ALIGN_CONTENT_MAP_SHARED,
|
|
18
|
-
} as const
|
|
19
|
-
|
|
20
|
-
export const ALIGN_CONTENT_MAP_Y = {
|
|
21
|
-
top: 'flex-start',
|
|
22
|
-
bottom: 'flex-end',
|
|
23
|
-
...ALIGN_CONTENT_MAP_SHARED,
|
|
24
|
-
} as const
|
|
25
|
-
|
|
26
|
-
export const ALIGN_CONTENT_DIRECTION = {
|
|
27
|
-
inline: 'row',
|
|
28
|
-
reverseInline: 'row-reverse',
|
|
29
|
-
rows: 'column',
|
|
30
|
-
reverseRows: 'column-reverse',
|
|
31
|
-
} as const
|
|
32
|
-
|
|
33
|
-
export type AlignContent = ({
|
|
34
|
-
direction,
|
|
35
|
-
alignX,
|
|
36
|
-
alignY,
|
|
37
|
-
}: {
|
|
38
|
-
direction: AlignContentDirectionKeys
|
|
39
|
-
alignX: AlignContentAlignXKeys
|
|
40
|
-
alignY: AlignContentAlignYKeys
|
|
41
|
-
}) => string | null
|
|
42
|
-
|
|
43
|
-
const alignContent: AlignContent = (attrs) => {
|
|
44
|
-
const { direction, alignX, alignY } = attrs
|
|
45
|
-
|
|
46
|
-
if (isEmpty(attrs) || !direction || !alignX || !alignY) {
|
|
47
|
-
return null
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Direct comparisons avoid the per-call 2-element array allocation that
|
|
51
|
-
// `['inline', 'reverseInline'].includes(direction)` paid. Hot path: fires
|
|
52
|
-
// for every styled component with a `direction` prop. Ported from
|
|
53
|
-
// vitus-labs `e573e6c4`.
|
|
54
|
-
const isReverted = direction === 'inline' || direction === 'reverseInline'
|
|
55
|
-
const dir = ALIGN_CONTENT_DIRECTION[direction]
|
|
56
|
-
const x = ALIGN_CONTENT_MAP_X[alignX]
|
|
57
|
-
const y = ALIGN_CONTENT_MAP_Y[alignY]
|
|
58
|
-
|
|
59
|
-
return `flex-direction: ${dir}; align-items: ${isReverted ? y : x}; justify-content: ${isReverted ? x : y};`
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export default alignContent
|
package/src/styles/extendCss.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export type ExtendCss = (
|
|
2
|
-
styles:
|
|
3
|
-
| ((css: (strings: TemplateStringsArray, ...values: any[]) => string) => string)
|
|
4
|
-
| string
|
|
5
|
-
| null
|
|
6
|
-
| undefined,
|
|
7
|
-
) => string
|
|
8
|
-
|
|
9
|
-
const simpleCss = (strings: TemplateStringsArray, ...values: any[]): string => {
|
|
10
|
-
let result = ''
|
|
11
|
-
for (let i = 0; i < strings.length; i++) {
|
|
12
|
-
result += strings[i]
|
|
13
|
-
if (i < values.length) result += String(values[i] ?? '')
|
|
14
|
-
}
|
|
15
|
-
return result
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const extendCss: ExtendCss = (styles) => {
|
|
19
|
-
if (!styles) return ''
|
|
20
|
-
if (typeof styles === 'function') {
|
|
21
|
-
return styles(simpleCss)
|
|
22
|
-
}
|
|
23
|
-
return styles
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default extendCss
|
package/src/styles/index.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
AlignContent,
|
|
3
|
-
AlignContentAlignXKeys,
|
|
4
|
-
AlignContentAlignYKeys,
|
|
5
|
-
AlignContentDirectionKeys,
|
|
6
|
-
} from './alignContent'
|
|
7
|
-
export {
|
|
8
|
-
ALIGN_CONTENT_DIRECTION,
|
|
9
|
-
ALIGN_CONTENT_MAP_X,
|
|
10
|
-
ALIGN_CONTENT_MAP_Y,
|
|
11
|
-
default as alignContent,
|
|
12
|
-
} from './alignContent'
|
|
13
|
-
export type { ExtendCss } from './extendCss'
|
|
14
|
-
export { default as extendCss } from './extendCss'
|
|
15
|
-
export type { ITheme, Styles, StylesTheme } from './styles'
|
|
16
|
-
export { default as styles } from './styles'
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { value } from '../../units'
|
|
2
|
-
|
|
3
|
-
type PropertyValue = string | number | null | undefined
|
|
4
|
-
type PV = PropertyValue
|
|
5
|
-
|
|
6
|
-
const isValidValue = (v: unknown) => !!v || v === 0
|
|
7
|
-
|
|
8
|
-
type CornerValues = {
|
|
9
|
-
full: PV
|
|
10
|
-
top: PV
|
|
11
|
-
bottom: PV
|
|
12
|
-
left: PV
|
|
13
|
-
right: PV
|
|
14
|
-
topLeft: PV
|
|
15
|
-
topRight: PV
|
|
16
|
-
bottomLeft: PV
|
|
17
|
-
bottomRight: PV
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const hasAnyValue = (v: CornerValues) =>
|
|
21
|
-
isValidValue(v.full) ||
|
|
22
|
-
isValidValue(v.top) ||
|
|
23
|
-
isValidValue(v.bottom) ||
|
|
24
|
-
isValidValue(v.left) ||
|
|
25
|
-
isValidValue(v.right) ||
|
|
26
|
-
isValidValue(v.topLeft) ||
|
|
27
|
-
isValidValue(v.topRight) ||
|
|
28
|
-
isValidValue(v.bottomLeft) ||
|
|
29
|
-
isValidValue(v.bottomRight)
|
|
30
|
-
|
|
31
|
-
const resolveCorners = (v: CornerValues) => {
|
|
32
|
-
const corners: PV[] = [v.full, v.full, v.full, v.full]
|
|
33
|
-
if (isValidValue(v.top)) {
|
|
34
|
-
corners[0] = v.top
|
|
35
|
-
corners[1] = v.top
|
|
36
|
-
}
|
|
37
|
-
if (isValidValue(v.bottom)) {
|
|
38
|
-
corners[2] = v.bottom
|
|
39
|
-
corners[3] = v.bottom
|
|
40
|
-
}
|
|
41
|
-
if (isValidValue(v.left)) {
|
|
42
|
-
corners[0] = v.left
|
|
43
|
-
corners[3] = v.left
|
|
44
|
-
}
|
|
45
|
-
if (isValidValue(v.right)) {
|
|
46
|
-
corners[1] = v.right
|
|
47
|
-
corners[2] = v.right
|
|
48
|
-
}
|
|
49
|
-
if (isValidValue(v.topLeft)) corners[0] = v.topLeft
|
|
50
|
-
if (isValidValue(v.topRight)) corners[1] = v.topRight
|
|
51
|
-
if (isValidValue(v.bottomRight)) corners[2] = v.bottomRight
|
|
52
|
-
if (isValidValue(v.bottomLeft)) corners[3] = v.bottomLeft
|
|
53
|
-
return corners
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const formatShorthand = (corners: PV[], calc: (p: PV) => any) => {
|
|
57
|
-
const [tl, tr, br, bl] = corners
|
|
58
|
-
if (corners.every((val, _, arr) => val === arr[0])) return `border-radius: ${calc(tl)};`
|
|
59
|
-
if (tl === br && tr === bl) return `border-radius: ${calc(tl)} ${calc(tr)};`
|
|
60
|
-
if (tl && tr === bl && br) return `border-radius: ${calc(tl)} ${calc(tr)} ${calc(br)};`
|
|
61
|
-
return `border-radius: ${calc(tl)} ${calc(tr)} ${calc(br)} ${calc(bl)};`
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const CORNER_CSS = [
|
|
65
|
-
'border-top-left-radius',
|
|
66
|
-
'border-top-right-radius',
|
|
67
|
-
'border-bottom-right-radius',
|
|
68
|
-
'border-bottom-left-radius',
|
|
69
|
-
] as const
|
|
70
|
-
|
|
71
|
-
const formatIndividual = (corners: PV[], calc: (p: PV) => any) => {
|
|
72
|
-
let output = ''
|
|
73
|
-
for (let i = 0; i < corners.length; i++) {
|
|
74
|
-
if (isValidValue(corners[i])) output += `${CORNER_CSS[i]}: ${calc(corners[i])};`
|
|
75
|
-
}
|
|
76
|
-
return output
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export type BorderRadius = (rootSize?: number) => (props: CornerValues) => string | null
|
|
80
|
-
|
|
81
|
-
const borderRadius: BorderRadius = (rootSize) => (props) => {
|
|
82
|
-
if (!hasAnyValue(props)) return null
|
|
83
|
-
const calc = (param: PV) => value(param, rootSize)
|
|
84
|
-
const corners = resolveCorners(props)
|
|
85
|
-
if (corners.every((val) => isValidValue(val))) return formatShorthand(corners, calc)
|
|
86
|
-
return formatIndividual(corners, calc)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export default borderRadius
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { value } from '../../units'
|
|
2
|
-
|
|
3
|
-
type CssUnits =
|
|
4
|
-
| 'px'
|
|
5
|
-
| 'rem'
|
|
6
|
-
| '%'
|
|
7
|
-
| 'em'
|
|
8
|
-
| 'ex'
|
|
9
|
-
| 'cm'
|
|
10
|
-
| 'mm'
|
|
11
|
-
| 'in'
|
|
12
|
-
| 'pt'
|
|
13
|
-
| 'pc'
|
|
14
|
-
| 'ch'
|
|
15
|
-
| 'vh'
|
|
16
|
-
| 'vw'
|
|
17
|
-
| 'vmin'
|
|
18
|
-
| 'vmax'
|
|
19
|
-
|
|
20
|
-
const isValidValue = (v: unknown) => !!v || v === 0
|
|
21
|
-
|
|
22
|
-
type Property = 'inset' | 'margin' | 'padding' | 'border-width' | 'border-style' | 'border-color'
|
|
23
|
-
type Value = string | number | null | undefined
|
|
24
|
-
type Side = 'top' | 'bottom' | 'left' | 'right'
|
|
25
|
-
|
|
26
|
-
type EdgeValues = {
|
|
27
|
-
full: Value
|
|
28
|
-
x: Value
|
|
29
|
-
y: Value
|
|
30
|
-
top: Value
|
|
31
|
-
left: Value
|
|
32
|
-
right: Value
|
|
33
|
-
bottom: Value
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
type Definitions = Record<Property, { unit?: CssUnits; edgeCss: (side: Side) => string }>
|
|
37
|
-
|
|
38
|
-
const definitions: Definitions = {
|
|
39
|
-
inset: { unit: 'rem', edgeCss: (side) => side },
|
|
40
|
-
margin: { unit: 'rem', edgeCss: (side) => `margin-${side}` },
|
|
41
|
-
padding: { unit: 'rem', edgeCss: (side) => `padding-${side}` },
|
|
42
|
-
'border-width': { unit: 'px', edgeCss: (side) => `border-${side}-width` },
|
|
43
|
-
'border-style': { edgeCss: (side) => `border-${side}-style` },
|
|
44
|
-
'border-color': { edgeCss: (side) => `border-${side}-color` },
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const hasAnyValue = (vals: EdgeValues) =>
|
|
48
|
-
isValidValue(vals.top) ||
|
|
49
|
-
isValidValue(vals.bottom) ||
|
|
50
|
-
isValidValue(vals.left) ||
|
|
51
|
-
isValidValue(vals.right) ||
|
|
52
|
-
isValidValue(vals.x) ||
|
|
53
|
-
isValidValue(vals.y) ||
|
|
54
|
-
isValidValue(vals.full)
|
|
55
|
-
|
|
56
|
-
const resolveSides = ({ full, x, y, top, left, right, bottom }: EdgeValues) => {
|
|
57
|
-
const sides: Value[] = [full, full, full, full]
|
|
58
|
-
if (isValidValue(x)) {
|
|
59
|
-
sides[1] = x
|
|
60
|
-
sides[3] = x
|
|
61
|
-
}
|
|
62
|
-
if (isValidValue(y)) {
|
|
63
|
-
sides[0] = y
|
|
64
|
-
sides[2] = y
|
|
65
|
-
}
|
|
66
|
-
if (isValidValue(top)) sides[0] = top
|
|
67
|
-
if (isValidValue(right)) sides[1] = right
|
|
68
|
-
if (isValidValue(bottom)) sides[2] = bottom
|
|
69
|
-
if (isValidValue(left)) sides[3] = left
|
|
70
|
-
return sides
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const formatShorthand = (property: Property, sides: Value[], calc: (v: Value) => Value) => {
|
|
74
|
-
const [t, r, b, l] = sides
|
|
75
|
-
if (sides.every((val, _, arr) => val === arr[0])) return `${property}: ${calc(t)};`
|
|
76
|
-
if (t === b && r === l) return `${property}: ${calc(t)} ${calc(r)};`
|
|
77
|
-
if (t && r === l && b) return `${property}: ${calc(t)} ${calc(r)} ${calc(b)};`
|
|
78
|
-
return `${property}: ${calc(t)} ${calc(r)} ${calc(b)} ${calc(l)};`
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const formatIndividual = (
|
|
82
|
-
sides: Value[],
|
|
83
|
-
edgeCss: (side: Side) => string,
|
|
84
|
-
calc: (v: Value) => Value,
|
|
85
|
-
) => {
|
|
86
|
-
const [t, r, b, l] = sides
|
|
87
|
-
let output = ''
|
|
88
|
-
if (isValidValue(t)) output += `${edgeCss('top')}: ${calc(t)};`
|
|
89
|
-
if (isValidValue(b)) output += `${edgeCss('bottom')}: ${calc(b)};`
|
|
90
|
-
if (isValidValue(l)) output += `${edgeCss('left')}: ${calc(l)};`
|
|
91
|
-
if (isValidValue(r)) output += `${edgeCss('right')}: ${calc(r)};`
|
|
92
|
-
return output
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export type Edge = (rootSize?: number) => (property: Property, values: EdgeValues) => string | null
|
|
96
|
-
|
|
97
|
-
const edge: Edge =
|
|
98
|
-
(rootSize = 16) =>
|
|
99
|
-
(property, values) => {
|
|
100
|
-
if (!hasAnyValue(values)) return null
|
|
101
|
-
const { unit, edgeCss } = definitions[property]
|
|
102
|
-
const calc = (param: Value) => (unit ? value(param, rootSize, unit) : param)
|
|
103
|
-
const sides = resolveSides(values)
|
|
104
|
-
if (sides.every((val) => isValidValue(val))) return formatShorthand(property, sides, calc)
|
|
105
|
-
return formatIndividual(sides, edgeCss, calc)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export default edge
|