@symbo.ls/uikit 1.2.0 → 1.2.2

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 (92) hide show
  1. package/.babelrc.json +3 -0
  2. package/.eslintrc.js +16 -0
  3. package/README.md +1 -1
  4. package/components/Atoms/Animation.js +53 -0
  5. package/components/Atoms/Block.js +151 -0
  6. package/components/Atoms/Collection.js +82 -0
  7. package/components/Atoms/Direction.js +10 -0
  8. package/components/Atoms/Flex.js +17 -0
  9. package/components/Atoms/Form.js +11 -0
  10. package/components/Atoms/Grid.js +30 -0
  11. package/components/Atoms/Iframe.js +16 -0
  12. package/components/Atoms/Img.js +17 -0
  13. package/components/Atoms/Interaction.js +9 -0
  14. package/components/Atoms/InteractiveComponent.js +78 -0
  15. package/components/Atoms/Media.js +164 -0
  16. package/components/Atoms/Overflow.js +7 -0
  17. package/components/Atoms/Picture.js +31 -0
  18. package/components/Atoms/Position.js +21 -0
  19. package/components/Atoms/Pseudo.js +7 -0
  20. package/components/Atoms/SVG.js +16 -0
  21. package/components/Atoms/Shape/index.js +42 -0
  22. package/components/Atoms/Shape/style.js +204 -0
  23. package/components/Atoms/Text.js +40 -0
  24. package/components/Atoms/Theme.js +136 -0
  25. package/components/Atoms/Timing.js +55 -0
  26. package/components/Atoms/Transform.js +8 -0
  27. package/components/Atoms/XYZ.js +7 -0
  28. package/components/Atoms/index.js +25 -0
  29. package/components/Atoms/package.json +13 -0
  30. package/components/Avatar/index.js +32 -0
  31. package/components/Avatar/package.json +12 -0
  32. package/components/Avatar/style.js +19 -0
  33. package/components/Banner/index.js +22 -0
  34. package/components/Banner/package.json +12 -0
  35. package/components/Banner/style.js +27 -0
  36. package/components/Box/index.js +44 -0
  37. package/components/Box/package.json +10 -0
  38. package/components/Button/README.md +11 -0
  39. package/components/Button/index.js +48 -0
  40. package/components/Button/package.json +12 -0
  41. package/components/ButtonSet/index.js +10 -0
  42. package/components/ButtonSet/package.json +12 -0
  43. package/components/Datepicker/index.js +156 -0
  44. package/components/Datepicker/package.json +13 -0
  45. package/components/Datepicker/style.js +18 -0
  46. package/components/Dropdown/index.js +52 -0
  47. package/components/Dropdown/package.json +12 -0
  48. package/components/Field/index.js +43 -0
  49. package/components/Field/package.json +13 -0
  50. package/components/Field/style.js +30 -0
  51. package/components/Icon/index.js +50 -0
  52. package/components/Icon/package.json +11 -0
  53. package/components/Icon/style.js +8 -0
  54. package/components/IconText/index.js +16 -0
  55. package/components/IconText/package.json +14 -0
  56. package/components/Input/index.js +32 -0
  57. package/components/Input/package.json +11 -0
  58. package/components/Label/index.js +25 -0
  59. package/components/Label/package.json +13 -0
  60. package/components/Link/index.js +38 -0
  61. package/components/Link/package.json +12 -0
  62. package/components/Notification/index.js +47 -0
  63. package/components/Notification/package.json +16 -0
  64. package/components/Pills/index.js +25 -0
  65. package/components/Pills/package.json +11 -0
  66. package/components/Range/index.js +131 -0
  67. package/components/Range/package.json +13 -0
  68. package/components/Select/index.js +36 -0
  69. package/components/Select/package.json +11 -0
  70. package/components/Sidebar/index.js +24 -0
  71. package/components/Sidebar/package.json +12 -0
  72. package/components/Slider/index.js +105 -0
  73. package/components/Slider/package.json +13 -0
  74. package/components/Slider/style.js +19 -0
  75. package/components/TextArea/index.js +15 -0
  76. package/components/TextArea/package.json +11 -0
  77. package/components/Tooltip/index.js +37 -0
  78. package/components/Tooltip/package.json +11 -0
  79. package/components/Tooltip/style.js +12 -0
  80. package/lerna.json +9 -0
  81. package/package.json +35 -33
  82. package/packages/react/index.js +5 -0
  83. package/packages/react/package.json +16 -0
  84. package/packages/uikit/README.md +38 -0
  85. package/{index.js → packages/uikit/index.js} +0 -2
  86. package/packages/uikit/package.json +40 -0
  87. package/react/box/README.md +114 -0
  88. package/react/box/index.d.ts +3 -0
  89. package/react/box/index.js +63 -0
  90. package/react/box/package.json +33 -0
  91. package/svgSprite.config.js +7 -0
  92. package/watch.js +12 -0
