css-in-props 3.2.3 → 3.2.8

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/package.json CHANGED
@@ -2,33 +2,47 @@
2
2
  "name": "css-in-props",
3
3
  "description": "Utilize props as CSS methods",
4
4
  "author": "symbo.ls",
5
- "version": "3.2.3",
5
+ "version": "3.2.8",
6
6
  "repository": "https://github.com/symbo-ls/smbls",
7
7
  "type": "module",
8
- "module": "src/index.js",
9
- "unpkg": "dist/iife/index.js",
10
- "jsdelivr": "dist/iife/index.js",
11
- "main": "src/index.js",
12
- "exports": "./dist/cjs/index.js",
8
+ "module": "./dist/esm/index.js",
9
+ "unpkg": "./dist/iife/index.js",
10
+ "jsdelivr": "./dist/iife/index.js",
11
+ "main": "./dist/cjs/index.js",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/esm/index.js",
15
+ "require": "./dist/cjs/index.js",
16
+ "browser": "./dist/iife/index.js",
17
+ "default": "./dist/esm/index.js"
18
+ }
19
+ },
13
20
  "source": "src/index.js",
14
21
  "publishConfig": {},
15
22
  "scripts": {
16
23
  "copy:package:cjs": "cp ../../build/package-cjs.json dist/cjs/package.json",
17
- "build:esm": "npx cross-env NODE_ENV=$NODE_ENV npx esbuild ./src/*.js ./src/**/*.js --target=es2017 --format=esm --outdir=dist/esm",
18
- "build:cjs": "npx cross-env NODE_ENV=$NODE_ENV npx esbuild ./src/*.js ./src/**/*.js --target=node16 --format=cjs --outdir=dist/cjs",
19
- "build:iife": "npx cross-env NODE_ENV=$NODE_ENV npx esbuild ./src/index.js --target=es2017 --format=iife --outdir=dist/iife --bundle --minify",
20
- "build": "npm run build:cjs",
21
- "prepublish": "rimraf -I dist && npm run build && npm run copy:package:cjs"
24
+ "build:esm": "cross-env NODE_ENV=$NODE_ENV esbuild src/*.js --target=es2020 --format=esm --outdir=dist/esm --define:process.env.NODE_ENV=process.env.NODE_ENV",
25
+ "build:cjs": "cross-env NODE_ENV=$NODE_ENV esbuild src/*.js --target=node18 --format=cjs --outdir=dist/cjs --define:process.env.NODE_ENV=process.env.NODE_ENV",
26
+ "build:iife": "cross-env NODE_ENV=$NODE_ENV esbuild src/index.js --bundle --target=es2020 --format=iife --global-name=CssInProps --outfile=dist/iife/index.js --define:process.env.NODE_ENV=process.env.NODE_ENV --external:@symbo.ls/* --external:@domql/* --external:smbls",
27
+ "build": "node ../../build/build.js",
28
+ "prepublish": "npm run build && npm run copy:package:cjs"
22
29
  },
23
30
  "files": [
24
- "src",
25
- "dist"
31
+ "dist",
32
+ "*.js",
33
+ "src"
26
34
  ],
27
35
  "dependencies": {
28
36
  "@domql/utils": "^3.2.3",
29
37
  "@symbo.ls/atoms": "^3.2.3",
30
38
  "@symbo.ls/emotion": "^3.2.3",
31
- "@symbo.ls/scratch": "^3.2.3"
39
+ "@symbo.ls/scratch": "^3.2.3",
40
+ "smbls": "^3.2.3"
32
41
  },
33
- "gitHead": "9fc1b79b41cdc725ca6b24aec64920a599634681"
42
+ "gitHead": "9fc1b79b41cdc725ca6b24aec64920a599634681",
43
+ "browser": "./dist/iife/index.js",
44
+ "sideEffects": false,
45
+ "devDependencies": {
46
+ "@babel/core": "^7.29.0"
47
+ }
34
48
  }
