anubis-ui 1.1.0 → 1.2.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/README.md CHANGED
@@ -146,18 +146,28 @@ For every config you want to change, add the corresponding section in your confi
146
146
  // colors.config.json
147
147
  "colors": ["primary", "secondary"],
148
148
 
149
- // selectors.config.json
150
- "selectors": {
151
- "states": ["hover"],
152
- "prefixes": ["bg", "text"]
153
- },
149
+ // states.config.json
150
+ "states": ["hover"],
151
+
152
+ // qol.config.json
153
+ "qol": [
154
+ {
155
+ "prefix": "bg",
156
+ "declaration": "background: ${color}"
157
+ }
158
+ ],
154
159
 
155
160
  // presets.config.json
156
- "presets": {
157
- "border": [
158
- { "default": "4px" }
159
- ]
160
- }
161
+ "presets": [
162
+ {
163
+ "prefix": "border",
164
+ "declaration": "border-width: ${value} !important; border-color: ${color} !important; border-style: solid;",
165
+ "variations": {
166
+ "default": "4px",
167
+ "thin": "2px"
168
+ }
169
+ }
170
+ ]
161
171
  }
162
172
  ```
163
173
  <sup>anubis.config.json (example)</sup>
@@ -212,65 +222,125 @@ Configure common style presets
212
222
  <summary>Default config</summary>
213
223
 
214
224
  ```json
215
- {
216
- "border": [
217
- { "default": "4px" },
218
- { "thinest": "1px" },
219
- { "thiner": "2px" },
220
- { "thin": "3px" },
221
- { "thick": "6px" },
222
- { "thicker": "8px" },
223
- { "thickest": "10px" },
224
- ],
225
-
226
- "innerBorder": [
227
- { "default": "4px" },
228
- { "thinest": "1px" },
229
- { "thiner": "2px" },
230
- { "thin": "3px" },
231
- { "thick": "6px" },
232
- { "thicker": "8px" },
233
- { "thickest": "10px" },
234
- ],
235
-
236
- "shadow": [
237
- { "default": "0px 0px 7px 1px" },
238
- { "densest": "0px 0px 3px 1px" },
239
- { "denser": "0px 0px 5px 1px" },
240
- { "dense": "0px 0px 5px 1px" },
241
- { "wide": "0px 0px 10px 1px" },
242
- { "wider": "0px 0px 15px 1px" },
243
- { "widest": "0px 0px 20px 1px" }
244
- ]
245
- }
225
+ [
226
+ {
227
+ "prefix": "bg",
228
+ "declaration": "background: ${color}"
229
+ },
230
+ {
231
+ "prefix": "border",
232
+ "declaration": "border-width: ${value} !important; border-color: ${color} !important; border-style: solid;",
233
+ "variations": {
234
+ "default": "4px",
235
+ "thinest": "1px",
236
+ "thiner": "2px",
237
+ "thin": "3px",
238
+ "thick": "6px",
239
+ "thicker": "8px",
240
+ "thickest": "10px",
241
+ "node": "0.2rem"
242
+ }
243
+ },
244
+ {
245
+ "prefix": "inner-border",
246
+ "declaration": "box-shadow: inset 0px 0px 0px ${value} ${color}",
247
+ "variations": {
248
+ "default": "4px",
249
+ "thinest": "1px",
250
+ "thiner": "2px",
251
+ "thin": "3px",
252
+ "thick": "6px",
253
+ "thicker": "8px",
254
+ "thickest": "10px",
255
+ "node": "0.2rem"
256
+ }
257
+ },
258
+ {
259
+ "prefix": "shadow",
260
+ "declaration": "box-shadow: ${value} ${color}",
261
+ "variations": {
262
+ "default": "0px 0px 7px 1px",
263
+ "densest": "0px 0px 3px 1px",
264
+ "denser": "0px 0px 5px 1px",
265
+ "dense": "0px 0px 5px 1px",
266
+ "wide": "0px 0px 10px 1px",
267
+ "wider": "0px 0px 15px 1px",
268
+ "widest": "0px 0px 20px 1px"
269
+ }
270
+ }
271
+ ]
246
272
  ```
247
273
  </details>
248
274
 
249
-
250
275
  ---
251
- ### Selectors (`selectors.config.json`)
252
- Define available states and style prefixes
253
-
276
+ ### Quality of Life (`qol.config.json`)
277
+ Define simple style rules that can have variations but don't require color values. These are CSS declarations that work independently.
254
278
  <details>
255
279
  <summary>Default config</summary>
256
280
 
257
281
  ```json
