@symbo.ls/uikit 3.7.0 → 3.7.4

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/Button.js ADDED
@@ -0,0 +1,72 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * A Button component
5
+ * The `Button` component represents a clickable button element with customizable styles and properties.
6
+ *
7
+ * @description
8
+ * @extends {FocusableComponent, IconText}
9
+ * @typedef {Object} Button
10
+ * @property {string} tag - The HTML tag used to render the button (e.g., 'button').
11
+ * @property {string} props.type - The type attribute of the button ('button' by default).
12
+ *
13
+ * @example
14
+ * // Example usage of the Button component:
15
+ * const myButton = {
16
+ * extends: Button
17
+ * }
18
+ */
19
+
20
+ export const Button = {
21
+ extends: ['IconText', 'FocusableComponent'],
22
+ tag: 'button',
23
+
24
+ fontSize: 'A',
25
+ type: 'button',
26
+ borderStyle: 'none',
27
+ display: 'inline-flex',
28
+ align: 'center center',
29
+ textDecoration: 'none',
30
+ lineHeight: '1',
31
+ whiteSpace: 'nowrap',
32
+ padding: 'Z B2',
33
+ fontWeight: '500',
34
+ fontFamily: 'inherit',
35
+ round: 'C2',
36
+
37
+ disabled: (el) => el.call('exec', el.props.disabled)
38
+ }
39
+
40
+ export const SquareButton = {
41
+ extends: 'Button',
42
+ fontSize: 'A',
43
+ width: 'A',
44
+ padding: 'Z',
45
+ aspectRatio: '1 / 1',
46
+ icon: 'smile',
47
+ boxSize: 'fit-content fit-content',
48
+ justifyContent: 'center',
49
+ round: 'Z',
50
+ boxSizing: 'content-box'
51
+ }
52
+
53
+ export const CircleButton = {
54
+ extends: 'SquareButton',
55
+ round: 'C'
56
+ }
57
+
58
+ export const KangorooButton = {
59
+ extends: 'Button',
60
+ childExtends: 'IconText'
61
+ }
62
+
63
+ export const ButtonSet = {
64
+ tag: 'nav',
65
+ display: 'flex',
66
+ childExtends: 'SquareButton'
67
+ }
68
+
69
+ export const IconButton = {
70
+ extends: ['SquareButton', 'ClickableItem'],
71
+ round: 'Z'
72
+ }
package/Dialog.js ADDED
@@ -0,0 +1,69 @@
1
+ 'use strict'
2
+
3
+ export const Dialog = {
4
+ display: 'flex',
5
+ tag: 'dialog',
6
+ flow: 'column',
7
+ border: '0',
8
+ theme: 'dialog',
9
+ round: 'Z2'
10
+ }
11
+
12
+ export const DialogHeader = {
13
+ extends: 'Hgroup',
14
+
15
+ minWidth: '100%',
16
+ gap: 'A',
17
+
18
+ Title: {
19
+ align: 'center space-between',
20
+
21
+ Text: { text: 'Title' },
22
+
23
+ SquareButton: {
24
+ icon: 'x',
25
+ theme: 'transparent'
26
+ }
27
+ },
28
+
29
+ Paragraph: {
30
+ color: 'caption'
31
+ }
32
+ }
33
+
34
+ export const DialogFooter = {
35
+ display: 'flex',
36
+
37
+ align: 'center flex-end',
38
+ gap: 'X2',
39
+ margin: 'auto - -',
40
+ padding: 'Y2 X2',
41
+
42
+ childExtends: {
43
+ extends: 'Button',
44
+ textTransform: 'uppercase',
45
+ background: 'transparent',
46
+ '@dark': {
47
+ theme: 'primary @dark .color-only'
48
+ },
49
+ '@light': {
50
+ theme: 'primary @light .color-only'
51
+ },
52
+ '&': {
53
+ padding: 'Z A'
54
+ },
55
+ ':hover': {
56
+ theme: 'tertiary'
57
+ },
58
+ ':active': {
59
+ background: 'white.1'
60
+ }
61
+ },
62
+
63
+ Cancel: {
64
+ text: 'cancel'
65
+ },
66
+ Ok: {
67
+ text: 'ok'
68
+ }
69
+ }
package/Dropdown.js ADDED
@@ -0,0 +1,130 @@
1
+ 'use strict'
2
+
3
+ export const DropdownList = {
4
+ display: 'flex',
5
+
6
+ attr: {
7
+ dropdown: true
8
+ },
9
+
10
+ padding: '0 Y',
11
+ maxHeight: 'G',
12
+ flow: 'column',
13
+ theme: 'quaternary',
14
+ overflow: 'hidden auto',
15
+ style: { listStyleType: 'none' },
16
+ transition: 'B defaultBezier',
17
+ transitionProperty: 'transform, opacity, visibility',
18
+ children: ({ props }) => props.options || [],
19
+ childrenAs: 'props',
20
+
21
+ '.hidden': {
22
+ transform: 'translate3d(0,10%,0)',
23
+ opacity: 0,
24
+ visibility: 'hidden'
25
+ },
26
+
27
+ childExtends: {
28
+ extends: 'Button',
29
+ state: {},
30
+ isActive: ({ key, state }) => state.active === key,
31
+ position: 'relative',
32
+ round: '0',
33
+ align: 'center flex-end',
34
+ flow: 'row-reverse',
35
+ padding: 'Z2 C Z2 Y2',
36
+ margin: '0',
37
+ gap: 'Y2',
38
+ theme: 'quaternary .child',
39
+
40
+ ':hover': {
41
+ style: {
42
+ svg: { opacity: '0.5' }
43
+ }
44
+ },
45
+
46
+ Icon: {
47
+ isActive: ({ key, state }) => state.active === key,
48
+ name: 'checkmark',
49
+ opacity: '0.1',
50
+ '.active': { opacity: '1' }
51
+ },
52
+
53
+ ':not(:first-child)': {
54
+ '@dark': { border: 'solid gray4.65' },
55
+ '@light': { border: 'solid gray11' },
56
+ borderWidth: '1px 0 0'
57
+ }
58
+ }
59
+ }
60
+
61
+ export const DropdownParent = {
62
+ position: 'relative',
63
+ zIndex: 999,
64
+ style: {
65
+ '&:hover': {
66
+ zIndex: 1000,
67
+ '& [dropdown]': {
68
+ transform: 'translate3d(0,0,0)',
69
+ opacity: 1,
70
+ visibility: 'visible'
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ export const DropdownParentFocus = {
77
+ position: 'relative',
78
+ tabindex: '0',
79
+ style: {
80
+ '&:focus-within': {
81
+ zIndex: 1000,
82
+ '& [dropdown]': {
83
+ transform: 'translate3d(0,0,0)',
84
+ opacity: 1,
85
+ visibility: 'visible'
86
+ }
87
+ }
88
+ },
89
+
90
+ Input_trigger: {
91
+ type: 'checkbox',
92
+ opacity: '0',
93
+ visibility: 'hidden',
94
+ position: 'absolute',
95
+ inset: '0',
96
+ onUpdate: (el) => el.node.blur()
97
+ },
98
+
99
+ Dropdown: {
100
+ // onClick: (ev, el) => el.parent.Input_trigger.node.blur()
101
+ onClick: () => {
102
+ document.activeElement?.blur()
103
+ }
104
+ }
105
+ }
106
+ export const DropdownSiblingFocus = {
107
+ props: {
108
+ position: 'relative',
109
+ tabindex: '0',
110
+ style: {
111
+ '&:focus-within': {
112
+ zIndex: 1000,
113
+ '& ~ [dropdown]': {
114
+ transform: 'translate3d(0,0,0)',
115
+ opacity: 1,
116
+ visibility: 'visible'
117
+ }
118
+ }
119
+ }
120
+ },
121
+
122
+ Input_trigger: {
123
+ type: 'checkbox',
124
+ opacity: '0',
125
+ visibility: 'hidden',
126
+ position: 'absolute',
127
+ inset: '0',
128
+ onUpdate: (el) => el.node.blur()
129
+ }
130
+ }
package/Icon/index.js ADDED
@@ -0,0 +1,228 @@
1
+ 'use strict'
2
+
3
+ const inheritFromIsActive = el => {
4
+ const { props } = el
5
+ const propsActive = props['.isActive']
6
+ if (!propsActive) return
7
+ return el.call('exec', propsActive.name || propsActive.icon)
8
+ }
9
+
10
+ const getIconName = (el, s) => {
11
+ const { key, props } = el
12
+ let icon = el.call('exec', props.name || props.icon || key, el)
13
+
14
+ if (el.call('isString', icon) && icon.includes('{{')) {
15
+ icon = el.call('replaceLiteralsWithObjectFields', icon)
16
+ }
17
+
18
+ return el.call('isString', icon) ? icon : key
19
+ }
20
+
21
+ export const Icon = {
22
+ extends: 'Svg',
23
+ width: 'A',
24
+ height: 'A',
25
+ display: 'inline-block',
26
+ style: { fill: 'currentColor', '*': { fill: 'currentColor' } },
27
+
28
+ props: (el, s, ctx) => {
29
+ const { props, parent } = el
30
+ const { icons: ICONS, useIconSprite, verbose } = ctx && ctx.designSystem
31
+ const { toCamelCase } = ctx && ctx.utils
32
+
33
+ const inheritFromIsActive = (el) => {
34
+ const { props } = el
35
+ const propsActive = props['.isActive']
36
+ if (!propsActive) return
37
+ return el.call('exec', propsActive.name || propsActive.icon)
38
+ }
39
+
40
+ const getSemanticIcon = (el, s, ctx) => {
41
+ const { semanticIcons: SEMANTIC_ICONS } = ctx && ctx.designSystem
42
+ const { toCamelCase } = ctx && ctx.utils
43
+
44
+ let iconName = getIconName(el, s)
45
+ const camelCase = toCamelCase(iconName)
46
+ const isArray = camelCase.split(/([a-z])([A-Z])/g)
47
+ const semanticIconRootName = isArray[1]
48
+ ? isArray[0]
49
+ : iconName.split('.')[0].split(' ')[0]
50
+ const semanticIcon =
51
+ SEMANTIC_ICONS && SEMANTIC_ICONS[semanticIconRootName]
52
+ if (semanticIcon) {
53
+ const iconKey = iconName.includes('.')
54
+ ? 'sfsymbols.' + iconName.split('.').slice(1).join('.')
55
+ : 'sfsymbols'
56
+ iconName =
57
+ semanticIcon[iconKey] ||
58
+ semanticIcon[iconName.split('.')[0].split(' ')[0]]
59
+ return {
60
+ tag: 'span',
61
+ semantic_symbols: true,
62
+ width: 'A',
63
+ height: 'A',
64
+ lineHeight: '1em',
65
+ ':after': {
66
+ fontSize: 'Z',
67
+ fontWeight: '300',
68
+ content: `"${iconName}"`,
69
+ textAlign: 'center',
70
+ display: 'inline-block',
71
+ style: {
72
+ color: 'currentColor',
73
+ fontFamily: "'SF Pro Icons', 'SF Pro', 'SF Symbols', 'Segoe UI'"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ const getIconName = (el, s) => {
81
+ const { key, props } = el
82
+ let icon = el.call('exec', props.name || props.icon || key, el)
83
+
84
+ if (el.call('isString', icon) && icon.includes('{{')) {
85
+ icon = el.call('replaceLiteralsWithObjectFields', icon)
86
+ }
87
+
88
+ return el.call('isString', icon) ? icon : key
89
+ }
90
+
91
+ const iconName = getIconName(el, s)
92
+ const camelCase = toCamelCase(iconName)
93
+ const isArray = camelCase.split(/([a-z])([A-Z])/g)
94
+ const semanticIcon = getSemanticIcon(el, s, ctx)
95
+ if (semanticIcon) return semanticIcon
96
+
97
+ let activeIconName
98
+ if (props.isActive) activeIconName = inheritFromIsActive(el)
99
+ const parentProps = parent.props
100
+ const parentPropsActive = parentProps['.isActive']
101
+ if (
102
+ parent &&
103
+ parentProps &&
104
+ parentProps.isActive &&
105
+ parentPropsActive &&
106
+ parentPropsActive.icon
107
+ ) {
108
+ activeIconName = el.call(
109
+ 'exec',
110
+ parentPropsActive.icon ||
111
+ parentPropsActive.Icon.name ||
112
+ parentPropsActive.Icon.icon,
113
+ el
114
+ )
115
+ }
116
+
117
+ if (el.call('isString', activeIconName) && activeIconName.includes('{{')) {
118
+ activeIconName = el.call(
119
+ 'replaceLiteralsWithObjectFields',
120
+ activeIconName
121
+ )
122
+ }
123
+
124
+ let iconInContext
125
+ if (ICONS[activeIconName]) iconInContext = activeIconName
126
+ if (ICONS[camelCase]) iconInContext = camelCase
127
+ else if (ICONS[isArray[0] + isArray[1]])
128
+ iconInContext = isArray[0] + isArray[1]
129
+ else if (ICONS[isArray[0]]) iconInContext = isArray[0]
130
+ else {
131
+ if (verbose) el.warn("Can't find icon:", iconName, iconInContext)
132
+ }
133
+
134
+ const iconFromLibrary = ICONS[iconInContext]
135
+ const directSrc = (parent && parent.props && parent.props.src) || props.src
136
+
137
+ return {
138
+ spriteId: useIconSprite && iconInContext,
139
+ src: iconFromLibrary || directSrc || ICONS.noIcon
140
+ }
141
+ },
142
+
143
+ attr: { viewBox: '0 0 24 24' }
144
+ }
145
+
146
+ export const IconText = {
147
+ display: 'flex',
148
+
149
+ align: 'center center',
150
+ lineHeight: 1,
151
+
152
+ '.reversed': {
153
+ flow: 'row-reverse'
154
+ },
155
+
156
+ '.vertical': {
157
+ flow: 'column'
158
+ },
159
+
160
+ Icon: {
161
+ if: el => {
162
+ const { parent, props } = el
163
+ return el.call(
164
+ 'exec',
165
+ parent.props.icon ||
166
+ props.name ||
167
+ props.sfSymbols ||
168
+ parent.props.sfSymbols,
169
+ el
170
+ )
171
+ },
172
+ icon: (el) => el.call('exec', el.parent.props.icon, el.parent)
173
+ },
174
+
175
+ text: ({ props }) => props.text
176
+ }
177
+
178
+ export const FileIcon = {
179
+ display: 'flex',
180
+ theme: 'tertiary',
181
+ boxSize: 'C1',
182
+ align: 'center center',
183
+ round: 'Z',
184
+ Icon: {
185
+ fontSize: 'B',
186
+ margin: 'auto',
187
+ icon: 'file'
188
+ }
189
+ }
190
+
191
+ const getSemanticIcon = (el, s, ctx) => {
192
+ const { semanticIcons: SEMANTIC_ICONS } = ctx && ctx.designSystem
193
+ const { toCamelCase } = ctx && ctx.utils
194
+
195
+ let iconName = getIconName(el, s)
196
+ const camelCase = toCamelCase(iconName)
197
+ const isArray = camelCase.split(/([a-z])([A-Z])/g)
198
+ const semanticIconRootName = isArray[1]
199
+ ? isArray[0]
200
+ : iconName.split('.')[0].split(' ')[0]
201
+ const semanticIcon = SEMANTIC_ICONS && SEMANTIC_ICONS[semanticIconRootName]
202
+ if (semanticIcon) {
203
+ const iconKey = iconName.includes('.')
204
+ ? 'sfsymbols.' + iconName.split('.').slice(1).join('.')
205
+ : 'sfsymbols'
206
+ iconName =
207
+ semanticIcon[iconKey] ||
208
+ semanticIcon[iconName.split('.')[0].split(' ')[0]]
209
+ return {
210
+ tag: 'span',
211
+ semantic_symbols: true,
212
+ width: 'A',
213
+ height: 'A',
214
+ lineHeight: '1em',
215
+ ':after': {
216
+ fontSize: 'Z',
217
+ fontWeight: '300',
218
+ content: `"${iconName}"`,
219
+ textAlign: 'center',
220
+ display: 'inline-block',
221
+ style: {
222
+ color: 'currentColor',
223
+ fontFamily: "'SF Pro Icons', 'SF Pro', 'SF Symbols', 'Segoe UI'"
224
+ }
225
+ }
226
+ }
227
+ }
228
+ }
package/Icon/style.js ADDED
@@ -0,0 +1,8 @@
1
+ 'use strict'
2
+
3
+ export default {
4
+ width: '1em',
5
+ height: '1em',
6
+ fill: 'currentColor',
7
+ display: 'inline-block'
8
+ }
@@ -0,0 +1,54 @@
1
+ 'use strict'
2
+
3
+ export const Checkbox = {
4
+ extends: 'Focusable',
5
+
6
+ tag: 'label',
7
+
8
+ boxSize: 'fit-content fit-content',
9
+ cursor: 'pointer',
10
+ round: 'Y',
11
+
12
+ Input: {
13
+ type: 'checkbox',
14
+ display: 'none',
15
+ ':checked + div': { theme: 'primary' },
16
+ ':checked + div > svg': {
17
+ transform: 'none',
18
+ opacity: '1'
19
+ },
20
+ attr: {
21
+ checked: el => el.call('exec', el.parent.props.checked)
22
+ }
23
+ },
24
+
25
+ Flex: {
26
+ align: 'center center',
27
+ fontSize: 'B1',
28
+ padding: 'V',
29
+ theme: 'field',
30
+ round: 'X2',
31
+ transition: 'background A defaultBezier',
32
+ Icon: {
33
+ icon: 'check',
34
+ opacity: '0',
35
+ transform: 'scale(0.9) rotate(-15deg)',
36
+ transition: 'opacity B defaultBezier'
37
+ }
38
+ }
39
+ }
40
+
41
+ export const CheckboxHgroup = {
42
+ display: 'flex',
43
+ tag: 'label',
44
+
45
+ boxSize: 'fit-content',
46
+ align: 'flex-start flex-start',
47
+ gap: 'A',
48
+
49
+ Checkbox: { tag: 'div' },
50
+ HgroupRows: {
51
+ gap: 'Z1',
52
+ margin: 'Y - - -'
53
+ }
54
+ }
package/Input/Input.js ADDED
@@ -0,0 +1,37 @@
1
+ 'use strict'
2
+
3
+ export const Input = {
4
+ extends: ['Focusable'],
5
+
6
+ tag: 'input',
7
+
8
+ border: 'none',
9
+ type: 'input',
10
+ theme: 'field',
11
+ fontSize: 'A',
12
+ round: 'C',
13
+ lineHeight: '1',
14
+ padding: 'Z2 B',
15
+
16
+ attr: {
17
+ pattern: ({ props }) => props.pattern,
18
+ minLength: ({ props }) => props.minlength,
19
+ maxLength: ({ props }) => props.maxlength,
20
+ name: ({ props }) => props.name,
21
+ autocomplete: ({ props }) => props.autocomplete,
22
+ placeholder: ({ props }) => props.placeholder,
23
+ value: el => {
24
+ if (!el.props || !el.props.value) return
25
+ const val = el.call('exec', el.props.value, el)
26
+ if (el.call('isString', val) && val.includes('{{')) {
27
+ return el.call('replaceLiteralsWithObjectFields', val)
28
+ }
29
+ return val
30
+ },
31
+ checked: el => el.call('exec', el.props.checked, el),
32
+ disabled: ({ props }) => props.disabled || null,
33
+ readonly: ({ props }) => props.readonly,
34
+ required: ({ props }) => props.required,
35
+ type: ({ props }) => props.type
36
+ }
37
+ }
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ export const NumberInput = {
4
+ extends: ['Flex', 'Input'],
5
+
6
+ type: 'number',
7
+ boxSize: 'C+X',
8
+ align: 'center center',
9
+ textAlign: 'center',
10
+ round: 'Y1',
11
+ theme: 'transparent',
12
+ border: 'solid gray3',
13
+ borderWidth: '1px',
14
+ placeholder: '0',
15
+ fontWeight: '400',
16
+ '::-webkit-inner-spin-button': {
17
+ appearance: 'none'
18
+ },
19
+
20
+ attr: {
21
+ step: ({ props }) => props.step,
22
+ min: ({ props }) => props.min,
23
+ max: ({ props }) => props.max
24
+ }
25
+ }
package/Input/Radio.js ADDED
@@ -0,0 +1,31 @@
1
+ 'use strict'
2
+
3
+ export const Radio = {
4
+ extends: 'Checkbox',
5
+
6
+ Input: {
7
+ type: 'radio',
8
+ ':checked + div:after': { opacity: '1' }
9
+ },
10
+
11
+ Flex: {
12
+ round: '100%',
13
+ padding: 'Y',
14
+ ':after': {
15
+ content: '""',
16
+ display: 'block',
17
+ boxSize: 'X+W1',
18
+ round: '100%',
19
+ background: 'white',
20
+ opacity: '0',
21
+ transition: 'opacity .15s ease-in-out'
22
+ },
23
+ Icon: null
24
+ }
25
+ }
26
+
27
+ export const RadioHgroup = {
28
+ extends: 'CheckboxHgroup',
29
+ Checkbox: null,
30
+ Radio: {}
31
+ }
@@ -0,0 +1,54 @@
1
+ 'use strict'
2
+
3
+ export const Textarea = {
4
+ tag: 'textarea',
5
+ extends: ['Input', 'Flex'],
6
+
7
+ variant: 'outlined',
8
+ fontfamily: 'Avenir',
9
+ round: 'Z1',
10
+ placeholder: 'Leave us a message...',
11
+ padding: 'A',
12
+ theme: 'field',
13
+ border: 'none',
14
+ maxWidth: 'G1_default',
15
+ minHeight: 'E_default',
16
+ width: '100%',
17
+ height: 'E1_default',
18
+ fontFamily: 'inherit',
19
+ style: { resize: 'none' },
20
+
21
+ '.simple': {
22
+ theme: 'field',
23
+ round: 'Z2',
24
+ lineHeight: 1.4
25
+ },
26
+
27
+ '.outlined': {
28
+ theme: 'field',
29
+ borderWidth: '1px',
30
+ borderStyle: 'solid',
31
+ lineHeight: 1.4,
32
+ placeholder: 'Leave us a message...',
33
+ resize: 'none'
34
+ },
35
+
36
+ html: (el, s) => el.props.value
37
+ }
38
+
39
+ export const TextareaWithButton = {
40
+ display: 'flex',
41
+ gap: 'Y2',
42
+ Textarea: {
43
+ height: 'C2+W',
44
+ minWidth: 'H',
45
+ padding: 'A',
46
+ fontSize: 'Z1',
47
+ round: 'Z2',
48
+ minHeight: 'fit-content'
49
+ },
50
+ SquareButton: {
51
+ background: 'blue',
52
+ Icon: { name: 'send' }
53
+ }
54
+ }