so://phie

figure

The vanilla alternative for writing JSX-based React applications
git clone git://soophie.de/figure

blob: 1a6986a7694a84865ad9703a9af4612b946887c8 (2892 bytes)[doc][blame][raw]

1<div id="app"></div>

2

3<script type="module">

4

5 import {useState, createElement} from 'https://cdn.skypack.dev/react';

6 import {render} from 'https://cdn.skypack.dev/react-dom';

7 import {createTlx} from './lib.js';

8

9 const tlx = createTlx(createElement);

10

11 const Counter = (props) => {

12 const [defaultValue, setDefaultValue] = useState(0);

13 const { min = 0, max = 999, value = defaultValue, setValue = setDefaultValue } = props ?? {};

14 const validate = (value) => {

15 if(/^\d+$/.test(value) && parseInt(value) <= max) {

16 setValue(parseInt(value));

17 }

18 }

19 return tlx`

20 <div style="display: inline-flex; width: 100%; border: 1px solid #a3a3a3; border-radius: 4px; overflow: hidden; height: 40px; box-sizing: border-box;">

21 ${Button({

22 text: '-',

23 onClick: () => setValue(value - 1),

24 styles: {

25 fontSize: '1.2rem',

26 borderWidth: '0px 1px 0px 0px'

27 },

28 disabled: value <= min

29 })}

30 <input type="text" @input="${(event) => validate(event.target.value)}" value="${value}" style="font-size: 1rem; text-align: center; border: none; flex: 1; min-width: 0; height: 40px; outline: none;">

31 ${Button({

32 text: '+',

33 onClick: () => setValue(value + 1),

34 styles: {

35 fontSize: '1.2rem',

36 borderWidth: '0px 0px 0px 1px'

37 },

38 disabled: value >= max

39 })}

40 </div>

41 `;

42 }

43

44 const Button = (props) => {

45 const styles = {

46 minWidth: '40px',

47 height: '40px',

48 border: 'none',

49 outline: 'none',

50 border: '1px solid #a3a3a3',

51 backgroundColor: props.disabled ? '#f5f5f5' : '#e5e5e5',

52 cursor: props.disabled ? 'default' : 'pointer',

53 fontSize: '1rem',

54 fontFamily: 'Inter',

55 ...props.styles

56 };

57 return tlx`

58 <button disabled="${props.disabled}" style="${styles}" @click="${() => props.onClick()}">${props.text}</button>

59 `;

60 }

61

62 const App = () => {

63 const [quantity, setQuantity] = useState(1);

64 const isDisabled = quantity <= 0;

65 return tlx`

66 <div style="margin: 100px; display: flex; width: 150px; flex-direction: column; gap: 15px; align-items: flex-start;">

67 ${Counter({ value: quantity, setValue: setQuantity })}

68 ${Button({

69 text: 'Add to cart',

70 styles: {

71 backgroundColor: isDisabled ? '#f5f5f5' : '#f97316',

72 borderColor: isDisabled ? '#d4d4d4' : '#c2410c',

73 color: isDisabled ? '#a3a3a3' : 'white',

74 borderRadius: '4px',

75 width: '100%'

76 },

77 onClick: () => alert(`Added ${quantity} ${quantity > 1 ? 'items' : 'item'} to the cart`),

78 disabled: isDisabled

79 })}

80 </div>

81 `;

82 }

83

84 const app = document.querySelector('#app');

85 render(createElement(App), app);

86

87</script>