258
- {
259
- "states": [
260
- "hover",
261
- "not-hover"
262
- ],
263
- "prefixes": [
264
- "bg",
265
- "text",
266
- "border",
267
- "inner-border",
268
- "shadow"
269
- ]
270
- }
282
+ [
283
+ {
284
+ "prefix": "smooth",
285
+ "standalone": true,
286
+ "declaration": "transition-duration: ${value}",
287
+ "variations": {
288
+ "default": "0.1s",
289
+ "slowest": "0.5s",
290
+ "slower": "0.3s",
291
+ "slow": "0.2s",
292
+ "quick": "0.07s",
293
+ "quicker": "0.05s",
294
+ "quickest": "0.03s"
295
+ }
296
+ },
297
+ {
298
+ "prefix": "rounded",
299
+ "standalone": true,
300
+ "declaration": "border-radius: ${value}",
301
+ "variations": {
302
+ "default": "8px",
303
+ "square": "0px",
304
+ "xs": "2px",
305
+ "sm": "4px",
306
+ "md": "8px",
307
+ "lg": "12px",
308
+ "xl": "16px",
309
+ "very": "9999px",
310
+ "full": "50%",
311
+ "half": "100%"
312
+ }
313
+ },
314
+ {
315
+ "prefix": "border",
316
+ "declaration": "border-style: ${value}",
317
+ "variations": {
318
+ "solid": "solid",
319
+ "dashed": "dashed",
320
+ "dotted": "dotted"
321
+ }
322
+ }
323
+ ]
271
324
  ```
272
325
  </details>
273
326
 
327
+ QoL rules can have:
328
+ 1. A prefix
329
+ 2. A declaration that uses ${value} for variations
330
+ 3. Optional variations with default values
331
+ 4. Optional `standalone` flag to allow usage without variations
332
+
333
+ The `standalone` flag allows a QoL rule to be used without any variation. When set to `true`, the rule can be used:
334
+ - With a variation: `rounded-lg`, `smooth-slow`
335
+ - Without a variation: `rounded`, `smooth` (will use the default value)
336
+
337
+ When `standalone` is `false` or not specified, the rule must always include a variation (e.g., `border-dashed`).
338
+
339
+ Example usage:
340
+ ```html
341
+ <div class="rounded-lg smooth-slow border-dashed" />
342
+ <div class="rounded smooth" /> <!-- Works because these are standalone -->
343
+ ```
274
344
 
275
345
  ## Available Utility Classes
276
346
  #### Colors
@@ -312,11 +382,10 @@ Define available states and style prefixes
312
382
  ├── src/
313
383
  │ ├── config/ # Configuration files
314
384
  │ ├── interfaces/ # TypeScript interfaces
315
- │ ├── manual/ # Manually trigger anubis actions
316
385
  │ └── tools/
317
- ├── extract/ # Class extraction logic
318
- ├── declaration/ # WIP - Style declaration handlers
319
- └── mapping/ # Class to CSS rule mapping
386
+ ├── extraction/ # Class extraction logic
387
+ ├── fileStuff/ # File handling utilities
388
+ └── mapping/ # Class to CSS rule mapping
320
389
  └── index.js # Plugin entry point
321
390
  ```
322
391
 
package/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { init: initConfig } = require('./dist/config/config.tool');
4
4
  const { log, logPrefix, logo } = require('./dist/tools/logger');
5
- const { init: initClassExtraction } = require('./dist/tools/extract/classes');
5
+ const { init: initClassExtraction } = require('./dist/tools/extraction/extractClasses');
6
6
 
7
7
  /** List every imported colors across the projet */
8
8
  const colors = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anubis-ui",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Class-based css generator",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -1,47 +1,26 @@
1
- import { readUserConfigFile, userConfig } from "../tools/fileHandling/configFile"
1
+ import { IEnvConfig } from "../interfaces/config.interface";
2
+ import { readUserConfigFile, userConfig } from "../tools/fileStuff/configFile"
2
3
  import { log } from "../tools/logger"
3
4
 
4
5
  const fs = require('fs')
5
6
  const path = require('path')
6
7
 
