@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.
Files changed (148) hide show
  1. package/README.md +113 -2
  2. package/dist/backdrop.module.css +1 -0
  3. package/dist/backdrop.scss +7 -0
  4. package/dist/color.inject.module.css +7 -0
  5. package/dist/color.module.css +3 -0
  6. package/dist/color.scss +84 -0
  7. package/dist/components/index.d.ts +4 -0
  8. package/dist/components/index.d.ts.map +1 -0
  9. package/dist/components/index.js +53 -0
  10. package/dist/components/style.css +1 -0
  11. package/dist/components/theme-provider.keys.d.ts +4 -0
  12. package/dist/components/theme-provider.keys.d.ts.map +1 -0
  13. package/dist/components/theme-provider.module.css +1 -0
  14. package/dist/components/theme-provider.types.d.ts +18 -0
  15. package/dist/components/theme-provider.types.d.ts.map +1 -0
  16. package/dist/components/theme-provider.vue.d.ts +19 -0
  17. package/dist/config.default.d.mts +4 -0
  18. package/dist/config.default.d.mts.map +1 -0
  19. package/dist/config.default.mjs +73 -0
  20. package/dist/config.default.mjs.map +1 -0
  21. package/dist/disabled.inject.module.css +5 -0
  22. package/dist/disabled.module.css +1 -0
  23. package/dist/disabled.scss +3 -0
  24. package/dist/display.module.css +2 -0
  25. package/dist/display.scss +63 -0
  26. package/dist/duration.scss +17 -0
  27. package/dist/elevation.module.css +33 -0
  28. package/dist/elevation.scss +46 -0
  29. package/dist/generate-BPYE5ALG.mjs +1037 -0
  30. package/dist/generate-BPYE5ALG.mjs.map +1 -0
  31. package/dist/generator/cli.d.mts +1 -0
  32. package/dist/generator/cli.mjs +103 -0
  33. package/dist/generator/cli.mjs.map +1 -0
  34. package/dist/generator/vite.d.mts +18 -0
  35. package/dist/generator/vite.d.mts.map +1 -0
  36. package/dist/generator/vite.mjs +117 -0
  37. package/dist/generator/vite.mjs.map +1 -0
  38. package/dist/index.d.mts +339 -0
  39. package/dist/index.d.mts.map +1 -0
  40. package/dist/index.mjs +909 -0
  41. package/dist/index.mjs.map +1 -0
  42. package/dist/is.scss +185 -0
  43. package/dist/load-config-64q6nzFy.mjs +48 -0
  44. package/dist/load-config-64q6nzFy.mjs.map +1 -0
  45. package/dist/ripple.scss +57 -0
  46. package/dist/round.inject.module.css +92 -0
  47. package/dist/round.module.css +14 -0
  48. package/dist/round.scss +90 -0
  49. package/dist/size.inject.module.css +50 -0
  50. package/dist/size.module.css +13 -0
  51. package/dist/size.scss +28 -0
  52. package/dist/theme.scss +16 -0
  53. package/dist/typography.inject.module.css +81 -0
  54. package/dist/typography.module.css +32 -0
  55. package/dist/typography.scss +21 -0
  56. package/dist/util.scss +78 -0
  57. package/dist/vars.scss +0 -0
  58. package/package.json +96 -4
  59. package/src/contracts/backdrop/backdrop.contract.ts +44 -0
  60. package/src/contracts/backdrop/backdrop.generator.ts +82 -0
  61. package/src/contracts/backdrop/backdrop.keys.ts +7 -0
  62. package/src/contracts/backdrop/backdrop.module.css +3 -0
  63. package/src/contracts/backdrop/backdrop.scss +7 -0
  64. package/src/contracts/backdrop/backdrop.types.ts +45 -0
  65. package/src/contracts/backdrop/index.ts +21 -0
  66. package/src/contracts/color/color.contract.spec.ts +75 -0
  67. package/src/contracts/color/color.contract.ts +97 -0
  68. package/src/contracts/color/color.generator.spec.ts +73 -0
  69. package/src/contracts/color/color.generator.ts +122 -0
  70. package/src/contracts/color/color.gradient.spec.ts +32 -0
  71. package/src/contracts/color/color.gradient.ts +52 -0
  72. package/src/contracts/color/color.inject.module.css +5 -0
  73. package/src/contracts/color/color.keys.ts +7 -0
  74. package/src/contracts/color/color.module.css +5 -0
  75. package/src/contracts/color/color.scss +84 -0
  76. package/src/contracts/color/color.serialize.spec.ts +57 -0
  77. package/src/contracts/color/color.serialize.ts +35 -0
  78. package/src/contracts/color/color.token.spec.ts +57 -0
  79. package/src/contracts/color/color.token.ts +89 -0
  80. package/src/contracts/color/color.types.ts +82 -0
  81. package/src/contracts/color/index.md +87 -0
  82. package/src/contracts/color/index.ts +25 -0
  83. package/src/contracts/contract.ts +115 -0
  84. package/src/contracts/disabled/disabled.contract.ts +32 -0
  85. package/src/contracts/disabled/disabled.generator.ts +32 -0
  86. package/src/contracts/disabled/disabled.inject.module.css +5 -0
  87. package/src/contracts/disabled/disabled.keys.ts +6 -0
  88. package/src/contracts/disabled/disabled.module.css +3 -0
  89. package/src/contracts/disabled/disabled.scss +3 -0
  90. package/src/contracts/disabled/disabled.types.ts +19 -0
  91. package/src/contracts/disabled/index.ts +21 -0
  92. package/src/contracts/display/display.contract.ts +41 -0
  93. package/src/contracts/display/display.generator.ts +57 -0
  94. package/src/contracts/display/display.instance.ts +173 -0
  95. package/src/contracts/display/display.keys.ts +9 -0
  96. package/src/contracts/display/display.module.css +4 -0
  97. package/src/contracts/display/display.scss +63 -0
  98. package/src/contracts/display/display.types.ts +75 -0
  99. package/src/contracts/display/index.ts +27 -0
  100. package/src/contracts/elevation/elevation.contract.ts +37 -0
  101. package/src/contracts/elevation/elevation.generator.ts +71 -0
  102. package/src/contracts/elevation/elevation.keys.ts +6 -0
  103. package/src/contracts/elevation/elevation.module.css +35 -0
  104. package/src/contracts/elevation/elevation.scss +46 -0
  105. package/src/contracts/elevation/elevation.types.ts +21 -0
  106. package/src/contracts/elevation/index.ts +20 -0
  107. package/src/contracts/generator.ts +38 -0
  108. package/src/contracts/index.md +48 -0
  109. package/src/contracts/index.ts +37 -0
  110. package/src/contracts/round/index.ts +21 -0
  111. package/src/contracts/round/round.contract.ts +75 -0
  112. package/src/contracts/round/round.generator.ts +33 -0
  113. package/src/contracts/round/round.inject.module.scss +36 -0
  114. package/src/contracts/round/round.keys.ts +7 -0
  115. package/src/contracts/round/round.module.css +16 -0
  116. package/src/contracts/round/round.scss +90 -0
  117. package/src/contracts/round/round.types.ts +44 -0
  118. package/src/contracts/size/index.ts +22 -0
  119. package/src/contracts/size/size.contract.ts +98 -0
  120. package/src/contracts/size/size.generator.spec.ts +101 -0
  121. package/src/contracts/size/size.generator.ts +51 -0
  122. package/src/contracts/size/size.inject.module.scss +12 -0
  123. package/src/contracts/size/size.keys.ts +8 -0
  124. package/src/contracts/size/size.module.css +15 -0
  125. package/src/contracts/size/size.scss +28 -0
  126. package/src/contracts/size/size.types.ts +63 -0
  127. package/src/contracts/size/units.scss +17 -0
  128. package/src/contracts/style/index.ts +11 -0
  129. package/src/contracts/style/style.generator.ts +36 -0
  130. package/src/contracts/style/style.key.ts +4 -0
  131. package/src/contracts/style/style.types.ts +16 -0
  132. package/src/contracts/typography/index.ts +26 -0
  133. package/src/contracts/typography/typography.contract.ts +52 -0
  134. package/src/contracts/typography/typography.generator.spec.ts +48 -0
  135. package/src/contracts/typography/typography.generator.ts +44 -0
  136. package/src/contracts/typography/typography.inject.module.css +54 -0
  137. package/src/contracts/typography/typography.keys.ts +12 -0
  138. package/src/contracts/typography/typography.module.css +36 -0
  139. package/src/contracts/typography/typography.scss +21 -0
  140. package/src/contracts/typography/typography.types.ts +90 -0
  141. package/src/generator/theme.default.css +657 -0
  142. package/src/styles/duration.scss +17 -0
  143. package/src/styles/index.md +18 -0
  144. package/src/styles/is.scss +185 -0
  145. package/src/styles/ripple.scss +57 -0
  146. package/src/styles/theme.scss +16 -0
  147. package/src/styles/util.scss +78 -0
  148. package/src/styles/vars.scss +0 -0
