@contember/utilities 0.0.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 (293) hide show
  1. package/dist/development/assert-types/AssertionError.js +9 -0
  2. package/dist/development/assert-types/AssertionError.js.map +1 -0
  3. package/dist/development/assert-types/Predicates.js +108 -0
  4. package/dist/development/assert-types/Predicates.js.map +1 -0
  5. package/dist/development/assert-types/assert.js +10 -0
  6. package/dist/development/assert-types/assert.js.map +1 -0
  7. package/dist/development/assert-types/assertNever.js +7 -0
  8. package/dist/development/assert-types/assertNever.js.map +1 -0
  9. package/dist/development/class-name/colorSchemeClassName.js +16 -0
  10. package/dist/development/class-name/colorSchemeClassName.js.map +1 -0
  11. package/dist/development/class-name/constants.js +7 -0
  12. package/dist/development/class-name/constants.js.map +1 -0
  13. package/dist/development/class-name/deduplicateClassName.js +7 -0
  14. package/dist/development/class-name/deduplicateClassName.js.map +1 -0
  15. package/dist/development/class-name/filterThemedClassName.js +68 -0
  16. package/dist/development/class-name/filterThemedClassName.js.map +1 -0
  17. package/dist/development/class-name/flatClassNameList.js +16 -0
  18. package/dist/development/class-name/flatClassNameList.js.map +1 -0
  19. package/dist/development/class-name/listClassName.js +9 -0
  20. package/dist/development/class-name/listClassName.js.map +1 -0
  21. package/dist/development/class-name/stateClassName.js +11 -0
  22. package/dist/development/class-name/stateClassName.js.map +1 -0
  23. package/dist/development/class-name/themeClassName.js +18 -0
  24. package/dist/development/class-name/themeClassName.js.map +1 -0
  25. package/dist/development/css-utilities/px.js +7 -0
  26. package/dist/development/css-utilities/px.js.map +1 -0
  27. package/dist/development/deprecate/deprecate.js +6 -0
  28. package/dist/development/deprecate/deprecate.js.map +1 -0
  29. package/dist/development/deprecate/fallback.js +11 -0
  30. package/dist/development/deprecate/fallback.js.map +1 -0
  31. package/dist/development/dom/dataAttribute.js +13 -0
  32. package/dist/development/dom/dataAttribute.js.map +1 -0
  33. package/dist/development/dom/getElementDimensions.js +22 -0
  34. package/dist/development/dom/getElementDimensions.js.map +1 -0
  35. package/dist/development/dom/getMatchingParentElement.js +17 -0
  36. package/dist/development/dom/getMatchingParentElement.js.map +1 -0
  37. package/dist/development/dom/getSizeFromResizeObserverEntry.js +24 -0
  38. package/dist/development/dom/getSizeFromResizeObserverEntry.js.map +1 -0
  39. package/dist/development/dom/isScrollable.js +22 -0
  40. package/dist/development/dom/isScrollable.js.map +1 -0
  41. package/dist/development/dom/parseTransformMatrix.js +29 -0
  42. package/dist/development/dom/parseTransformMatrix.js.map +1 -0
  43. package/dist/development/dom/stateDataAttributes.js +11 -0
  44. package/dist/development/dom/stateDataAttributes.js.map +1 -0
  45. package/dist/development/dom/svgSizeProps.js +15 -0
  46. package/dist/development/dom/svgSizeProps.js.map +1 -0
  47. package/dist/development/functional/extend.js +33 -0
  48. package/dist/development/functional/extend.js.map +1 -0
  49. package/dist/development/functional/omit.js +15 -0
  50. package/dist/development/functional/omit.js.map +1 -0
  51. package/dist/development/functional/pick.js +15 -0
  52. package/dist/development/functional/pick.js.map +1 -0
  53. package/dist/development/functional/range.js +7 -0
  54. package/dist/development/functional/range.js.map +1 -0
  55. package/dist/development/functional/setHasOneOf.js +7 -0
  56. package/dist/development/functional/setHasOneOf.js.map +1 -0
  57. package/dist/development/index.js +94 -0
  58. package/dist/development/index.js.map +1 -0
  59. package/dist/development/string-utilities/capitalize.js +7 -0
  60. package/dist/development/string-utilities/capitalize.js.map +1 -0
  61. package/dist/development/string-utilities/kebabCase.js +8 -0
  62. package/dist/development/string-utilities/kebabCase.js.map +1 -0
  63. package/dist/development/string-utilities/trimString.js +8 -0
  64. package/dist/development/string-utilities/trimString.js.map +1 -0
  65. package/dist/production/assert-types/AssertionError.js +9 -0
  66. package/dist/production/assert-types/AssertionError.js.map +1 -0
  67. package/dist/production/assert-types/Predicates.js +108 -0
  68. package/dist/production/assert-types/Predicates.js.map +1 -0
  69. package/dist/production/assert-types/assert.js +10 -0
  70. package/dist/production/assert-types/assert.js.map +1 -0
  71. package/dist/production/assert-types/assertNever.js +7 -0
  72. package/dist/production/assert-types/assertNever.js.map +1 -0
  73. package/dist/production/class-name/colorSchemeClassName.js +16 -0
  74. package/dist/production/class-name/colorSchemeClassName.js.map +1 -0
  75. package/dist/production/class-name/constants.js +7 -0
  76. package/dist/production/class-name/constants.js.map +1 -0
  77. package/dist/production/class-name/deduplicateClassName.js +7 -0
  78. package/dist/production/class-name/deduplicateClassName.js.map +1 -0
  79. package/dist/production/class-name/filterThemedClassName.js +68 -0
  80. package/dist/production/class-name/filterThemedClassName.js.map +1 -0
  81. package/dist/production/class-name/flatClassNameList.js +16 -0
  82. package/dist/production/class-name/flatClassNameList.js.map +1 -0
  83. package/dist/production/class-name/listClassName.js +9 -0
  84. package/dist/production/class-name/listClassName.js.map +1 -0
  85. package/dist/production/class-name/stateClassName.js +11 -0
  86. package/dist/production/class-name/stateClassName.js.map +1 -0
  87. package/dist/production/class-name/themeClassName.js +18 -0
  88. package/dist/production/class-name/themeClassName.js.map +1 -0
  89. package/dist/production/css-utilities/px.js +7 -0
  90. package/dist/production/css-utilities/px.js.map +1 -0
  91. package/dist/production/deprecate/deprecate.js +6 -0
  92. package/dist/production/deprecate/deprecate.js.map +1 -0
  93. package/dist/production/deprecate/fallback.js +11 -0
  94. package/dist/production/deprecate/fallback.js.map +1 -0
  95. package/dist/production/dom/dataAttribute.js +13 -0
  96. package/dist/production/dom/dataAttribute.js.map +1 -0
  97. package/dist/production/dom/getElementDimensions.js +22 -0
  98. package/dist/production/dom/getElementDimensions.js.map +1 -0
  99. package/dist/production/dom/getMatchingParentElement.js +17 -0
  100. package/dist/production/dom/getMatchingParentElement.js.map +1 -0
  101. package/dist/production/dom/getSizeFromResizeObserverEntry.js +24 -0
  102. package/dist/production/dom/getSizeFromResizeObserverEntry.js.map +1 -0
  103. package/dist/production/dom/isScrollable.js +22 -0
  104. package/dist/production/dom/isScrollable.js.map +1 -0
  105. package/dist/production/dom/parseTransformMatrix.js +29 -0
  106. package/dist/production/dom/parseTransformMatrix.js.map +1 -0
  107. package/dist/production/dom/stateDataAttributes.js +11 -0
  108. package/dist/production/dom/stateDataAttributes.js.map +1 -0
  109. package/dist/production/dom/svgSizeProps.js +15 -0
  110. package/dist/production/dom/svgSizeProps.js.map +1 -0
  111. package/dist/production/functional/extend.js +33 -0
  112. package/dist/production/functional/extend.js.map +1 -0
  113. package/dist/production/functional/omit.js +15 -0
  114. package/dist/production/functional/omit.js.map +1 -0
  115. package/dist/production/functional/pick.js +15 -0
  116. package/dist/production/functional/pick.js.map +1 -0
  117. package/dist/production/functional/range.js +7 -0
  118. package/dist/production/functional/range.js.map +1 -0
  119. package/dist/production/functional/setHasOneOf.js +7 -0
  120. package/dist/production/functional/setHasOneOf.js.map +1 -0
  121. package/dist/production/index.js +94 -0
  122. package/dist/production/index.js.map +1 -0
  123. package/dist/production/string-utilities/capitalize.js +7 -0
  124. package/dist/production/string-utilities/capitalize.js.map +1 -0
  125. package/dist/production/string-utilities/kebabCase.js +8 -0
  126. package/dist/production/string-utilities/kebabCase.js.map +1 -0
  127. package/dist/production/string-utilities/trimString.js +8 -0
  128. package/dist/production/string-utilities/trimString.js.map +1 -0
  129. package/dist/types/assert-types/AssertionError.d.ts +4 -0
  130. package/dist/types/assert-types/AssertionError.d.ts.map +1 -0
  131. package/dist/types/assert-types/Predicates.d.ts +27 -0
  132. package/dist/types/assert-types/Predicates.d.ts.map +1 -0
  133. package/dist/types/assert-types/assert.d.ts +3 -0
  134. package/dist/types/assert-types/assert.d.ts.map +1 -0
  135. package/dist/types/assert-types/assertNever.d.ts +2 -0
  136. package/dist/types/assert-types/assertNever.d.ts.map +1 -0
  137. package/dist/types/assert-types/index.d.ts +6 -0
  138. package/dist/types/assert-types/index.d.ts.map +1 -0
  139. package/dist/types/assert-types/types.d.ts +5 -0
  140. package/dist/types/assert-types/types.d.ts.map +1 -0
  141. package/dist/types/class-name/colorSchemeClassName.d.ts +35 -0
  142. package/dist/types/class-name/colorSchemeClassName.d.ts.map +1 -0
  143. package/dist/types/class-name/constants.d.ts +42 -0
  144. package/dist/types/class-name/constants.d.ts.map +1 -0
  145. package/dist/types/class-name/deduplicateClassName.d.ts +2 -0
  146. package/dist/types/class-name/deduplicateClassName.d.ts.map +1 -0
  147. package/dist/types/class-name/filterThemedClassName.d.ts +7 -0
  148. package/dist/types/class-name/filterThemedClassName.d.ts.map +1 -0
  149. package/dist/types/class-name/flatClassNameList.d.ts +3 -0
  150. package/dist/types/class-name/flatClassNameList.d.ts.map +1 -0
  151. package/dist/types/class-name/index.d.ts +10 -0
  152. package/dist/types/class-name/index.d.ts.map +1 -0
  153. package/dist/types/class-name/listClassName.d.ts +9 -0
  154. package/dist/types/class-name/listClassName.d.ts.map +1 -0
  155. package/dist/types/class-name/stateClassName.d.ts +19 -0
  156. package/dist/types/class-name/stateClassName.d.ts.map +1 -0
  157. package/dist/types/class-name/themeClassName.d.ts +87 -0
  158. package/dist/types/class-name/themeClassName.d.ts.map +1 -0
  159. package/dist/types/class-name/types.d.ts +13 -0
  160. package/dist/types/class-name/types.d.ts.map +1 -0
  161. package/dist/types/css-utilities/index.d.ts +2 -0
  162. package/dist/types/css-utilities/index.d.ts.map +1 -0
  163. package/dist/types/css-utilities/px.d.ts +6 -0
  164. package/dist/types/css-utilities/px.d.ts.map +1 -0
  165. package/dist/types/deprecate/deprecate.d.ts +19 -0
  166. package/dist/types/deprecate/deprecate.d.ts.map +1 -0
  167. package/dist/types/deprecate/fallback.d.ts +2 -0
  168. package/dist/types/deprecate/fallback.d.ts.map +1 -0
  169. package/dist/types/deprecate/index.d.ts +4 -0
  170. package/dist/types/deprecate/index.d.ts.map +1 -0
  171. package/dist/types/deprecate/types.d.ts +2 -0
  172. package/dist/types/deprecate/types.d.ts.map +1 -0
  173. package/dist/types/dom/dataAttribute.d.ts +2 -0
  174. package/dist/types/dom/dataAttribute.d.ts.map +1 -0
  175. package/dist/types/dom/getElementDimensions.d.ts +14 -0
  176. package/dist/types/dom/getElementDimensions.d.ts.map +1 -0
  177. package/dist/types/dom/getMatchingParentElement.d.ts +2 -0
  178. package/dist/types/dom/getMatchingParentElement.d.ts.map +1 -0
  179. package/dist/types/dom/getSizeFromResizeObserverEntry.d.ts +5 -0
  180. package/dist/types/dom/getSizeFromResizeObserverEntry.d.ts.map +1 -0
  181. package/dist/types/dom/index.d.ts +9 -0
  182. package/dist/types/dom/index.d.ts.map +1 -0
  183. package/dist/types/dom/isScrollable.d.ts +7 -0
  184. package/dist/types/dom/isScrollable.d.ts.map +1 -0
  185. package/dist/types/dom/parseTransformMatrix.d.ts +15 -0
  186. package/dist/types/dom/parseTransformMatrix.d.ts.map +1 -0
  187. package/dist/types/dom/stateDataAttributes.d.ts +4 -0
  188. package/dist/types/dom/stateDataAttributes.d.ts.map +1 -0
  189. package/dist/types/dom/svgSizeProps.d.ts +7 -0
  190. package/dist/types/dom/svgSizeProps.d.ts.map +1 -0
  191. package/dist/types/functional/extend.d.ts +5 -0
  192. package/dist/types/functional/extend.d.ts.map +1 -0
  193. package/dist/types/functional/index.d.ts +6 -0
  194. package/dist/types/functional/index.d.ts.map +1 -0
  195. package/dist/types/functional/omit.d.ts +2 -0
  196. package/dist/types/functional/omit.d.ts.map +1 -0
  197. package/dist/types/functional/pick.d.ts +2 -0
  198. package/dist/types/functional/pick.d.ts.map +1 -0
  199. package/dist/types/functional/range.d.ts +9 -0
  200. package/dist/types/functional/range.d.ts.map +1 -0
  201. package/dist/types/functional/setHasOneOf.d.ts +2 -0
  202. package/dist/types/functional/setHasOneOf.d.ts.map +1 -0
  203. package/dist/types/index.d.ts +9 -0
  204. package/dist/types/index.d.ts.map +1 -0
  205. package/dist/types/string-utilities/capitalize.d.ts +2 -0
  206. package/dist/types/string-utilities/capitalize.d.ts.map +1 -0
  207. package/dist/types/string-utilities/index.d.ts +4 -0
  208. package/dist/types/string-utilities/index.d.ts.map +1 -0
  209. package/dist/types/string-utilities/kebabCase.d.ts +2 -0
  210. package/dist/types/string-utilities/kebabCase.d.ts.map +1 -0
  211. package/dist/types/string-utilities/trimString.d.ts +9 -0
  212. package/dist/types/string-utilities/trimString.d.ts.map +1 -0
  213. package/dist/types/tsconfig.tsbuildinfo +1 -0
  214. package/dist/types/types/Any.d.ts +4 -0
  215. package/dist/types/types/Any.d.ts.map +1 -0
  216. package/dist/types/types/DeepPartial.d.ts +4 -0
  217. package/dist/types/types/DeepPartial.d.ts.map +1 -0
  218. package/dist/types/types/Narrow.d.ts +11 -0
  219. package/dist/types/types/Narrow.d.ts.map +1 -0
  220. package/dist/types/types/NonNullableRequired.d.ts +4 -0
  221. package/dist/types/types/NonNullableRequired.d.ts.map +1 -0
  222. package/dist/types/types/NonOptional.d.ts +8 -0
  223. package/dist/types/types/NonOptional.d.ts.map +1 -0
  224. package/dist/types/types/ObjectKeyValue.d.ts +4 -0
  225. package/dist/types/types/ObjectKeyValue.d.ts.map +1 -0
  226. package/dist/types/types/PolymorphicRefs.d.ts +46 -0
  227. package/dist/types/types/PolymorphicRefs.d.ts.map +1 -0
  228. package/dist/types/types/Primitive.d.ts +2 -0
  229. package/dist/types/types/Primitive.d.ts.map +1 -0
  230. package/dist/types/types/RequiredDeepPlainObject.d.ts +4 -0
  231. package/dist/types/types/RequiredDeepPlainObject.d.ts.map +1 -0
  232. package/dist/types/types/Try.d.ts +2 -0
  233. package/dist/types/types/Try.d.ts.map +1 -0
  234. package/dist/types/types/TypeofStringLiteral.d.ts +2 -0
  235. package/dist/types/types/TypeofStringLiteral.d.ts.map +1 -0
  236. package/dist/types/types/index.d.ts +13 -0
  237. package/dist/types/types/index.d.ts.map +1 -0
  238. package/package.json +42 -0
  239. package/src/assert-types/AssertionError.ts +5 -0
  240. package/src/assert-types/Predicates.ts +88 -0
  241. package/src/assert-types/assert.ts +15 -0
  242. package/src/assert-types/assertNever.ts +3 -0
  243. package/src/assert-types/index.ts +5 -0
  244. package/src/assert-types/types.ts +5 -0
  245. package/src/class-name/colorSchemeClassName.ts +46 -0
  246. package/src/class-name/constants.ts +43 -0
  247. package/src/class-name/deduplicateClassName.ts +3 -0
  248. package/src/class-name/filterThemedClassName.ts +86 -0
  249. package/src/class-name/flatClassNameList.ts +18 -0
  250. package/src/class-name/index.ts +9 -0
  251. package/src/class-name/listClassName.ts +13 -0
  252. package/src/class-name/stateClassName.ts +32 -0
  253. package/src/class-name/themeClassName.ts +116 -0
  254. package/src/class-name/types.ts +17 -0
  255. package/src/css-utilities/index.ts +1 -0
  256. package/src/css-utilities/px.ts +16 -0
  257. package/src/deprecate/deprecate.ts +31 -0
  258. package/src/deprecate/fallback.ts +7 -0
  259. package/src/deprecate/index.ts +3 -0
  260. package/src/deprecate/types.ts +2 -0
  261. package/src/dom/dataAttribute.ts +11 -0
  262. package/src/dom/getElementDimensions.ts +36 -0
  263. package/src/dom/getMatchingParentElement.ts +13 -0
  264. package/src/dom/getSizeFromResizeObserverEntry.ts +26 -0
  265. package/src/dom/index.ts +8 -0
  266. package/src/dom/isScrollable.ts +24 -0
  267. package/src/dom/parseTransformMatrix.ts +35 -0
  268. package/src/dom/stateDataAttributes.ts +8 -0
  269. package/src/dom/svgSizeProps.ts +21 -0
  270. package/src/functional/extend.ts +37 -0
  271. package/src/functional/index.ts +5 -0
  272. package/src/functional/omit.ts +13 -0
  273. package/src/functional/pick.ts +13 -0
  274. package/src/functional/range.ts +11 -0
  275. package/src/functional/setHasOneOf.ts +3 -0
  276. package/src/index.ts +8 -0
  277. package/src/string-utilities/capitalize.ts +3 -0
  278. package/src/string-utilities/index.ts +3 -0
  279. package/src/string-utilities/kebabCase.ts +5 -0
  280. package/src/string-utilities/trimString.ts +12 -0
  281. package/src/tsconfig.json +6 -0
  282. package/src/types/Any.ts +3 -0
  283. package/src/types/DeepPartial.ts +7 -0
  284. package/src/types/Narrow.ts +21 -0
  285. package/src/types/NonNullableRequired.ts +1 -0
  286. package/src/types/NonOptional.ts +7 -0
  287. package/src/types/ObjectKeyValue.ts +1 -0
  288. package/src/types/PolymorphicRefs.ts +68 -0
  289. package/src/types/Primitive.ts +1 -0
  290. package/src/types/RequiredDeepPlainObject.ts +3 -0
  291. package/src/types/Try.ts +4 -0
  292. package/src/types/TypeofStringLiteral.ts +1 -0
  293. package/src/types/index.ts +24 -0
