@ui0/theme 0.0.0-stage → 0.1.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/README.md +113 -2
- package/dist/backdrop.module.css +1 -0
- package/dist/backdrop.scss +7 -0
- package/dist/color.inject.module.css +7 -0
- package/dist/color.module.css +3 -0
- package/dist/color.scss +84 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +53 -0
- package/dist/components/style.css +1 -0
- package/dist/components/theme-provider.keys.d.ts +4 -0
- package/dist/components/theme-provider.keys.d.ts.map +1 -0
- package/dist/components/theme-provider.module.css +1 -0
- package/dist/components/theme-provider.types.d.ts +18 -0
- package/dist/components/theme-provider.types.d.ts.map +1 -0
- package/dist/components/theme-provider.vue.d.ts +19 -0
- package/dist/config.default.d.mts +4 -0
- package/dist/config.default.d.mts.map +1 -0
- package/dist/config.default.mjs +73 -0
- package/dist/config.default.mjs.map +1 -0
- package/dist/disabled.inject.module.css +5 -0
- package/dist/disabled.module.css +1 -0
- package/dist/disabled.scss +3 -0
- package/dist/display.module.css +2 -0
- package/dist/display.scss +63 -0
- package/dist/duration.scss +17 -0
- package/dist/elevation.module.css +33 -0
- package/dist/elevation.scss +46 -0
- package/dist/generate-BPYE5ALG.mjs +1037 -0
- package/dist/generate-BPYE5ALG.mjs.map +1 -0
- package/dist/generator/cli.d.mts +1 -0
- package/dist/generator/cli.mjs +103 -0
- package/dist/generator/cli.mjs.map +1 -0
- package/dist/generator/vite.d.mts +18 -0
- package/dist/generator/vite.d.mts.map +1 -0
- package/dist/generator/vite.mjs +117 -0
- package/dist/generator/vite.mjs.map +1 -0
- package/dist/index.d.mts +339 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +909 -0
- package/dist/index.mjs.map +1 -0
- package/dist/is.scss +185 -0
- package/dist/load-config-64q6nzFy.mjs +48 -0
- package/dist/load-config-64q6nzFy.mjs.map +1 -0
- package/dist/ripple.scss +57 -0
- package/dist/round.inject.module.css +92 -0
- package/dist/round.module.css +14 -0
- package/dist/round.scss +90 -0
- package/dist/size.inject.module.css +50 -0
- package/dist/size.module.css +13 -0
- package/dist/size.scss +28 -0
- package/dist/theme.scss +16 -0
- package/dist/typography.inject.module.css +81 -0
- package/dist/typography.module.css +32 -0
- package/dist/typography.scss +21 -0
- package/dist/util.scss +78 -0
- package/dist/vars.scss +0 -0
- package/package.json +96 -4
- package/src/contracts/backdrop/backdrop.contract.ts +44 -0
- package/src/contracts/backdrop/backdrop.generator.ts +82 -0
- package/src/contracts/backdrop/backdrop.keys.ts +7 -0
- package/src/contracts/backdrop/backdrop.module.css +3 -0
- package/src/contracts/backdrop/backdrop.scss +7 -0
- package/src/contracts/backdrop/backdrop.types.ts +45 -0
- package/src/contracts/backdrop/index.ts +21 -0
- package/src/contracts/color/color.contract.spec.ts +75 -0
- package/src/contracts/color/color.contract.ts +97 -0
- package/src/contracts/color/color.generator.spec.ts +73 -0
- package/src/contracts/color/color.generator.ts +122 -0
- package/src/contracts/color/color.gradient.spec.ts +32 -0
- package/src/contracts/color/color.gradient.ts +52 -0
- package/src/contracts/color/color.inject.module.css +5 -0
- package/src/contracts/color/color.keys.ts +7 -0
- package/src/contracts/color/color.module.css +5 -0
- package/src/contracts/color/color.scss +84 -0
- package/src/contracts/color/color.serialize.spec.ts +57 -0
- package/src/contracts/color/color.serialize.ts +35 -0
- package/src/contracts/color/color.token.spec.ts +57 -0
- package/src/contracts/color/color.token.ts +89 -0
- package/src/contracts/color/color.types.ts +82 -0
- package/src/contracts/color/index.md +87 -0
- package/src/contracts/color/index.ts +25 -0
- package/src/contracts/contract.ts +115 -0
- package/src/contracts/disabled/disabled.contract.ts +32 -0
- package/src/contracts/disabled/disabled.generator.ts +32 -0
- package/src/contracts/disabled/disabled.inject.module.css +5 -0
- package/src/contracts/disabled/disabled.keys.ts +6 -0
- package/src/contracts/disabled/disabled.module.css +3 -0
- package/src/contracts/disabled/disabled.scss +3 -0
- package/src/contracts/disabled/disabled.types.ts +19 -0
- package/src/contracts/disabled/index.ts +21 -0
- package/src/contracts/display/display.contract.ts +41 -0
- package/src/contracts/display/display.generator.ts +57 -0
- package/src/contracts/display/display.instance.ts +173 -0
- package/src/contracts/display/display.keys.ts +9 -0
- package/src/contracts/display/display.module.css +4 -0
- package/src/contracts/display/display.scss +63 -0
- package/src/contracts/display/display.types.ts +75 -0
- package/src/contracts/display/index.ts +27 -0
- package/src/contracts/elevation/elevation.contract.ts +37 -0
- package/src/contracts/elevation/elevation.generator.ts +71 -0
- package/src/contracts/elevation/elevation.keys.ts +6 -0
- package/src/contracts/elevation/elevation.module.css +35 -0
- package/src/contracts/elevation/elevation.scss +46 -0
- package/src/contracts/elevation/elevation.types.ts +21 -0
- package/src/contracts/elevation/index.ts +20 -0
- package/src/contracts/generator.ts +38 -0
- package/src/contracts/index.md +48 -0
- package/src/contracts/index.ts +37 -0
- package/src/contracts/round/index.ts +21 -0
- package/src/contracts/round/round.contract.ts +75 -0
- package/src/contracts/round/round.generator.ts +33 -0
- package/src/contracts/round/round.inject.module.scss +36 -0
- package/src/contracts/round/round.keys.ts +7 -0
- package/src/contracts/round/round.module.css +16 -0
- package/src/contracts/round/round.scss +90 -0
- package/src/contracts/round/round.types.ts +44 -0
- package/src/contracts/size/index.ts +22 -0
- package/src/contracts/size/size.contract.ts +98 -0
- package/src/contracts/size/size.generator.spec.ts +101 -0
- package/src/contracts/size/size.generator.ts +51 -0
- package/src/contracts/size/size.inject.module.scss +12 -0
- package/src/contracts/size/size.keys.ts +8 -0
- package/src/contracts/size/size.module.css +15 -0
- package/src/contracts/size/size.scss +28 -0
- package/src/contracts/size/size.types.ts +63 -0
- package/src/contracts/size/units.scss +17 -0
- package/src/contracts/style/index.ts +11 -0
- package/src/contracts/style/style.generator.ts +36 -0
- package/src/contracts/style/style.key.ts +4 -0
- package/src/contracts/style/style.types.ts +16 -0
- package/src/contracts/typography/index.ts +26 -0
- package/src/contracts/typography/typography.contract.ts +52 -0
- package/src/contracts/typography/typography.generator.spec.ts +48 -0
- package/src/contracts/typography/typography.generator.ts +44 -0
- package/src/contracts/typography/typography.inject.module.css +54 -0
- package/src/contracts/typography/typography.keys.ts +12 -0
- package/src/contracts/typography/typography.module.css +36 -0
- package/src/contracts/typography/typography.scss +21 -0
- package/src/contracts/typography/typography.types.ts +90 -0
- package/src/generator/theme.default.css +657 -0
- package/src/styles/duration.scss +17 -0
- package/src/styles/index.md +18 -0
- package/src/styles/is.scss +185 -0
- package/src/styles/ripple.scss +57 -0
- package/src/styles/theme.scss +16 -0
- package/src/styles/util.scss +78 -0
- package/src/styles/vars.scss +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { ThemePresetName, Ui0ThemePresetAppearanceConfig } from '@ui0/types'
|
|
2
|
+
import { hashClassName as viteHashClassName } from '@ui0/vite/css-modules'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
|
|
5
|
+
import { hashClassName } from '../../generator/hash'
|
|
6
|
+
import type { ContractContext } from '../generator'
|
|
7
|
+
import createSizeGenerator from './size.generator'
|
|
8
|
+
|
|
9
|
+
const ctx = (config: Ui0ThemePresetAppearanceConfig = {}): ContractContext => ({
|
|
10
|
+
presetName: 'test' as ThemePresetName,
|
|
11
|
+
config,
|
|
12
|
+
settings: {},
|
|
13
|
+
hash: hashClassName
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
describe('createSizeGenerator - vars', () => {
|
|
17
|
+
it('expands control/child base heights into the height scales and derived unit scales', () => {
|
|
18
|
+
const g = createSizeGenerator(ctx({ size: { control: 42, child: 24 } }))
|
|
19
|
+
const vars = g.vars()
|
|
20
|
+
expect(vars.s.m).toBe('42px')
|
|
21
|
+
expect(vars.s.l).toBe('50px')
|
|
22
|
+
expect(vars.sc.m).toBe('24px')
|
|
23
|
+
expect(vars.uc[1]).toBe('calc(var(--0-s-m) * var(--0-s-density, 1) / 14)')
|
|
24
|
+
expect(vars.ucc[1]).toBe('calc(var(--0-sc-m) * var(--0-s-density, 1) / 10)')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('emits the density base whenever the contract sizes anything', () => {
|
|
28
|
+
const g = createSizeGenerator(ctx({ size: { control: '2.5rem' } }))
|
|
29
|
+
expect(g.vars().s.density).toBe(1)
|
|
30
|
+
const empty = createSizeGenerator(ctx({}))
|
|
31
|
+
expect(empty.vars().s).toBeUndefined()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('passes string sizes through verbatim', () => {
|
|
35
|
+
const g = createSizeGenerator(ctx({ size: { control: '2.5rem' } }))
|
|
36
|
+
expect(g.vars().s.m).toBe('2.5rem')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('has no per-scheme values', () => {
|
|
40
|
+
const g = createSizeGenerator(ctx({ size: { control: 42 } }))
|
|
41
|
+
expect(g.vars('dark')).toEqual({})
|
|
42
|
+
expect(g.vars('light')).toEqual({})
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('createSizeGenerator - css', () => {
|
|
47
|
+
it('emits a setter class per scale step pointing --0-s at the step', () => {
|
|
48
|
+
// the setters ship in size.inject.module.scss (sass-expanded formatting);
|
|
49
|
+
// flatten the whitespace to assert rule-shaped output
|
|
50
|
+
const flat = createSizeGenerator(ctx()).css().replace(/\s+/g, ' ')
|
|
51
|
+
expect(flat).toContain(`.${hashClassName('sizeXl')} { --0-s: var(--0-s-xl); }`)
|
|
52
|
+
expect(flat).toContain(`.${hashClassName('sizeXxxs')} { --0-s: var(--0-s-xxxs); }`)
|
|
53
|
+
expect(flat).toContain(`.${hashClassName('sizeM')} { --0-s: var(--0-s-m); }`)
|
|
54
|
+
expect(flat).toContain(`.${hashClassName('sizeCustom')} { --0-s: var(--0-s-custom); }`)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('does not depend on the preset config (setters resolve through vars)', () => {
|
|
58
|
+
const a = createSizeGenerator(ctx({ size: { control: 42 } })).css()
|
|
59
|
+
const b = createSizeGenerator(ctx({})).css()
|
|
60
|
+
expect(a).toBe(b)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
describe('createSizeGenerator - class/styles', () => {
|
|
65
|
+
it('maps every logical class name to the hashed dist name', () => {
|
|
66
|
+
const classes = createSizeGenerator(ctx()).class()
|
|
67
|
+
expect(Object.keys(classes)).toEqual(
|
|
68
|
+
expect.arrayContaining([
|
|
69
|
+
'sizeXxxs',
|
|
70
|
+
'sizeXxs',
|
|
71
|
+
'sizeXs',
|
|
72
|
+
'sizeS',
|
|
73
|
+
'sizeM',
|
|
74
|
+
'sizeL',
|
|
75
|
+
'sizeXl',
|
|
76
|
+
'sizeXxl',
|
|
77
|
+
'sizeXxxl',
|
|
78
|
+
'sizeCustom',
|
|
79
|
+
'sized',
|
|
80
|
+
'child',
|
|
81
|
+
'fontSizing'
|
|
82
|
+
])
|
|
83
|
+
)
|
|
84
|
+
for (const [name, hashed] of Object.entries(classes)) {
|
|
85
|
+
expect(hashed).toBe(hashClassName(name))
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('stays in lockstep with the @ui0/vite distiller hasher', () => {
|
|
90
|
+
const classes = createSizeGenerator(ctx()).class()
|
|
91
|
+
for (const [name, hashed] of Object.entries(classes)) {
|
|
92
|
+
expect(hashed).toBe(viteHashClassName(name))
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('exposes the s namespace and no inline styles', () => {
|
|
97
|
+
const g = createSizeGenerator(ctx())
|
|
98
|
+
expect(g.namespace).toBe('s')
|
|
99
|
+
expect(g.styles()).toEqual({})
|
|
100
|
+
})
|
|
101
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// The size contract's generator endpoint: turns the preset's size settings
|
|
2
|
+
// (Ui0ThemeConfig.size: control/child base heights) into the contract's css
|
|
3
|
+
// vars - the --0-s-*/--0-sc-* height scales and the derived --0-uc*/--0-ucc*
|
|
4
|
+
// unit scales. The `size` prop setters are static - they ship in
|
|
5
|
+
// size.inject.module.scss (compiled + hashed at build); class() re-exports
|
|
6
|
+
// the registry map from size.module.css, so prop values resolve to the same
|
|
7
|
+
// hashed names the distiller publishes.
|
|
8
|
+
import type { CSSModuleClassList, VarList } from '@ui0/types'
|
|
9
|
+
import type { ThemeContractGenerator } from '@ui0/types'
|
|
10
|
+
|
|
11
|
+
import { renderScale, renderUnits, SCALE_RATIO } from '../../generator/scales'
|
|
12
|
+
import type { ContractContext, ContractFactory } from '../generator'
|
|
13
|
+
|
|
14
|
+
import sizeCss from './size.inject.module.scss'
|
|
15
|
+
import $size from './size.module.css'
|
|
16
|
+
|
|
17
|
+
const CONTROL_UNIT_DIVIDER = 14
|
|
18
|
+
const CONTROL_CHILD_UNIT_DIVIDER = 10
|
|
19
|
+
|
|
20
|
+
const sizeGenerator: ContractFactory = (ctx: ContractContext): ThemeContractGenerator => {
|
|
21
|
+
const { config } = ctx
|
|
22
|
+
|
|
23
|
+
function vars(): Record<string, VarList> {
|
|
24
|
+
const out: Record<string, VarList> = {}
|
|
25
|
+
const size = config.size
|
|
26
|
+
if (size?.control !== undefined) {
|
|
27
|
+
out.s = renderScale(size.control, SCALE_RATIO)
|
|
28
|
+
out.uc = renderUnits('uc', `calc(var(--0-s-m) * var(--0-s-density, 1) / ${CONTROL_UNIT_DIVIDER})`, 8)
|
|
29
|
+
}
|
|
30
|
+
if (size?.child !== undefined) {
|
|
31
|
+
out.sc = renderScale(size.child)
|
|
32
|
+
out.ucc = renderUnits('ucc', `calc(var(--0-sc-m) * var(--0-s-density, 1) / ${CONTROL_CHILD_UNIT_DIVIDER})`, 4)
|
|
33
|
+
}
|
|
34
|
+
// base density multiplier; the global .density-* classes flip it at
|
|
35
|
+
// runtime. (a per-theme density setting returns with the density contract)
|
|
36
|
+
if (size?.control !== undefined || size?.child !== undefined) {
|
|
37
|
+
out.s = { ...out.s, density: 1 }
|
|
38
|
+
}
|
|
39
|
+
return out
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
namespace: 's',
|
|
44
|
+
vars: (scheme) => (scheme ? {} : vars()),
|
|
45
|
+
css: () => sizeCss,
|
|
46
|
+
class: (): CSSModuleClassList => ({ ...$size }),
|
|
47
|
+
styles: () => ({})
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default sizeGenerator
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
@use 'sass:string';
|
|
2
|
+
|
|
3
|
+
@value sizeXxxs, sizeXxs, sizeXs, sizeS, sizeM, sizeL, sizeXl, sizeXxl, sizeXxxl, sizeCustom from './size.module.css';
|
|
4
|
+
|
|
5
|
+
@each $step in (xxxs, xxs, xs, s, m, l, xl, xxl, xxxl) {
|
|
6
|
+
.size#{string.to-upper-case(string.slice($step, 1, 1))}#{string.slice($step, 2)} {
|
|
7
|
+
--0-s: var(--0-s-#{$step});
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
.sizeCustom {
|
|
11
|
+
--0-s: var(--0-s-custom);
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ThemeContractDeal } from '@ui0/types'
|
|
2
|
+
import type { InjectionKey, Ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
import type { Size, SizeDensity } from './size.types'
|
|
5
|
+
|
|
6
|
+
export const SizeRefKey = Symbol('SizeRefKey') as InjectionKey<Ref<Size>>
|
|
7
|
+
export const SizeDensityRefKey = Symbol('DensityRefKey') as InjectionKey<Ref<SizeDensity>>
|
|
8
|
+
export const SizeContractKey = Symbol('SizeContractKey') as InjectionKey<ThemeContractDeal>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
--0-s - own size(height)
|
|
3
|
+
--0-sc - size of a child component in complex component
|
|
4
|
+
*/
|
|
5
|
+
@mixin use() {
|
|
6
|
+
--0-s: calc(var(--0-s, var(--0-s-m)) * var(--0-s-density, 1));
|
|
7
|
+
--0-sc: calc(var(--0-sc, var(--0-sc-m)) * var(--0-s-density, 1));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
$size-current: calc(var(--0-s, var(--0-s-m)) * var(--0-s-density, 1));
|
|
11
|
+
|
|
12
|
+
@mixin apply {
|
|
13
|
+
height: var(--0-s);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@mixin follow {
|
|
17
|
+
height: var(--0-s);
|
|
18
|
+
}
|
|
19
|
+
@mixin size {
|
|
20
|
+
height: var(--0-s);
|
|
21
|
+
}
|
|
22
|
+
@mixin child-size {
|
|
23
|
+
height: var(--0-sc);
|
|
24
|
+
}
|
|
25
|
+
@mixin sizeable($h: var(--0-s, var(--0-s-m)), $hc: var(--0-sc, var(--0-sc-m))) {
|
|
26
|
+
--0-s: calc(#{$h} * var(--0-s-density, 1));
|
|
27
|
+
--0-sc: calc(#{$hc} * var(--0-s-density, 1));
|
|
28
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { MaybeUnits, InheritValue, LiteralUnion } from '@ui0/types'
|
|
2
|
+
|
|
3
|
+
/* -------------------------------------------------------------------------- */
|
|
4
|
+
/* Size */
|
|
5
|
+
/* -------------------------------------------------------------------------- */
|
|
6
|
+
|
|
7
|
+
export type SizeXXXS = 'xxx-small' | 'xxxs'
|
|
8
|
+
export type SizeXXS = 'xx-small' | 'xxs'
|
|
9
|
+
export type SizeXS = 'x-small' | 'xs'
|
|
10
|
+
export type SizeS = 'small' | 's'
|
|
11
|
+
export type SizeM = 'medium' | 'm'
|
|
12
|
+
export type SizeL = 'large' | 'l'
|
|
13
|
+
export type SizeXL = 'x-large' | 'xl'
|
|
14
|
+
export type SizeXXL = 'xx-large' | 'xxl'
|
|
15
|
+
export type SizeXXXL = 'xxx-large' | 'xxxl'
|
|
16
|
+
|
|
17
|
+
export type Size =
|
|
18
|
+
| SizeXXXS
|
|
19
|
+
| SizeXXS
|
|
20
|
+
| SizeXS
|
|
21
|
+
| SizeS
|
|
22
|
+
| SizeM
|
|
23
|
+
| SizeL
|
|
24
|
+
| SizeXL
|
|
25
|
+
| SizeXXL
|
|
26
|
+
| SizeXXXL
|
|
27
|
+
| 'custom'
|
|
28
|
+
| 'smaller'
|
|
29
|
+
| 'larger'
|
|
30
|
+
| InheritValue
|
|
31
|
+
|
|
32
|
+
export type SizeDensity = LiteralUnion<'normal' | 'compact' | 'child'>
|
|
33
|
+
|
|
34
|
+
export interface SizeProps {
|
|
35
|
+
size?: Size
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface DensityProps {
|
|
39
|
+
density?: SizeDensity
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** the size contract's settings inside a theme preset (appearance config) */
|
|
43
|
+
export interface SizeThemeAppearanceConfig {
|
|
44
|
+
/** the control's base height -> expands into the --0-s-* scale */
|
|
45
|
+
control?: MaybeUnits
|
|
46
|
+
/** a control's child (icon etc.) base height -> the --0-sc-* scale */
|
|
47
|
+
child?: MaybeUnits
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** the absolute scale steps a `size` prop can pick (long and short spellings) */
|
|
51
|
+
export const SizeValuesAbsolute: Size[] = ['xxxs', 'xxs', 'xs', 's', 'm', 'l', 'xl', 'xxl', 'xxxl']
|
|
52
|
+
|
|
53
|
+
// registration: the contract announces itself to the package registries
|
|
54
|
+
// (interface merging - no central import of the contracts anywhere)
|
|
55
|
+
declare module '@ui0/types/theme' {
|
|
56
|
+
interface Ui0ThemePresetAppearanceConfig {
|
|
57
|
+
size?: SizeThemeAppearanceConfig
|
|
58
|
+
}
|
|
59
|
+
interface Ui0ThemeContractSettings {
|
|
60
|
+
size?: boolean
|
|
61
|
+
}
|
|
62
|
+
interface Ui0ThemeContracts extends SizeProps, DensityProps {}
|
|
63
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
@mixin use {
|
|
2
|
+
// based on a input size of a component
|
|
3
|
+
--0c-u1: calc(var(--0c-s) / 14);
|
|
4
|
+
--0c-u2: calc(var(--0c-u1) * 2);
|
|
5
|
+
--0c-u3: calc(var(--0c-u1) * 3);
|
|
6
|
+
--0c-u4: calc(var(--0c-u1) * 4);
|
|
7
|
+
--0c-u5: calc(var(--0c-u1) * 5);
|
|
8
|
+
--0c-u6: calc(var(--0c-u1) * 6);
|
|
9
|
+
--0c-u7: calc(var(--0c-u1) * 7);
|
|
10
|
+
--0c-u8: calc(var(--0c-u1) * 8);
|
|
11
|
+
|
|
12
|
+
// child units (e.g. an icon inside a button)
|
|
13
|
+
--0c-uc1: calc(var(--0c-sc) / 10);
|
|
14
|
+
--0c-uc2: calc(var(--0c-uc1) * 2);
|
|
15
|
+
--0c-uc3: calc(var(--0c-uc1) * 3);
|
|
16
|
+
--0c-uc4: calc(var(--0c-uc1) * 4);
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ThemeContract } from '@ui0/types'
|
|
2
|
+
|
|
3
|
+
import { ThemeContractFlags } from '../../constants'
|
|
4
|
+
import { StyleContractKey } from './style.key'
|
|
5
|
+
|
|
6
|
+
export type * from './style.types'
|
|
7
|
+
export const style: ThemeContract = {
|
|
8
|
+
key: StyleContractKey,
|
|
9
|
+
name: 'style',
|
|
10
|
+
flag: ThemeContractFlags.generator
|
|
11
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// The style contract's generator endpoint: passes arbitrary css through from
|
|
2
|
+
// the preset config - `style.vars` become `--0-style-*` custom properties on
|
|
3
|
+
// the theme block, `style.raw` lands as plain declarations. No classes of its
|
|
4
|
+
// own.
|
|
5
|
+
import type { CSSModuleClassList, StyleList, VarList } from '@ui0/types'
|
|
6
|
+
import type { ThemeContractGenerator } from '@ui0/types'
|
|
7
|
+
|
|
8
|
+
import type { ContractFactory } from '../generator'
|
|
9
|
+
|
|
10
|
+
const styleGenerator: ContractFactory = (ctx): ThemeContractGenerator => {
|
|
11
|
+
const { config } = ctx
|
|
12
|
+
|
|
13
|
+
function vars(): Record<string, VarList> {
|
|
14
|
+
const style = config.style
|
|
15
|
+
if (!style?.vars) return {}
|
|
16
|
+
return {
|
|
17
|
+
style: Object.fromEntries(Object.entries(style.vars))
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function styles(): StyleList {
|
|
22
|
+
const style = config.style
|
|
23
|
+
if (!style?.raw) return {}
|
|
24
|
+
return { ...style.raw }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
namespace: 'style',
|
|
29
|
+
vars: (scheme) => (scheme ? {} : vars()),
|
|
30
|
+
css: () => '',
|
|
31
|
+
class: (): CSSModuleClassList => ({}),
|
|
32
|
+
styles: (scheme) => (scheme ? {} : styles())
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default styleGenerator
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StyleList } from '@ui0/types'
|
|
2
|
+
|
|
3
|
+
declare module '@ui0/types/theme' {
|
|
4
|
+
interface Ui0ThemePresetAppearanceConfig {
|
|
5
|
+
style?: {
|
|
6
|
+
vars?: StyleList
|
|
7
|
+
raw?: StyleList
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
interface Ui0ThemeContractSettings {
|
|
11
|
+
style?: boolean
|
|
12
|
+
}
|
|
13
|
+
interface Ui0ThemeContracts {
|
|
14
|
+
style?: StyleList
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// The typography contract's registry entry, generated from
|
|
2
|
+
// packages/templates/contract. Wiring left (see the generator output):
|
|
3
|
+
// 1. add `typography` to src/contracts/index.ts (next to round/size/...)
|
|
4
|
+
// 2. add typographyGenerator to src/generator.ts (contractGenerators)
|
|
5
|
+
import { ThemeContractFlags } from '../../constants'
|
|
6
|
+
import type { ThemeContract } from '../../types'
|
|
7
|
+
import { typographyDeal } from './typography.contract'
|
|
8
|
+
import { TypographyContractKey, TypographyRefKey } from './typography.keys'
|
|
9
|
+
import type { TypographyProps } from './typography.types'
|
|
10
|
+
|
|
11
|
+
export { default as $style } from './typography.module.css'
|
|
12
|
+
export type * from './typography.types'
|
|
13
|
+
export * from './typography.keys'
|
|
14
|
+
|
|
15
|
+
export const TypographyPropsKeys: ReadonlyArray<keyof TypographyProps> = [
|
|
16
|
+
'typography'
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
export const typography: ThemeContract = {
|
|
20
|
+
key: TypographyContractKey,
|
|
21
|
+
name: 'typography',
|
|
22
|
+
ref: TypographyRefKey,
|
|
23
|
+
deal: typographyDeal,
|
|
24
|
+
flag: ThemeContractFlags.dealer + ThemeContractFlags.generator,
|
|
25
|
+
props: TypographyPropsKeys
|
|
26
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// The typography contract's processing endpoint: closes over the provider and
|
|
2
|
+
// returns the deal that maps the `typography` prop onto classes/styles at
|
|
3
|
+
// runtime, resolving `inherit` against the provided context ref.
|
|
4
|
+
import type { ClassList, CSSModuleClassList } from '@ui0/types'
|
|
5
|
+
import type { Ref } from 'vue'
|
|
6
|
+
|
|
7
|
+
import { EMPTY_OBJ } from '../../constants'
|
|
8
|
+
import type { ContractProvider, ThemeContractDeal } from '../../types'
|
|
9
|
+
import { mergeCssModulesStyles } from '@ui0/util'
|
|
10
|
+
|
|
11
|
+
import type { TypographyProps } from './typography.types'
|
|
12
|
+
import $typography from './typography.module.css'
|
|
13
|
+
|
|
14
|
+
// the prop -> class wiring: the prop value IS the logical class name from the
|
|
15
|
+
// registry (e.g. `typography="fw700"`), resolved to its hashed form from the
|
|
16
|
+
// module map (merged with the component's own $style)
|
|
17
|
+
function typographyClasses(
|
|
18
|
+
props: TypographyProps,
|
|
19
|
+
styles?: CSSModuleClassList
|
|
20
|
+
): ClassList {
|
|
21
|
+
const $ = mergeCssModulesStyles($typography, styles)
|
|
22
|
+
const out: ClassList = []
|
|
23
|
+
if (props.typography && $[props.typography]) out.push($[props.typography])
|
|
24
|
+
return out
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function typographyDeal(instance: ContractProvider): ThemeContractDeal {
|
|
28
|
+
const props = instance.props
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
classes: () => {
|
|
32
|
+
if (!props.typography) return instance.inject([])
|
|
33
|
+
|
|
34
|
+
if (props.typography === 'inherit') {
|
|
35
|
+
const ctx = instance.context as Record<
|
|
36
|
+
string,
|
|
37
|
+
Ref<any> | undefined
|
|
38
|
+
> | null
|
|
39
|
+
if (ctx?.typography) {
|
|
40
|
+
return instance.inject(
|
|
41
|
+
typographyClasses({ typography: ctx.typography.value }, instance.$styles)
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return instance.inject(
|
|
47
|
+
typographyClasses(props as TypographyProps, instance.$styles)
|
|
48
|
+
)
|
|
49
|
+
},
|
|
50
|
+
styles: () => instance.inject(EMPTY_OBJ)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { hashClassName } from '../../generator/hash'
|
|
4
|
+
import type { ThemePresetName } from '../../types'
|
|
5
|
+
import type { ContractContext } from '../generator'
|
|
6
|
+
import createTypographyGenerator from './typography.generator'
|
|
7
|
+
|
|
8
|
+
const ctx = (config = {}): ContractContext => ({
|
|
9
|
+
presetName: 'test' as ThemePresetName,
|
|
10
|
+
config,
|
|
11
|
+
settings: {},
|
|
12
|
+
hash: hashClassName
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
describe('createTypographyGenerator', () => {
|
|
16
|
+
it('emits a var for the configured base', () => {
|
|
17
|
+
const vars = createTypographyGenerator(
|
|
18
|
+
ctx({ typography: { base: '4px' } })
|
|
19
|
+
).vars()
|
|
20
|
+
expect(vars.typography.base).toBe('4px')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('emits nothing without config', () => {
|
|
24
|
+
expect(createTypographyGenerator(ctx()).vars()).toEqual({})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('maps the registry class names onto the hashed dist names', () => {
|
|
28
|
+
const classes = createTypographyGenerator(ctx()).class()
|
|
29
|
+
expect(classes.fw100).toBe(hashClassName('fw100'))
|
|
30
|
+
expect(classes['tt-uppercase']).toBe(hashClassName('tt-uppercase'))
|
|
31
|
+
expect(classes['tw-stable']).toBe(hashClassName('tw-stable'))
|
|
32
|
+
expect(Object.keys(classes)).toHaveLength(32)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('ships the contract css from the inject module, hashed', () => {
|
|
36
|
+
const css = createTypographyGenerator(ctx()).css()
|
|
37
|
+
expect(css).toContain(`.${hashClassName('fw700')} { font-weight: 700 }`)
|
|
38
|
+
expect(css).toContain(`.${hashClassName('ta-center')} { text-align: center }`)
|
|
39
|
+
expect(css).not.toContain('@value')
|
|
40
|
+
expect(css).not.toContain('.fw700')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('has no per-scheme values', () => {
|
|
44
|
+
const g = createTypographyGenerator(ctx({ typography: { base: '4px' } }))
|
|
45
|
+
expect(g.vars('dark')).toEqual({})
|
|
46
|
+
expect(g.namespace).toBe('t')
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// The typography contract's generator endpoint: turns the contract's slice of
|
|
2
|
+
// the appearance config (TypographyThemeAppearanceConfig) into css vars and
|
|
3
|
+
// ships the contract's own static css (the font-weight / text-transform /
|
|
4
|
+
// text-align / text-orientation / text-wrap utility setters). The setter css
|
|
5
|
+
// lives in typography.inject.module.css - the ui0 css-modules pipeline
|
|
6
|
+
// compiles it and hashes the selectors at build; class() re-exports the
|
|
7
|
+
// registry map from typography.module.css, so logical names resolve to the
|
|
8
|
+
// same hashes everywhere.
|
|
9
|
+
import type { CSSModuleClassList, ThemeContractGenerator, VarList } from '@ui0/types'
|
|
10
|
+
import { toUnits, tryToUnits } from '@ui0/util'
|
|
11
|
+
|
|
12
|
+
import type { ContractContext, ContractFactory } from '../generator'
|
|
13
|
+
|
|
14
|
+
import typographyCss from './typography.inject.module.css'
|
|
15
|
+
import $typography from './typography.module.css'
|
|
16
|
+
|
|
17
|
+
const typographyGenerator: ContractFactory = (ctx: ContractContext): ThemeContractGenerator => {
|
|
18
|
+
function vars(): Record<string, VarList> {
|
|
19
|
+
// after registration (see typography.types.ts) this reads
|
|
20
|
+
// `config.typography`; typed loosely until the contract is named.
|
|
21
|
+
|
|
22
|
+
if (ctx.settings.typography) {
|
|
23
|
+
const { headingRatio, fontSizeHeading, fontSize } = ctx.settings.typography
|
|
24
|
+
return {
|
|
25
|
+
typo: {
|
|
26
|
+
fs: tryToUnits(fontSize),
|
|
27
|
+
'h-ratio': headingRatio,
|
|
28
|
+
'h-fs': toUnits(fontSizeHeading) || tryToUnits(fontSize)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return {}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
namespace: 't',
|
|
37
|
+
vars: (scheme) => (scheme ? {} : vars()),
|
|
38
|
+
css: () => typographyCss,
|
|
39
|
+
class: (): CSSModuleClassList => ({ ...$typography }),
|
|
40
|
+
styles: () => ({})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default typographyGenerator
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
@value fw100, fw200, fw300, fw400, fw500, fw600, fw700, fw800, fw900 from './typography.module.css';
|
|
2
|
+
@value tt-uppercase, tt-lowercase, tt-capitalize, tt-none, tt-full, tt-full-size-kana from './typography.module.css';
|
|
3
|
+
@value ta-start, ta-end, ta-center, ta-left, ta-right, ta-justify, ta-match-parent from './typography.module.css';
|
|
4
|
+
@value to-mixed, to-sideways, to-sideways-right, to-use-glyph-orientation, to-upright from './typography.module.css';
|
|
5
|
+
@value tw-nowrap, tw-wrap, tw-balance, tw-pretty, tw-stable from './typography.module.css';
|
|
6
|
+
|
|
7
|
+
.fw100 { font-weight: 100 }
|
|
8
|
+
.fw200 { font-weight: 200 }
|
|
9
|
+
.fw300 { font-weight: 300 }
|
|
10
|
+
.fw400 { font-weight: 400 }
|
|
11
|
+
.fw500 { font-weight: 500 }
|
|
12
|
+
.fw600 { font-weight: 600 }
|
|
13
|
+
.fw700 { font-weight: 700 }
|
|
14
|
+
.fw800 { font-weight: 800 }
|
|
15
|
+
.fw900 { font-weight: 900 }
|
|
16
|
+
|
|
17
|
+
.tt-uppercase { text-transform: uppercase }
|
|
18
|
+
.tt-lowercase { text-transform: lowercase }
|
|
19
|
+
.tt-capitalize { text-transform: capitalize }
|
|
20
|
+
.tt-none { text-transform: none }
|
|
21
|
+
.tt-full { text-transform: full-width }
|
|
22
|
+
.tt-full-size-kana { text-transform: full-size-kana }
|
|
23
|
+
|
|
24
|
+
.ta-start { text-align: start }
|
|
25
|
+
.ta-end { text-align: end }
|
|
26
|
+
.ta-center { text-align: center }
|
|
27
|
+
.ta-left { text-align: left }
|
|
28
|
+
.ta-right { text-align: right }
|
|
29
|
+
.ta-justify { text-align: justify }
|
|
30
|
+
.ta-match-parent { text-align: match-parent }
|
|
31
|
+
|
|
32
|
+
.to-mixed { text-orientation: mixed }
|
|
33
|
+
.to-sideways { text-orientation: sideways }
|
|
34
|
+
.to-sideways-right { text-orientation: sideways-right }
|
|
35
|
+
.to-use-glyph-orientation { text-orientation: use-glyph-orientation }
|
|
36
|
+
.to-upright { text-orientation: upright }
|
|
37
|
+
|
|
38
|
+
.tw-nowrap { text-wrap: nowrap }
|
|
39
|
+
.tw-wrap { text-wrap: wrap }
|
|
40
|
+
.tw-balance { text-wrap: balance }
|
|
41
|
+
.tw-pretty { text-wrap: pretty }
|
|
42
|
+
.tw-stable { text-wrap: stable }
|
|
43
|
+
h1, h2, h3, h4, h5, h6 {
|
|
44
|
+
--0-typo-step: 0.25rem; /* шаг (длина) */
|
|
45
|
+
font-size: calc(var(--0-typo-h-fs, var(--0-typo-fs, 1rem)) + var(--0-typo-step) * var(--0-typo-x));
|
|
46
|
+
line-height: calc(1 + 1 / var(--0-typo-x));
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
h1 { --0-typo-x: 6; }
|
|
50
|
+
h2 { --0-typo-x: 5; }
|
|
51
|
+
h3 { --0-typo-x: 4; }
|
|
52
|
+
h4 { --0-typo-x: 3; }
|
|
53
|
+
h5 { --0-typo-x: 2; }
|
|
54
|
+
h6 { --0-typo-x: 1; }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { InjectionKey, Ref } from 'vue'
|
|
2
|
+
|
|
3
|
+
import type { ThemeContract } from '../../types'
|
|
4
|
+
import type { TypographyProp } from './typography.types'
|
|
5
|
+
|
|
6
|
+
/** context key the deal resolves `inherit` against (see useThemeContract) */
|
|
7
|
+
export const TypographyRefKey = Symbol('TypographyRefKey') as InjectionKey<
|
|
8
|
+
Ref<TypographyProp | undefined>
|
|
9
|
+
>
|
|
10
|
+
export const TypographyContractKey = Symbol(
|
|
11
|
+
'TypographyContractKey'
|
|
12
|
+
) as InjectionKey<ThemeContract>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
.fw100,
|
|
3
|
+
.fw200,
|
|
4
|
+
.fw300,
|
|
5
|
+
.fw400,
|
|
6
|
+
.fw500,
|
|
7
|
+
.fw600,
|
|
8
|
+
.fw700,
|
|
9
|
+
.fw800,
|
|
10
|
+
.fw900,
|
|
11
|
+
.tt-uppercase,
|
|
12
|
+
.tt-lowercase,
|
|
13
|
+
.tt-capitalize,
|
|
14
|
+
.tt-none,
|
|
15
|
+
.tt-full,
|
|
16
|
+
.tt-full-size-kana,
|
|
17
|
+
.ta-center,
|
|
18
|
+
.ta-end,
|
|
19
|
+
.ta-justify,
|
|
20
|
+
.ta-left,
|
|
21
|
+
.ta-match-parent,
|
|
22
|
+
.ta-right,
|
|
23
|
+
.ta-start,
|
|
24
|
+
.to-mixed,
|
|
25
|
+
.to-sideways,
|
|
26
|
+
.to-sideways-right,
|
|
27
|
+
.to-use-glyph-orientation,
|
|
28
|
+
.to-upright,
|
|
29
|
+
.tw-nowrap,
|
|
30
|
+
.tw-wrap,
|
|
31
|
+
.tw-balance,
|
|
32
|
+
.tw-pretty,
|
|
33
|
+
.tw-stable,
|
|
34
|
+
{
|
|
35
|
+
/*@shared*/
|
|
36
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Component-namespace wiring for the typography contract: the generator emits
|
|
2
|
+
// `--0-typography-base` on the theme blocks; this mixin mirrors it into the
|
|
3
|
+
// component namespace so a component can consume (and locally override) it.
|
|
4
|
+
@mixin init() {
|
|
5
|
+
--0-typo-base: 1.2;
|
|
6
|
+
|
|
7
|
+
code {
|
|
8
|
+
//background-color: rgba(var(--r-c-foreground-v), 0.2);
|
|
9
|
+
border-radius: 0;
|
|
10
|
+
}
|
|
11
|
+
h1, h2, h3, h4, h5, h6 {
|
|
12
|
+
font-size: calc(var(--0-typo-h-fs, var(--0-typo-fs)) * var(--0-typo-h-ratio, 1) * var(--0-typo-x, 1));
|
|
13
|
+
}
|
|
14
|
+
h1 { --0-typo-x: 6; }
|
|
15
|
+
h2 { --0-typo-x: 5; }
|
|
16
|
+
h3 { --0-typo-x: 4; }
|
|
17
|
+
h4 { --0-typo-x: 3; }
|
|
18
|
+
h5 { --0-typo-x: 2; }
|
|
19
|
+
h6 { --0-typo-x: 1; }
|
|
20
|
+
body { font-size: var(--0-typo-font-size); }
|
|
21
|
+
}
|