@contember/utilities 1.2.0-beta.3 → 1.2.0-rc.1
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/development/assert-types/Predicates.js +20 -4
- package/dist/development/assert-types/Predicates.js.map +1 -1
- package/dist/development/assert-types/assert.js.map +1 -1
- package/dist/development/class-name/colorSchemeClassName.js +16 -0
- package/dist/development/class-name/colorSchemeClassName.js.map +1 -0
- package/dist/development/class-name/constants.js +7 -0
- package/dist/development/class-name/constants.js.map +1 -0
- package/dist/development/class-name/deduplicateClassName.js.map +1 -0
- package/dist/development/class-name/filterThemedClassName.js +68 -0
- package/dist/development/class-name/filterThemedClassName.js.map +1 -0
- package/dist/development/class-name/{Internal/flatClassNameList.js → flatClassNameList.js} +1 -1
- package/dist/development/class-name/flatClassNameList.js.map +1 -0
- package/dist/development/class-name/listClassName.js +2 -2
- package/dist/development/class-name/listClassName.js.map +1 -1
- package/dist/development/class-name/stateClassName.js +3 -6
- package/dist/development/class-name/stateClassName.js.map +1 -1
- package/dist/development/class-name/themeClassName.js +18 -0
- package/dist/development/class-name/themeClassName.js.map +1 -0
- package/dist/development/deprecate/currentOrDeprecated.js +20 -0
- package/dist/development/deprecate/currentOrDeprecated.js.map +1 -0
- package/dist/development/deprecate/deprecate.js +6 -0
- package/dist/development/deprecate/deprecate.js.map +1 -0
- package/dist/development/dom/stateDataAttributes.js +11 -0
- package/dist/development/dom/stateDataAttributes.js.map +1 -0
- package/dist/development/dom/svgSizeProps.js.map +1 -1
- package/dist/development/functional/omit.js +15 -0
- package/dist/development/functional/omit.js.map +1 -0
- package/dist/development/functional/pick.js.map +1 -1
- package/dist/development/index.js +31 -8
- package/dist/development/index.js.map +1 -1
- package/dist/development/string-utilities/kebabCase.js +8 -0
- package/dist/development/string-utilities/kebabCase.js.map +1 -0
- package/dist/production/assert-types/Predicates.js +20 -4
- package/dist/production/assert-types/Predicates.js.map +1 -1
- package/dist/production/assert-types/assert.js.map +1 -1
- package/dist/production/class-name/colorSchemeClassName.js +16 -0
- package/dist/production/class-name/colorSchemeClassName.js.map +1 -0
- package/dist/production/class-name/constants.js +7 -0
- package/dist/production/class-name/constants.js.map +1 -0
- package/dist/production/class-name/deduplicateClassName.js.map +1 -0
- package/dist/production/class-name/filterThemedClassName.js +68 -0
- package/dist/production/class-name/filterThemedClassName.js.map +1 -0
- package/dist/production/class-name/{Internal/flatClassNameList.js → flatClassNameList.js} +1 -1
- package/dist/production/class-name/flatClassNameList.js.map +1 -0
- package/dist/production/class-name/listClassName.js +2 -2
- package/dist/production/class-name/listClassName.js.map +1 -1
- package/dist/production/class-name/stateClassName.js +3 -6
- package/dist/production/class-name/stateClassName.js.map +1 -1
- package/dist/production/class-name/themeClassName.js +18 -0
- package/dist/production/class-name/themeClassName.js.map +1 -0
- package/dist/production/deprecate/currentOrDeprecated.js +20 -0
- package/dist/production/deprecate/currentOrDeprecated.js.map +1 -0
- package/dist/production/deprecate/deprecate.js +6 -0
- package/dist/production/deprecate/deprecate.js.map +1 -0
- package/dist/production/dom/stateDataAttributes.js +11 -0
- package/dist/production/dom/stateDataAttributes.js.map +1 -0
- package/dist/production/dom/svgSizeProps.js.map +1 -1
- package/dist/production/functional/omit.js +15 -0
- package/dist/production/functional/omit.js.map +1 -0
- package/dist/production/functional/pick.js.map +1 -1
- package/dist/production/index.js +31 -8
- package/dist/production/index.js.map +1 -1
- package/dist/production/string-utilities/kebabCase.js +8 -0
- package/dist/production/string-utilities/kebabCase.js.map +1 -0
- package/dist/types/assert-types/Predicates.d.ts +6 -2
- package/dist/types/assert-types/Predicates.d.ts.map +1 -1
- package/dist/types/assert-types/assert.d.ts +2 -1
- package/dist/types/assert-types/assert.d.ts.map +1 -1
- package/dist/types/assert-types/index.d.ts +1 -0
- package/dist/types/assert-types/index.d.ts.map +1 -1
- package/dist/types/assert-types/types.d.ts +5 -0
- package/dist/types/assert-types/types.d.ts.map +1 -0
- package/dist/types/class-name/colorSchemeClassName.d.ts +35 -0
- package/dist/types/class-name/colorSchemeClassName.d.ts.map +1 -0
- package/dist/types/class-name/constants.d.ts +42 -0
- package/dist/types/class-name/constants.d.ts.map +1 -0
- package/dist/types/class-name/deduplicateClassName.d.ts.map +1 -0
- package/dist/types/class-name/filterThemedClassName.d.ts +7 -0
- package/dist/types/class-name/filterThemedClassName.d.ts.map +1 -0
- package/dist/types/class-name/flatClassNameList.d.ts +3 -0
- package/dist/types/class-name/flatClassNameList.d.ts.map +1 -0
- package/dist/types/class-name/index.d.ts +7 -4
- package/dist/types/class-name/index.d.ts.map +1 -1
- package/dist/types/class-name/stateClassName.d.ts +9 -3
- package/dist/types/class-name/stateClassName.d.ts.map +1 -1
- package/dist/types/class-name/themeClassName.d.ts +87 -0
- package/dist/types/class-name/themeClassName.d.ts.map +1 -0
- package/dist/types/class-name/types.d.ts +14 -0
- package/dist/types/class-name/types.d.ts.map +1 -0
- package/dist/types/deprecate/currentOrDeprecated.d.ts +35 -0
- package/dist/types/deprecate/currentOrDeprecated.d.ts.map +1 -0
- package/dist/types/deprecate/deprecate.d.ts +19 -0
- package/dist/types/deprecate/deprecate.d.ts.map +1 -0
- package/dist/types/deprecate/index.d.ts +4 -0
- package/dist/types/deprecate/index.d.ts.map +1 -0
- package/dist/types/deprecate/types.d.ts +2 -0
- package/dist/types/deprecate/types.d.ts.map +1 -0
- package/dist/types/dom/index.d.ts +1 -0
- package/dist/types/dom/index.d.ts.map +1 -1
- package/dist/types/dom/stateDataAttributes.d.ts +4 -0
- package/dist/types/dom/stateDataAttributes.d.ts.map +1 -0
- package/dist/types/dom/svgSizeProps.d.ts.map +1 -1
- package/dist/types/functional/index.d.ts +1 -0
- package/dist/types/functional/index.d.ts.map +1 -1
- package/dist/types/functional/omit.d.ts +2 -0
- package/dist/types/functional/omit.d.ts.map +1 -0
- package/dist/types/functional/pick.d.ts +1 -1
- package/dist/types/functional/pick.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/string-utilities/index.d.ts +1 -0
- package/dist/types/string-utilities/index.d.ts.map +1 -1
- package/dist/types/string-utilities/kebabCase.d.ts +2 -0
- package/dist/types/string-utilities/kebabCase.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/types/types/DeepPartial.d.ts.map +1 -0
- package/dist/types/types/NonNullableRequired.d.ts.map +1 -0
- package/dist/types/types/NonOptional.d.ts +8 -0
- package/dist/types/types/NonOptional.d.ts.map +1 -0
- package/dist/types/types/ObjectKeyValue.d.ts.map +1 -0
- package/dist/types/types/PolymorphicRefs.d.ts.map +1 -0
- package/dist/types/types/Primitive.d.ts +2 -0
- package/dist/types/types/Primitive.d.ts.map +1 -0
- package/dist/types/types/RequiredDeepPlainObject.d.ts +4 -0
- package/dist/types/types/RequiredDeepPlainObject.d.ts.map +1 -0
- package/dist/types/types/Try.d.ts.map +1 -0
- package/dist/types/types/TypeofStringLiteral.d.ts +2 -0
- package/dist/types/types/TypeofStringLiteral.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +11 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/package.json +4 -1
- package/src/assert-types/Predicates.ts +26 -5
- package/src/assert-types/assert.ts +2 -1
- package/src/assert-types/index.ts +1 -0
- package/src/assert-types/types.ts +5 -0
- package/src/class-name/colorSchemeClassName.ts +46 -0
- package/src/class-name/constants.ts +43 -0
- package/src/class-name/filterThemedClassName.ts +86 -0
- package/src/class-name/{Internal/flatClassNameList.ts → flatClassNameList.ts} +2 -2
- package/src/class-name/index.ts +7 -4
- package/src/class-name/listClassName.ts +2 -2
- package/src/class-name/stateClassName.ts +13 -8
- package/src/class-name/themeClassName.ts +117 -0
- package/src/class-name/types.ts +18 -0
- package/src/deprecate/currentOrDeprecated.ts +51 -0
- package/src/deprecate/deprecate.ts +31 -0
- package/src/deprecate/index.ts +3 -0
- package/src/deprecate/types.ts +2 -0
- package/src/dom/index.ts +1 -0
- package/src/dom/stateDataAttributes.ts +8 -0
- package/src/dom/svgSizeProps.ts +0 -2
- package/src/functional/index.ts +1 -0
- package/src/functional/omit.ts +13 -0
- package/src/functional/pick.ts +1 -1
- package/src/index.ts +2 -1
- package/src/string-utilities/index.ts +1 -0
- package/src/string-utilities/kebabCase.ts +5 -0
- package/src/types/NonOptional.ts +7 -0
- package/src/types/Primitive.ts +1 -0
- package/src/types/RequiredDeepPlainObject.ts +3 -0
- package/src/types/TypeofStringLiteral.ts +1 -0
- package/src/types/index.ts +20 -0
- package/dist/development/class-name/GlobalClassNamePrefixContext.js +0 -6
- package/dist/development/class-name/GlobalClassNamePrefixContext.js.map +0 -1
- package/dist/development/class-name/Internal/deduplicateClassName.js.map +0 -1
- package/dist/development/class-name/Internal/flatClassNameList.js.map +0 -1
- package/dist/development/class-name/useClassName.js +0 -18
- package/dist/development/class-name/useClassName.js.map +0 -1
- package/dist/development/class-name/useClassNameFactory.js +0 -21
- package/dist/development/class-name/useClassNameFactory.js.map +0 -1
- package/dist/production/class-name/GlobalClassNamePrefixContext.js +0 -6
- package/dist/production/class-name/GlobalClassNamePrefixContext.js.map +0 -1
- package/dist/production/class-name/Internal/deduplicateClassName.js.map +0 -1
- package/dist/production/class-name/Internal/flatClassNameList.js.map +0 -1
- package/dist/production/class-name/useClassName.js +0 -18
- package/dist/production/class-name/useClassName.js.map +0 -1
- package/dist/production/class-name/useClassNameFactory.js +0 -21
- package/dist/production/class-name/useClassNameFactory.js.map +0 -1
- package/dist/types/class-name/GlobalClassNamePrefixContext.d.ts +0 -2
- package/dist/types/class-name/GlobalClassNamePrefixContext.d.ts.map +0 -1
- package/dist/types/class-name/Internal/deduplicateClassName.d.ts.map +0 -1
- package/dist/types/class-name/Internal/flatClassNameList.d.ts +0 -3
- package/dist/types/class-name/Internal/flatClassNameList.d.ts.map +0 -1
- package/dist/types/class-name/Types.d.ts +0 -5
- package/dist/types/class-name/Types.d.ts.map +0 -1
- package/dist/types/class-name/useClassName.d.ts +0 -10
- package/dist/types/class-name/useClassName.d.ts.map +0 -1
- package/dist/types/class-name/useClassNameFactory.d.ts +0 -3
- package/dist/types/class-name/useClassNameFactory.d.ts.map +0 -1
- package/dist/types/typescript-utilities/DeepPartial.d.ts.map +0 -1
- package/dist/types/typescript-utilities/NonNullableRequired.d.ts.map +0 -1
- package/dist/types/typescript-utilities/ObjectKeyValue.d.ts.map +0 -1
- package/dist/types/typescript-utilities/PolymorphicRefs.d.ts.map +0 -1
- package/dist/types/typescript-utilities/Try.d.ts.map +0 -1
- package/dist/types/typescript-utilities/index.d.ts +0 -6
- package/dist/types/typescript-utilities/index.d.ts.map +0 -1
- package/src/class-name/GlobalClassNamePrefixContext.ts +0 -3
- package/src/class-name/Types.ts +0 -2
- package/src/class-name/useClassName.ts +0 -29
- package/src/class-name/useClassNameFactory.ts +0 -31
- package/src/typescript-utilities/index.ts +0 -5
- /package/dist/development/class-name/{Internal/deduplicateClassName.js → deduplicateClassName.js} +0 -0
- /package/dist/production/class-name/{Internal/deduplicateClassName.js → deduplicateClassName.js} +0 -0
- /package/dist/types/class-name/{Internal/deduplicateClassName.d.ts → deduplicateClassName.d.ts} +0 -0
- /package/dist/types/{typescript-utilities → types}/DeepPartial.d.ts +0 -0
- /package/dist/types/{typescript-utilities → types}/NonNullableRequired.d.ts +0 -0
- /package/dist/types/{typescript-utilities → types}/ObjectKeyValue.d.ts +0 -0
- /package/dist/types/{typescript-utilities → types}/PolymorphicRefs.d.ts +0 -0
- /package/dist/types/{typescript-utilities → types}/Try.d.ts +0 -0
- /package/src/class-name/{Internal/deduplicateClassName.ts → deduplicateClassName.ts} +0 -0
- /package/src/{typescript-utilities → types}/DeepPartial.ts +0 -0
- /package/src/{typescript-utilities → types}/NonNullableRequired.ts +0 -0
- /package/src/{typescript-utilities → types}/ObjectKeyValue.ts +0 -0
- /package/src/{typescript-utilities → types}/PolymorphicRefs.ts +0 -0
- /package/src/{typescript-utilities → types}/Try.ts +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/utilities",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "1.2.0-
|
|
4
|
+
"version": "1.2.0-rc.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/production/index.js",
|
|
@@ -35,5 +35,8 @@
|
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": "^17 || ^18"
|
|
37
37
|
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"type-fest": "^3.12.0"
|
|
40
|
+
},
|
|
38
41
|
"stableVersion": "0.0.0"
|
|
39
42
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Predicate, SlugString, UnionOfPredicateTypes } from './types'
|
|
2
|
+
|
|
1
3
|
export function isNull(value: unknown): value is null {
|
|
2
4
|
return value === null
|
|
3
5
|
}
|
|
@@ -7,7 +9,7 @@ export function isNotNull<T>(value: unknown): value is T {
|
|
|
7
9
|
export function isUndefined(value: unknown): value is undefined {
|
|
8
10
|
return value === undefined
|
|
9
11
|
}
|
|
10
|
-
export function isDefined<T>(value: unknown): value is T {
|
|
12
|
+
export function isDefined<T>(value: unknown): value is Exclude<T, undefined> {
|
|
11
13
|
return value !== undefined
|
|
12
14
|
}
|
|
13
15
|
export function isNotNullish<T>(value: T): value is Exclude<T, null | undefined> {
|
|
@@ -25,6 +27,9 @@ export function isFalse(value: unknown): value is false {
|
|
|
25
27
|
export function isString(value: unknown): value is string {
|
|
26
28
|
return typeof value === 'string'
|
|
27
29
|
}
|
|
30
|
+
export function isSlugString(value: unknown): value is SlugString {
|
|
31
|
+
return isNonEmptyString(value) && /^[a-z0-9_-]+$/.test(value)
|
|
32
|
+
}
|
|
28
33
|
export function isNonEmptyString(value: unknown): value is string {
|
|
29
34
|
return isString(value) && value.length > 0
|
|
30
35
|
}
|
|
@@ -45,10 +50,26 @@ export function isNonNegativeNumber(value: unknown): value is number {
|
|
|
45
50
|
export function isNumericString(value: string): value is string {
|
|
46
51
|
return isString(value) && !isNaN(parseFloat(value))
|
|
47
52
|
}
|
|
48
|
-
export function isOneOfFactory<U, T = any>(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
export function isOneOfFactory<U, T = any>(
|
|
54
|
+
members: T extends Array<U> | ReadonlyArray<U> ? T : never,
|
|
55
|
+
): (value: unknown) => value is U {
|
|
56
|
+
return function isOneOfFactoryProduct(value: unknown): value is U {
|
|
57
|
+
return members.includes(value as U)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function satisfiesOneOfFactory<T extends Array<Predicate<any, any>>>(
|
|
61
|
+
...predicates: T
|
|
62
|
+
): Predicate<unknown, UnionOfPredicateTypes<T>> {
|
|
63
|
+
return (value: any): value is UnionOfPredicateTypes<T> => {
|
|
64
|
+
return predicates.some(predicate => predicate(value))
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function isArrayOfMembersSatisfyingFactory<T>(
|
|
68
|
+
predicate: (value: unknown) => value is T,
|
|
69
|
+
): (value: unknown) => value is Array<T> {
|
|
70
|
+
return function isArrayOfMembersSatisfyingProduct(value: unknown): value is Array<T> {
|
|
71
|
+
return Array.isArray(value) && value.every(predicate)
|
|
72
|
+
}
|
|
52
73
|
}
|
|
53
74
|
export function isHTMLElement(value: unknown): value is HTMLElement {
|
|
54
75
|
return value instanceof HTMLElement
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AssertionError } from './AssertionError'
|
|
2
|
+
import { Predicate } from './types'
|
|
2
3
|
|
|
3
4
|
export function assert<
|
|
4
5
|
In,
|
|
@@ -6,7 +7,7 @@ export function assert<
|
|
|
6
7
|
>(
|
|
7
8
|
that: string | undefined = undefined,
|
|
8
9
|
value: In,
|
|
9
|
-
predicate: (value: In) => value is Out,
|
|
10
|
+
predicate: Predicate<In, Out>, // (value: In) => value is Out,
|
|
10
11
|
): asserts value is Out {
|
|
11
12
|
if (!predicate(value)) {
|
|
12
13
|
throw new AssertionError(value, that)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { KebabCase } from 'type-fest'
|
|
2
|
+
import { COLOR_SCHEME_CLASS_NAME_REG_EXP } from './constants'
|
|
3
|
+
import { ColorSchemeClassName } from './types'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a string with a color scheme class name, prefixed with `scheme-`
|
|
7
|
+
*
|
|
8
|
+
* @param scheme - Color scheme name
|
|
9
|
+
* @returns A color scheme class name
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const colorScheme = colorSchemeClassName('system')
|
|
14
|
+
* // ^ 'scheme-system'
|
|
15
|
+
*
|
|
16
|
+
* return (
|
|
17
|
+
* <div className={colorScheme}>
|
|
18
|
+
* <button className={controlsThemeClassName}>Click me</button>
|
|
19
|
+
* </div>
|
|
20
|
+
*
|
|
21
|
+
* // renders:
|
|
22
|
+
* // <div class="scheme-system">
|
|
23
|
+
* // <button class="scheme-system theme-default-controls theme-danger-controls:hover">Click me</button>
|
|
24
|
+
* // </div>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function colorSchemeClassName<S extends KebabCase<string> = KebabCase<string>>(scheme: S): ColorSchemeClassName<S>;
|
|
28
|
+
export function colorSchemeClassName<S extends KebabCase<string> = KebabCase<string>>(scheme: null | undefined): undefined;
|
|
29
|
+
export function colorSchemeClassName<S extends KebabCase<string> = KebabCase<string>>(scheme: S | null | undefined): ColorSchemeClassName<S> | undefined;
|
|
30
|
+
export function colorSchemeClassName<S extends KebabCase<string> = KebabCase<string>>(scheme: S | null | undefined): ColorSchemeClassName<S> | undefined {
|
|
31
|
+
if (typeof scheme === 'string') {
|
|
32
|
+
return `scheme-${scheme}`
|
|
33
|
+
} else {
|
|
34
|
+
return undefined
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Tests if a string is a color scheme CSS class
|
|
40
|
+
* @param value - String to test
|
|
41
|
+
* @returns `true` if the string is a color scheme CSS class
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export function isColorSchemeClassName<T extends string>(value: string): value is ColorSchemeClassName<T> {
|
|
45
|
+
return COLOR_SCHEME_CLASS_NAME_REG_EXP.test(value)
|
|
46
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RegExp that matches theme class names
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*
|
|
6
|
+
* If theme is `default` then it will match:
|
|
7
|
+
*
|
|
8
|
+
* - theme-default
|
|
9
|
+
* - theme-default:hover
|
|
10
|
+
* - theme-default:active
|
|
11
|
+
* - theme-default:focus
|
|
12
|
+
* - theme-default-content
|
|
13
|
+
* - theme-default-content:hover
|
|
14
|
+
* - theme-default-content:active
|
|
15
|
+
* - theme-default-content:focus
|
|
16
|
+
* - theme-default-controls
|
|
17
|
+
* - theme-default-controls:hover
|
|
18
|
+
* - theme-default-controls:active
|
|
19
|
+
* - theme-default-controls:focus
|
|
20
|
+
*
|
|
21
|
+
* If theme is `brand-color` then it will match:
|
|
22
|
+
*
|
|
23
|
+
* - theme-brand-color
|
|
24
|
+
* - theme-brand-color:hover
|
|
25
|
+
* - theme-brand-color:active
|
|
26
|
+
* - theme-brand-color:focus
|
|
27
|
+
* - theme-brand-color-content
|
|
28
|
+
* - theme-brand-color-content:hover
|
|
29
|
+
* - theme-brand-color-content:active
|
|
30
|
+
* - theme-brand-color-content:focus
|
|
31
|
+
* - theme-brand-color-controls
|
|
32
|
+
* - theme-brand-color-controls:hover
|
|
33
|
+
* - theme-brand-color-controls:active
|
|
34
|
+
* - theme-brand-color-controls:focus
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
export const THEME_CLASS_NAME_REG_EXP = /^theme-(?<name>[\w-]+?)(?:-(?<scope>content|controls))?(?<state>:[\w]+(?:[\w-]+)?)?$/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Regular expression for testing if a string is a color scheme CSS class
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export const COLOR_SCHEME_CLASS_NAME_REG_EXP = /^scheme-(?<colorScheme>[a-z0-9]|[a-z0-9]+[a-z-]+[a-z])$/
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { KebabCase } from 'type-fest'
|
|
2
|
+
import { isColorSchemeClassName } from './colorSchemeClassName'
|
|
3
|
+
import { THEME_CLASS_NAME_REG_EXP } from './constants'
|
|
4
|
+
import { flatClassNameList } from './flatClassNameList'
|
|
5
|
+
import { contentThemeClassName, controlsThemeClassName } from './themeClassName'
|
|
6
|
+
import { ColorSchemeClassName, NestedClassName } from './types'
|
|
7
|
+
|
|
8
|
+
export type ThemeConfig = { content: string | undefined, controls: string | undefined }
|
|
9
|
+
|
|
10
|
+
export function filterThemedClassName(
|
|
11
|
+
nestedClassName: NestedClassName,
|
|
12
|
+
defaultColorSchemeContext: ColorSchemeClassName,
|
|
13
|
+
) {
|
|
14
|
+
const theme: ThemeConfig = { content: undefined, controls: undefined }
|
|
15
|
+
const stateThemes: Record<string, ThemeConfig> = {}
|
|
16
|
+
let colorScheme: ColorSchemeClassName | undefined = undefined
|
|
17
|
+
|
|
18
|
+
const flatClassName = flatClassNameList(nestedClassName).map(className => {
|
|
19
|
+
if (isColorSchemeClassName(className)) {
|
|
20
|
+
colorScheme = className
|
|
21
|
+
return undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const match = className.match(THEME_CLASS_NAME_REG_EXP)
|
|
25
|
+
|
|
26
|
+
if (match) {
|
|
27
|
+
const name = match.groups!.name as KebabCase<string>
|
|
28
|
+
const scope = match.groups!.scope as KebabCase<string>
|
|
29
|
+
const state = match.groups!.state as `:${KebabCase<string>}`
|
|
30
|
+
|
|
31
|
+
if (state) {
|
|
32
|
+
stateThemes[state] = stateThemes[state] ?? { content: undefined, controls: undefined }
|
|
33
|
+
|
|
34
|
+
if (!scope) {
|
|
35
|
+
stateThemes[state].content = name
|
|
36
|
+
stateThemes[state].controls = name
|
|
37
|
+
} else if (scope === 'content') {
|
|
38
|
+
stateThemes[state].content = name
|
|
39
|
+
} else if (scope === 'controls') {
|
|
40
|
+
stateThemes[state].controls = name
|
|
41
|
+
} else {
|
|
42
|
+
throw new Error(`Unknown theme scope: ${scope}`)
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
if (!scope) {
|
|
46
|
+
theme.content = name
|
|
47
|
+
theme.controls = name
|
|
48
|
+
} else if (scope === 'content') {
|
|
49
|
+
theme.content = name
|
|
50
|
+
} else if (scope === 'controls') {
|
|
51
|
+
theme.controls = name
|
|
52
|
+
} else {
|
|
53
|
+
throw new Error(`Unknown theme scope: ${scope}`)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return undefined
|
|
58
|
+
} else {
|
|
59
|
+
return className
|
|
60
|
+
}
|
|
61
|
+
}).filter(Boolean) as string[]
|
|
62
|
+
|
|
63
|
+
const themeClassNames: (string | undefined)[] = []
|
|
64
|
+
|
|
65
|
+
const content = contentThemeClassName(theme.content)
|
|
66
|
+
const controls = controlsThemeClassName(theme.controls)
|
|
67
|
+
|
|
68
|
+
themeClassNames.push(content, controls)
|
|
69
|
+
|
|
70
|
+
for (const state in stateThemes) {
|
|
71
|
+
const { content, controls } = stateThemes[state]
|
|
72
|
+
|
|
73
|
+
const contentClassName = contentThemeClassName(content, state as `:${KebabCase<string>}`)
|
|
74
|
+
const controlsClassName = controlsThemeClassName(controls, state as `:${KebabCase<string>}`)
|
|
75
|
+
|
|
76
|
+
themeClassNames.push(contentClassName, controlsClassName)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const flatThemedClassName = flatClassNameList(themeClassNames)
|
|
80
|
+
|
|
81
|
+
if (flatThemedClassName.length > 0 || colorScheme) {
|
|
82
|
+
return [colorScheme ?? defaultColorSchemeContext, ...flatThemedClassName, ...flatClassName]
|
|
83
|
+
} else {
|
|
84
|
+
return flatClassName
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { assertNever } from '
|
|
2
|
-
import { NestedClassName } from '
|
|
1
|
+
import { assertNever } from '../assert-types'
|
|
2
|
+
import { NestedClassName } from './types'
|
|
3
3
|
|
|
4
4
|
export function flatClassNameList(className: NestedClassName): string[] {
|
|
5
5
|
if (!className) {
|
package/src/class-name/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
1
|
+
export * from './colorSchemeClassName'
|
|
2
|
+
export * from './constants'
|
|
3
|
+
export * from './deduplicateClassName'
|
|
4
|
+
export * from './filterThemedClassName'
|
|
5
|
+
export * from './flatClassNameList'
|
|
3
6
|
export * from './listClassName'
|
|
4
7
|
export * from './stateClassName'
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
8
|
+
export * from './themeClassName'
|
|
9
|
+
export * from './types'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { deduplicateClassName } from './
|
|
2
|
-
import { flatClassNameList } from './
|
|
1
|
+
import { deduplicateClassName } from './deduplicateClassName'
|
|
2
|
+
import { flatClassNameList } from './flatClassNameList'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Combines a list of class names into a single string, even nested
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { toKebabCase } from '../string-utilities'
|
|
2
|
+
import { ClassNameStateMap } from './types'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return value.replace(UPPER_CASE_REG_EXP, '-$1').toLowerCase()
|
|
4
|
+
export interface StateClassNameOptions {
|
|
5
|
+
glue?: string;
|
|
6
|
+
removeFalsy?: boolean;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -13,12 +13,17 @@ function toKebabCase(value: string) {
|
|
|
13
13
|
* stateClassName({ foo: true, bar: false, baz: 1 }) // => 'foo baz-1'
|
|
14
14
|
*
|
|
15
15
|
* @param state - State map object with class names as keys and literals as values.
|
|
16
|
-
* @param
|
|
16
|
+
* @param options - Options object
|
|
17
|
+
* @param options.glue - Glue to use between the class name and the value, default is '-'. Set to '' to disable.
|
|
18
|
+
* @param options.removeFalsy - Whether to remove falsy class names, default is true.
|
|
17
19
|
* @returns Combined class names as string
|
|
18
20
|
*/
|
|
19
|
-
export function stateClassName(
|
|
21
|
+
export function stateClassName(
|
|
22
|
+
state: ClassNameStateMap | null = null,
|
|
23
|
+
{ glue = '-', removeFalsy = true }: StateClassNameOptions = {},
|
|
24
|
+
): string[] {
|
|
20
25
|
const entries = Object.entries(state ?? []).map(
|
|
21
|
-
([className, value]) => value || value === 0
|
|
26
|
+
([className, value]) => value || value === 0 || !removeFalsy
|
|
22
27
|
? (value === true ? toKebabCase(className) : `${toKebabCase(className)}${glue}${value}`)
|
|
23
28
|
: '',
|
|
24
29
|
).filter(Boolean)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { KebabCase } from 'type-fest'
|
|
2
|
+
import { colorSchemeClassName } from './colorSchemeClassName'
|
|
3
|
+
import { ThemeContentClassName, ThemeControlsClassName } from './types'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a string with a content theme class name, prefixed with `theme-` and suffixed with `-content`
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: Make sure to use color scheme class in combination with theme class names.
|
|
9
|
+
*
|
|
10
|
+
* @param contentTheme - Theme name basis for content
|
|
11
|
+
* @param state - State of the theme starting with a ":", e.g. `":hover"`, `":focus"`, `":active"`, `":focus-visible"`
|
|
12
|
+
* @returns A content theme class name
|
|
13
|
+
*
|
|
14
|
+
* @see {@link controlsThemeClassName}
|
|
15
|
+
* @see {@link (colorSchemeClassName:3)}
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const colorScheme = colorSchemeClassName('system')
|
|
20
|
+
* // ^ 'scheme-system'
|
|
21
|
+
* const contentThemeClassName = contentThemeClassName('default')
|
|
22
|
+
* // ^ 'theme-default-content:hover'
|
|
23
|
+
* const dangerOnMouseOverTheme = controlsThemeClassName('danger', ':hover')
|
|
24
|
+
* // ^ 'theme-danger-controls:hover'
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <div className={`${colorScheme} ${contentThemeClassName}`}>
|
|
28
|
+
* <button className={`${colorScheme} ${dangerOnMouseOverTheme}`}>Delete</button>
|
|
29
|
+
* </div>
|
|
30
|
+
* )
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export function contentThemeClassName<
|
|
34
|
+
ContentTheme extends KebabCase<string> = KebabCase<string>,
|
|
35
|
+
State extends `:${KebabCase<string>}` | null | undefined = undefined,
|
|
36
|
+
>(
|
|
37
|
+
theme: ContentTheme | null | undefined,
|
|
38
|
+
state?: State | null | undefined,
|
|
39
|
+
) {
|
|
40
|
+
return theme ? `theme-${theme}-content${state ?? ''}` as ThemeContentClassName<ContentTheme, State> : undefined
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Returns a string with a controls theme class name, prefixed with `theme-` and suffixed with `-controls`
|
|
45
|
+
*
|
|
46
|
+
* IMPORTANT: Make sure to use color scheme class in combination with theme class names.
|
|
47
|
+
*
|
|
48
|
+
* @param theme - Theme name basis for controls
|
|
49
|
+
* @param state - State of the theme starting with a ":", e.g. `":hover"`, `":focus"`, `":active"`, `":focus-visible"`
|
|
50
|
+
* @returns A controls theme class name
|
|
51
|
+
*
|
|
52
|
+
* @see {@link contentThemeClassName}
|
|
53
|
+
* @see {@link (colorSchemeClassName:3)}
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```tsx
|
|
57
|
+
* const colorScheme = colorSchemeClassName('system')
|
|
58
|
+
* // ^ 'scheme-system'
|
|
59
|
+
* const contentThemeClassName = contentThemeClassName('default')
|
|
60
|
+
* // ^ 'theme-default-content:hover'
|
|
61
|
+
* const dangerOnMouseOverTheme = controlsThemeClassName('danger', ':hover')
|
|
62
|
+
* // ^ 'theme-danger-controls:hover'
|
|
63
|
+
*
|
|
64
|
+
* return (
|
|
65
|
+
* <div className={`${colorScheme} ${contentThemeClassName}`}>
|
|
66
|
+
* <button className={`${colorScheme} ${dangerOnMouseOverTheme}`}>Delete</button>
|
|
67
|
+
* </div>
|
|
68
|
+
* )
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export function controlsThemeClassName<
|
|
72
|
+
ControlsTheme extends KebabCase<string> = KebabCase<string>,
|
|
73
|
+
State extends `:${KebabCase<string>}` | null | undefined = undefined,
|
|
74
|
+
>(
|
|
75
|
+
theme: ControlsTheme | null | undefined,
|
|
76
|
+
state?: State | null | undefined,
|
|
77
|
+
) {
|
|
78
|
+
return theme ? `theme-${theme}-controls${state ?? ''}` as ThemeControlsClassName<ControlsTheme, State> : undefined
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns a tuple with a content theme class name and a controls theme class name, prefixed with `theme-` and suffixed with `-content` and `-controls` respectively
|
|
83
|
+
*
|
|
84
|
+
* IMPORTANT: Make sure to use color scheme class in combination with theme class names.
|
|
85
|
+
*
|
|
86
|
+
* @param theme - Theme name basis for content and controls
|
|
87
|
+
* @param state - State of the theme starting with a ":", e.g. `":hover"`, `":focus"`, `":active"`, `":focus-visible"`
|
|
88
|
+
* @returns A tuple with a content theme class name and a controls theme class name
|
|
89
|
+
*
|
|
90
|
+
* @see {@link contentThemeClassName}
|
|
91
|
+
* @see {@link controlsThemeClassName}
|
|
92
|
+
* @see {@link (colorSchemeClassName:3)}
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```tsx
|
|
96
|
+
* const colorScheme = colorSchemeClassName('system')
|
|
97
|
+
* // ^ 'scheme-system'
|
|
98
|
+
* const errorTheme = themeClassName('danger').join(' ')
|
|
99
|
+
* // ^ 'theme-danger-content theme-danger-controls'
|
|
100
|
+
*
|
|
101
|
+
* return (
|
|
102
|
+
* <div className={`${colorScheme} ${errorTheme}`}>File not found</div>
|
|
103
|
+
* )
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export function themeClassName<
|
|
107
|
+
Theme extends KebabCase<string> = KebabCase<string>,
|
|
108
|
+
State extends `:${KebabCase<string>}` | null | undefined = undefined,
|
|
109
|
+
>(
|
|
110
|
+
theme: Theme | null | undefined,
|
|
111
|
+
state?: State | null | undefined,
|
|
112
|
+
) {
|
|
113
|
+
return [
|
|
114
|
+
contentThemeClassName(theme, state),
|
|
115
|
+
controlsThemeClassName(theme, state),
|
|
116
|
+
] as const
|
|
117
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react'
|
|
2
|
+
import { KebabCase } from 'type-fest'
|
|
3
|
+
|
|
4
|
+
export type NestedClassName = string | false | null | undefined | (string | false | null | undefined)[] | NestedClassName[]
|
|
5
|
+
export type ClassNameStateMap = { [key: string]: string | number | boolean | null | undefined }
|
|
6
|
+
|
|
7
|
+
export type ComponentClassNameProps = PropsWithChildren<{
|
|
8
|
+
className?: NestedClassName;
|
|
9
|
+
componentClassName?: string | string[];
|
|
10
|
+
}>
|
|
11
|
+
|
|
12
|
+
export type ColorSchemeClassName<T extends KebabCase<string> = KebabCase<string>> = `scheme-${T}`
|
|
13
|
+
export type ThemeContentClassName<T extends KebabCase<string> = KebabCase<string>, S extends `:${KebabCase<string>}` | null | undefined = undefined> = S extends string
|
|
14
|
+
? `theme-${T}-content${S}`
|
|
15
|
+
: `theme-${T}-content`
|
|
16
|
+
export type ThemeControlsClassName<T extends KebabCase<string> = KebabCase<string>, S extends `:${KebabCase<string>}` | null | undefined = undefined> = S extends string
|
|
17
|
+
? `theme-${T}-controls${S}`
|
|
18
|
+
: `theme-${T}-controls`
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves current or deprecated value. If both are defined, it will throw an error in development mode.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*
|
|
6
|
+
* Errors are thrown only in development mode. In production mode, the deprecated value is returned.
|
|
7
|
+
*
|
|
8
|
+
* @param current - Current value that replaces deprecated value
|
|
9
|
+
* @param deprecated - Deprecated value that will be removed in the next release
|
|
10
|
+
* @param shouldThrow - Whether to throw an error if both current and deprecated are defined
|
|
11
|
+
* @returns Deprecated value if it is defined, otherwise current value
|
|
12
|
+
* @throws Error if both current and deprecated are defined
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const current = 'current'
|
|
17
|
+
* const deprecated = 'deprecated'
|
|
18
|
+
*
|
|
19
|
+
* const value = currentOrDeprecated(current, deprecated)
|
|
20
|
+
*
|
|
21
|
+
* console.log(value) // 'deprecated'
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const current = 'current'
|
|
27
|
+
* const deprecated = undefined
|
|
28
|
+
*
|
|
29
|
+
* const value = currentOrDeprecated(current, deprecated)
|
|
30
|
+
*
|
|
31
|
+
* console.log(value) // 'current'
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function currentOrDeprecated<R, D>(current: R, deprecated: D, shouldThrow: boolean = false): R | D {
|
|
35
|
+
if (deprecated !== undefined) {
|
|
36
|
+
if (current !== undefined && import.meta.env.DEV) {
|
|
37
|
+
console.error('Current value:', current)
|
|
38
|
+
console.error('Deprecated value:', deprecated)
|
|
39
|
+
|
|
40
|
+
if (shouldThrow) {
|
|
41
|
+
throw new Error(`You are using deprecated together with current value which is mutually exclusive. Use only one of them.`)
|
|
42
|
+
} else {
|
|
43
|
+
console.error(`You are using deprecated together with current value which is mutually exclusive. Use only one of them.`)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return deprecated
|
|
48
|
+
} else {
|
|
49
|
+
return current
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SemverString } from './types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Logs a deprecation warning if the assertion is `false`.
|
|
5
|
+
* @internal
|
|
6
|
+
*
|
|
7
|
+
* @param removal - Version when the deprecated feature will be removed
|
|
8
|
+
* @param assertion - Condition that must be true to avoid the deprecation warning
|
|
9
|
+
* @param deprecated - Name of the deprecated feature
|
|
10
|
+
* @param replacement - Name of the feature that replaces the deprecated feature
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const { visible } = props
|
|
15
|
+
* deprecate(visible !== 'default', '1.3.0', '"default"', '"hidden"')
|
|
16
|
+
* // Logs: Use of "default" is deprecated and might be removed in the next release. Use "hidden" instead.
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function deprecate(removal: SemverString, assertion: boolean, deprecated: string, replacement: string): void {
|
|
20
|
+
if (assertion === false) {
|
|
21
|
+
if (import.meta.env.DEV) {
|
|
22
|
+
const shouldThrow = Boolean(import.meta.env.VITE_CONTEMBER_ADMIN_STRICT_DEPRECATIONS)
|
|
23
|
+
|
|
24
|
+
if (shouldThrow) {
|
|
25
|
+
throw new Error(`Support for ${deprecated} was planned to be removed in the ${removal} release. Replace it with ${replacement} instead.`)
|
|
26
|
+
} else {
|
|
27
|
+
console.warn(`Use of ${deprecated} is deprecated and might be removed in the next release. Use ${replacement} instead.`)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/dom/index.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { toKebabCase } from '../string-utilities'
|
|
2
|
+
import { dataAttribute } from './dataAttribute'
|
|
3
|
+
|
|
4
|
+
export function stateDataAttributes(state: Record<string, unknown>) {
|
|
5
|
+
return Object.fromEntries(Object.entries(state).map(
|
|
6
|
+
([key, value]) => [`data-${toKebabCase(key).toLowerCase()}`, dataAttribute(value)],
|
|
7
|
+
))
|
|
8
|
+
}
|
package/src/dom/svgSizeProps.ts
CHANGED
package/src/functional/index.ts
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function omit<T extends Object, K extends keyof T>(object: T, properties: ReadonlyArray<K>, strict: boolean = false): Omit<T, K> {
|
|
2
|
+
const next: Partial<T> = { ...object }
|
|
3
|
+
|
|
4
|
+
for (let key of properties) {
|
|
5
|
+
if (key in object) {
|
|
6
|
+
delete next[key]
|
|
7
|
+
} else if (strict) {
|
|
8
|
+
throw new Error(`Key "${String(key)}" does not exist in object ${JSON.stringify(object)}`)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return next as Omit<T, K>
|
|
13
|
+
}
|
package/src/functional/pick.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function pick<T extends Object, K extends keyof T>(object: T, properties: K
|
|
1
|
+
export function pick<T extends Object, K extends keyof T>(object: T, properties: ReadonlyArray<K>): Pick<T, K> {
|
|
2
2
|
const next: Partial<Pick<T, K>> = {}
|
|
3
3
|
|
|
4
4
|
for (let key of properties) {
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export * from './assert-types'
|
|
2
2
|
export * from './class-name'
|
|
3
3
|
export * from './css-utilities'
|
|
4
|
+
export * from './deprecate'
|
|
4
5
|
export * from './dom'
|
|
5
6
|
export * from './functional'
|
|
6
7
|
export * from './string-utilities'
|
|
7
|
-
export * from './
|
|
8
|
+
export * from './types'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Primitive = string | number | boolean | null | undefined
|