@@ -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
+ }
@@ -0,0 +1,18 @@
1
+ import { assertNever } from '../assert-types'
2
+ import { NestedClassName } from './types'
3
+
4
+ export function flatClassNameList(className: NestedClassName): string[] {
5
+ if (!className) {
6
+ return []
7
+ } else if (typeof className === 'string') {
8
+ return className.split(' ').filter(Boolean)
9
+ } else if (Array.isArray(className)) {
10
+ return className.flatMap(flatClassNameList)
11
+ } else {
12
+ if (import.meta.env.DEV) {
13
+ console.error(`Unexpected className: ${JSON.stringify(className)}`)
14
+ }
15
+
16
+ assertNever(className)
17
+ }
18
+ }
@@ -0,0 +1,9 @@
1
+ export * from './colorSchemeClassName'
2
+ export * from './constants'
3
+ export * from './deduplicateClassName'
4
+ export * from './filterThemedClassName'
5
+ export * from './flatClassNameList'
6
+ export * from './listClassName'
7
+ export * from './stateClassName'
8
+ export * from './themeClassName'
9
+ export * from './types'
@@ -0,0 +1,13 @@
1
+ import { deduplicateClassName } from './deduplicateClassName'
2
+ import { flatClassNameList } from './flatClassNameList'
3
+ import { NestedClassName } from './types'
4
+
5
+ /**
6
+ * Combines a list of class names into a single string, even nested
7
+ *
8
+ * @param list - List of class names
9
+ * @returns Combined class names as string
10
+ */
11
+ export function listClassName(list: NestedClassName) {
12
+ return deduplicateClassName(flatClassNameList(list)).join(' ')
13
+ }
@@ -0,0 +1,32 @@
1
+ import { toKebabCase } from '../string-utilities'
2
+ import { ClassNameStateMap } from './types'
3
+
4
+ export interface StateClassNameOptions {
5
+ glue?: string;
6
+ removeFalsy?: boolean;
7
+ }
8
+
9
+ /**
10
+ * Combines a state map of class names into a single string
11
+ *
12
+ * @example
13
+ * stateClassName({ foo: true, bar: false, baz: 1 }) // => 'foo baz-1'
14
+ *
15
+ * @param state - State map object with class names as keys and literals as values.
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.
19
+ * @returns Combined class names as string
20
+ */
21
+ export function stateClassName(
22
+ state: ClassNameStateMap | null = null,
23
+ { glue = '-', removeFalsy = true }: StateClassNameOptions = {},
24
+ ): string[] {
25
+ const entries = Object.entries(state ?? []).map(
26
+ ([className, value]) => value || value === 0 || !removeFalsy
27
+ ? (value === true ? toKebabCase(className) : `${toKebabCase(className)}${glue}${value}`)
28
+ : '',
29
+ ).filter(Boolean)
30
+
31
+ return entries
32
+ }
@@ -0,0 +1,116 @@
1
+ import { KebabCase } from 'type-fest'
2
+ import { ThemeContentClassName, ThemeControlsClassName } from './types'
3
+
4
+ /**
5
+ * Returns a string with a content theme class name, prefixed with `theme-` and suffixed with `-content`
6
+ *
7
+ * IMPORTANT: Make sure to use color scheme class in combination with theme class names.
8
+ *
9
+ * @param contentTheme - Theme name basis for content
10
+ * @param state - State of the theme starting with a ":", e.g. `":hover"`, `":focus"`, `":active"`, `":focus-visible"`
11
+ * @returns A content theme class name
12
+ *
13
+ * @see {@link controlsThemeClassName}
14
+ * @see {@link (colorSchemeClassName:3)}
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * const colorScheme = colorSchemeClassName('system')
19
+ * // ^ 'scheme-system'
20
+ * const contentThemeClassName = contentThemeClassName('default')
21
+ * // ^ 'theme-default-content:hover'
22
+ * const dangerOnMouseOverTheme = controlsThemeClassName('danger', ':hover')
23
+ * // ^ 'theme-danger-controls:hover'
24
+ *
25
+ * return (
26
+ * <div className={`${colorScheme} ${contentThemeClassName}`}>
27
+ * <button className={`${colorScheme} ${dangerOnMouseOverTheme}`}>Delete</button>
28
+ * </div>
29
+ * )
30
+ * ```
31
+ */
32
+ export function contentThemeClassName<
33
+ ContentTheme extends KebabCase<string> = KebabCase<string>,
34
+ State extends `:${KebabCase<string>}` | null | undefined = undefined,
35
+ >(
36
+ theme: ContentTheme | null | undefined,
37
+ state?: State | null | undefined,
38
+ ) {
39
+ return theme ? `theme-${theme}-content${state ?? ''}` as ThemeContentClassName<ContentTheme, State> : undefined
40
+ }
41
+
42
+ /**
43
+ * Returns a string with a controls theme class name, prefixed with `theme-` and suffixed with `-controls`
44
+ *
45
+ * IMPORTANT: Make sure to use color scheme class in combination with theme class names.
46
+ *
47
+ * @param theme - Theme name basis for controls
48
+ * @param state - State of the theme starting with a ":", e.g. `":hover"`, `":focus"`, `":active"`, `":focus-visible"`
49
+ * @returns A controls theme class name
50
+ *
51
+ * @see {@link contentThemeClassName}
52
+ * @see {@link (colorSchemeClassName:3)}
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * const colorScheme = colorSchemeClassName('system')
57
+ * // ^ 'scheme-system'
58
+ * const contentThemeClassName = contentThemeClassName('default')
59
+ * // ^ 'theme-default-content:hover'
60
+ * const dangerOnMouseOverTheme = controlsThemeClassName('danger', ':hover')
61
+ * // ^ 'theme-danger-controls:hover'
62
+ *
63
+ * return (
64
+ * <div className={`${colorScheme} ${contentThemeClassName}`}>
65
+ * <button className={`${colorScheme} ${dangerOnMouseOverTheme}`}>Delete</button>
66
+ * </div>
67
+ * )
68
+ * ```
69
+ */
70
+ export function controlsThemeClassName<
71
+ ControlsTheme extends KebabCase<string> = KebabCase<string>,
72
+ State extends `:${KebabCase<string>}` | null | undefined = undefined,
73
+ >(
74
+ theme: ControlsTheme | null | undefined,
75
+ state?: State | null | undefined,
76
+ ) {
77
+ return theme ? `theme-${theme}-controls${state ?? ''}` as ThemeControlsClassName<ControlsTheme, State> : undefined
78
+ }
79
+
80
+ /**
81
+ * 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
82
+ *
83
+ * IMPORTANT: Make sure to use color scheme class in combination with theme class names.
84
+ *
85
+ * @param theme - Theme name basis for content and controls
86
+ * @param state - State of the theme starting with a ":", e.g. `":hover"`, `":focus"`, `":active"`, `":focus-visible"`
87
+ * @returns A tuple with a content theme class name and a controls theme class name
88
+ *
89
+ * @see {@link contentThemeClassName}
90
+ * @see {@link controlsThemeClassName}
91
+ * @see {@link (colorSchemeClassName:3)}
92
+ *
93
+ * @example
94
+ * ```tsx
95
+ * const colorScheme = colorSchemeClassName('system')
96
+ * // ^ 'scheme-system'
97
+ * const errorTheme = themeClassName('danger').join(' ')
98
+ * // ^ 'theme-danger-content theme-danger-controls'
99
+ *
100
+ * return (
101
+ * <div className={`${colorScheme} ${errorTheme}`}>File not found</div>
102
+ * )
103
+ * ```
104
+ */
105
+ export function themeClassName<
106
+ Theme extends KebabCase<string> = KebabCase<string>,
107
+ State extends `:${KebabCase<string>}` | null | undefined = undefined,
108
+ >(
109
+ theme: Theme | null | undefined,
110
+ state?: State | null | undefined,
111
+ ) {
112
+ return [
113
+ contentThemeClassName(theme, state),
114
+ controlsThemeClassName(theme, state),
115
+ ] as const
116
+ }
@@ -0,0 +1,17 @@
1
+ import { KebabCase } from 'type-fest'
2
+
3
+ export type NestedClassName = string | false | null | undefined | (string | false | null | undefined)[] | NestedClassName[]
4
+ export type ClassNameStateMap = { [key: string]: string | number | boolean | null | undefined }
5
+
6
+ export interface ComponentClassNameProps {
7
+ className?: NestedClassName;
8
+ componentClassName?: string | string[];
9
+ }
10
+
11
+ export type ColorSchemeClassName<T extends KebabCase<string> = KebabCase<string>> = `scheme-${T}`
12
+ export type ThemeContentClassName<T extends KebabCase<string> = KebabCase<string>, S extends `:${KebabCase<string>}` | null | undefined = undefined> = S extends string
13
+ ? `theme-${T}-content${S}`
14
+ : `theme-${T}-content`
15
+ export type ThemeControlsClassName<T extends KebabCase<string> = KebabCase<string>, S extends `:${KebabCase<string>}` | null | undefined = undefined> = S extends string
16
+ ? `theme-${T}-controls${S}`
17
+ : `theme-${T}-controls`
@@ -0,0 +1 @@
1
+ export * from './px'
@@ -0,0 +1,16 @@
1
+ export function px<V extends number>(value: V): `${V}px`;
2
+ export function px<V extends false>(value: V): '';
3
+ export function px<V extends null>(value: V): '';
4
+ export function px<V extends undefined>(value: V): '';
5
+ // NOTE: Next overload fixes:
6
+ // The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.
7
+ export function px<V extends number | false | null | undefined>(value?: V): string;
8
+ /**
9
+ * Converts a value to a string in the format '10px'
10
+ *
11
+ * @param value - The value to convert to a string.
12
+ * @returns Returns a string in the format '10px' or '' when value is falsy.
13
+ */
14
+ export function px<V extends number | false | null | undefined>(value?: V): string {
15
+ return typeof value === 'number' && !(isNaN(value) || value === Infinity || value === -Infinity) ? value + 'px' : ''
16
+ }
@@ -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 condition - Condition under which the deprecation warning will be logged
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, condition: boolean, deprecated: string, replacement: string | null): void {
20
+ if (condition === true) {
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.${replacement ? ` Replace it with ${replacement} instead.` : 'Remove it.'}`)
26
+ } else {
27
+ console.warn(`Use of ${deprecated} is deprecated and might be removed in the next release.${replacement ? ` Use ${replacement} instead.` : 'There is no replacement.'}`)
28
+ }
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,7 @@
1
+ export function fallback<R>(current: R, condition: boolean, mapped: R): R {
2
+ if (condition === true) {
3
+ return mapped
4
+ } else {
5
+ return current
6
+ }
7
+ }
@@ -0,0 +1,3 @@
1
+ export * from './deprecate'
2
+ export * from './fallback'
3
+ export * from './types'
@@ -0,0 +1,2 @@
1
+
2
+ export type SemverString = `${number}.${number}.${number}`
@@ -0,0 +1,11 @@
1
+ export function dataAttribute(value: unknown): string | true | undefined {
2
+ if (value === false || value === undefined || value === null) {
3
+ return undefined
4
+ } else if (value === true) {
5
+ // Closest to HTML: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
6
+ // React issue: https://github.com/facebook/react/issues/24812
7
+ return ''
8
+ } else {
9
+ return String(value)
10
+ }
11
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Calls the callback with the element's dimensions.
3
+ *
4
+ * @param element - The element to observe for dimensions
5
+ * @param callback - The callback to call with the element's dimensions
6
+ */
7
+ export function getElementDimensionsCallback(
8
+ element: HTMLElement,
9
+ callback: (dimensions: DOMRectReadOnly) => void,
10
+ ) {
11
+ const observer = new IntersectionObserver((entries, observer) => {
12
+ if (entries.length === 1) {
13
+ callback(entries[0].boundingClientRect)
14
+ } else {
15
+ const entry = entries.find(entry => entry.boundingClientRect.width > 0 || entry.boundingClientRect.height > 0) || entries[0]
16
+ callback(entry.boundingClientRect)
17
+ }
18
+
19
+ observer.disconnect()
20
+ })
21
+
22
+ observer.observe(element)
23
+ }
24
+
25
+ /**
26
+ * Returns a promise that resolves with the element's dimensions.
27
+ * @param element - The element to observe for dimensions
28
+ * @returns A promise that resolves with the element's dimensions
29
+ */
30
+ export function getElementDimensions(
31
+ element: HTMLElement,
32
+ ): Promise<DOMRectReadOnly> {
33
+ return new Promise(resolve => {
34
+ getElementDimensionsCallback(element, resolve)
35
+ })
36
+ }
@@ -0,0 +1,13 @@
1
+ export function getMatchingParentElement(element: HTMLElement | null, predicate: (element: HTMLElement | null) => boolean | Promise<boolean>): HTMLElement {
2
+ if (!element || !element.parentElement) {
3
+ if (document.scrollingElement instanceof HTMLElement) {
4
+ return document.scrollingElement
5
+ } else {
6
+ return document.body
7
+ }
8
+ } else if (predicate(element.parentElement)) {
9
+ return element.parentElement
10
+ } else {
11
+ return getMatchingParentElement(element.parentElement, predicate)
12
+ }
13
+ }
@@ -0,0 +1,26 @@
1
+ export function getSizeFromResizeObserverEntryFactory(box: ResizeObserverOptions['box']) {
2
+ return function getSizeFromResizeObserverEntry(entry: ResizeObserverEntry): { height: number, width: number } {
3
+ const boxSize = box === 'border-box'
4
+ ? entry.borderBoxSize
5
+ : box === 'content-box'
6
+ ? entry.contentBoxSize
7
+ : entry.devicePixelContentBoxSize
8
+
9
+ if (boxSize) {
10
+ const formatBoxSize: ResizeObserverSize[] = Array.isArray(boxSize) ? boxSize : [boxSize]
11
+
12
+ return formatBoxSize.reduce(
13
+ (previous, { inlineSize, blockSize }) => ({
14
+ width: previous.width + inlineSize,
15
+ height: previous.height + blockSize,
16
+ }),
17
+ { height: 0, width: 0 },
18
+ )
19
+ } else {
20
+ return {
21
+ width: entry.contentRect.width,
22
+ height: entry.contentRect.height,
23
+ }
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,8 @@
1
+ export * from './dataAttribute'
2
+ export * from './getElementDimensions'
3
+ export * from './getMatchingParentElement'
4
+ export * from './getSizeFromResizeObserverEntry'
5
+ export * from './isScrollable'
6
+ export * from './parseTransformMatrix'
7
+ export * from './stateDataAttributes'
8
+ export * from './svgSizeProps'
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Checks if an element is scrollable
3
+ * @param element - Element to check
4
+ * @returns Boolean indicating if the element is scrollable
5
+ */
6
+ export function isScrollable(element: HTMLElement | null) {
7
+ if (element === document.scrollingElement) {
8
+ return true
9
+ } else if (element instanceof HTMLElement) {
10
+ const contentOverflows = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth
11
+
12
+ if (contentOverflows) {
13
+ if ((getComputedStyle(element)).overflow === 'hidden') {
14
+ return false
15
+ } else {
16
+ return contentOverflows
17
+ }
18
+ } else {
19
+ return false
20
+ }
21
+ } else {
22
+ return false
23
+ }
24
+ }
@@ -0,0 +1,35 @@
1
+ import { assert, isNumber } from '../assert-types'
2
+
3
+ const MATRIX_REG_EXP = /^matrix\((.+)\)/
4
+
5
+ function isTransformMatrixTuple(value: unknown): value is [number, number, number, number, number, number] {
6
+ if (Array.isArray(value) && value.length === 6 && value.filter(isNumber).length === 6) {
7
+ return true
8
+ } else {
9
+ return false
10
+ }
11
+ }
12
+
13
+ /**
14
+ * Parses a CSS transform matrix string into an object.
15
+ *
16
+ * @param transform - CSS transform matrix string.
17
+ * @returns Object with the transform matrix values or undefined.
18
+ */
19
+ export function parseTransformMatrix(transform = '') {
20
+ let matches: RegExpMatchArray | null = null
21
+
22
+ if (matches = transform.match(MATRIX_REG_EXP)) {
23
+ const vector = matches[1].split(',').map(value => parseFloat(value))
24
+ assert('transform matrix is tuple of six numbers', vector, isTransformMatrixTuple)
25
+
26
+ return {
27
+ scaleX: vector[0],
28
+ skewY: vector[1],
29
+ skewX: vector[2],
30
+ scaleY: vector[3],
31
+ translateX: vector[4],
32
+ translateY: vector[5],
33
+ }
34
+ }
35
+ }
@@ -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
+ }
@@ -0,0 +1,21 @@
1
+ export interface SvgSizeProps {
2
+ width: number;
3
+ height: number;
4
+ viewBox: string;
5
+ }
6
+
7
+ export function svgSizeProps(
8
+ width: number,
9
+ height?: number,
10
+ crop: number = 0,
11
+ ): SvgSizeProps {
12
+ const viewBoxWidth = width - crop * 2
13
+ const viewBoxHeight = (height ?? width) - crop * 2
14
+ const viewBoxX = crop
15
+ const viewBoxY = crop
16
+ return {
17
+ width: viewBoxWidth,
18
+ height: viewBoxHeight,
19
+ viewBox: `${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}`,
20
+ }
21
+ }
@@ -0,0 +1,37 @@
1
+ /** @internal */
2
+ export function extend<B, E>(
3
+ base: B,
4
+ extension: E,
5
+ ) {
6
+ base = Object.freeze(base)
7
+ extension = Object.freeze(extension)
8
+
9
+ if (typeof base !== typeof extension) {
10
+ return extension === undefined ? base : extension
11
+ } else {
12
+ if (typeof base === 'object' && typeof extension === 'object') {
13
+ if (Array.isArray(base) && Array.isArray(extension)) {
14
+ return Object.freeze([...base, ...extension])
15
+ } else if (base && extension) {
16
+ if ('$$typeof' in extension) {
17
+ return extension
18
+ }
19
+
20
+ const keys = [...new Set([
21
+ ...Object.keys(base),
22
+ ...Object.keys(extension),
23
+ ])]
24
+
25
+ const entries: [string, unknown][] = keys.map(
26
+ key => [key, extend((base as Record<string, unknown>)[key], (extension as Record<string, unknown>)[key])],
27
+ )
28
+
29
+ return Object.freeze(Object.fromEntries(entries))
30
+ } else {
31
+ return extension
32
+ }
33
+ } else {
34
+ return extension
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,5 @@
1
+ export * from './extend'
2
+ export * from './omit'
3
+ export * from './pick'
4
+ export * from './range'
5
+ export * from './setHasOneOf'
@@ -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
+ }
@@ -0,0 +1,13 @@
1
+ export function pick<T extends Object, K extends keyof T>(object: T, properties: ReadonlyArray<K>): Pick<T, K> {
2
+ const next: Partial<Pick<T, K>> = {}
3
+
4
+ for (let key of properties) {
5
+ if (key in object) {
6
+ next[key] = object[key]
7
+ } else {
8
+ throw new Error(`Key "${String(key)}" does not exist in object ${JSON.stringify(object)}`)
9
+ }
10
+ }
11
+
12
+ return next as Pick<T, K>
13
+ }
@@ -0,0 +1,11 @@
1
+
2
+ /**
3
+ * Get a list of numbers between start and end, inclusive, with the given step size (defaulting to 1)
4
+ * @param start - The starting number.
5
+ * @param end - The ending number.
6
+ * @param step - The step size, optional, defaults to 1.
7
+ * @returns A list of numbers between start and end, inclusive, with the given step size (defaulting to 1)
8
+ */
9
+ export function range(start: number, end: number, step = 1): number[] {
10
+ return Array.from({ length: Math.floor(Math.abs(end - start) / step) + 1 }, (_, i) => start + i * (end > start ? 1 : -1) * Math.abs(step))
11
+ }
@@ -0,0 +1,3 @@
1
+ export function setHasOneOf<T>(set: Set<T>, values: T[]): boolean {
2
+ return values.some(value => set.has(value))
3
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './assert-types'
2
+ export * from './class-name'
3
+ export * from './css-utilities'
4
+ export * from './deprecate'
5
+ export * from './dom'
6
+ export * from './functional'
7
+ export * from './string-utilities'
8
+ export * from './types'