package/src/_transform.js CHANGED
@@ -15,18 +15,12 @@ export const transformClassname = (
15
15
 
16
16
  if (!isObject(props)) return
17
17
 
18
- // merge(elementClass, registry)
19
- // if (registry && Object.keys(registry)[0] !== Object.keys(CSS_PROPS_REGISTRY)[0]) {
20
- // merge(elementClass, CSS_PROPS_REGISTRY)
21
- // }
22
-
23
18
  for (const key in props) {
24
19
  const setter = keySetters[key.slice(0, 1)]
25
20
  const hasCSS = elementClass[key]
26
21
 
27
22
  if (setter) setter(key, props[key], classCss, element, true)
28
23
  else if (isFunction(hasCSS)) {
29
- // const stack = hasCSS(element)
30
24
  const stack = hasCSS(element, element.state, element.context)
31
25
  const exec = isArray(stack)
32
26
  ? stack.reduce((a, c) => {
@@ -58,7 +52,6 @@ export const extractCSSfromProps = (element) => {
58
52
 
59
53
  const preprop = CSS_PROPS_REGISTRY[key]
60
54
  if (preprop) {
61
- // const stack = hasCSS(element)
62
55
  const stack = preprop(element, element.state, element.context)
63
56
  const exec = isArray(stack)
64
57
  ? stack.reduce((a, c) => {
@@ -74,7 +67,7 @@ export const extractCSSfromProps = (element) => {
74
67
  continue
75
68
  }
76
69
 
77
- if (DEFAULT_CSS_PROPERTIES_LIST.includes(key)) {
70
+ if (DEFAULT_CSS_PROPERTIES_LIST.has(key)) {
78
71
  css[key] = val
79
72
  continue
80
73
  }
package/src/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  export * from './transform'
4
- // export * from './set'
5
4
  export * from './emotion'
6
5
  export * from './props'
7
6
  export * from './props/defaults'
@@ -1,9 +1,15 @@
1
1
  'use strict'
2
2
 
3
- import { isObject } from '@domql/utils'
3
+ import { isObject, isString } from '@domql/utils'
4
4
  import { emotion } from '@symbo.ls/emotion'
5
5
  import { getTimingByKey, getTimingFunction } from '@symbo.ls/scratch'
6
6
 
7
+ const TIMING_FUNCTIONS = ['ease', 'linear', 'ease-in', 'ease-out', 'ease-in-out', 'step-start', 'step-end']
8
+ const FILL_MODES = ['none', 'forwards', 'backwards', 'both']
9
+ const DIRECTIONS = ['normal', 'reverse', 'alternate', 'alternate-reverse']
10
+ const PLAY_STATES = ['running', 'paused']
11
+ const isDuration = v => /^[\d.]+m?s$/.test(v)
12
+
7
13
  const applyAnimationProps = (animation, element) => {
8
14
  const { emotion: ctxEmotion } = element.context
9
15
  const { keyframes } = ctxEmotion || emotion
@@ -13,16 +19,74 @@ const applyAnimationProps = (animation, element) => {
13
19
  return keyframes(record)
14
20
  }
15
21
 
22
+ /**
23
+ * Parse CSS animation shorthand string into individual properties.
24
+ * Identifies the animation name by looking it up in the ANIMATION registry.
25
+ * Other tokens are classified by type: duration, timing-function, iteration-count, etc.
26
+ */
27
+ const parseAnimationShorthand = (val, el) => {
28
+ const { ANIMATION } = el.context && el.context.designSystem || {}
29
+ const tokens = val.split(/\s+/)
30
+ let name = null
31
+ const durations = []
32
+ let timingFunction = null
33
+ let iterationCount = null
34
+ let direction = null
35
+ let fillMode = null
36
+ let playState = null
37
+
38
+ for (const token of tokens) {
39
+ if (ANIMATION && ANIMATION[token]) {
40
+ name = token
41
+ } else if (isDuration(token)) {
42
+ durations.push(token)
43
+ } else if (TIMING_FUNCTIONS.includes(token) || token.startsWith('cubic-bezier') || token.startsWith('steps(')) {
44
+ timingFunction = token
45
+ } else if (token === 'infinite' || /^\d+$/.test(token)) {
46
+ iterationCount = token === 'infinite' ? token : Number(token)
47
+ } else if (DIRECTIONS.includes(token)) {
48
+ direction = token
49
+ } else if (FILL_MODES.includes(token)) {
50
+ fillMode = token
51
+ } else if (PLAY_STATES.includes(token)) {
52
+ playState = token
53
+ } else if (!name) {
54
+ // Fallback: treat unknown token as animation name
55
+ name = token
56
+ }
57
+ }
58
+
59
+ return { name, durations, timingFunction, iterationCount, direction, fillMode, playState }
60
+ }
61
+
16
62
  export const ANIMATION_PROPS = {
17
- animation: (val, el) => ({
18
- animationName: applyAnimationProps(val, el),
19
- animationDuration: getTimingByKey(el.props.animationDuration || 'A').timing,
20
- animationDelay: getTimingByKey(el.props.animationDelay || '0s').timing,
21
- animationTimingFunction: getTimingFunction(el.props.animationTimingFunction || 'ease'),
22
- animationFillMode: el.props.animationFillMode || 'both',
23
- animationPlayState: el.props.animationPlayState,
24
- animationDirection: el.props.animationDirection
25
- }),
63
+ animation: (val, el) => {
64
+ // Support CSS shorthand: 'animationName 2s linear infinite'
65
+ if (isString(val) && val.includes(' ')) {
66
+ const parsed = parseAnimationShorthand(val, el)
67
+ return {
68
+ animationName: applyAnimationProps(parsed.name || val, el),
69
+ animationDuration: parsed.durations[0] || getTimingByKey(el.props.animationDuration || 'A').timing,
70
+ animationDelay: parsed.durations[1] || getTimingByKey(el.props.animationDelay || '0s').timing,
71
+ animationTimingFunction: parsed.timingFunction || getTimingFunction(el.props.animationTimingFunction || 'ease'),
72
+ animationFillMode: parsed.fillMode || el.props.animationFillMode || 'both',
73
+ animationIterationCount: parsed.iterationCount != null ? parsed.iterationCount : (el.props.animationIterationCount || 1),
74
+ animationPlayState: parsed.playState || el.props.animationPlayState,
75
+ animationDirection: parsed.direction || el.props.animationDirection
76
+ }
77
+ }
78
+ // Single name (no spaces) — original behavior
79
+ return {
80
+ animationName: applyAnimationProps(val, el),
81
+ animationDuration: getTimingByKey(el.props.animationDuration || 'A').timing,
82
+ animationDelay: getTimingByKey(el.props.animationDelay || '0s').timing,
83
+ animationTimingFunction: getTimingFunction(el.props.animationTimingFunction || 'ease'),
84
+ animationFillMode: el.props.animationFillMode || 'both',
85
+ animationIterationCount: el.props.animationIterationCount || 1,
86
+ animationPlayState: el.props.animationPlayState,
87
+ animationDirection: el.props.animationDirection
88
+ }
89
+ },
26
90
  animationName: (val, el) => ({
27
91
  animationName: applyAnimationProps(val, el)
28
92
  }),
@@ -34,5 +98,17 @@ export const ANIMATION_PROPS = {
34
98
  }),
35
99
  animationTimingFunction: (val) => ({
36
100
  animationTimingFunction: getTimingFunction(val)
101
+ }),
102
+ animationIterationCount: (val) => ({
103
+ animationIterationCount: val
104
+ }),
105
+ animationFillMode: (val) => ({
106
+ animationFillMode: val
107
+ }),
108
+ animationPlayState: (val) => ({
109
+ animationPlayState: val
110
+ }),
111
+ animationDirection: (val) => ({
112
+ animationDirection: val
37
113
  })
38
114
  }
@@ -1,4 +1,4 @@
1
- export const DEFAULT_CSS_PROPERTIES_LIST = [
1
+ export const DEFAULT_CSS_PROPERTIES_LIST = new Set([
2
2
  'accentColor',
3
3
  'alignContent',
4
4
  'alignItems',
@@ -315,4 +315,4 @@ export const DEFAULT_CSS_PROPERTIES_LIST = [
315
315
  'wordWrap',
316
316
  'writingMode',
317
317
  'zIndex'
318
- ]
318
+ ])
package/src/props/flex.js CHANGED
@@ -5,14 +5,13 @@ import { isString } from '@domql/utils'
5
5
  export const FLEX_PROPS = {
6
6
  flow: (value, el) => {
7
7
  const { props } = el
8
- // const DISPLAY_FLEX_ALLOWED = ['flex', 'inline-flex']
9
- // if (!DISPLAY_FLEX_ALLOWED.includes(props.display)) return
10
8
  const { reverse } = props
11
9
  if (!isString(value)) return
12
10
  let [direction, wrap] = (value || 'row').split(' ')
13
11
  if (value.startsWith('x') || value === 'row') direction = 'row'
14
12
  if (value.startsWith('y') || value === 'column') direction = 'column'
15
13
  return {
14
+ display: 'flex',
16
15
  flexFlow:
17
16
  (direction || '') +
18
17
  (!direction.includes('-reverse') && reverse ? '-reverse' : '') +
@@ -22,15 +21,11 @@ export const FLEX_PROPS = {
22
21
  },
23
22
 
24
23
  wrap: (value, { props }) => {
25
- // const DISPLAY_FLEX_ALLOWED = ['flex', 'inline-flex']
26
- // if (!DISPLAY_FLEX_ALLOWED.includes(props.display)) return
27
- return { flexWrap: value }
24
+ return { display: 'flex', flexWrap: value }
28
25
  },
29
26
 
30
27
  align: (value, { props }) => {
31
- // const DISPLAY_FLEX_ALLOWED = ['flex', 'inline-flex']
32
- // if (!DISPLAY_FLEX_ALLOWED.includes(props.display)) return
33
28
  const [alignItems, justifyContent] = value.split(' ')
34
- return { alignItems, justifyContent }
29
+ return { display: 'flex', alignItems, justifyContent }
35
30
  }
36
31
  }
@@ -8,14 +8,15 @@ import {
8
8
  transformBoxShadow,
9
9
  transformBorder,
10
10
  transformBackgroundImage,
11
+ resolveColorsInGradient,
11
12
  transformSizeRatio
12
13
  } from '@symbo.ls/scratch'
13
14
 
14
- import { isString } from '@domql/utils'
15
+ import { isDefined, isString } from '@domql/utils'
15
16
 
16
17
  export const getSystemGlobalTheme = ({ context, state }) => {
17
- const rootState = state && state.root
18
- return rootState && rootState.globalTheme ? rootState.globalTheme : context.designSystem && context.designSystem.globalTheme
18
+ const theme = state?.root?.globalTheme || context.designSystem?.globalTheme
19
+ return theme === 'auto' ? null : theme
19
20
  }
20
21
 
21
22
  export const THEME_PROPS = {
@@ -44,6 +45,9 @@ export const THEME_PROPS = {
44
45
  background: (val, element) => {
45
46
  const globalTheme = getSystemGlobalTheme(element)
46
47
  if (!val) return
48
+ if (isString(val) && val.includes('gradient')) {
49
+ return { background: resolveColorsInGradient(val, globalTheme) }
50
+ }
47
51
  return {
48
52
  background: getMediaColor(val, globalTheme)
49
53
  }
@@ -62,9 +66,9 @@ export const THEME_PROPS = {
62
66
  if (!val) return
63
67
  const file = ctx.files && ctx.files[val]
64
68
  if (file && file.content) val = file.content.src
65
- return ({
69
+ return {
66
70
  backgroundImage: transformBackgroundImage(val, globalTheme)
67
- })
71
+ }
68
72
  },
69
73
 
70
74
  textStroke: (val) => ({
@@ -88,6 +92,26 @@ export const THEME_PROPS = {
88
92
  borderColor: getMediaColor(val, globalTheme)
89
93
  }
90
94
  },
95
+ borderTopColor: (val, element) => {
96
+ const globalTheme = getSystemGlobalTheme(element)
97
+ if (!val) return
98
+ return { borderTopColor: getMediaColor(val, globalTheme) }
99
+ },
100
+ borderBottomColor: (val, element) => {
101
+ const globalTheme = getSystemGlobalTheme(element)
102
+ if (!val) return
103
+ return { borderBottomColor: getMediaColor(val, globalTheme) }
104
+ },
105
+ borderLeftColor: (val, element) => {
106
+ const globalTheme = getSystemGlobalTheme(element)
107
+ if (!val) return
108
+ return { borderLeftColor: getMediaColor(val, globalTheme) }
109
+ },
110
+ borderRightColor: (val, element) => {
111
+ const globalTheme = getSystemGlobalTheme(element)
112
+ if (!val) return
113
+ return { borderRightColor: getMediaColor(val, globalTheme) }
114
+ },
91
115
  borderLeft: (val) => ({
92
116
  borderLeft: transformBorder(val)
93
117
  }),
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+
3
+ import { mergeArray } from '@domql/utils'
4
+ import * as preprocs from './props'
5
+
6
+ import { Text } from '@symbo.ls/atoms'
7
+
8
+ // TODO: due to recent updates inherit from BOX instead
9
+ export const CSS_PROPS_REGISTRY = mergeArray([Text]).class
10
+ export const CSS_PREPROCS_DEFAULTS = mergeArray(Object.values(preprocs))
@@ -50,10 +50,11 @@ export const usePropsAsCSS = (sourceObj, element, opts) => {
50
50
  if (isArray(val)) {
51
51
  val = val.reduce((a, c) => merge(a, c), {})
52
52
  }
53
- const result = CSS_PROPS_REGISTRY[key](val, element, element.state, element.context)
53
+ let result = CSS_PROPS_REGISTRY[key](val, element, element.state, element.context)
54
+ if (isArray(result)) result = result.reduce((a, c) => merge(a, c), {})
54
55
  if (result) setToObj(key, result)
55
56
  if (!isProd && isObject(obj[key])) obj[key].label = key
56
- } else if (DEFAULT_CSS_PROPERTIES_LIST.includes(key)) {
57
+ } else if (DEFAULT_CSS_PROPERTIES_LIST.has(key)) {
57
58
  // they can be grouped
58
59
  const result = exec(value, element)
59
60
  setToObj(key, { [key]: result })
@@ -81,8 +82,9 @@ export const useSelectorsAsCSS = (sourceObj, element) => {
81
82
  export const useCssInProps = (selectorProps, element, opts = { unpack: true }) => {
82
83
  const [cssObj, restProps] = usePropsAsCSS(selectorProps, element, opts)
83
84
  const selectorsObj = useSelectorsAsCSS(restProps, element)
84
- if (Object.keys(selectorsObj).length) {
85
- // console.log(opts.unpack, cssObj, selectorsObj)
85
+ let hasSelectors = false
86
+ for (const _k in selectorsObj) { hasSelectors = true; break } // eslint-disable-line
87
+ if (hasSelectors) {
86
88
  if (opts.unpack) return overwrite(cssObj, selectorsObj)
87
89
  cssObj._selectors = selectorsObj
88
90
  }
@@ -12,25 +12,13 @@ const applyMediaProps = (key, selectorProps, element) => {
12
12
  const { context } = element
13
13
  if (!context.designSystem?.MEDIA) return
14
14
 
15
- // const globalTheme = getSystemGlobalTheme(element)
16
15
  const mediaValue = context.designSystem.MEDIA[key.slice(1)]
17
16
  const generatedClass = useCssInProps(selectorProps, element)
18
- // const name = key.slice(1)
19
- // console.log('==generatedClass', generatedClass)
20
17
 
21
- // Theme handling
22
- // if (globalTheme && ['dark', 'light'].includes(name)) {
23
- // return name === globalTheme ? merge(result, generatedClass) : undefined
24
- // }
25
-
26
- // Media query construction
27
18
  const mediaKey = mediaValue
28
19
  ? '@media ' + (mediaValue === 'print' ? mediaValue : `screen and ${mediaValue}`)
29
20
  : key
30
21
 
31
- // result[mediaKey] = generatedClass
32
- // console.log(result, mediaKey)
33
- // return result[mediaKey]
34
22
  return { [mediaKey]: generatedClass }
35
23
  }
36
24
 
@@ -41,10 +29,6 @@ const applyAndProps = (key, selectorProps, element) => {
41
29
 
42
30
  const applySelectorProps = (key, selectorProps, element) => {
43
31
  const selectorKey = `&${key}`
44
- // if (key === ':after') {
45
- // console.log(selectorKey)
46
- // console.log(useCssInProps(selectorProps, element))
47
- // }
48
32
  return { [selectorKey]: useCssInProps(selectorProps, element) }
49
33
  }
50
34
 
@@ -84,8 +68,6 @@ export const applyTrueProps = (selectorProps, element) => {
84
68
  * Mapping of key prefixes to their handler functions
85
69
  */
86
70
  export const transformersByPrefix = {
87
- // Media and theme handlers
88
- // key, props, result, element, isSubtree
89
71
  '@': applyMediaProps,
90
72
 
91
73
  // Selector handlers
@@ -1,4 +0,0 @@
1
- {
2
- "type": "commonjs",
3
- "main": "index.js"
4
- }
@@ -1,57 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var animation_exports = {};
20
- __export(animation_exports, {
21
- ANIMATION_PROPS: () => ANIMATION_PROPS
22
- });
23
- module.exports = __toCommonJS(animation_exports);
24
- var import_utils = require("@domql/utils");
25
- var import_emotion = require("@symbo.ls/emotion");
26
- var import_scratch = require("@symbo.ls/scratch");
27
- const applyAnimationProps = (animation, element) => {
28
- const { emotion: ctxEmotion } = element.context;
29
- const { keyframes } = ctxEmotion || import_emotion.emotion;
30
- if ((0, import_utils.isObject)(animation)) return { animationName: keyframes(animation) };
31
- const { ANIMATION } = element.context && element.context.designSystem;
32
- const record = ANIMATION[animation];
33
- return keyframes(record);
34
- };
35
- const ANIMATION_PROPS = {
36
- animation: (val, el) => ({
37
- animationName: applyAnimationProps(val, el),
38
- animationDuration: (0, import_scratch.getTimingByKey)(el.props.animationDuration || "A").timing,
39
- animationDelay: (0, import_scratch.getTimingByKey)(el.props.animationDelay || "0s").timing,
40
- animationTimingFunction: (0, import_scratch.getTimingFunction)(el.props.animationTimingFunction || "ease"),
41
- animationFillMode: el.props.animationFillMode || "both",
42
- animationPlayState: el.props.animationPlayState,
43
- animationDirection: el.props.animationDirection
44
- }),
45
- animationName: (val, el) => ({
46
- animationName: applyAnimationProps(val, el)
47
- }),
48
- animationDuration: (val) => ({
49
- animationDuration: (0, import_scratch.getTimingByKey)(val).timing
50
- }),
51
- animationDelay: (val) => ({
52
- animationDelay: (0, import_scratch.getTimingByKey)(val).timing
53
- }),
54
- animationTimingFunction: (val) => ({
55
- animationTimingFunction: (0, import_scratch.getTimingFunction)(val)
56
- })
57
- };