7
- interface IPreset {
8
- [key: string]: string
9
- }
10
- interface IEnvConfig {
11
- files: {
12
- targets: string|string[],
13
- ignore: string[]
14
- },
15
- colors: string[],
16
- selectors: {
17
- states: string[],
18
- prefixes: string[]
19
- },
20
- presets: {
21
- 'border': IPreset[],
22
- 'inner-border': IPreset[],
23
- 'shadow': IPreset[],
24
- },
25
- [key: string]: any
26
- }
27
-
28
8
  const anubisConfigFolder = path.join(__dirname, '..', '..', 'src', 'config');
29
9
  const anubisConfigFiles = [
10
+ 'qol',
30
11
  'files',
31
12
  'colors',
13
+ 'states',
32
14
  'presets',
33
- 'selectors'
34
15
  ]
35
16
 
36
17
  const config = {
18
+ qol: [],
19
+ presets: [],
20
+
37
21
  files: { targets: [], ignore: [] },
38
22
  colors: [],
39
- selectors: { states: [], prefixes: [] },
40
- presets: {
41
- border: [],
42
- "inner-border": [],
43
- shadow: [],
44
- },
23
+ states: [],
45
24
  } as IEnvConfig
46
25
 
47
26
  const init = () => {
@@ -69,6 +48,7 @@ const init = () => {
69
48
  }
70
49
 
71
50
  const checkUserConfig = () => {
51
+ if (!userConfig) { return }
72
52
 
73
53
  // todo - also check values
74
54
  const userConfigKeys = Object.keys(userConfig)
@@ -1,33 +1,47 @@
1
- {
2
- "border": [
3
- { "default": "4px" },
4
- { "thinest": "1px" },
5
- { "thiner": "2px" },
6
- { "thin": "3px" },
7
- { "thick": "6px" },
8
- { "thicker": "8px" },
9
- { "thickest": "10px" },
10
- { "node": "0.2rem" }
11
- ],
12
-
13
- "innerBorder": [
14
- { "default": "4px" },
15
- { "thinest": "1px" },
16
- { "thiner": "2px" },
17
- { "thin": "3px" },
18
- { "thick": "6px" },
19
- { "thicker": "8px" },
20
- { "thickest": "10px" },
21
- { "node": "0.2rem" }
22
- ],
23
-
24
- "shadow": [
25
- { "default": "0px 0px 7px 1px" },
26
- { "densest": "0px 0px 3px 1px" },
27
- { "denser": "0px 0px 5px 1px" },
28
- { "dense": "0px 0px 5px 1px" },
29
- { "wide": "0px 0px 10px 1px" },
30
- { "wider": "0px 0px 15px 1px" },
31
- { "widest": "0px 0px 20px 1px" }
32
- ]
33
- }
1
+ [
2
+ {
3
+ "prefix": "bg",
4
+ "declaration": "background: ${color}"
5
+ },
6
+ {
7
+ "prefix": "border",
8
+ "declaration": "border-width: ${value} !important; border-color: ${color} !important; border-style: solid;",
9
+ "variations": {
10
+ "default": "4px",
11
+ "thinest": "1px",
12
+ "thiner": "2px",
13
+ "thin": "3px",
14
+ "thick": "6px",
15
+ "thicker": "8px",
16
+ "thickest": "10px",
17
+ "node": "0.2rem"
18
+ }
19
+ },
20
+ {
21
+ "prefix": "inner-border",
22
+ "declaration": "box-shadow: inset 0px 0px 0px ${value} ${color}",
23
+ "variations": {
24
+ "default": "4px" ,
25
+ "thinest": "1px" ,
26
+ "thiner": "2px" ,
27
+ "thin": "3px" ,
28
+ "thick": "6px" ,
29
+ "thicker": "8px" ,
30
+ "thickest": "10px" ,
31
+ "node": "0.2rem"
32
+ }
33
+ },
34
+ {
35
+ "prefix": "shadow",
36
+ "declaration": "box-shadow: ${value} ${color}",
37
+ "variations": {
38
+ "default": "0px 0px 7px 1px" ,
39
+ "densest": "0px 0px 3px 1px" ,
40
+ "denser": "0px 0px 5px 1px" ,
41
+ "dense": "0px 0px 5px 1px" ,
42
+ "wide": "0px 0px 10px 1px" ,
43
+ "wider": "0px 0px 15px 1px" ,
44
+ "widest": "0px 0px 20px 1px"
45
+ }
46
+ }
47
+ ]
@@ -0,0 +1,42 @@
1
+ [
2
+ {
3
+ "prefix": "smooth",
4
+ "standalone": true,
5
+ "declaration": "transition-duration: ${value}",
6
+ "variations": {
7
+ "default": "0.1s",
8
+ "slowest": "0.5s",
9
+ "slower": "0.3s",
10
+ "slow": "0.2s",
11
+ "quick": "0.07s",
12
+ "quicker": "0.05s",
13
+ "quickest": "0.03s"
14
+ }
15
+ },
16
+ {
17
+ "prefix": "rounded",
18
+ "standalone": true,
19
+ "declaration": "border-radius: ${value}",
20
+ "variations": {
21
+ "default": "8px",
22
+ "square": "0px",
23
+ "xs": "2px",
24
+ "sm": "4px",
25
+ "md": "8px",
26
+ "lg": "12px",
27
+ "xl": "16s",
28
+ "very": "9999px",
29
+ "full": "50%",
30
+ "half": "100%"
31
+ }
32
+ },
33
+ {
34
+ "prefix": "border",
35
+ "declaration": "border-style: ${value}",
36
+ "variations": {
37
+ "solid": "solid",
38
+ "dashed": "dashed",
39
+ "dotted": "dotted"
40
+ }
41
+ }
42
+ ]
@@ -0,0 +1,4 @@
1
+ [
2
+ "hover",
3
+ "not-hover"
4
+ ]
@@ -0,0 +1,16 @@
1
+ import { IPreset } from "./preset.interface"
2
+
3
+ export interface IFilePatterns {
4
+ targets: string|string[],
5
+ ignore: string[]
6
+ }
7
+
8
+ export interface IEnvConfig {
9
+ qol: IPreset[]
10
+ presets: IPreset[],
11
+ files: IFilePatterns,
12
+
13
+ colors: string[],
14
+ states: string[],
15
+ [key: string]: any
16
+ }
@@ -0,0 +1,18 @@
1
+ export interface IVariation {
2
+ [key: string]: string
3
+ }
4
+
5
+ export interface IPreset {
6
+ // [key: string]: string
7
+ prefix: string,
8
+ declaration: string,
9
+
10
+ /** When true, class can be called without variation, creating a rule with default variation */
11
+ standalone?: boolean,
12
+
13
+ /**In a quasar project (quasar.variabls.scss), will set as !default the precised key with the default variations */
14
+ globalVariableOverride?: string,
15
+
16
+ /** List of every possible variations */
17
+ variations: IVariation
18
+ }
@@ -1,21 +1,19 @@
1
- import { config } from "../../../config/config.tool"
2
- import { buildCssRuleFile } from "../../fileHandling/cssFile"
3
- import { mapClassesIntoRules } from "../../mapping/mapClassIntoRule"
4
- import { getFiles } from "../../fileHandling/file.tools"
1
+ import { getFiles } from "../fileStuff/file.tools"
2
+ import { mapClassesIntoRules } from "../mapping/mapClassIntoRule"
3
+ import { buildCssRuleFile } from "../fileStuff/cssFile"
4
+ import { config } from "../../config/config.tool"
5
5
 
6
6
  const fs = require('fs')
7
7
 
8
8
  /** Fetch vue file based on config target patterns */
9
9
  const init = async () => {
10
10
  const files = await getFiles(config.files)
11
- // console.log({ files })
12
11
 
13
12
  const uniqueClasses = await getUniqueClasses(files)
14
13
  const mappedRules = mapClassesIntoRules(uniqueClasses)
15
- // console.log({ uniqueClasses, mappedRules })
16
14
 
17
15
  const file = buildCssRuleFile(mappedRules)
18
- // console.log({ file })
16
+ return file
19
17
  }
20
18
 
21
19
  /** Extract detected class and map into a flat set */
@@ -27,8 +25,6 @@ const getUniqueClasses = async (files: string[]): Promise<string[]> => {
27
25
  ?.sort()
28
26
 
29
27
  const uniqueClasses = Array.from(new Set(extractedClasses))
30
- // log(`${uniqueClasses?.length} classes found`)
31
-
32
28
  return uniqueClasses
33
29
  }
34
30
 
@@ -37,16 +33,20 @@ const extractClasses = async (filePath: string): Promise<string[]> => {
37
33
  const file = await fs.promises.readFile(filePath, 'utf-8')
38
34
  if (!file) { return [] }
39
35
 
40
- const { states, prefixes } = config.selectors
36
+ const { states, qol, presets } = config
41
37
 
42
- const partialStates = `(${states?.map(s => `${s}:`)?.join('|')})`
43
- const partialPrefixes = `(${prefixes?.map(p => `${p}-`)?.join('|')})`
38
+ const partialPrefixes = presets?.map(p => `${p.prefix}-`)
39
+ const partialQol = qol?.map(q => `${q.prefix}`)
44
40
 
45
- const classDetectionRegex = new RegExp(`${partialStates}?${partialPrefixes}(\\w+(-+)?)+`, 'gi')
41
+ const mappedPrefixes = [
42
+ ...partialPrefixes,
43
+ ...partialQol
44
+ ]?.join('|')
45
+ const mappedStates = `(${states?.map(s => `${s}:`)?.join('|')})`
46
46
 
47
- const matches = file.match(classDetectionRegex)
48
- if (!matches?.length) { return [] }
47
+ const classDetectionRegex = new RegExp(`${mappedStates}?(${mappedPrefixes})(-?(\\w+(-+)?)+)?`, 'gi')
49
48
 
49
+ const matches = file.match(classDetectionRegex) || []
50
50
  return matches
51
51
  }
52
52
 
@@ -1,4 +1,5 @@
1
1
  import { config } from "../../config/config.tool"
2
+ import { IPreset } from "../../interfaces/preset.interface"
2
3
  import { log } from "../logger"
3
4
 
4
5
  const mapClassesIntoRules = (classes: string[]) => {
@@ -13,31 +14,52 @@ const mapClassesIntoRules = (classes: string[]) => {
13
14
  }
14
15
 
15
16
  const mapClassIntoRule = (stringClass: string) => {
16
- const colorExists = config.colors?.some(color => stringClass.includes(color))
17
- if (!colorExists) { return }
18
-
19
17
  const params = getClassInfos(stringClass)
20
- // console.log({ params })
21
18
 
22
- const rule = mapIntoRule(params)
23
- // console.log({ rule })
19
+ /**
20
+ * _ If no variations are found, maybe it's just a color like bg-primary
21
+ * _ So we need to check if the color exists to avoid useless computing
22
+ * */
23
+ if (!params.preset) {
24
+ const { colorExists } = checkOpacity(params.color)
25
+
26
+ if (!colorExists) {
27
+ return
28
+ }
29
+ }
30
+
31
+ /**
32
+ * _ If the current QoL isn't standalone (can be called without variation)
33
+ * _ no
34
+ */
35
+ if (!params.color && !params.preset?.standalone) {
36
+ return
37
+ }
24
38
 
39
+ const rule = mapIntoRule(params)
25
40
  return rule
26
41
  }
27
42
 
28
- const getClassInfos = (stringClass: string): { state?: string, prefix?: string, color: string, variation?: { key: string, value: string } } => {
43
+ const getClassInfos = (stringClass: string) => {
29
44
  const { cleanedClass, state } = getStateInfos(stringClass)
30
45
  const { cleanedColor, prefix } = getPrefixInfos(cleanedClass)
31
- const { color, variation } = getVariantInfos({ cleanedColor, prefix })
46
+ const { preset, variation } = getPresetInfos({ cleanedColor, prefix })
47
+
48
+ return {
49
+ state,
32
50
 
33
- // console.log({ state, color, prefix, variation })
34
- return { state, color, prefix, variation }
51
+ color: cleanedColor,
52
+ prefix,
53
+
54
+ preset,
55
+ variation
56
+ }
35
57
  }
36
58
 
37
59
  const getStateInfos = (stringClass: string) => {
38
60
  let state = undefined
39
61
 
40
- for (const configState of config.selectors?.states) {
62
+ for (const configState of config.states) {
41
63
  if (!stringClass.startsWith(configState)) { continue }
42
64
 
43
65
  state = configState
@@ -51,62 +73,67 @@ const getStateInfos = (stringClass: string) => {
51
73
  }
52
74
 
53
75
  const getPrefixInfos = (stringClass: string): { cleanedColor: string, prefix: string } => {
54
- let prefix = ''
76
+ const prefixes = [
77
+ ...config.presets?.map(q => q.prefix),
78
+ ...config.qol?.map(q => q.prefix)
79
+ ]
55
80
 
56
- for (const configPrefix of config.selectors.prefixes) {
57
- if (!stringClass.startsWith(configPrefix)) { continue }
81
+ for (const prefix of prefixes) {
82
+ if (!stringClass.startsWith(prefix)) { continue }
58
83
 
59
- prefix = configPrefix
84
+ return {
85
+ cleanedColor: stringClass?.slice(prefix.length + 1),
86
+ prefix
87
+ }
60
88
  }
61
89
 
62
- return {
63
- cleanedColor: stringClass?.slice(prefix.length + 1),
64
- prefix,
65
- }
90
+ return null
66
91
  }
67
92
 
68
- const getVariantInfos = ({ cleanedColor, prefix }: { cleanedColor: string, prefix?: string }): { color: string, variation?: { key: string, value: string } } => {
69
- // _ Handle opacity | bg-primary-10
70
- const opacityDetectionRegex = new RegExp(/(?:(\w-?)+)-\d{2}$/, 'gm') // Strings that end with two digits
71
- const isOpacity = opacityDetectionRegex.test(cleanedColor)
72
- if (isOpacity) {
93
+ const getPresetInfos = ({ cleanedColor, prefix }: { cleanedColor: string, prefix?: string }) => {
94
+ /**
95
+ * _ Find preset variants matching the prefix from the config
96
+ * _ Since a prefix can be in multiple presets and qol, filter every matching prefixes then flatten everything
97
+ * TODO fix first default occurence getting picked when duplicate
98
+ * */
99
+ const possiblePresets = [...config.presets, ...config.qol]
100
+ ?.filter(p => p.prefix === prefix)
101
+ ?.flat()
102
+ if (!possiblePresets?.length) { return { matchingPreset: null, variation: null } }
103
+
104
+ const { colorExists } = checkOpacity(cleanedColor)
105
+
106
+ /**
107
+ * Find the preset where the variations exists
108
+ * If the color exists, it is a preset, so use the preset
109
+ * */
110
+ const matchingPreset = colorExists || !cleanedColor
111
+ ? possiblePresets[0]
112
+ : possiblePresets?.find(({ variations }) => !variations || Object.keys(variations)?.find(v => cleanedColor.endsWith(v)))
113
+
114
+ if (!matchingPreset) {
115
+ log(`No preset found for ${cleanedColor || prefix}`)
116
+
73
117
  return {
74
- color: cleanedColor // Opacity is included in the color name, whoops on me for this one (and every other one tho)
75
- // color: cleanedColor?.slice(0, -3),
76
- // variation: {
77
- // key: 'opacity',
78
- // value: cleanedColor?.slice(-2),
79
- // }
118
+ matchingPreset,
119
+ variation: null
80
120
  }
81
121
  }
82
122
 
83
- // _ Find preset variants matching the prefix from the config
84
- const variants = config.presets[prefix as keyof typeof config.presets]
85
- if (!variants) { return { color: cleanedColor } }
86
-
87
- // _ Map found variants into a key/value object
88
- const matchingVariants = variants
89
- ?.map(v => Object.entries(v))
90
- ?.flat()
91
- ?.map(([key, value]) => ({ key, value }))
92
- // ?.filter(({ key }) => key !== 'default')
123
+ const possibleVariations = (matchingPreset.variations || { default: '' })
93
124
 
94
- const variation = matchingVariants?.find(({ key }) => cleanedColor.endsWith(key)) || matchingVariants?.find(({ key }) => key === 'default')
95
- // console.log({ variation })
125
+ const matchingVariation = Object.keys(possibleVariations)
126
+ ?.find(v => cleanedColor.endsWith(v)) || 'default'
96
127
 
97
- const color = variation && variation.key !== 'default'
98
- ? cleanedColor?.slice(0, variation.key.length + 1)
99
- : cleanedColor
128
+ const variation = possibleVariations[matchingVariation]
100
129
 
101
130
  return {
102
- color,
103
- variation
131
+ preset: matchingPreset,
132
+ variation,
104
133
  }
105
134
  }
106
135
 
107
- function mapIntoRule({ state, prefix, color, variation }: { state?: string, prefix?: string, color: string, variation?: { key: string, value: string } }) {
108
- const colorVar = `var(--${color})`
109
-
136
+ const mapIntoRule = ({ state, prefix, color, preset, variation }) => {
110
137
  // _ Set state selector
111
138
  let stateSelector = ''
112
139
  switch (state) {
@@ -119,50 +146,47 @@ function mapIntoRule({ state, prefix, color, variation }: { state?: string, pref
119
146
  break
120
147
  }
121
148
 
122
- let declaration = ''
123
-
124
- // _ Set prefix declaration
125
- // ! Don't forget to add the prefix in the selector.config root file
126
- switch (prefix) {
127
- case 'bg':
128
- declaration = `background: ${colorVar} !important`
129
- break
130
-
131
- case 'text':
132
- declaration = `color: ${colorVar} !important`
133
- break
134
-
135
- case 'border':
136
- declaration = `border-width: ${variation?.value} !important; border-color: ${colorVar} !important; border-style: solid`
137
- break
138
-
139
- case 'inner-border':
140
- declaration = `box-shadow: inset ${variation?.value} ${colorVar} !important`
141
- break
142
-
143
- case 'shadow':
144
- declaration = `box-shadow: ${variation?.value} ${colorVar} !important`
145
- break
149
+ let selector = `${prefix}${color ? `-${color}` : ''}`
150
+ if (state) {
151
+ selector = `${state}\\:${selector}${stateSelector}`
152
+ }
146
153
 
147
- default:
148
- // _ custom rule from config file
149
- const customDeclaration = config.customRules?.find((r: any) => r.prefix === prefix)?.declaration
150
- if (!customDeclaration) { return }
154
+ const colorVar = `var(--${color})`
155
+ let declaration = preset.declaration
156
+ ?.replace('${value}', variation)
157
+ ?.replace('${color}', colorVar)
151
158
 
152
- declaration = customDeclaration?.replace('${value}', color) + ' !important'
153
- break
159
+ if (!declaration.endsWith(';')) {
160
+ declaration += ';'
154
161
  }
155
162
 
156
- let selector = `${prefix}-${color}`
157
- if (state) {
158
- selector = `${state}\\:${selector}${stateSelector}`
163
+ if (!declaration.includes('!important')) {
164
+ declaration = declaration
165
+ ?.replace(';', ' !important;')
159
166
  }
160
167
 
161
168
  const rule = `.${selector} { ${declaration} }`
162
-
163
169
  return rule
164
170
  }
165
171
 
172
+ /**
173
+ * _ Check if a color includes opacity (ends with 2 digits)
174
+ * * Opacity is included in the color name during mixin declaration
175
+ * */
176
+ const checkOpacity = (color: string) => {
177
+ const opacityDetectionRegex = new RegExp(/(?:(\w-?)+)-\d{2}$/, 'gm') // Strings that end with two digits
178
+ const isOpacity = opacityDetectionRegex.test(color)
179
+
180
+ const baseColor = isOpacity ? color?.slice(0, -3) : color
181
+ const colorExists = config.colors?.some(configColor => configColor === baseColor)
182
+
183
+ return {
184
+ colorExists,
185
+ isOpacity,
186
+ baseColor
187
+ }
188
+ }
189
+
166
190
  export {
167
191
  mapClassesIntoRules,
168
192
  mapClassIntoRule
@@ -1,13 +0,0 @@
1
- {
2
- "states": [
3
- "hover",
4
- "not-hover"
5
- ],
6
- "prefixes": [
7
- "bg",
8
- "text",
9
- "border",
10
- "inner-border",
11
- "shadow"
12
- ]
13
- }
@@ -1,19 +0,0 @@
1
- interface IConfigDeclaration {
2
- [key: string]: string,
3
- }
4
-
5
- export interface IConfigPresets {
6
- defaultInnerBorderWidth?: string
7
- innerBorderWidths?: IConfigDeclaration[]
8
-
9
- defaultBorderWidth?: string
10
- borderWidths?: IConfigDeclaration[]
11
-
12
- defaultShadow?: string,
13
- shadowWidths?: IConfigDeclaration[]
14
-
15
- defaultBorderRadius?: string
16
- borderRadiuses?: IConfigDeclaration[]
17
-
18
- fontWeights?: IConfigDeclaration[]
19
- }
@@ -1,3 +0,0 @@
1
- import { IDeclaration } from "../../interfaces/declaration.interface";
2
-
3
- const declareColor = (options: { name: string, color: string, theme?: string }) => {}