@charcoal-ui/styled 2.3.0 → 2.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.
- package/dist/builders/border.d.ts +10 -0
- package/dist/builders/border.d.ts.map +1 -0
- package/dist/builders/borderRadius.d.ts +7 -0
- package/dist/builders/borderRadius.d.ts.map +1 -0
- package/dist/builders/colors.d.ts +13 -0
- package/dist/builders/colors.d.ts.map +1 -0
- package/dist/builders/elementEffect.d.ts +7 -0
- package/dist/builders/elementEffect.d.ts.map +1 -0
- package/dist/builders/o.d.ts +115 -0
- package/dist/builders/o.d.ts.map +1 -0
- package/dist/builders/outline.d.ts +10 -0
- package/dist/builders/outline.d.ts.map +1 -0
- package/dist/builders/size.d.ts +23 -0
- package/dist/builders/size.d.ts.map +1 -0
- package/dist/builders/spacing.d.ts +15 -0
- package/dist/builders/spacing.d.ts.map +1 -0
- package/dist/builders/transition.d.ts +7 -0
- package/dist/builders/transition.d.ts.map +1 -0
- package/dist/builders/typography.d.ts +11 -0
- package/dist/builders/typography.d.ts.map +1 -0
- package/dist/{lib.d.ts → factories/lib.d.ts} +13 -14
- package/dist/factories/lib.d.ts.map +1 -0
- package/dist/index.cjs +765 -643
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +91 -30
- package/dist/index.d.ts.map +1 -1
- package/dist/index.modern.js +555 -393
- package/dist/index.modern.js.map +1 -1
- package/dist/index.module.js +765 -643
- package/dist/index.module.js.map +1 -1
- package/dist/index.story.d.ts +1 -0
- package/dist/index.story.d.ts.map +1 -1
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/internals/index.d.ts +42 -0
- package/dist/internals/index.d.ts.map +1 -0
- package/dist/util.d.ts +36 -2
- package/dist/util.d.ts.map +1 -1
- package/package.json +8 -5
- package/src/__snapshots__/index.test.tsx.snap +768 -0
- package/src/builders/border.ts +63 -0
- package/src/builders/borderRadius.ts +32 -0
- package/src/builders/colors.ts +198 -0
- package/src/builders/elementEffect.ts +54 -0
- package/src/builders/o.ts +43 -0
- package/src/builders/outline.ts +79 -0
- package/src/builders/size.ts +61 -0
- package/src/builders/spacing.ts +113 -0
- package/src/builders/transition.ts +32 -0
- package/src/builders/typography.ts +97 -0
- package/src/{lib.ts → factories/lib.ts} +30 -25
- package/src/index.story.tsx +2 -2
- package/src/index.test.tsx +24 -0
- package/src/index.ts +47 -696
- package/src/internals/index.ts +84 -0
- package/src/util.ts +46 -3
- package/dist/lib.d.ts.map +0 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CharcoalAbstractTheme } from '@charcoal-ui/theme'
|
|
2
|
+
import { CSSObject } from 'styled-components'
|
|
3
|
+
import { keyof } from '../util'
|
|
4
|
+
import { Internal, createInternal } from '../internals'
|
|
5
|
+
import {
|
|
6
|
+
defineConstantProperties,
|
|
7
|
+
defineProperties,
|
|
8
|
+
definePropertyChains,
|
|
9
|
+
} from '../factories/lib'
|
|
10
|
+
|
|
11
|
+
export const borderDirections = ['top', 'right', 'bottom', 'left'] as const
|
|
12
|
+
type BorderDirection = typeof borderDirections[number]
|
|
13
|
+
|
|
14
|
+
function borderProperty(direction: BorderDirection) {
|
|
15
|
+
return `border-${direction}`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function borderShorthand(color: string) {
|
|
19
|
+
return `solid 1px ${color}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const createBorderCss =
|
|
23
|
+
<T extends CharcoalAbstractTheme>(theme: T) =>
|
|
24
|
+
(
|
|
25
|
+
variant: keyof T['border'],
|
|
26
|
+
directions: readonly BorderDirection[]
|
|
27
|
+
): Internal => {
|
|
28
|
+
const all = directions.length === 0
|
|
29
|
+
const value = borderShorthand(theme.border[variant].color)
|
|
30
|
+
|
|
31
|
+
return createInternal({
|
|
32
|
+
toCSS() {
|
|
33
|
+
return {
|
|
34
|
+
...(all
|
|
35
|
+
? { border: value }
|
|
36
|
+
: directions.reduce<CSSObject>(
|
|
37
|
+
(acc, direction) => ({
|
|
38
|
+
...acc,
|
|
39
|
+
[borderProperty(direction)]: value,
|
|
40
|
+
}),
|
|
41
|
+
{}
|
|
42
|
+
)),
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default function border<T extends CharcoalAbstractTheme>(theme: T) {
|
|
49
|
+
const borderTypes = keyof<T['border']>(theme.border)
|
|
50
|
+
|
|
51
|
+
const borderCss = createBorderCss(theme)
|
|
52
|
+
const borderObject = defineConstantProperties(
|
|
53
|
+
{},
|
|
54
|
+
{
|
|
55
|
+
border: defineProperties({}, borderTypes, (variant) =>
|
|
56
|
+
definePropertyChains(borderDirections, (modifiers) =>
|
|
57
|
+
borderCss(variant, modifiers)
|
|
58
|
+
)
|
|
59
|
+
),
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
return borderObject
|
|
63
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CharcoalAbstractTheme } from '@charcoal-ui/theme'
|
|
2
|
+
import { px } from '@charcoal-ui/utils'
|
|
3
|
+
import { Internal, createInternal } from '../internals'
|
|
4
|
+
import { defineConstantProperties } from '../factories/lib'
|
|
5
|
+
|
|
6
|
+
export const createBorderRadiusCss =
|
|
7
|
+
<T extends CharcoalAbstractTheme>(theme: T) =>
|
|
8
|
+
(size: keyof T['borderRadius']): Internal => {
|
|
9
|
+
return createInternal({
|
|
10
|
+
toCSS() {
|
|
11
|
+
return {
|
|
12
|
+
borderRadius: px(theme.borderRadius[size]),
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default function borderRadius<T extends CharcoalAbstractTheme>(
|
|
19
|
+
theme: T
|
|
20
|
+
) {
|
|
21
|
+
// 角丸
|
|
22
|
+
const borderRadiusCss = createBorderRadiusCss(theme)
|
|
23
|
+
const borderRadiusObject = defineConstantProperties(
|
|
24
|
+
{},
|
|
25
|
+
{
|
|
26
|
+
borderRadius: (radius: keyof T['borderRadius']) =>
|
|
27
|
+
borderRadiusCss(radius),
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return borderRadiusObject
|
|
32
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { CharcoalAbstractTheme } from '@charcoal-ui/theme'
|
|
2
|
+
import {
|
|
3
|
+
applyEffect,
|
|
4
|
+
applyEffectToGradient,
|
|
5
|
+
customPropertyToken,
|
|
6
|
+
dur,
|
|
7
|
+
gradient,
|
|
8
|
+
GradientDirection,
|
|
9
|
+
} from '@charcoal-ui/utils'
|
|
10
|
+
import { CSSObject } from 'styled-components'
|
|
11
|
+
import warning from 'warning'
|
|
12
|
+
import {
|
|
13
|
+
keyof,
|
|
14
|
+
objectAssign,
|
|
15
|
+
isSupportedEffect,
|
|
16
|
+
onEffectPseudo,
|
|
17
|
+
variable,
|
|
18
|
+
} from '../util'
|
|
19
|
+
import {
|
|
20
|
+
createInternal,
|
|
21
|
+
Internal,
|
|
22
|
+
Context,
|
|
23
|
+
shouldCancelHalfLeading,
|
|
24
|
+
} from '../internals'
|
|
25
|
+
import {
|
|
26
|
+
defineConstantProperties,
|
|
27
|
+
defineProperties,
|
|
28
|
+
definePropertyChains,
|
|
29
|
+
} from '../factories/lib'
|
|
30
|
+
import { TRANSITION_DURATION } from './transition'
|
|
31
|
+
|
|
32
|
+
const colorProperties = ['bg', 'font'] as const
|
|
33
|
+
export type ColorProperty = typeof colorProperties[number]
|
|
34
|
+
|
|
35
|
+
function targetProperty(target: ColorProperty) {
|
|
36
|
+
return target === 'bg' ? 'background-color' : 'color'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const createColorCss =
|
|
40
|
+
<T extends CharcoalAbstractTheme>(_theme: T) =>
|
|
41
|
+
(
|
|
42
|
+
target: ColorProperty,
|
|
43
|
+
color: keyof T['color'],
|
|
44
|
+
effects: readonly (keyof T['effect'])[] = []
|
|
45
|
+
): Internal => {
|
|
46
|
+
function toCSS() {
|
|
47
|
+
return {
|
|
48
|
+
[targetProperty(target)]: variable(
|
|
49
|
+
customPropertyToken(color.toString())
|
|
50
|
+
),
|
|
51
|
+
...effects.filter(isSupportedEffect).reduce<CSSObject>(
|
|
52
|
+
(acc, effect) => ({
|
|
53
|
+
...acc,
|
|
54
|
+
...onEffectPseudo(effect, {
|
|
55
|
+
[targetProperty(target)]: variable(
|
|
56
|
+
customPropertyToken(color.toString(), [effect])
|
|
57
|
+
),
|
|
58
|
+
}),
|
|
59
|
+
}),
|
|
60
|
+
{}
|
|
61
|
+
),
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return createInternal({
|
|
66
|
+
toCSS,
|
|
67
|
+
context:
|
|
68
|
+
effects.length > 0
|
|
69
|
+
? target === 'font'
|
|
70
|
+
? {
|
|
71
|
+
colorTransition: true,
|
|
72
|
+
}
|
|
73
|
+
: {
|
|
74
|
+
backgroundColorTransition: true,
|
|
75
|
+
}
|
|
76
|
+
: {},
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const createGradientColorCss =
|
|
81
|
+
<T extends CharcoalAbstractTheme>(theme: T) =>
|
|
82
|
+
(
|
|
83
|
+
color: keyof T['gradientColor'],
|
|
84
|
+
effects: readonly (keyof T['effect'])[] = [],
|
|
85
|
+
direction: GradientDirection
|
|
86
|
+
): Internal => {
|
|
87
|
+
const toLinearGradient = gradient(direction)
|
|
88
|
+
|
|
89
|
+
function toCSS(context: Context): CSSObject {
|
|
90
|
+
const optimized = !shouldCancelHalfLeading(context)
|
|
91
|
+
const duration = dur(TRANSITION_DURATION)
|
|
92
|
+
|
|
93
|
+
if (optimized && effects.length > 0) {
|
|
94
|
+
return {
|
|
95
|
+
position: 'relative',
|
|
96
|
+
zIndex: 0,
|
|
97
|
+
overflow: 'hidden',
|
|
98
|
+
...effects.filter(isSupportedEffect).reduce<CSSObject>(
|
|
99
|
+
(acc, effect) => ({
|
|
100
|
+
...acc,
|
|
101
|
+
'&::before': {
|
|
102
|
+
zIndex: -1,
|
|
103
|
+
...overlayElement,
|
|
104
|
+
transition: `${duration} background-color`,
|
|
105
|
+
},
|
|
106
|
+
'&::after': {
|
|
107
|
+
zIndex: -2,
|
|
108
|
+
...overlayElement,
|
|
109
|
+
...toLinearGradient(theme.gradientColor[color]),
|
|
110
|
+
},
|
|
111
|
+
...onEffectPseudo(effect, {
|
|
112
|
+
'&::before': {
|
|
113
|
+
backgroundColor: applyEffect(
|
|
114
|
+
null,
|
|
115
|
+
theme.effect[effect] ?? []
|
|
116
|
+
),
|
|
117
|
+
},
|
|
118
|
+
}),
|
|
119
|
+
}),
|
|
120
|
+
{}
|
|
121
|
+
),
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
warning(
|
|
126
|
+
effects.length === 0,
|
|
127
|
+
// eslint-disable-next-line max-len
|
|
128
|
+
`'Transition' will not be applied. You can get around this by specifying 'preserveHalfLeading' or both 'padding' and 'typograpy'.`
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
...toLinearGradient(theme.gradientColor[color]),
|
|
133
|
+
...effects.filter(isSupportedEffect).reduce<CSSObject>(
|
|
134
|
+
(acc, effect) => ({
|
|
135
|
+
...acc,
|
|
136
|
+
...onEffectPseudo(effect, {
|
|
137
|
+
...toLinearGradient(
|
|
138
|
+
applyEffectToGradient(theme.effect[effect] ?? [])(
|
|
139
|
+
theme.gradientColor[color]
|
|
140
|
+
)
|
|
141
|
+
),
|
|
142
|
+
}),
|
|
143
|
+
}),
|
|
144
|
+
{}
|
|
145
|
+
),
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return createInternal({ toCSS })
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const overlayElement: CSSObject = {
|
|
153
|
+
content: "''",
|
|
154
|
+
display: 'block',
|
|
155
|
+
position: 'absolute',
|
|
156
|
+
width: '100%',
|
|
157
|
+
height: '100%',
|
|
158
|
+
top: 0,
|
|
159
|
+
left: 0,
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export default function colors<T extends CharcoalAbstractTheme>(theme: T) {
|
|
163
|
+
const colors = keyof<T['color']>(theme.color)
|
|
164
|
+
const effects = keyof<T['effect']>(theme.effect)
|
|
165
|
+
|
|
166
|
+
// 色
|
|
167
|
+
const gradientColors = keyof<T['gradientColor']>(theme.gradientColor)
|
|
168
|
+
const colorCss = createColorCss(theme)
|
|
169
|
+
const gradientColorCss = createGradientColorCss(theme)
|
|
170
|
+
|
|
171
|
+
const colorObject = defineConstantProperties(
|
|
172
|
+
{},
|
|
173
|
+
{
|
|
174
|
+
bg: objectAssign(
|
|
175
|
+
defineProperties({}, colors, (color) =>
|
|
176
|
+
definePropertyChains(effects, (modifiers) =>
|
|
177
|
+
colorCss('bg', color, modifiers)
|
|
178
|
+
)
|
|
179
|
+
),
|
|
180
|
+
defineProperties(
|
|
181
|
+
{},
|
|
182
|
+
gradientColors,
|
|
183
|
+
(color) => (direction: GradientDirection) =>
|
|
184
|
+
definePropertyChains(effects, (modifiers) =>
|
|
185
|
+
gradientColorCss(color, modifiers, direction)
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
),
|
|
189
|
+
font: defineProperties({}, colors, (color) =>
|
|
190
|
+
definePropertyChains(effects, (modifiers) =>
|
|
191
|
+
colorCss('font', color, modifiers)
|
|
192
|
+
)
|
|
193
|
+
),
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return colorObject
|
|
198
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { CharcoalAbstractTheme, EffectType } from '@charcoal-ui/theme'
|
|
2
|
+
import { CSSObject } from 'styled-components'
|
|
3
|
+
import {
|
|
4
|
+
isSupportedEffect,
|
|
5
|
+
keyof,
|
|
6
|
+
onEffectPseudo,
|
|
7
|
+
ReadonlyArrayConstructor,
|
|
8
|
+
unreachable,
|
|
9
|
+
} from '../util'
|
|
10
|
+
import { Internal, createInternal } from '../internals'
|
|
11
|
+
import { definePropertyChains } from '../factories/lib'
|
|
12
|
+
|
|
13
|
+
export const createElementEffectCss =
|
|
14
|
+
<
|
|
15
|
+
T extends CharcoalAbstractTheme,
|
|
16
|
+
TElementEffect extends T['elementEffect']
|
|
17
|
+
>(theme: {
|
|
18
|
+
elementEffect: TElementEffect
|
|
19
|
+
}) =>
|
|
20
|
+
(effects: readonly (keyof TElementEffect)[] = []): Internal =>
|
|
21
|
+
createInternal({
|
|
22
|
+
toCSS() {
|
|
23
|
+
return effects.filter(isSupportedEffect).reduce<CSSObject>(
|
|
24
|
+
(acc, effect) => ({
|
|
25
|
+
...acc,
|
|
26
|
+
...onEffectPseudo(effect, {
|
|
27
|
+
opacity:
|
|
28
|
+
!(Array as ReadonlyArrayConstructor).isArray(
|
|
29
|
+
theme.elementEffect[effect]
|
|
30
|
+
) && theme.elementEffect[effect]?.type === 'opacity'
|
|
31
|
+
? theme.elementEffect[effect]?.opacity
|
|
32
|
+
: unreachable(),
|
|
33
|
+
}),
|
|
34
|
+
}),
|
|
35
|
+
{}
|
|
36
|
+
)
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
export default function elementEffect<T extends CharcoalAbstractTheme>(
|
|
41
|
+
theme: T
|
|
42
|
+
) {
|
|
43
|
+
const effectTypes = keyof<T['elementEffect']>(
|
|
44
|
+
theme.elementEffect
|
|
45
|
+
) as EffectType[]
|
|
46
|
+
|
|
47
|
+
// 要素へのエフェクト (etc: 透過)
|
|
48
|
+
const elementEffectCss = createElementEffectCss(theme)
|
|
49
|
+
const elementEffectObject = definePropertyChains(effectTypes, (modifiers) =>
|
|
50
|
+
elementEffectCss(modifiers)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
return elementEffectObject
|
|
54
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CharcoalAbstractTheme } from '@charcoal-ui/theme'
|
|
2
|
+
import { objectAssign } from '../util'
|
|
3
|
+
import border from './border'
|
|
4
|
+
import borderRadius from './borderRadius'
|
|
5
|
+
import colors from './colors'
|
|
6
|
+
import elementEffect from './elementEffect'
|
|
7
|
+
import outline from './outline'
|
|
8
|
+
import size from './size'
|
|
9
|
+
import spacing from './spacing'
|
|
10
|
+
import typography from './typography'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* `theme(o => [...])` の `o` の部分を構築する
|
|
14
|
+
*
|
|
15
|
+
* @param theme テーマオブジェクト
|
|
16
|
+
* @param DO_NOTHING_IT_IS_JUST_CALLED_FOR_TYPE_INFERENCE 型推論のためだけに使う場合にランタイムコストをゼロにするフラグ
|
|
17
|
+
*/
|
|
18
|
+
export default function createO<T extends CharcoalAbstractTheme>(
|
|
19
|
+
theme: {
|
|
20
|
+
// factoryの第二引数に入れ込むものだけ明示的に型変数を展開しておくことで型の具象化を遅延する
|
|
21
|
+
color: T['color']
|
|
22
|
+
gradientColor: T['gradientColor']
|
|
23
|
+
border: T['border']
|
|
24
|
+
outline: T['outline']
|
|
25
|
+
} & Omit<T, 'color' | 'gradientColor' | 'border' | 'outline'>,
|
|
26
|
+
DO_NOTHING_IT_IS_JUST_CALLED_FOR_TYPE_INFERENCE = false
|
|
27
|
+
) {
|
|
28
|
+
if (DO_NOTHING_IT_IS_JUST_CALLED_FOR_TYPE_INFERENCE) {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
30
|
+
return {} as never
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return objectAssign(
|
|
34
|
+
colors(theme),
|
|
35
|
+
typography(theme),
|
|
36
|
+
spacing(theme),
|
|
37
|
+
size(theme),
|
|
38
|
+
elementEffect(theme),
|
|
39
|
+
border(theme),
|
|
40
|
+
borderRadius(theme),
|
|
41
|
+
outline(theme)
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { CharcoalAbstractTheme } from '@charcoal-ui/theme'
|
|
2
|
+
import { px, notDisabledSelector } from '@charcoal-ui/utils'
|
|
3
|
+
import { CSSObject } from 'styled-components'
|
|
4
|
+
import { keyof } from '../util'
|
|
5
|
+
import { Internal, createInternal } from '../internals'
|
|
6
|
+
import {
|
|
7
|
+
defineConstantProperties,
|
|
8
|
+
defineProperties,
|
|
9
|
+
definePropertyChains,
|
|
10
|
+
} from '../factories/lib'
|
|
11
|
+
|
|
12
|
+
export const outlineType = ['focus'] as const
|
|
13
|
+
type OutlineType = typeof outlineType[number]
|
|
14
|
+
|
|
15
|
+
const outlineCss = (weight: number, color: string) => ({
|
|
16
|
+
boxShadow: `0 0 0 ${px(weight)} ${color}`,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export const createOutlineColorCss =
|
|
20
|
+
<T extends CharcoalAbstractTheme>(theme: T) =>
|
|
21
|
+
(
|
|
22
|
+
variant: keyof T['outline'],
|
|
23
|
+
modifiers: readonly OutlineType[]
|
|
24
|
+
): Internal => {
|
|
25
|
+
const weight = theme.outline[variant].weight
|
|
26
|
+
const color = theme.outline[variant].color
|
|
27
|
+
|
|
28
|
+
return createInternal({
|
|
29
|
+
toCSS() {
|
|
30
|
+
return modifiers.includes('focus')
|
|
31
|
+
? onFocus(outlineCss(weight, color))
|
|
32
|
+
: { '&&': { [notDisabledSelector]: outlineCss(weight, color) } }
|
|
33
|
+
},
|
|
34
|
+
context: {
|
|
35
|
+
boxShadowTransition: true,
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @see https://developer.mozilla.org/ja/docs/Web/CSS/:focus-visible#selectively_showing_the_focus_indicator
|
|
42
|
+
*/
|
|
43
|
+
const onFocus = (css: CSSObject) => ({
|
|
44
|
+
[notDisabledSelector]: {
|
|
45
|
+
'&:focus, &:active': {
|
|
46
|
+
outline: 'none',
|
|
47
|
+
...css,
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
'&:focus:not(:focus-visible), &:active:not(:focus-visible)': {
|
|
51
|
+
outline: 'none',
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
'&:focus-visible': {
|
|
55
|
+
outline: 'none',
|
|
56
|
+
...css,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
export default function outline<T extends CharcoalAbstractTheme>(theme: T) {
|
|
62
|
+
const outlineCss = createOutlineColorCss(theme)
|
|
63
|
+
|
|
64
|
+
const outlineObject = defineConstantProperties(
|
|
65
|
+
{},
|
|
66
|
+
{
|
|
67
|
+
outline: defineProperties(
|
|
68
|
+
{},
|
|
69
|
+
keyof<T['outline']>(theme.outline),
|
|
70
|
+
(variant) =>
|
|
71
|
+
definePropertyChains(outlineType, (modifiers) =>
|
|
72
|
+
outlineCss(variant, modifiers)
|
|
73
|
+
)
|
|
74
|
+
),
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return outlineObject
|
|
79
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { columnSystem } from '@charcoal-ui/foundation'
|
|
2
|
+
import { CharcoalAbstractTheme } from '@charcoal-ui/theme'
|
|
3
|
+
import { px } from '@charcoal-ui/utils'
|
|
4
|
+
import { Internal, createInternal } from '../internals'
|
|
5
|
+
import { defineProperties, defineConstantProperties } from '../factories/lib'
|
|
6
|
+
|
|
7
|
+
export const fixedProperties = ['width', 'height'] as const
|
|
8
|
+
type FixedProperty = typeof fixedProperties[number]
|
|
9
|
+
|
|
10
|
+
export const createFixedPxCss =
|
|
11
|
+
<T extends CharcoalAbstractTheme>(theme: T) =>
|
|
12
|
+
(property: FixedProperty, size: keyof T['spacing'] | 'auto'): Internal =>
|
|
13
|
+
createInternal({
|
|
14
|
+
toCSS() {
|
|
15
|
+
return {
|
|
16
|
+
[property]: size === 'auto' ? 'auto' : px(theme.spacing[size]),
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
export const createFixedRelativeCss =
|
|
22
|
+
<T extends CharcoalAbstractTheme>(_theme: T) =>
|
|
23
|
+
(property: FixedProperty, amount: '100%' | 'auto'): Internal =>
|
|
24
|
+
createInternal({
|
|
25
|
+
toCSS() {
|
|
26
|
+
return {
|
|
27
|
+
[property]: amount,
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export const createFixedColumnCss =
|
|
33
|
+
<T extends CharcoalAbstractTheme>(theme: T) =>
|
|
34
|
+
(property: FixedProperty, span: number): Internal =>
|
|
35
|
+
createInternal({
|
|
36
|
+
toCSS() {
|
|
37
|
+
return {
|
|
38
|
+
[property]: px(
|
|
39
|
+
columnSystem(span, theme.grid.unit.column, theme.grid.unit.gutter)
|
|
40
|
+
),
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
export default function size<T extends CharcoalAbstractTheme>(theme: T) {
|
|
46
|
+
const fixedPxCss = createFixedPxCss(theme)
|
|
47
|
+
const fixedColumnCss = createFixedColumnCss(theme)
|
|
48
|
+
const fixedRelativeCss = createFixedRelativeCss(theme)
|
|
49
|
+
const fixedObject = defineProperties({}, fixedProperties, (property) =>
|
|
50
|
+
defineConstantProperties(
|
|
51
|
+
{},
|
|
52
|
+
{
|
|
53
|
+
px: (size: keyof T['spacing'] | 'auto') => fixedPxCss(property, size),
|
|
54
|
+
column: (span: number) => fixedColumnCss(property, span),
|
|
55
|
+
auto: fixedRelativeCss(property, 'auto'),
|
|
56
|
+
full: fixedRelativeCss(property, '100%'),
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
return fixedObject
|
|
61
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { CharcoalAbstractTheme } from '@charcoal-ui/theme'
|
|
2
|
+
import { px } from '@charcoal-ui/utils'
|
|
3
|
+
import { CSSObject } from 'styled-components'
|
|
4
|
+
import { Internal, createInternal, Context } from '../internals'
|
|
5
|
+
import { defineProperties, defineMethodChains } from '../factories/lib'
|
|
6
|
+
|
|
7
|
+
export const spacingProperties = ['margin', 'padding'] as const
|
|
8
|
+
export const spacingDirections = [
|
|
9
|
+
'top',
|
|
10
|
+
'right',
|
|
11
|
+
'bottom',
|
|
12
|
+
'left',
|
|
13
|
+
'vertical',
|
|
14
|
+
'horizontal',
|
|
15
|
+
'all',
|
|
16
|
+
] as const
|
|
17
|
+
type SpacingProperty = typeof spacingProperties[number]
|
|
18
|
+
type SpacingDirection = typeof spacingDirections[number]
|
|
19
|
+
|
|
20
|
+
function spacingProperty(
|
|
21
|
+
property: SpacingProperty,
|
|
22
|
+
direction: 'top' | 'right' | 'bottom' | 'left'
|
|
23
|
+
) {
|
|
24
|
+
return `${property}-${direction}`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const createSpacingCss =
|
|
28
|
+
<T extends CharcoalAbstractTheme>(theme: { spacing: T['spacing'] }) =>
|
|
29
|
+
(
|
|
30
|
+
property: SpacingProperty,
|
|
31
|
+
modifiers: readonly [SpacingDirection, keyof T['spacing'] | 'auto'][]
|
|
32
|
+
): Internal => {
|
|
33
|
+
const { top, right, bottom, left } = modifiers.reduce(
|
|
34
|
+
(acc, [direction, size]) => {
|
|
35
|
+
if (direction === 'all') {
|
|
36
|
+
acc.top = size
|
|
37
|
+
acc.right = size
|
|
38
|
+
acc.bottom = size
|
|
39
|
+
acc.left = size
|
|
40
|
+
} else if (direction === 'vertical') {
|
|
41
|
+
acc.top = size
|
|
42
|
+
acc.bottom = size
|
|
43
|
+
} else if (direction === 'horizontal') {
|
|
44
|
+
acc.right = size
|
|
45
|
+
acc.left = size
|
|
46
|
+
} else {
|
|
47
|
+
acc[direction] = size
|
|
48
|
+
}
|
|
49
|
+
return acc
|
|
50
|
+
},
|
|
51
|
+
{} as Partial<
|
|
52
|
+
Record<'top' | 'right' | 'bottom' | 'left', keyof T['spacing'] | 'auto'>
|
|
53
|
+
>
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
const hasVerticalPadding =
|
|
57
|
+
property === 'padding' &&
|
|
58
|
+
top !== undefined &&
|
|
59
|
+
bottom !== undefined &&
|
|
60
|
+
top !== 'auto' &&
|
|
61
|
+
bottom !== 'auto'
|
|
62
|
+
|
|
63
|
+
function toCSS({ cancelHalfLeadingPx = 0 }: Context): CSSObject {
|
|
64
|
+
return {
|
|
65
|
+
...(top !== undefined && {
|
|
66
|
+
[spacingProperty(property, 'top')]:
|
|
67
|
+
top === 'auto'
|
|
68
|
+
? 'auto'
|
|
69
|
+
: px(
|
|
70
|
+
theme.spacing[top] +
|
|
71
|
+
(hasVerticalPadding ? cancelHalfLeadingPx : 0)
|
|
72
|
+
),
|
|
73
|
+
}),
|
|
74
|
+
...(bottom !== undefined && {
|
|
75
|
+
[spacingProperty(property, 'bottom')]:
|
|
76
|
+
bottom === 'auto'
|
|
77
|
+
? 'auto'
|
|
78
|
+
: px(
|
|
79
|
+
theme.spacing[bottom] +
|
|
80
|
+
(hasVerticalPadding ? cancelHalfLeadingPx : 0)
|
|
81
|
+
),
|
|
82
|
+
}),
|
|
83
|
+
...(right !== undefined && {
|
|
84
|
+
[spacingProperty(property, 'right')]:
|
|
85
|
+
right === 'auto' ? 'auto' : px(theme.spacing[right]),
|
|
86
|
+
}),
|
|
87
|
+
...(left !== undefined && {
|
|
88
|
+
[spacingProperty(property, 'left')]:
|
|
89
|
+
left === 'auto' ? 'auto' : px(theme.spacing[left]),
|
|
90
|
+
}),
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return createInternal({
|
|
95
|
+
toCSS,
|
|
96
|
+
context: hasVerticalPadding ? { hasVerticalPadding: true } : {},
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default function spacing<T extends CharcoalAbstractTheme>(theme: T) {
|
|
101
|
+
const spacingCss = createSpacingCss(theme)
|
|
102
|
+
const spacingObject = defineProperties(
|
|
103
|
+
{},
|
|
104
|
+
spacingProperties,
|
|
105
|
+
(spacingProperty) =>
|
|
106
|
+
defineMethodChains(
|
|
107
|
+
spacingDirections,
|
|
108
|
+
(modifiers) => spacingCss(spacingProperty, modifiers),
|
|
109
|
+
{} as keyof T['spacing'] | 'auto' // 推論のためのメタタイプ
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
return spacingObject
|
|
113
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { dur } from '@charcoal-ui/utils'
|
|
2
|
+
import { isPresent } from '../util'
|
|
3
|
+
import { Internal, createInternal, Context } from '../internals'
|
|
4
|
+
|
|
5
|
+
// TODO: deprecate
|
|
6
|
+
export const TRANSITION_DURATION = 0.2
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* context の状態を元に transition を追加する。必ず一番最後に呼ぶ
|
|
10
|
+
*/
|
|
11
|
+
export default function transition(_theme: unknown): Internal {
|
|
12
|
+
const duration = dur(TRANSITION_DURATION)
|
|
13
|
+
const transition = (property: string[]) => ({
|
|
14
|
+
transition: property.map((v) => `${duration} ${v}`).join(', '),
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
function toCSS({
|
|
18
|
+
colorTransition = false,
|
|
19
|
+
backgroundColorTransition = false,
|
|
20
|
+
boxShadowTransition = false,
|
|
21
|
+
}: Context) {
|
|
22
|
+
return transition(
|
|
23
|
+
[
|
|
24
|
+
colorTransition ? 'color' : null,
|
|
25
|
+
backgroundColorTransition ? 'background-color' : null,
|
|
26
|
+
boxShadowTransition ? 'box-shadow' : null,
|
|
27
|
+
].filter(isPresent)
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return createInternal({ toCSS })
|
|
32
|
+
}
|