@startlibs/form 1.0.12 → 1.1.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 (92) hide show
  1. package/lib/AutoComplete.mjs +550 -0
  2. package/lib/AutoComplete.mjs.map +1 -0
  3. package/lib/Checkbox.mjs +76 -0
  4. package/lib/Checkbox.mjs.map +1 -0
  5. package/lib/Combobox.mjs +544 -0
  6. package/lib/Combobox.mjs.map +1 -0
  7. package/lib/ComboboxWithCustom.mjs +77 -0
  8. package/lib/ComboboxWithCustom.mjs.map +1 -0
  9. package/lib/DatePicker.mjs +625 -0
  10. package/lib/DatePicker.mjs.map +1 -0
  11. package/lib/EditableBox.mjs +496 -0
  12. package/lib/EditableBox.mjs.map +1 -0
  13. package/lib/Errors.mjs +176 -0
  14. package/lib/Errors.mjs.map +1 -0
  15. package/lib/ExpandableBox.mjs +209 -0
  16. package/lib/ExpandableBox.mjs.map +1 -0
  17. package/lib/Field.mjs +65 -0
  18. package/lib/Field.mjs.map +1 -0
  19. package/lib/FieldBox.mjs +80 -0
  20. package/lib/FieldBox.mjs.map +1 -0
  21. package/lib/Form.mjs +322 -0
  22. package/lib/Form.mjs.map +1 -0
  23. package/lib/FormValue.mjs +111 -0
  24. package/lib/FormValue.mjs.map +1 -0
  25. package/lib/InputboxGroup.mjs +104 -0
  26. package/lib/InputboxGroup.mjs.map +1 -0
  27. package/lib/Radiobox.mjs +67 -0
  28. package/lib/Radiobox.mjs.map +1 -0
  29. package/lib/RichText.mjs +634 -0
  30. package/lib/RichText.mjs.map +1 -0
  31. package/lib/TextInput.mjs +359 -0
  32. package/lib/TextInput.mjs.map +1 -0
  33. package/lib/alt/checkbox/SimpleCheckbox.mjs +82 -0
  34. package/lib/alt/checkbox/SimpleCheckbox.mjs.map +1 -0
  35. package/lib/alt/checkbox/ToggleCheckbox.mjs +68 -0
  36. package/lib/alt/checkbox/ToggleCheckbox.mjs.map +1 -0
  37. package/lib/alt/radiobox/CleanTabRadiobox.mjs +44 -0
  38. package/lib/alt/radiobox/CleanTabRadiobox.mjs.map +1 -0
  39. package/lib/alt/radiobox/IconRadioBox.mjs +52 -0
  40. package/lib/alt/radiobox/IconRadioBox.mjs.map +1 -0
  41. package/lib/alt/radiobox/SimpleRadiobox.mjs +61 -0
  42. package/lib/alt/radiobox/SimpleRadiobox.mjs.map +1 -0
  43. package/lib/alt/radiobox/TabRadiobox.mjs +54 -0
  44. package/lib/alt/radiobox/TabRadiobox.mjs.map +1 -0
  45. package/lib/enhanceInput.mjs +131 -0
  46. package/lib/enhanceInput.mjs.map +1 -0
  47. package/lib/index.cjs +5345 -0
  48. package/lib/index.cjs.map +1 -0
  49. package/lib/index.mjs +28 -0
  50. package/lib/index.mjs.map +1 -0
  51. package/lib/useConfirmDialog.mjs +117 -0
  52. package/lib/useConfirmDialog.mjs.map +1 -0
  53. package/lib/useDraftConfirmation.mjs +56 -0
  54. package/lib/useDraftConfirmation.mjs.map +1 -0
  55. package/lib/validation.mjs +91 -0
  56. package/lib/validation.mjs.map +1 -0
  57. package/lib/withFormImageInput.mjs +281 -0
  58. package/lib/withFormImageInput.mjs.map +1 -0
  59. package/package.json +44 -25
  60. package/src/AutoComplete.jsx +642 -0
  61. package/src/Checkbox.jsx +45 -0
  62. package/src/Combobox.jsx +606 -0
  63. package/src/ComboboxWithCustom.jsx +68 -0
  64. package/src/DatePicker.jsx +733 -0
  65. package/src/EditableBox.jsx +502 -0
  66. package/src/Errors.jsx +174 -0
  67. package/src/ExpandableBox.jsx +207 -0
  68. package/src/Field.jsx +76 -0
  69. package/src/FieldBox.jsx +136 -0
  70. package/src/Form.jsx +291 -0
  71. package/src/FormValue.jsx +67 -0
  72. package/src/IconRadioBoxOldHubt.jsx +93 -0
  73. package/src/InputboxGroup.jsx +121 -0
  74. package/src/Radiobox.jsx +33 -0
  75. package/src/RichText.jsx +812 -0
  76. package/src/TextInput.jsx +519 -0
  77. package/src/alt/checkbox/SimpleCheckbox.jsx +162 -0
  78. package/src/alt/checkbox/ToggleCheckbox.jsx +143 -0
  79. package/src/alt/radiobox/CleanTabRadiobox.jsx +46 -0
  80. package/src/alt/radiobox/IconRadioBox.jsx +93 -0
  81. package/src/alt/radiobox/SimpleRadiobox.jsx +153 -0
  82. package/src/alt/radiobox/TabRadiobox.jsx +73 -0
  83. package/src/enhanceInput.jsx +107 -0
  84. package/src/index.js +27 -0
  85. package/src/useConfirmDialog.jsx +105 -0
  86. package/src/useDraftConfirmation.jsx +60 -0
  87. package/src/validation.js +92 -0
  88. package/src/withFormImageInput.jsx +297 -0
  89. package/.babelrc +0 -28
  90. package/lib/index.js +0 -6258
  91. package/rollup.config.js +0 -43
  92. package/yarn-error.log +0 -1607