package/.babelrc.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "presets": []
3
+ }
package/.eslintrc.js ADDED
@@ -0,0 +1,16 @@
1
+ module.exports = {
2
+ "extends": "standard",
3
+ "plugins": ["jest"],
4
+ "parser": "@babel/eslint-parser",
5
+ "env": {
6
+ "es6": true,
7
+ "browser": true,
8
+ "node": true,
9
+ "jest": true
10
+ },
11
+ overrides: [{
12
+ files: [ 'test/**/*.test.js' ],
13
+ env: { jest: true },
14
+ plugins: [ 'jest' ]
15
+ }]
16
+ }
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Symbols
2
2
 
3
- UI Library in composition of [Scratch](https://github.com/symbo.ls/scratch) and [DOMQL](https://github.com/symbo.ls/domql) or [DOMQL](https://github.com/symbo-ls/smbls/tree/main/packages/all/packages/react)
3
+ UI Library in composition of [Scratch](https://github.com/symbo.ls/scratch) and [DOMQL](https://github.com/symbo.ls/domql)
4
4
 
5
5
  Check out the [documentation page](https://docs.symbols.app/).
6
6
 
@@ -0,0 +1,53 @@
1
+ 'use strict'
2
+
3
+ import { getTimingByKey, getTimingFunction } from '@symbo.ls/scratch'
4
+ import { isObject } from '@domql/utils'
5
+ import { convertPropsToClass } from './Media' // eslint-disable-line no-unused-vars
6
+ import { emotion } from '@symbo.ls/create-emotion'
7
+ const { keyframes } = emotion
8
+
9
+ const applyAnimationProps = (animation, element) => {
10
+ if (isObject(animation)) return { animationName: keyframes(animation) }
11
+ const { ANIMATION } = element.context && element.context.system
12
+ const record = ANIMATION[animation]
13
+ return keyframes(record)
14
+ }
15
+
16
+ export const Animation = {
17
+ class: {
18
+ animation: (el) => el.props.animation && {
19
+ animationName: applyAnimationProps(el.props.animation, el),
20
+ animationDuration: getTimingByKey(el.props.animationDuration || 'A').timing,
21
+ animationDelay: getTimingByKey(el.props.animationDelay || '0s').timing,
22
+ animationTimingFunction: getTimingFunction(el.props.animationTimingFunction || 'ease'),
23
+ animationFillMode: el.props.animationFillMode || 'both',
24
+ animationPlayState: el.props.animationPlayState,
25
+ animationDirection: el.props.animationDirection
26
+ },
27
+ animationName: (el) => el.props.animationName && {
28
+ animationName: applyAnimationProps(el.props.animationName, el)
29
+ },
30
+
31
+ animationDuration: ({ props }) => props.animationDuration && ({
32
+ animationDuration: getTimingByKey(props.animationDuration).timing
33
+ }),
34
+ animationDelay: ({ props }) => props.animationDelay && ({
35
+ animationDelay: getTimingByKey(props.animationDelay).timing
36
+ }),
37
+ animationTimingFunction: ({ props }) => props.animationTimingFunction && ({
38
+ animationTimingFunction: getTimingFunction(props.animationTimingFunction)
39
+ }),
40
+ animationFillMode: ({ props }) => props.animationFillMode && ({
41
+ animationFillMode: props.animationFillMode
42
+ }),
43
+ animationPlayState: ({ props }) => props.animationPlayState && ({
44
+ animationPlayState: props.animationPlayState
45
+ }),
46
+ animationIterationCount: ({ props }) => props.animationIterationCount && ({
47
+ animationIterationCount: props.animationIterationCount || 1
48
+ }),
49
+ animationDirection: ({ props }) => props.animationDirection && ({
50
+ animationDirection: props.animationDirection
51
+ })
52
+ }
53
+ }
@@ -0,0 +1,151 @@
1
+ 'use strict'
2
+
3
+ import { getSpacingBasedOnRatio, getSpacingByKey, isString } from '@symbo.ls/scratch'
4
+
5
+ const transfromGap = gap => isString(gap) && ({
6
+ gap: gap.split(' ').map(v => getSpacingByKey(v, 'gap').gap).join(' ')
7
+ })
8
+
9
+ export const Block = {
10
+ class: {
11
+ boxSizing: ({ props }) => props.boxSizing ? ({ boxSizing: props.boxSizing }) : {
12
+ boxSizing: 'border-box'
13
+ },
14
+
15
+ display: ({ props }) => props.display && ({ display: props.display }),
16
+
17
+ hide: ({ props }) => props.hide && ({ display: 'none' }),
18
+
19
+ width: ({ props }) => props.width && getSpacingBasedOnRatio(props, 'width'),
20
+ height: ({ props }) => props.height && getSpacingBasedOnRatio(props, 'height'),
21
+ boxSize: ({ props }) => {
22
+ if (typeof props.boxSize !== 'string') return
23
+ const [height, width] = props.boxSize.split(' ')
24
+ return {
25
+ ...getSpacingByKey(height, 'height'),
26
+ ...getSpacingByKey(width || height, 'width')
27
+ }
28
+ },
29
+
30
+ maxWidth: ({ props }) => props.maxWidth && getSpacingBasedOnRatio(props, 'maxWidth'),
31
+ minWidth: ({ props }) => props.minWidth && getSpacingBasedOnRatio(props, 'minWidth'),
32
+ widthRange: ({ props }) => {
33
+ if (typeof props.widthRange !== 'string') return
34
+ const [minWidth, maxWidth] = props.widthRange.split(' ')
35
+ return {
36
+ ...getSpacingByKey(minWidth, 'minWidth'),
37
+ ...getSpacingByKey(maxWidth || minWidth, 'maxWidth')
38
+ }
39
+ },
40
+
41
+ maxHeight: ({ props }) => props.maxHeight && getSpacingBasedOnRatio(props, 'maxHeight'),
42
+ minHeight: ({ props }) => props.minHeight && getSpacingBasedOnRatio(props, 'minHeight'),
43
+ heightRange: ({ props }) => {
44
+ if (typeof props.heightRange !== 'string') return
45
+ const [minHeight, maxHeight] = props.heightRange.split(' ')
46
+ return {
47
+ ...getSpacingByKey(minHeight, 'minHeight'),
48
+ ...getSpacingByKey(maxHeight || minHeight, 'maxHeight')
49
+ }
50
+ },
51
+
52
+ direction: ({ props }) => props.direction && ({ direction: props.direction }),
53
+
54
+ aspectRatio: ({ props }) => props.aspectRatio && ({ aspectRatio: props.aspectRatio }),
55
+
56
+ borderWidth: ({ props }) => props.borderWidth ? getSpacingBasedOnRatio(props, 'borderWidth') : null,
57
+
58
+ padding: ({ props }) => props.padding ? getSpacingBasedOnRatio(props, 'padding') : null,
59
+ paddingInline: ({ props }) => {
60
+ if (typeof props.paddingInline !== 'string') return
61
+ const [paddingInlineStart, paddingInlineEnd] = props.paddingInline.split(' ')
62
+ return {
63
+ ...getSpacingByKey(paddingInlineStart, 'paddingInlineStart'),
64
+ ...getSpacingByKey(paddingInlineEnd || paddingInlineStart, 'paddingInlineEnd')
65
+ }
66
+ },
67
+ paddingBlock: ({ props }) => {
68
+ if (typeof props.paddingBlock !== 'string') return
69
+ const [paddingBlockStart, paddingBlockEnd] = props.paddingBlock.split(' ')
70
+ return {
71
+ ...getSpacingByKey(paddingBlockStart, 'paddingBlockStart'),
72
+ ...getSpacingByKey(paddingBlockEnd || paddingBlockStart, 'paddingBlockEnd')
73
+ }
74
+ },
75
+ paddingInlineStart: ({ props }) => props.paddingInlineStart ? getSpacingBasedOnRatio(props, 'paddingInlineStart') : null,
76
+ paddingInlineEnd: ({ props }) => props.paddingInlineEnd ? getSpacingBasedOnRatio(props, 'paddingInlineEnd') : null,
77
+ paddingBlockStart: ({ props }) => props.paddingBlockStart ? getSpacingBasedOnRatio(props, 'paddingBlockStart') : null,
78
+ paddingBlockEnd: ({ props }) => props.paddingBlockEnd ? getSpacingBasedOnRatio(props, 'paddingBlockEnd') : null,
79
+
80
+ margin: ({ props }) => props.margin ? getSpacingBasedOnRatio(props, 'margin') : null,
81
+ marginInline: ({ props }) => {
82
+ if (typeof props.marginInline !== 'string') return
83
+ const [marginInlineStart, marginInlineEnd] = props.marginInline.split(' ')
84
+ return {
85
+ ...getSpacingByKey(marginInlineStart, 'marginInlineStart'),
86
+ ...getSpacingByKey(marginInlineEnd || marginInlineStart, 'marginInlineEnd')
87
+ }
88
+ },
89
+ marginBlock: ({ props }) => {
90
+ if (typeof props.marginBlock !== 'string') return
91
+ const [marginBlockStart, marginBlockEnd] = props.marginBlock.split(' ')
92
+ return {
93
+ ...getSpacingByKey(marginBlockStart, 'marginBlockStart'),
94
+ ...getSpacingByKey(marginBlockEnd || marginBlockStart, 'marginBlockEnd')
95
+ }
96
+ },
97
+ marginInlineStart: ({ props }) => props.marginInlineStart ? getSpacingBasedOnRatio(props, 'marginInlineStart') : null,
98
+ marginInlineEnd: ({ props }) => props.marginInlineEnd ? getSpacingBasedOnRatio(props, 'marginInlineEnd') : null,
99
+ marginBlockStart: ({ props }) => props.marginBlockStart ? getSpacingBasedOnRatio(props, 'marginBlockStart') : null,
100
+ marginBlockEnd: ({ props }) => props.marginBlockEnd ? getSpacingBasedOnRatio(props, 'marginBlockEnd') : null,
101
+
102
+ gap: ({ props }) => props.gap ? transfromGap(props.gap) : null,
103
+ gridArea: ({ props }) => props.gridArea && ({ gridArea: props.gridArea }),
104
+
105
+ flex: ({ props }) => props.flex && ({ flex: props.flex }),
106
+ flexDirection: ({ props }) => props.flexDirection && ({ flexDirection: props.flexDirection }),
107
+ alignItems: ({ props }) => props.alignItems && ({ alignItems: props.alignItems }),
108
+ alignContent: ({ props }) => props.alignContent && ({ alignContent: props.alignContent }),
109
+ justifyContent: ({ props }) => props.justifyContent && ({ justifyContent: props.justifyContent }),
110
+ justifyItems: ({ props }) => props.justifyItems && ({ justifyItems: props.justifyItems }),
111
+ alignSelf: ({ props }) => props.alignSelf && ({ alignSelf: props.alignSelf }),
112
+ order: ({ props }) => props.order && ({ order: props.order }),
113
+
114
+ flexWrap: ({ props }) => props.flexWrap && ({
115
+ display: 'flex',
116
+ flexFlow: props.flexWrap
117
+ }),
118
+ flexFlow: ({ props }) => props.flexFlow && ({
119
+ display: 'flex',
120
+ flexFlow: props.flexFlow
121
+ }),
122
+ flexAlign: ({ props }) => {
123
+ if (typeof props.flexAlign !== 'string') return
124
+ const [alignItems, justifyContent] = props.flexAlign.split(' ')
125
+ return {
126
+ display: 'flex',
127
+ alignItems: alignItems,
128
+ justifyContent: justifyContent
129
+ }
130
+ },
131
+
132
+ gridColumn: ({ props }) => props.gridColumn && ({ gridColumn: props.gridColumn }),
133
+ gridColumnStart: ({ props }) => props.columnStart ? ({ gridColumnStart: props.columnStart }) : null,
134
+ gridRow: ({ props }) => props.gridRow && ({ gridRow: props.gridRow }),
135
+ gridRowStart: ({ props }) => props.rowStart ? ({ gridRowStart: props.rowStart }) : null,
136
+
137
+ size: ({ props }) => {
138
+ if (typeof props.heightRange !== 'string') return
139
+ const [minHeight, maxHeight] = props.heightRange.split(' ')
140
+ return {
141
+ ...getSpacingByKey(minHeight, 'minHeight'),
142
+ ...getSpacingByKey(maxHeight || minHeight, 'maxHeight')
143
+ }
144
+ },
145
+
146
+ columns: ({ props }) => props.columns && ({ columns: props.columns })
147
+ }
148
+ }
149
+
150
+ export const Span = { tag: 'span' }
151
+ // export const Article = { tag: 'article' }
@@ -0,0 +1,82 @@
1
+ 'use strict'
2
+
3
+ import { isNot, isArray, isObject, isObjectLike, diff, deepClone } from '@domql/utils'
4
+
5
+ export const Collection = {
6
+ define: {
7
+ $setCollection: (param, el, state) => {
8
+ if (!param) return
9
+
10
+ let data = isArray(param) ? param : []
11
+
12
+ if (isObject(param)) {
13
+ for (const obj in param) { data.push(param[obj]) }
14
+ }
15
+
16
+ data = data.map(item => !isObjectLike(item) ? {
17
+ props: { value: item }
18
+ } : item)
19
+
20
+ if (data.length) {
21
+ const t = setTimeout(() => {
22
+ el.set({ tag: 'fragment', ...data }, { preventDefineUpdate: '$setCollection' })
23
+ clearTimeout(t)
24
+ })
25
+ }
26
+
27
+ return data
28
+ },
29
+
30
+ $setStateCollection: (param, el, state) => {
31
+ if (!param) return
32
+ if (param.parse) param = param.parse()
33
+ if (isNot(param)('array', 'object')) return
34
+
35
+ if (el.key === 'cnt') {
36
+ if (el.__stateCollectionCache) {
37
+ const d = diff(param, el.__stateCollectionCache) // eslint-disable-line
38
+ } else {
39
+ el.__stateCollectionCache = deepClone(param)
40
+ }
41
+ }
42
+
43
+ const obj = { tag: 'fragment' }
44
+
45
+ for (const key in param) {
46
+ const value = param[key]
47
+ obj[key] = { state: isObjectLike(value) ? value : { value } }
48
+ }
49
+
50
+ const set = () => {
51
+ el.set(obj, { preventDefineUpdate: '$setStateCollection' })
52
+ }
53
+
54
+ if (el.props.lazyLoad) {
55
+ window.requestAnimationFrame(set)
56
+ } else set()
57
+
58
+ return obj
59
+ },
60
+
61
+ $setPropsCollection: (param, el, state) => {
62
+ if (!param) return
63
+ if (isNot(param)('array', 'object')) return
64
+
65
+ const obj = { tag: 'fragment' }
66
+ for (const key in param) {
67
+ const value = param[key]
68
+ obj[key] = { props: isObjectLike(value) ? value : { value } }
69
+ }
70
+
71
+ const set = () => {
72
+ el.set(obj, { preventDefineUpdate: '$setStateCollection' })
73
+ }
74
+
75
+ if (el.props.lazyLoad) {
76
+ window.requestAnimationFrame(set)
77
+ } else set()
78
+
79
+ return obj
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+
3
+ export const Direction = {
4
+ props: {
5
+ direction: 'ltr'
6
+ },
7
+ class: {
8
+ direction: ({ props }) => ({ direction: props.direction })
9
+ }
10
+ }
@@ -0,0 +1,17 @@
1
+ 'use strict'
2
+
3
+ export const Flex = {
4
+ props: {
5
+ display: 'flex'
6
+ },
7
+
8
+ class: {
9
+ flow: ({ props }) => props.flow && ({ flexFlow: props.flow }),
10
+ wrap: ({ props }) => props.wrap && ({ flexWrap: props.wrap }),
11
+ align: ({ props }) => {
12
+ if (typeof props.align !== 'string') return
13
+ const [alignItems, justifyContent] = props.align.split(' ')
14
+ return { alignItems, justifyContent }
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ export const Form = {
4
+ tag: 'form',
5
+ props: {},
6
+ attr: {
7
+ action: ({ props }) => props.action,
8
+ method: ({ props }) => props.method,
9
+ enctype: ({ props }) => props.enctype
10
+ }
11
+ }
@@ -0,0 +1,30 @@
1
+ 'use strict'
2
+
3
+ import { getSpacingBasedOnRatio } from '@symbo.ls/scratch'
4
+
5
+ export const Grid = {
6
+ props: { display: 'grid' },
7
+
8
+ class: {
9
+ area: ({ props }) => props.area ? ({ gridArea: props.area }) : null,
10
+ template: ({ props }) => props.template ? ({ gridTemplate: props.template }) : null,
11
+ templateAreas: ({ props }) => props.templateAreas ? ({ gridTemplateAreas: props.templateAreas }) : null,
12
+
13
+ column: ({ props }) => props.column ? ({ gridColumn: props.column }) : null,
14
+ columns: ({ props }) => props.columns ? ({ gridTemplateColumns: props.columns }) : null,
15
+ templateColumns: ({ props }) => props.templateColumns ? ({ gridTemplateColumns: props.templateColumns }) : null,
16
+ autoColumns: ({ props }) => props.autoColumns ? ({ gridAutoColumns: props.autoColumns }) : null,
17
+ columnStart: ({ props }) => props.columnStart ? ({ gridColumnStart: props.columnStart }) : null,
18
+
19
+ row: ({ props }) => props.row ? ({ gridRow: props.row }) : null,
20
+ rows: ({ props }) => props.rows ? ({ gridTemplateRows: props.rows }) : null,
21
+ templateRows: ({ props }) => props.templateRows ? ({ gridTemplateRows: props.templateRows }) : null,
22
+ autoRows: ({ props }) => props.autoRows ? ({ gridAutoRows: props.autoRows }) : null,
23
+ rowStart: ({ props }) => props.rowStart ? ({ gridRowStart: props.rowStart }) : null,
24
+
25
+ autoFlow: ({ props }) => props.autoFlow ? ({ gridAutoFlow: props.autoFlow }) : null,
26
+
27
+ columnGap: ({ props }) => props.columnGap ? getSpacingBasedOnRatio(props, 'columnGap') : null,
28
+ rowGap: ({ props }) => props.rowGap ? getSpacingBasedOnRatio(props, 'rowGap') : null
29
+ }
30
+ }
@@ -0,0 +1,16 @@
1
+ 'use strict'
2
+
3
+ export const Iframe = {
4
+ tag: 'iframe',
5
+ props: {
6
+ position: 'relative',
7
+ minWidth: 'H',
8
+ minHeight: 'H'
9
+ },
10
+ attr: {
11
+ src: ({ props }) => props.src,
12
+ loading: ({ props }) => props.loading,
13
+ allowfullscreen: ({ props }) => props.allowfullscreen,
14
+ referrerpolicy: ({ props }) => props.referrerpolicy
15
+ }
16
+ }
@@ -0,0 +1,17 @@
1
+ 'use strict'
2
+
3
+ export const Img = {
4
+ tag: 'img',
5
+
6
+ props: {
7
+ src: '',
8
+ alt: '',
9
+ title: ''
10
+ },
11
+
12
+ attr: {
13
+ src: ({ props }) => props.src,
14
+ alt: ({ props }) => props.alt,
15
+ title: ({ props }) => props.title || props.alt
16
+ }
17
+ }
@@ -0,0 +1,9 @@
1
+ 'use strict'
2
+
3
+ export const Interaction = {
4
+ class: {
5
+ userSelect: ({ props }) => props.userSelect && ({ userSelect: props.userSelect }),
6
+ pointerEvents: ({ props }) => props.pointerEvents && ({ pointerEvents: props.pointerEvents }),
7
+ cursor: ({ props }) => props.cursor && ({ cursor: props.cursor })
8
+ }
9
+ }
@@ -0,0 +1,78 @@
1
+ 'use strict'
2
+
3
+ const style = {
4
+ appearance: 'none',
5
+ border: 'none',
6
+ cursor: 'pointer',
7
+ fontFamily: 'inherit'
8
+ }
9
+
10
+ export const Hoverable = {
11
+ props: {
12
+ transition: 'C defaultBezier',
13
+ transitionProperty: 'opacity, transform',
14
+ opacity: 0.85,
15
+
16
+ ':hover': {
17
+ opacity: 0.9,
18
+ transform: 'scale(1.015)'
19
+ },
20
+ ':active': {
21
+ opacity: 1,
22
+ transform: 'scale(1.015)'
23
+ },
24
+ '.active': {
25
+ opacity: 1,
26
+ transform: 'scale(1.015)',
27
+
28
+ ':hover': { opacity: 1 }
29
+ }
30
+ }
31
+ }
32
+
33
+ export const Clickable = {
34
+ extend: Hoverable,
35
+ props: {
36
+ ':active': {
37
+ opacity: 1,
38
+ transform: 'scale(1.015)'
39
+ },
40
+ '.active': {
41
+ opacity: 1
42
+ }
43
+ }
44
+ }
45
+
46
+ export const Focusable = {
47
+ props: {
48
+ border: 'none',
49
+ outline: 'solid, 0, blue .3',
50
+ ':focus-visible': {
51
+ opacity: 1,
52
+ outline: 'solid, X, blue .3'
53
+ }
54
+ },
55
+
56
+ attr: {
57
+ placeholder: ({ props }) => props.placeholder,
58
+ tabIndex: ({ props }) => props.tabIndex
59
+ }
60
+ }
61
+
62
+ export const FocusableComponent = {
63
+ extend: Focusable,
64
+ tag: 'button',
65
+ props: {
66
+ fontSize: 'A',
67
+ type: 'button',
68
+ border: 'none',
69
+ textDecoration: 'none',
70
+ lineHeight: '1',
71
+ whiteSpace: 'nowrap',
72
+ fontFamily: 'inherit',
73
+ style
74
+ },
75
+ attr: {
76
+ type: ({ props }) => props.type
77
+ }
78
+ }
@@ -0,0 +1,164 @@
1
+ 'use strict'
2
+
3
+ import { merge, isArray } from '@domql/utils'
4
+ import { getSystemTheme } from './Theme'
5
+
6
+ const keySetters = {
7
+ '@': (key, props, result, element, isSubtree) => applyMediaProps(key, props, isSubtree ? result : result.media, element),
8
+ ':': (key, props, result, element, isSubtree) => applySelectorProps(key, props, isSubtree ? result : result.selector, element),
9
+ '[': (key, props, result, element, isSubtree) => applySelectorProps(key, props, isSubtree ? result : result.selector, element),
10
+ '&': (key, props, result, element, isSubtree) => applySelectorProps(key, props, isSubtree ? result : result.selector, element),
11
+ $: (key, props, result, element, isSubtree) => applyCaseProps(key, props, isSubtree ? result : result.case, element),
12
+ '.': (key, props, result, element, isSubtree) => applyConditionalCaseProps(key, props, isSubtree ? result : result.case, element),
13
+ '!': (key, props, result, element, isSubtree) => applyConditionalFalsyProps(key, props, isSubtree ? result : result.case, element)
14
+ }
15
+
16
+ const execClass = (key, props, result, element) => {
17
+ const { class: className } = element
18
+ const classnameExec = className[key]
19
+
20
+ if (typeof classnameExec !== 'function') return
21
+
22
+ let classExec = classnameExec({
23
+ props,
24
+ context: element.context,
25
+ state: element.state
26
+ })
27
+ if (isArray(classExec)) {
28
+ classExec = classExec.reduce((a, c) => merge(a, c), {})
29
+ }
30
+
31
+ for (const finalProp in classExec) {
32
+ result[finalProp] = classExec[finalProp]
33
+ }
34
+
35
+ return classExec
36
+ }
37
+
38
+ const convertPropsToClass = (props, result, element) => {
39
+ const propsClassObj = {}
40
+
41
+ for (const key in props) {
42
+ const setter = keySetters[key.slice(0, 1)]
43
+ if (setter) {
44
+ setter(key, props[key], propsClassObj, element, true)
45
+ continue
46
+ } else {
47
+ execClass(key, props, propsClassObj, element)
48
+ }
49
+ }
50
+
51
+ return propsClassObj
52
+ }
53
+
54
+ const applyMediaProps = (key, props, result, element) => {
55
+ const { context } = element
56
+ if (!context.system || !context.system.MEDIA) return
57
+ const globalTheme = getSystemTheme(element)
58
+ const { MEDIA } = context.system
59
+ const mediaName = MEDIA[key.slice(1)]
60
+ const generatedClass = convertPropsToClass(props, result, element)
61
+
62
+ const name = key.slice(1)
63
+ const isTheme = ['dark', 'light'].includes(name)
64
+ const matchesGlobal = name === globalTheme
65
+
66
+ if (globalTheme && isTheme) {
67
+ if (matchesGlobal) return merge(result, generatedClass)
68
+ return
69
+ }
70
+
71
+ const mediaKey = `@media screen and ${mediaName}`
72
+ result[mediaKey] = generatedClass
73
+ return result[mediaKey]
74
+ }
75
+
76
+ const applySelectorProps = (key, props, result, element) => {
77
+ const selectorKey = `&${key}`
78
+ result[selectorKey] = convertPropsToClass(props, result, element)
79
+ return result[selectorKey]
80
+ }
81
+
82
+ const applyCaseProps = (key, props, result, element) => {
83
+ const { CASES } = element.context && element.context.system
84
+ const caseKey = key.slice(1)
85
+ const isPropTrue = element.props[caseKey]
86
+ if (!CASES[caseKey] && !isPropTrue) return
87
+ return merge(result, convertPropsToClass(props, result, element))
88
+ }
89
+
90
+ const applyConditionalCaseProps = (key, props, result, element) => {
91
+ const caseKey = key.slice(1)
92
+ const isPropTrue = element.props[caseKey] || element.state[caseKey] === true
93
+ if (!isPropTrue) return // remove classname if not here
94
+ return merge(result, convertPropsToClass(props, result, element))
95
+ }
96
+
97
+ const applyConditionalFalsyProps = (key, props, result, element) => {
98
+ const caseKey = key.slice(1)
99
+ const isPropTrue = element.props[caseKey] || element.state[caseKey] === true
100
+ if (!isPropTrue) return merge(result, convertPropsToClass(props, result, element))
101
+ }
102
+
103
+ const applyTrueProps = (props, result, element) => merge(result, convertPropsToClass(props, result, element))
104
+
105
+ const beforeClassAssign = (element, s) => {
106
+ const { props, class: className } = element
107
+
108
+ const CLASS_NAMES = {
109
+ media: {},
110
+ selector: {},
111
+ case: {}
112
+ }
113
+
114
+ for (const key in props) {
115
+ const setter = keySetters[key.slice(0, 1)]
116
+ if (setter) setter(key, props[key], CLASS_NAMES, element)
117
+ }
118
+
119
+ merge(className, CLASS_NAMES)
120
+ }
121
+
122
+ export const initUpdate = element => {
123
+ const { props, class: className } = element
124
+ const globalTheme = getSystemTheme(element)
125
+
126
+ const parentProps = element.parent.props
127
+ if (parentProps && parentProps.spacingRatio && parentProps.inheritSpacingRatio) {
128
+ element.setProps({
129
+ spacingRatio: parentProps.spacingRatio,
130
+ inheritSpacingRatio: true
131
+ }, {
132
+ preventRecursive: true,
133
+ ignoreInitUpdate: true
134
+ })
135
+ }
136
+
137
+ if (globalTheme) {
138
+ const CLASS_NAMES = {
139
+ media: {},
140
+ selector: {},
141
+ case: {}
142
+ }
143
+
144
+ for (const key in props) {
145
+ const setter = keySetters[key.slice(0, 1)]
146
+ if (key === 'theme') {
147
+ props.update({
148
+ themeModifier: globalTheme
149
+ }, { preventRecursive: true, ignoreInitUpdate: true, preventDefineUpdate: '$setStateCollection' })
150
+ } else if (key === 'true') applyTrueProps(props[key], CLASS_NAMES, element)
151
+ if (setter) setter(key, props[key], CLASS_NAMES, element)
152
+ }
153
+
154
+ if (Object.keys(CLASS_NAMES.media).length) {
155
+ className.media = CLASS_NAMES.media
156
+ }
157
+ className.selector = CLASS_NAMES.selector
158
+ className.case = CLASS_NAMES.case
159
+ }
160
+ }
161
+
162
+ export const Media = {
163
+ on: { beforeClassAssign, initUpdate }
164
+ }