@@ -0,0 +1,21 @@
1
+ import type { ComponentElevation } from '@ui0/types'
2
+
3
+ export interface ElevationProps {
4
+ elevation?: ComponentElevation
5
+ }
6
+
7
+ export interface ElevationThemeAppearanceConfig {
8
+ steps?: number
9
+ }
10
+
11
+ // registration: the contract announces itself to the package registries
12
+ // (interface merging - no central import of the contracts anywhere)
13
+ declare module '@ui0/types/theme' {
14
+ interface Ui0ThemePresetAppearanceConfig {
15
+ elevation?: ElevationThemeAppearanceConfig
16
+ }
17
+ interface Ui0ThemeContractSettings {
18
+ elevation?: boolean
19
+ }
20
+ interface Ui0ThemeContracts extends ElevationProps {}
21
+ }
@@ -0,0 +1,20 @@
1
+ import type { ThemeContract } from '@ui0/types'
2
+
3
+ import { ThemeContractFlags } from '../../constants'
4
+ import { elevationDeal } from './elevation.contract'
5
+ import { ElevationContractKey, ElevationRefKey } from './elevation.keys'
6
+ import type { ElevationProps } from './elevation.types'
7
+
8
+ export { default as $style } from './elevation.module.css'
9
+ export type * from './elevation.types'
10
+ export * from './elevation.keys'
11
+ export const ElevationPropsKeys: ReadonlyArray<keyof ElevationProps> = ['elevation']
12
+
13
+ export const elevation: ThemeContract = {
14
+ key: ElevationContractKey,
15
+ name: 'elevation',
16
+ ref: ElevationRefKey,
17
+ deal: elevationDeal,
18
+ flag: ThemeContractFlags.dealer + ThemeContractFlags.generator,
19
+ props: ElevationPropsKeys
20
+ }
@@ -0,0 +1,38 @@
1
+ // Contract generator infra - the context a contract factory receives from
2
+ // the orchestrator (src/generator/contracts.ts) and the factory type every
3
+ // <name>.generator.ts implements. A contract generator turns its slice of
4
+ // the preset's settings (Ui0ThemeConfig.<name>) into CSS: the class rules
5
+ // (css()) plus the vars it wants hoisted into the theme blocks (vars()).
6
+ // The values are authored in the theme config; the contract only wires its
7
+ // prop values onto them.
8
+ import type {
9
+ ThemeContractGenerator,
10
+ ThemePresetName,
11
+ Ui0ThemePresetAppearanceConfig,
12
+ Ui0ThemeContractSettings
13
+ } from '@ui0/types'
14
+
15
+ export interface ContractContext {
16
+ /** the preset this generator instance is created for */
17
+ presetName: ThemePresetName
18
+ /**
19
+ * the resolved appearance config (extends flattened, base merged under
20
+ * the scheme) the vars are generated from
21
+ */
22
+ config: Ui0ThemePresetAppearanceConfig
23
+ /**
24
+ * the consumer-side contract settings (ThemePluginConfig.contracts) - a
25
+ * contract reads its own slice to toggle behavior preset-independently
26
+ * (e.g. which backdrop functions ship at all)
27
+ */
28
+ settings: Ui0ThemeContractSettings
29
+ /** class-name hasher - the same algorithm the distiller hashes module.css with */
30
+ hash: (name: string) => string
31
+ }
32
+
33
+ export type ContractFactory = (ctx: ContractContext) => ThemeContractGenerator
34
+
35
+ /** identity helper so a <name>.generator.ts gets its factory context-typed */
36
+ export function defineContract(factory: ContractFactory): ContractFactory {
37
+ return factory
38
+ }
@@ -0,0 +1,48 @@
1
+ <size>/ - one folder per component prop contract
2
+
3
+ <size>.module.css the class registry - the single source of logical names
4
+ <size>.inject.module.scss (or .css) the contract's own static css: rules with
5
+ plain logical selectors whose names are imported from the registry
6
+ (`@value name from './<size>.module.css';`); the build compiles it (sass for
7
+ scss), validates the imports against the registry and the selectors against
8
+ the imports, hashes the selectors (same name-only hash) and inlines the result
9
+ into the generated theme.css; the generator imports it as a string and
10
+ returns it from css(), class() re-exports the registry map
11
+ <size>.scss the matching mixin(s) (@use '@ui0/theme/<size>')
12
+ <size>.types.ts the prop typing (Sizeable and friends)
13
+ <size>.generator.ts the generator endpoint (default-exported factory): theme
14
+ vars + setter classes; may optionally expose localScss() - config-generated
15
+ scss data (varName -> value, like the display breakpoints) the consumer's
16
+ loader writes next to theme.css as <size>.scss
17
+
18
+ Each contract also builds into the package dist (@ui0/vite/css-modules -
19
+ ui0CssModulesHash, wired via scripts/build-contracts.ts and the theme
20
+ tsdown/vitest configs):
21
+ <size>.scss -> dist/<size>.scss (source copy, relative @use rewritten to
22
+ package exports) and <size>.module.css -> dist/<size>.module.css as
23
+ `@value className: classHash;` lines - the shipped names for consumers.
24
+ An inject module additionally distills to dist/<size>.inject.module.css
25
+ (`@value name: hash;` map lines + the hashed css).
26
+ The hash (name-only sha256 inside ui0-css-modules-hash.ts) is the same one
27
+ the plugin hands to TS imports. The same plugin serves component packages:
28
+ ui0CssModulesHash({ entries: ['src/components'] }) distills every
29
+ `<component>.module.css` the same way.
30
+
31
+ color/ the paint contract (color/fill/gradient) - see color/index.md for the
32
+ v2 prop dsl, the ColorToken type and the delivery model. v1 is archived at
33
+ color-legacy/ (unregistered, reference only)
34
+ size/ size.scss size.module.css size.types.ts
35
+ round/ round.scss round.module.css round.types.ts
36
+ backdrop/ backdrop.scss backdrop.module.css backdrop.types.ts
37
+ elevation/ elevation.scss elevation.module.css elevation.types.ts
38
+ disabled/ disabled.scss disabled.module.css disabled.types.ts
39
+
40
+ The generator registry lives at src/generator.ts (contractGenerators) -
41
+ external contracts will merge their default-exported factories there (or pass
42
+ their own map to runContractGenerators' `factories` param).
43
+
44
+ useThemeContract.ts / useThemeContract.spec.ts
45
+ The useThemeContract(props, $styles) composable: a component-context
46
+ bridge over the contracts - provides/injects the prop refs (color, fill,
47
+ round, size, density, elevation, backdrop, disabled) for descendants and feeds
48
+ them to ContractProvider from contract.ts.
@@ -0,0 +1,37 @@
1
+ import type { ThemeContract, ThemeContractName } from '@ui0/types'
2
+
3
+ import { backdrop, BackdropPropsKeys } from './backdrop'
4
+ import { color, ColorPropsKeys } from './color'
5
+ import { disabled, DisabledPropsKeys } from './disabled'
6
+ import { display } from './display'
7
+ import { elevation, ElevationPropsKeys } from './elevation'
8
+ import { round, RoundPropsKeys } from './round'
9
+ import { size, SizePropsKeys } from './size'
10
+ import { style } from './style'
11
+ import { typography } from './typography'
12
+ export type * from './backdrop'
13
+ export type * from './color'
14
+ export type * from './disabled'
15
+ export type * from './elevation'
16
+ export type * from './round'
17
+ export type * from './size'
18
+
19
+ export const contracts: Record<ThemeContractName, ThemeContract> = {
20
+ color,
21
+ backdrop,
22
+ round,
23
+ elevation,
24
+ style,
25
+ disabled,
26
+ display,
27
+ typography,
28
+ size
29
+ }
30
+ export const props = [
31
+ ColorPropsKeys,
32
+ RoundPropsKeys,
33
+ SizePropsKeys,
34
+ ElevationPropsKeys,
35
+ BackdropPropsKeys,
36
+ DisabledPropsKeys
37
+ ].flat()
@@ -0,0 +1,21 @@
1
+ import type { ThemeContract } from '@ui0/types'
2
+
3
+ import { ThemeContractFlags } from '../../constants'
4
+ import { roundDeal } from './round.contract'
5
+ import { RoundContractKey, RoundRefKey } from './round.keys'
6
+ import type { RoundProps } from './round.types'
7
+
8
+ export { default as $style } from './round.module.css'
9
+ export type * from './round.types'
10
+ export * from './round.keys'
11
+
12
+ export const RoundPropsKeys: ReadonlyArray<keyof RoundProps> = ['round', 'round-target']
13
+
14
+ export const round: ThemeContract = {
15
+ key: RoundContractKey,
16
+ name: 'round',
17
+ ref: RoundRefKey,
18
+ deal: roundDeal,
19
+ flag: ThemeContractFlags.dealer + ThemeContractFlags.generator,
20
+ props: RoundPropsKeys
21
+ }
@@ -0,0 +1,75 @@
1
+ // The round contract's processing endpoint. The runtime wiring is minimal
2
+ // for now: radius values are computed in the component namespace
3
+ // (round.scss) and no round settings land on the theme block yet - the deal
4
+ // returns no classes until a rounding setting arrives in the config.
5
+ import type { CSSModuleClassList, Indexed } from '@ui0/types'
6
+ import type { ContractProvider, ThemeContractDeal } from '@ui0/types'
7
+ import { mergeCssModulesStyles, propsToCssModuleClassNext } from '@ui0/util'
8
+
9
+ import { EMPTY_OBJ } from '../../constants'
10
+ import type { RoundProps } from './round.types'
11
+
12
+ import $round from './round.module.css'
13
+ export type PropClassImpl<T = Record<string, unknown>> = keyof T | [keyof T, Indexed]
14
+
15
+ export function roundDeal(instance: ContractProvider): ThemeContractDeal {
16
+ return {
17
+ classes() {
18
+ const { props, $styles } = instance
19
+ const $ = mergeCssModulesStyles($round, $styles)
20
+ console.log('props', instance.props)
21
+
22
+ console.log(
23
+ 'propsToCssModuleClassNext(props, [getRoundPropClasses($), getRoundTargetPropClasses($)], $)',
24
+ propsToCssModuleClassNext(props, [getRoundPropClasses($), getRoundTargetPropClasses($)], $)
25
+ )
26
+
27
+ return propsToCssModuleClassNext(props, [getRoundPropClasses($), getRoundTargetPropClasses($)], $)
28
+ },
29
+ styles: () => instance.inject(EMPTY_OBJ)
30
+ }
31
+ }
32
+
33
+ function getRoundTargetPropClasses(style: CSSModuleClassList = $round): PropClassImpl<RoundProps> {
34
+ return [
35
+ 'roundTarget',
36
+ {
37
+ 'top-left-none': style.tln,
38
+ 'bottom-left-none': style.bln,
39
+ 'top-right-none': style.trn,
40
+ 'bottom-right-none': style.brn,
41
+
42
+ 'top-none': style.tn,
43
+ 'bottom-none': style.bn,
44
+ 'right-none': style.rn,
45
+ 'left-none': style.ln,
46
+
47
+ 'bottom-left': style.bl,
48
+ 'bottom-right': style.br,
49
+ 'top-right': style.tr,
50
+ 'top-left': style.tl
51
+ }
52
+ ]
53
+ }
54
+ function getRoundPropClasses(style: CSSModuleClassList = $round): PropClassImpl<RoundProps> {
55
+ return [
56
+ 'round',
57
+ {
58
+ true: style.rFull,
59
+ none: style.rNone,
60
+ full: style.rFull,
61
+
62
+ basic: style.rBasic,
63
+ smooth: style.rSmooth,
64
+ hard: style.rHard,
65
+
66
+ round: style.round,
67
+
68
+ left: [style.tl, style.bl],
69
+
70
+ right: [style.tr, style.br],
71
+ bottom: [style.br, style.bl],
72
+ top: [style.tl, style.tr]
73
+ }
74
+ ]
75
+ }
@@ -0,0 +1,33 @@
1
+ // The round contract's generator endpoint: corner-radius setter classes.
2
+ // The resolved rounding values live in the component namespace (--0c-r-*, see
3
+ // round.scss); a setter class points the per-corner slots at one of
4
+ // them, falling back to the theme-level --0-r-* when the component never ran
5
+ // apply() (its own computed default wins where it did). The setter css is
6
+ // static - it ships in round.inject.module.scss (compiled + hashed at build);
7
+ // class() re-exports the registry map from round.module.css.
8
+ import type { CSSModuleClassList, StyleList } from '@ui0/types'
9
+ import type { ThemeContractGenerator } from '@ui0/types'
10
+
11
+ import type { ContractFactory } from '../generator'
12
+
13
+ import roundCss from './round.inject.module.scss'
14
+ import $round from './round.module.css'
15
+
16
+ const roundGenerator: ContractFactory = (): ThemeContractGenerator => {
17
+ return {
18
+ namespace: 'r',
19
+ vars: () => ({}),
20
+ css: () => roundCss,
21
+ class: (): CSSModuleClassList => ({ ...$round }),
22
+ styles: (): StyleList => ({
23
+ '--0-r-base': '4px',
24
+ '--0-r-tl': '0px',
25
+ '--0-r-tr': '0px',
26
+ '--0-r-bl': '0px',
27
+ '--0-r-basic': 'calc(var(--0-s-m, 42px) * var(--0-s-density, 1))',
28
+ '--0-r-br': '0px'
29
+ })
30
+ }
31
+ }
32
+
33
+ export default roundGenerator
@@ -0,0 +1,36 @@
1
+ @value rFull, rSmooth, rBasic, rHard, rNone, rounded, rl, rr, rt, rb, tl, tr, bl, br from './round.module.css';
2
+
3
+ @mixin corners($name) {
4
+ --0-r-tl: var(--0c-r-#{$name}, var(--0-r-#{$name}));
5
+ --0-r-tr: var(--0c-r-#{$name}, var(--0-r-#{$name}));
6
+ --0-r-bl: var(--0c-r-#{$name}, var(--0-r-#{$name}));
7
+ --0-r-br: var(--0c-r-#{$name}, var(--0-r-#{$name}));
8
+ }
9
+
10
+ .rFull { @include corners(full); }
11
+ .rSmooth { @include corners(smooth); }
12
+ .rBasic { @include corners(basic); }
13
+ .rHard { @include corners(hard); }
14
+ .rNone { @include corners(none); }
15
+ .rounded { @include corners(basic); }
16
+
17
+ .rl {
18
+ --0-r-tl: var(--0c-r-basic, var(--0-r-basic));
19
+ --0-r-bl: var(--0c-r-basic, var(--0-r-basic));
20
+ }
21
+ .rr {
22
+ --0-r-tr: var(--0c-r-basic, var(--0-r-basic));
23
+ --0-r-br: var(--0c-r-basic, var(--0-r-basic));
24
+ }
25
+ .rt {
26
+ --0-r-tl: var(--0c-r-basic, var(--0-r-basic));
27
+ --0-r-tr: var(--0c-r-basic, var(--0-r-basic));
28
+ }
29
+ .rb {
30
+ --0-r-bl: var(--0c-r-basic, var(--0-r-basic));
31
+ --0-r-br: var(--0c-r-basic, var(--0-r-basic));
32
+ }
33
+ .tl { --0-r-tl: var(--0c-r-basic, var(--0-r-basic)); }
34
+ .tr { --0-r-tr: var(--0c-r-basic, var(--0-r-basic)); }
35
+ .bl { --0-r-bl: var(--0c-r-basic, var(--0-r-basic)); }
36
+ .br { --0-r-br: var(--0c-r-basic, var(--0-r-basic)); }
@@ -0,0 +1,7 @@
1
+ import type { ComponentRound, ComponentRoundTarget } from '@ui0/types'
2
+ import type { ThemeContractDeal } from '@ui0/types'
3
+ import type { InjectionKey, Ref } from 'vue'
4
+
5
+ export const RoundRefKey = Symbol('RoundRefKey') as InjectionKey<Ref<ComponentRound>>
6
+ export const RoundTargetRefKey = Symbol('RoundTargetRefKey') as InjectionKey<Ref<ComponentRoundTarget>>
7
+ export const RoundContractKey = Symbol('RoundContractKey') as InjectionKey<ThemeContractDeal>
@@ -0,0 +1,16 @@
1
+ .rounded,
2
+ .rBasic,
3
+ .rSmooth,
4
+ .rHard,
5
+ .rNone,
6
+ .rFull,
7
+ .rl,
8
+ .rr,
9
+ .rt,
10
+ .rb,
11
+ .br,
12
+ .bl,
13
+ .tl,
14
+ .tr {
15
+ /*@*/
16
+ }
@@ -0,0 +1,90 @@
1
+ // Corner radius application for a component.
2
+ //
3
+ // Rounding names (--0-r-none/hard/basic/smooth/full) are a THEME concern: the
4
+ // generator emits whatever the config's `roundings` section declares, on the
5
+ // .theme-* rule. This mixin provides a COMPUTED default for each name (a
6
+ // proportion of the control's current height) and resolves it into the
7
+ // --0c-r-* component namespace with the theme value winning via the var()
8
+ // fallback. The resolved defaults MUST live under --0c-r-* (not --0-r-*):
9
+ // a self-referential `--0-r-x: var(--0-r-x, …)` on the element is a CSS cycle
10
+ // (guaranteed-invalid at computed-value time) and kills every consumer - the
11
+ // setter classes read the --0c-r-* names.
12
+
13
+ @mixin init {
14
+ @property --0-r-tl {
15
+ syntax: '<length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]?';
16
+ inherits: false;
17
+ initial-value: 0;
18
+ }
19
+ @property --0-r-tr {
20
+ syntax: '<length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]?';
21
+ inherits: false;
22
+ initial-value: 0;
23
+ }
24
+ @property --0-r-bl {
25
+ syntax: '<length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]?';
26
+ inherits: false;
27
+ initial-value: 0;
28
+ }
29
+ @property --0-r-br {
30
+ syntax: '<length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]?';
31
+ inherits: false;
32
+ initial-value: 0;
33
+ }
34
+ }
35
+
36
+ @mixin use() {
37
+ border-start-start-radius: var(--0-r-tl, 0px);
38
+ border-start-end-radius: var(--0-r-tr, 0px);
39
+ border-end-start-radius: var(--0-r-bl, 0px);
40
+ border-end-end-radius: var(--0-r-br, 0px);
41
+ }
42
+
43
+ // $basic - the size the proportions are taken from; defaults to the control's
44
+ // current (density-aware) height.
45
+ @mixin apply($basic: null) {
46
+ @if $basic == null {
47
+ $basic: calc(var(--0-s-cur, 42px) * var(--0-s-density, 1));
48
+ }
49
+
50
+ // computed defaults in the component namespace; a theme-declared --0-r-*
51
+ // wins over each via the var() fallback (element-level --0-r-* would be a
52
+ // self-referential cycle, so the names must differ)
53
+ --0c-r-full: var(--0-r-full, calc(#{$basic} / 2));
54
+ --0c-r-smooth: var(--0-r-smooth, calc(#{$basic} / 4));
55
+ --0c-r-basic: var(--0-r-basic, calc(#{$basic} / 8));
56
+ --0c-r-hard: var(--0-r-hard, calc(#{$basic} / 14));
57
+ --0c-r-none: var(--0-r-none, 0px);
58
+ // @include reset();
59
+ }
60
+
61
+ @mixin full() {
62
+ --0-r-tl: var(--0c-r-full, var(--0-r-full));
63
+ --0-r-tr: var(--0c-r-full, var(--0-r-full));
64
+ --0-r-bl: var(--0c-r-full, var(--0-r-full));
65
+ --0-r-br: var(--0c-r-full, var(--0-r-full));
66
+ }
67
+ @mixin smooth() {
68
+ --0-r-tl: var(--0c-r-smooth, var(--0-r-smooth));
69
+ --0-r-tr: var(--0c-r-smooth, var(--0-r-smooth));
70
+ --0-r-bl: var(--0c-r-smooth, var(--0-r-smooth));
71
+ --0-r-br: var(--0c-r-smooth, var(--0-r-smooth));
72
+ }
73
+ @mixin basic() {
74
+ --0-r-tl: var(--0c-r-basic, var(--0-r-basic));
75
+ --0-r-tr: var(--0c-r-basic, var(--0-r-basic));
76
+ --0-r-bl: var(--0c-r-basic, var(--0-r-basic));
77
+ --0-r-br: var(--0c-r-basic, var(--0-r-basic));
78
+ }
79
+ @mixin hard() {
80
+ --0-r-tl: var(--0c-r-hard, var(--0-r-hard));
81
+ --0-r-tr: var(--0c-r-hard, var(--0-r-hard));
82
+ --0-r-bl: var(--0c-r-hard, var(--0-r-hard));
83
+ --0-r-br: var(--0c-r-hard, var(--0-r-hard));
84
+ }
85
+ @mixin reset() {
86
+ --0-r-tl: 0px;
87
+ --0-r-tr: 0px;
88
+ --0-r-bl: 0px;
89
+ --0-r-br: 0px;
90
+ }
@@ -0,0 +1,44 @@
1
+ import type { InheritValue, LiteralUnion } from '@ui0/types'
2
+
3
+ export interface RoundProps {
4
+ round?: Round
5
+ roundTarget?: RoundTarget
6
+ }
7
+
8
+ export interface RoundThemeAppearanceConfig {
9
+ rounding: 'relative' | 'static'
10
+ }
11
+
12
+ // registration: the contract announces itself to the package registries
13
+ // (interface merging - no central import of the contracts anywhere)
14
+ declare module '@ui0/types/theme' {
15
+ interface Ui0ThemePresetAppearanceConfig {
16
+ round?: RoundThemeAppearanceConfig
17
+ }
18
+ interface Ui0ThemeContractSettings {
19
+ round?: {
20
+ rounding: 'relative' | 'static'
21
+ }
22
+ }
23
+ interface Ui0ThemeContracts extends RoundProps {}
24
+ }
25
+ export type RoundTarget =
26
+ | InheritValue
27
+ | 'top'
28
+ | 'bottom'
29
+ | 'left'
30
+ | 'right'
31
+ | 'top-none'
32
+ | 'bottom-none'
33
+ | 'left-none'
34
+ | 'right-none'
35
+ | 'top-left'
36
+ | 'top-right'
37
+ | 'bottom-left'
38
+ | 'bottom-right'
39
+ | 'top-left-none'
40
+ | 'top-right-none'
41
+ | 'bottom-left-none'
42
+ | 'bottom-right-none'
43
+
44
+ export type Round = LiteralUnion<InheritValue | 'basic' | 'full' | 'none' | 'hard' | 'smooth'>
@@ -0,0 +1,22 @@
1
+ import type { ThemeContract } from '@ui0/types'
2
+
3
+ import { ThemeContractFlags } from '../../constants'
4
+ import { sizeDeal } from './size.contract'
5
+ import { SizeContractKey, SizeRefKey } from './size.keys'
6
+ import type { DensityProps, SizeProps } from './size.types'
7
+
8
+ export { default as $style } from './size.module.css'
9
+ export type * from './size.types'
10
+ export * from './size.keys'
11
+ export { default as sizeGenerator } from './size.generator'
12
+
13
+ export const SizePropsKeys: ReadonlyArray<keyof (SizeProps & DensityProps)> = ['size', 'density']
14
+
15
+ export const size: ThemeContract = {
16
+ ref: SizeRefKey,
17
+ name: 'size',
18
+ props: SizePropsKeys,
19
+ deal: sizeDeal,
20
+ flag: ThemeContractFlags.dealer + ThemeContractFlags.generator,
21
+ key: SizeContractKey
22
+ }
@@ -0,0 +1,98 @@
1
+ // The size contract's processing endpoint: closes over the provider and
2
+ // returns the deal that maps the `size`/`density` props onto classes,
3
+ // resolving `inherit`/`smaller`/`larger` against the provided context refs.
4
+ import type { ClassList, CSSModuleClassList } from '@ui0/types'
5
+ import type { ContractProvider, ThemeContractDeal } from '@ui0/types'
6
+ import { arrayPickNext, arrayPickPrev, isArray, mergeCssModulesStyles, toCamelCase } from '@ui0/util'
7
+
8
+ import { EMPTY_OBJ } from '../../constants'
9
+ import type { DensityProps, Size, SizeProps } from './size.types'
10
+ import { SizeValuesAbsolute } from './size.types'
11
+
12
+ import $size from './size.module.css'
13
+
14
+ type Sizers = SizeProps & DensityProps
15
+
16
+ function sizeClasses(props: Sizers, styles?: CSSModuleClassList): ClassList {
17
+ const out: ClassList = []
18
+ const { size, density } = props
19
+ const normalizedSizing = (isArray(density) ? density : [toCamelCase(density)]) as string[]
20
+
21
+ const $ = mergeCssModulesStyles($size, styles)
22
+ if (size) {
23
+ out.push($.sized)
24
+ const cls = getSizePropClasses($)[size]
25
+ if (cls) out.push(cls)
26
+ }
27
+
28
+ if (normalizedSizing) {
29
+ normalizedSizing.forEach((d) => {
30
+ if ($ && $[d]) out.push($[d])
31
+ })
32
+ }
33
+ return out
34
+ }
35
+
36
+ function getSizePropClasses(styles: CSSModuleClassList): Record<Size | 'inherit', string> {
37
+ return {
38
+ 'xxx-large': styles.sizeXxxl,
39
+ 'xx-large': styles.sizeXxl,
40
+ 'x-large': styles.sizeXl,
41
+ large: styles.sizeL,
42
+ 'x-small': styles.sizeXs,
43
+ 'xx-small': styles.sizeXxs,
44
+ 'xxx-small': styles.sizeXxxs,
45
+ small: styles.sizeS,
46
+ medium: styles.sizeM,
47
+
48
+ xxxl: styles.sizeXxxl,
49
+ xxl: styles.sizeXxl,
50
+ xl: styles.sizeXl,
51
+ l: styles.sizeL,
52
+ xs: styles.sizeXs,
53
+ xxs: styles.sizeXxs,
54
+ xxxs: styles.sizeXxxs,
55
+ s: styles.sizeS,
56
+ m: styles.sizeM,
57
+
58
+ larger: '',
59
+ inherit: '',
60
+ smaller: '',
61
+ custom: styles.sizeCustom
62
+ }
63
+ }
64
+
65
+ export function sizeDeal(instance: ContractProvider): ThemeContractDeal {
66
+ const props = instance.props
67
+
68
+ return {
69
+ classes: () => {
70
+ const { size, density } = props
71
+ if (!size && !density) return instance.inject([])
72
+
73
+ if (instance.context) {
74
+ const out: Record<string, any> = {}
75
+ const ctxSize = instance.context.size
76
+
77
+ if (ctxSize) {
78
+ if (size === 'inherit') out['size'] = ctxSize.value
79
+ if (size === 'smaller' || size === 'larger') {
80
+ out['size'] = (size === 'smaller' ? arrayPickPrev : arrayPickNext)(SizeValuesAbsolute, ctxSize.value)
81
+ }
82
+ }
83
+ const ctxDensity = instance.context.density
84
+ if (ctxDensity && density === 'inherit') {
85
+ out['density'] = ctxDensity.value
86
+ }
87
+
88
+ if (!('density' in out) && props.density) out['density'] = props.density
89
+ if (!('size' in out) && props.size) out['size'] = props.size
90
+
91
+ return instance.inject(sizeClasses(out, instance.$styles))
92
+ }
93
+
94
+ return instance.inject(sizeClasses(props, instance.$styles))
95
+ },
96
+ styles: () => instance.inject(EMPTY_OBJ)
97
+ }
98
+ }