@@ -0,0 +1,519 @@
1
+ import React, {useState, forwardRef, useEffect} from 'react'
2
+ import {Field} from './Field'
3
+ import {useInput} from './enhanceInput'
4
+ import styled, {css} from 'styled-components'
5
+ import {Loading} from '@startlibs/components'
6
+ import {getScrollParent, ifUndefined, callIfFunction, getColor, customTheme, intToHour, digitsToPattern, isTouchDevice, media} from '@startlibs/utils'
7
+ import {darken} from 'polished'
8
+ import _ from 'lodash/fp'
9
+ import {Icon} from '@startlibs/components'
10
+ import {useEnsureRef, useRefState} from '@startlibs/core'
11
+
12
+ const InputWithTextAfter = styled.div`
13
+ display: flex;
14
+ align-items: center;
15
+ border: 1px solid ${getColor('gray210')};
16
+ border-radius: ${props => props.rounded ? '100px' : '8px'};
17
+ background: white;
18
+ ${props => props.focused && css`
19
+ border-color: ${getColor('gray180')};
20
+ box-shadow: 0px 0px 0px 2px rgba(0,0,0,0.1);
21
+ `}
22
+ ${props => props.hasErrors && css`
23
+ border-color: ${getColor('alert')} !important;
24
+ `}
25
+ input {
26
+ border: none;
27
+ box-shadow: none !important;
28
+ flex: 1;
29
+ min-width: 0;
30
+ }
31
+ `
32
+ const TextAfterLabel = styled.span`
33
+ padding-right: 0.7rem;
34
+ color: ${getColor('gray180')};
35
+ font-size: 14px;
36
+ white-space: nowrap;
37
+ ${media.mobile`
38
+ padding-right: 1rem;
39
+ `}
40
+ `
41
+
42
+ const InputWithIcon = styled.div`
43
+ position: relative;
44
+ width: 100%;
45
+ input, textarea {
46
+ display: block;
47
+ }
48
+ `
49
+ const InputIcon = styled(Icon)`
50
+ position: absolute;
51
+ left: ${props => props.rounded ? '13px' : '0.7rem'};
52
+ top: 50%;
53
+ transform: translateY(-50%);
54
+ font-size: 23px;
55
+ color: ${getColor('gray180')};
56
+ pointer-events: none;
57
+ z-index: 1;
58
+ line-height: 0;
59
+ ${media.mobile`
60
+ left: ${props => props.rounded ? '1.25rem' : '1rem'};
61
+ `}
62
+ `
63
+
64
+ const InputLoading = styled(Loading)`
65
+ bottom: 8px;
66
+ right: 0.6rem;
67
+ left: auto;
68
+ top: auto;
69
+ ${media.mobile`
70
+ bottom: 10px;
71
+ `}
72
+ `
73
+
74
+ const Input = styled.input`
75
+ width: 100%;
76
+ font-size: 14px;
77
+ border: 1px solid ${getColor('gray210')};
78
+ border-radius: 8px;
79
+ outline: 0;
80
+ outline: none;
81
+ color: ${getColor('gray60')};
82
+ background: white;
83
+ position: relative;
84
+ height: 3rem;
85
+ padding: 0 0.7rem;
86
+ overflow: auto;
87
+ ${media.mobile`
88
+ height: 42px;
89
+ padding: 0 1rem;
90
+ @supports (-webkit-touch-callout: none) {
91
+ font-size: 16px;
92
+ }
93
+ `}
94
+
95
+ ::-webkit-input-placeholder {
96
+ color: rgba(0,0,0,0.3);
97
+ }
98
+ ::-moz-placeholder {
99
+ color: rgba(0,0,0,0.3);
100
+ }
101
+ :-moz-placeholder {
102
+ color: rgba(0,0,0,0.3);
103
+ }
104
+ :-ms-input-placeholder {
105
+ color: rgba(0,0,0,0.3);
106
+ }
107
+ ${props => !props.hasTextBox && !props.noFocus && css`
108
+ :focus {
109
+ border-color: ${getColor('gray180')};
110
+ box-shadow: 0px 0px 0px 2px rgba(0,0,0,0.1);
111
+ }
112
+ ${props => props.hasErrors && css`
113
+ border-color: ${getColor('alert')} !important;
114
+ `}
115
+ `}
116
+ ::-ms-clear { //Clear IE pseudo-buttons
117
+ display: none;
118
+ }
119
+ ${props => props.locked && css`
120
+ padding-right: 2.25rem;
121
+ background: rgba(0,0,0,0.075);
122
+ pointer-events: none;
123
+ `}
124
+ ${props => props.isTextArea && css`
125
+ resize: none;
126
+ min-height: ${props => props.regularInputHeight ? 36 : props.minHeight || 60}px;
127
+ padding: .7rem;
128
+ display: block;
129
+ ${props => props.autoResize ? 'overflow:hidden;' : 'overflow:auto;'}
130
+ ${media.mobile`
131
+ padding: 1rem;
132
+ ${props => props.regularInputHeight && 'min-height: 42px;'}
133
+ `}
134
+ `}
135
+ ${props => props.rounded && css`
136
+ border-radius: 100px;
137
+ padding-left: 1.25rem;
138
+ padding-right: 1.25rem;
139
+ `}
140
+ ${props => props.hasIcon && css`
141
+ padding-left: ${props.rounded ? '3rem' : '2.5rem'};
142
+ ${media.mobile`
143
+ padding-left: ${props.rounded ? '3.25rem' : '2.75rem'};
144
+ `}
145
+ `}
146
+ ${customTheme('TextInput')}
147
+ `
148
+
149
+ const InputWithTextBox = styled.div`
150
+ display: flex;
151
+ border-radius: ${props => props.rounded ? '100px' : '8px'};
152
+ position: relative;
153
+ :before {
154
+ position: absolute;
155
+ border-radius: ${props => props.rounded ? '100px' : '8px'};
156
+ top: 0;
157
+ bottom: 0;
158
+ right: 0;
159
+ left: 0;
160
+ z-index: 2;
161
+ pointer-events: none;
162
+ }
163
+ ${props => props.focused && css`
164
+ box-shadow: 0px 0px 0px 2px rgba(0,0,0,0.1);
165
+ :before {
166
+ content: '';
167
+ border: 1px solid ${getColor('gray180')};
168
+ }
169
+ `}
170
+ ${props => props.hasErrors && css`
171
+ :before {
172
+ content: '';
173
+ border: 1px solid ${getColor('alert')};
174
+ }
175
+ `}
176
+ ${props => props.textBoxBefore && css`
177
+ input {
178
+ border-top-left-radius: 0;
179
+ border-bottom-left-radius: 0;
180
+ }
181
+ `}
182
+ ${props => props.textBoxAfter && css`
183
+ input {
184
+ border-top-right-radius: 0;
185
+ border-bottom-right-radius: 0;
186
+ }
187
+ `}
188
+ `
189
+ const TextBox = styled.span`
190
+ display: flex;
191
+ align-items: center;
192
+ padding: 0 0.7rem;
193
+ z-index: 1;
194
+ background-color: ${props => darken(0.075, getColor('gray240')(props))};
195
+ border: 1px solid ${getColor('gray210')};
196
+ cursor: text;
197
+ white-space: nowrap;
198
+ `
199
+ const TextBoxBefore = styled(TextBox)`
200
+ border-top-left-radius: ${props => props.rounded ? '100px' : '8px'};
201
+ border-bottom-left-radius: ${props => props.rounded ? '100px' : '8px'};
202
+ ${props => props.rounded && 'padding-left: 1.25rem;'}
203
+ margin-right: -1px;
204
+ `
205
+ const TextBoxAfter = styled(TextBox)`
206
+ border-top-right-radius: ${props => props.rounded ? '100px' : '8px'};
207
+ border-bottom-right-radius: ${props => props.rounded ? '100px' : '8px'};
208
+ ${props => props.rounded && 'padding-right: 1.25rem;'}
209
+ margin-left: -1px;
210
+ `
211
+
212
+ const doAutoResize = (element) => {
213
+ const scrollContainer = getScrollParent(element)
214
+ const lastTop = scrollContainer.scrollTop || scrollContainer.pageYOffset
215
+ element.style.height = 'auto'
216
+ element.style.height = (element.scrollHeight) + 'px'
217
+ if (scrollContainer === window) {
218
+ scrollContainer.scroll(scrollContainer.pageXOffset,lastTop)
219
+ } else {
220
+ scrollContainer.scrollTop = lastTop
221
+ }
222
+ }
223
+
224
+ export const useTextInput = (
225
+ {
226
+ onFocus,
227
+ onBlur,
228
+ autoResize,
229
+ autoSelectOnFocus,
230
+ constraint,
231
+ pattern,
232
+ path,
233
+ rawValue,
234
+ rawSetValue,
235
+ rawHasErrors,
236
+ transformOnBlur,
237
+ raw,
238
+ showValue,
239
+ deleteTrailing,
240
+ ...rest
241
+ },
242
+ ref
243
+ ) => {
244
+
245
+ const [formValue, setFormValue, {hasErrors}] = useInput({path,value:rawValue,setValue:rawSetValue,...rest},raw)
246
+ const [focused, setFocused] = useState()
247
+
248
+ const lastSelection = useRefState()
249
+ const lastValue = useRefState(showValue(formValue))
250
+
251
+ const handleOnFocus = (e) => {
252
+ setFocused(true)
253
+ if (!!autoSelectOnFocus && !!ref.current) {
254
+ setTimeout(() => ref.current?.select(), 0)
255
+ }
256
+ callIfFunction(onFocus, e)
257
+ }
258
+ const handleOnBlur = (e) => {
259
+ setFocused(false)
260
+ callIfFunction(onBlur, e)
261
+ if (transformOnBlur) {
262
+ setFormValue(transformOnBlur(formValue))
263
+ }
264
+ }
265
+
266
+ useEffect(() => {
267
+ if (lastSelection.get() === 1 && constraint === 'capitalize') {
268
+ ref.current.setSelectionRange(lastSelection.get(), lastSelection.get())
269
+ }
270
+ })
271
+
272
+ useEffect(() => {
273
+ if (autoResize) {
274
+ doAutoResize(ref.current)
275
+ }
276
+ },[])
277
+
278
+ useEffect(() => {
279
+ if (!!autoSelectOnFocus && !!ref.current && document.activeElement === ref.current) {
280
+ setTimeout(() => ref.current?.select(), 0)
281
+ }
282
+ }, [autoSelectOnFocus])
283
+
284
+
285
+
286
+ const handleChange = (e) => {
287
+ if (autoResize) {
288
+ doAutoResize(ref.current)
289
+ }
290
+ const target = e.target
291
+ try {
292
+ lastSelection.set(target.selectionEnd)
293
+ } catch(e) {}
294
+ if (constraint || pattern) {
295
+ setFormValue(validateConstraint(target.value, constraint, showValue(formValue), pattern), ref.current)
296
+ } else {
297
+ setFormValue(target.value, ref.current)
298
+ }
299
+ }
300
+
301
+ const validateConstraint = (value, constraint, prevValue, pattern) => {
302
+ let newValue = ''
303
+ if (value === (lastValue.get()+"") || (lastValue.get() && (lastValue.get()+"").indexOf(value)>=0 && !pattern)) {
304
+ newValue = value
305
+ if (deleteTrailing) {
306
+ if (_.isString(deleteTrailing) && value.slice(-deleteTrailing.length) === deleteTrailing) {
307
+ newValue = value.slice(0,-deleteTrailing.length)
308
+ } else if (_.isRegExp(deleteTrailing) && deleteTrailing.test(value)) {
309
+ newValue = value.replace(deleteTrailing,'')
310
+ }
311
+ }
312
+ lastValue.set(showValue(newValue))
313
+ return newValue
314
+ }
315
+ if (pattern) {
316
+ newValue = value.match(pattern)?.slice(1)?.join("") || ""
317
+ // if (newValue.length < value.length - 1) {
318
+ // newValue = value
319
+ // }
320
+ } else if (constraint === 'price') {
321
+ if (value.indexOf(',') >= 0) value = value.replace(/\./g, '') // ponytail: '.' é separador de milhar quando já há ',' decimal (ex: colar "2.000,45")
322
+ value = value.replace('.', ',').replace(/[^0-9,]/g, '')
323
+ const number = parseFloat(value.replace(',', '.'))
324
+ const commas = value.split(',')
325
+ const fixedNumber = number.toFixed(2)
326
+ newValue = !!commas[0] && commas.length === 2 && parseFloat(fixedNumber) === number && fixedNumber.split('.')[1].indexOf(commas[1]) === 0 ? value : digitsToPattern('>3???????#,##', value)
327
+ } else if (constraint === 'capitalize') {
328
+ // v = "R$ "+(parseInt(v.replace(/[^1-9]*([0-9]*)(,?)([0-9]{0,3}).*/,"$1$3") || 0)/100).toFixed(2).replace(".",",");
329
+ newValue = value.replace(/^[a-z]/, function(e) { return e.toUpperCase() })
330
+ } else if (constraint === 'number' || constraint === 'hour' || constraint === 'hour-int') {
331
+ newValue = value.replace(/\D/g, '')
332
+ if (newValue !== '') {
333
+ newValue = window.parseInt(newValue, 10)
334
+ if (constraint !== 'number') {
335
+ if ((newValue + '').length > 4 || newValue > 2399) {
336
+ newValue = prevValue
337
+ } else {
338
+ const resultHour = intToHour(newValue, false)
339
+ const val = resultHour.replace(/\D/g, '')
340
+ const result = (isNaN(parseInt(val, 10)) ? undefined : parseInt(val, 10))
341
+ newValue = constraint === 'hour-int' ? result : resultHour
342
+ }
343
+ }
344
+ }
345
+ } else if (constraint === 'cpf') {
346
+ newValue = digitsToPattern('###.###.###-##', value)
347
+ } else if (constraint === 'cnpj') {
348
+ newValue = digitsToPattern('##.###.###/####-##', value)
349
+ } else if (_.isFunction(constraint)) {
350
+ newValue = constraint(value)
351
+ } else if (_.isRegExp(constraint)) {
352
+ newValue = value.replace(constraint, '')
353
+ } else {
354
+ newValue = digitsToPattern(constraint, value)
355
+ }
356
+ lastValue.set(showValue(newValue))
357
+ return newValue
358
+ }
359
+ return [formValue, {onChange: handleChange, onFocus: handleOnFocus, onBlur: handleOnBlur}, rawHasErrors || hasErrors, focused]
360
+ }
361
+
362
+
363
+ export const TextInput = styled(forwardRef((
364
+ {
365
+ showValue = _.identity,
366
+ label,
367
+ type = 'text',
368
+ helpText,
369
+ descText,
370
+ bellowDescText,
371
+ mandatory,
372
+ isLoading,
373
+ locked,
374
+ textBoxBefore,
375
+ textBoxAfter,
376
+ textAfter,
377
+ icon,
378
+ className,
379
+ fieldClassName = '',
380
+ FieldType = Field,
381
+ margin,
382
+
383
+ value: rawValue,
384
+ setValue: rawSetValue,
385
+ hasErrors: rawHasErrors,
386
+
387
+ textarea = false,
388
+ onImage = false,
389
+ rounded,
390
+ autoFocus,
391
+ noFocus,
392
+ autoSelectOnFocus,
393
+
394
+ onFocus,
395
+ onBlur,
396
+ pattern,
397
+ autoResize,
398
+ constraint,
399
+ path,
400
+ raw,
401
+
402
+ tabIndex = 1,
403
+
404
+ ...rest
405
+ },
406
+ forwardedRef
407
+ ) => {
408
+ const ref = useEnsureRef(forwardedRef)
409
+ const [value, events, hasErrors, focused] = useTextInput({path, onFocus, onBlur, autoResize, autoSelectOnFocus, constraint, pattern, rawValue, rawSetValue, rawHasErrors, raw, showValue, ...rest}, ref)
410
+ const inputTag = textarea ? 'textarea' : 'input'
411
+
412
+ const focusInput = () => ref.current.focus()
413
+
414
+ const wrapInput = (input) => {
415
+ if (textBoxBefore) {
416
+ return (
417
+ <InputWithTextBox focused={focused} hasErrors={hasErrors} onClick={focusInput} textBoxBefore rounded={rounded}>
418
+ <TextBoxBefore rounded={rounded}>{textBoxBefore}</TextBoxBefore>
419
+ {input}
420
+ </InputWithTextBox>)
421
+ } else if (textBoxAfter) {
422
+ return (
423
+ <InputWithTextBox focused={focused} hasErrors={hasErrors} onClick={focusInput} textBoxAfter rounded={rounded}>
424
+ {input}
425
+ <TextBoxAfter rounded={rounded}>{textBoxAfter}</TextBoxAfter>
426
+ </InputWithTextBox>)
427
+ } else if (textAfter) {
428
+ return (
429
+ <InputWithTextAfter focused={focused} hasErrors={hasErrors} onClick={focusInput} rounded={rounded}>
430
+ {input}
431
+ <TextAfterLabel>{textAfter}</TextAfterLabel>
432
+ </InputWithTextAfter>)
433
+ } else {
434
+ return input
435
+ }
436
+ }
437
+ const input = wrapInput(<Input
438
+ {...rest}
439
+ as={inputTag}
440
+ className={!label ? className : undefined}
441
+ isTextArea={textarea}
442
+ data-hj-whitelist={type !== "password"}
443
+ locked={locked}
444
+ rounded={rounded}
445
+ hasIcon={!!icon}
446
+ autoFocus={!isTouchDevice() && autoFocus}
447
+ noFocus={noFocus}
448
+ hasErrors={hasErrors}
449
+ isOnImage={onImage}
450
+ ref={ref}
451
+ tabIndex={tabIndex}
452
+ type={type}
453
+ value={ifUndefined(showValue(value),'')}
454
+ hasTextBox={textBoxBefore || textBoxAfter || textAfter}
455
+ autoResize={autoResize}
456
+ rows={1}
457
+ {...events}
458
+ />)
459
+
460
+ const wrappedInput = icon
461
+ ? <InputWithIcon>
462
+ <InputIcon icon={icon} rounded={rounded}/>
463
+ {input}
464
+ </InputWithIcon>
465
+ : input
466
+
467
+ return (
468
+ !label
469
+ ? wrappedInput
470
+ : <FieldType
471
+ className={fieldClassName+ ' ' + className}
472
+ value={value}
473
+ focused={focused}
474
+ mandatory={mandatory}
475
+ isOnImage={onImage}
476
+ descText={descText}
477
+ bellowDescText={bellowDescText}
478
+ helpText={helpText}
479
+ label={label}
480
+ labelClick={focusInput}
481
+ margin={margin}
482
+ >
483
+ {isLoading && <InputLoading absolute size={20}/>}
484
+ {wrappedInput}
485
+ </FieldType>
486
+ )
487
+
488
+ }))``
489
+
490
+ TextInput.Input = Input
491
+ export default TextInput
492
+
493
+ const FloatingFieldType = styled(Field)`
494
+ input {
495
+ height: 5rem;
496
+ box-shadow: 0 1px 4px rgba(0,0,0,.2);
497
+ border-radius: 8px;
498
+ font-size: 16px;
499
+ font-weight: 400;
500
+ padding: 16px 1rem 0;
501
+ }
502
+ ${Field.Label} {
503
+ position: absolute;
504
+ top: 1.5rem;
505
+ left: 1rem;
506
+ font-size: 20px;
507
+ font-weight: normal;
508
+ transition: all .2s ease;
509
+ color: rgba(0,0,0,.2);
510
+ pointer-events: none;
511
+ z-index: 1;
512
+ ${props => (props.value || props.focused) && `
513
+ top: 12px;
514
+ font-size: 14px;
515
+ color: rgba(0,0,0,.4);
516
+ `}
517
+ }
518
+ `
519
+ export const FloatLabelTextInput = (props) => <TextInput {...props} FieldType={FloatingFieldType}/>
@@ -0,0 +1,162 @@
1
+ import React from 'react'
2
+
3
+ import {Icon} from '@startlibs/components'
4
+ import { getColor, ifProp, media } from '@startlibs/utils';
5
+ import styled, {css} from 'styled-components'
6
+ import {lighten, desaturate} from 'polished'
7
+ import {Checkbox} from '../../Checkbox'
8
+ import {HelpText} from '../../Field'
9
+
10
+ const CheckboxPseudoInput = styled.div`
11
+ border-radius: 4px;
12
+ content: '';
13
+ border: 1px solid ${getColor('gray210')};
14
+ width: 18px;
15
+ height: 18px;
16
+ background-color: white;
17
+ position: absolute;
18
+ left: -2rem;
19
+ top: 50%;
20
+ transform: translateY(-50%);
21
+
22
+ ${ifProp('focused', css`
23
+ box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1);
24
+ border-color: ${getColor('gray180')};
25
+ `)}
26
+
27
+ ${Icon} {
28
+ position: absolute;
29
+ top: 50%;
30
+ left: 50%;
31
+ transform: translate(-50%,-50%);
32
+ font-weight: bold;
33
+ font-size: 16px;
34
+ color: ${getColor('gray90')};
35
+ }
36
+ `
37
+ const TextLabel = styled.span `
38
+ font-size: 13px;
39
+ line-height: 16px;
40
+ margin: 2px 0;
41
+ display: block;
42
+ `
43
+ const DescText = styled.div `
44
+ color: rgba(0,0,0,0.4);
45
+ display: block;
46
+ font-size: 12px;
47
+ font-weight: 400;
48
+ `
49
+ const TextLabelContainer = styled.div `
50
+ display: flex;
51
+ align-items: center;
52
+ position: relative;
53
+ ${HelpText} {
54
+ margin-left: 0.25rem;
55
+ }
56
+ `
57
+ const CheckboxContent = styled.div `
58
+ cursor: pointer;
59
+ position: relative;
60
+ padding-left: 2rem;
61
+ transition: background 0.2s linear;
62
+ ${props => props.framed && css`
63
+ border: 1px solid ${getColor('gray210')};
64
+ border-radius: 8px;
65
+ min-height: 3rem;
66
+ min-width: 8rem;
67
+ background: white;
68
+ width: 100%;
69
+ align-items: center;
70
+ display: flex;
71
+ :hover {
72
+ background: rgb(245,245,245);
73
+ }
74
+ :active {
75
+ background: rgb(235,235,235);
76
+ transition: none;
77
+ }
78
+ padding: 10px 12px 10px 32px;
79
+ ${media.desktop`
80
+ padding: 7px 12px 7px 32px;
81
+ `}
82
+ ${props => props.hasErrors && css`
83
+ border-color: ${getColor('alert')} !important;
84
+ `}
85
+ ${props => props.checked && props.highlightSelected && css`
86
+ border-color: ${getColor('main')};
87
+ background: ${props => desaturate(0.3, lighten(0.52, getColor("main")(props)))};
88
+ :hover {
89
+ background: ${props => desaturate(0.3, lighten(0.52, getColor("main")(props)))};
90
+ }
91
+ ${CheckboxPseudoInput} {
92
+ ${Icon} {
93
+ color: ${getColor('main')};
94
+ }
95
+ }
96
+ `}
97
+ ${props => props.checked && props.ultraHighlightSelected && css`
98
+ border-color: ${getColor('main')};
99
+ background: ${getColor('main')};
100
+ color: white;
101
+ a, a.link {
102
+ color: white;
103
+ }
104
+ :hover {
105
+ background: ${getColor('main')};
106
+ }
107
+ ${CheckboxPseudoInput} {
108
+ ${Icon} {
109
+ color: ${getColor('main')};
110
+ }
111
+ }
112
+ ${HelpText} {
113
+ color: rgba(255, 255, 255, 0.65);
114
+ }
115
+ ${DescText} {
116
+ color: rgba(255, 255, 255, 0.65);
117
+ }
118
+ `}
119
+ ${props => props.disabled && css`
120
+ background-color: rgba(0,0,0,0.075) !important;
121
+ color: rgba(0,0,0,0.6); !important;
122
+ &[disabled] {
123
+ opacity: 0.75 !important;
124
+ }
125
+ ${CheckboxPseudoInput} {
126
+ background: transparent;
127
+ }
128
+ `}
129
+ `}
130
+ `
131
+
132
+ export const SimpleCheckbox = styled(({path, disabled, label, descText, helpText, isFirst, isLast, tabIndex, className,framedBoxes,highlightSelected,ultraHighlightSelected,...rest}) =>
133
+ <Checkbox
134
+ className={className}
135
+ path={path}
136
+ tabIndex={tabIndex}
137
+ {...rest}
138
+ >{({checked, hasErrors, focused}) =>
139
+ <CheckboxContent checked={checked} framed={framedBoxes} highlightSelected={highlightSelected} ultraHighlightSelected={ultraHighlightSelected} hasErrors={hasErrors} disabled={disabled}>
140
+ <div className="textContainer">
141
+ <TextLabelContainer>
142
+ <CheckboxPseudoInput focused={focused} tabIndex={tabIndex}>
143
+ {checked && <Icon icon="check"/>}
144
+ </CheckboxPseudoInput>
145
+ <TextLabel>{label}</TextLabel>{helpText && <HelpText>{helpText}</HelpText>}
146
+ </TextLabelContainer>
147
+ {descText && <DescText>{descText}</DescText>}
148
+ </div>
149
+ </CheckboxContent>
150
+ }</Checkbox>
151
+ )`
152
+ cursor: pointer;
153
+ position: relative;
154
+ margin-bottom: 1rem;
155
+ display: flex;
156
+ ${ifProp('disabled', css`
157
+ pointer-events: none;
158
+ `)}
159
+ .textContainer {
160
+ width: 100%;
161
+ }
162
+ `