fron-ui 1.0.0rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +38 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +7 -0
  7. data/.yardopts +8 -0
  8. data/Gemfile +8 -0
  9. data/Gemfile.lock +105 -0
  10. data/Rakefile +37 -0
  11. data/Readme.md +4 -0
  12. data/db.json +192 -0
  13. data/fron-ui.gemspec +21 -0
  14. data/lib/fron-ui.rb +1 -0
  15. data/lib/fron_ui.rb +5 -0
  16. data/lib/fron_ui/version.rb +7 -0
  17. data/opal/fron-ui/base.rb +49 -0
  18. data/opal/fron-ui/behaviors/action.rb +40 -0
  19. data/opal/fron-ui/behaviors/actions.rb +40 -0
  20. data/opal/fron-ui/behaviors/confirmation.rb +23 -0
  21. data/opal/fron-ui/behaviors/dropdown.rb +27 -0
  22. data/opal/fron-ui/behaviors/file.rb +48 -0
  23. data/opal/fron-ui/behaviors/intendable_children.rb +76 -0
  24. data/opal/fron-ui/behaviors/keydown.rb +31 -0
  25. data/opal/fron-ui/behaviors/loop.rb +41 -0
  26. data/opal/fron-ui/behaviors/render.rb +30 -0
  27. data/opal/fron-ui/behaviors/rest.rb +121 -0
  28. data/opal/fron-ui/behaviors/selectable_children.rb +67 -0
  29. data/opal/fron-ui/behaviors/serialize.rb +32 -0
  30. data/opal/fron-ui/behaviors/shortcuts.rb +35 -0
  31. data/opal/fron-ui/behaviors/state.rb +56 -0
  32. data/opal/fron-ui/behaviors/transition.rb +63 -0
  33. data/opal/fron-ui/components/action.rb +18 -0
  34. data/opal/fron-ui/components/box.rb +17 -0
  35. data/opal/fron-ui/components/button.rb +61 -0
  36. data/opal/fron-ui/components/calendar.rb +129 -0
  37. data/opal/fron-ui/components/checkbox.rb +57 -0
  38. data/opal/fron-ui/components/chooser.rb +246 -0
  39. data/opal/fron-ui/components/color_panel.rb +235 -0
  40. data/opal/fron-ui/components/color_picker.rb +111 -0
  41. data/opal/fron-ui/components/container.rb +61 -0
  42. data/opal/fron-ui/components/date_picker.rb +141 -0
  43. data/opal/fron-ui/components/drag.rb +76 -0
  44. data/opal/fron-ui/components/dropdown.rb +72 -0
  45. data/opal/fron-ui/components/icon.rb +29 -0
  46. data/opal/fron-ui/components/image.rb +77 -0
  47. data/opal/fron-ui/components/input.rb +30 -0
  48. data/opal/fron-ui/components/label.rb +9 -0
  49. data/opal/fron-ui/components/list.rb +34 -0
  50. data/opal/fron-ui/components/loader.rb +63 -0
  51. data/opal/fron-ui/components/modal.rb +0 -0
  52. data/opal/fron-ui/components/notifications.rb +73 -0
  53. data/opal/fron-ui/components/number.rb +202 -0
  54. data/opal/fron-ui/components/progress.rb +52 -0
  55. data/opal/fron-ui/components/slider.rb +47 -0
  56. data/opal/fron-ui/components/tabs.rb +149 -0
  57. data/opal/fron-ui/components/textarea.rb +13 -0
  58. data/opal/fron-ui/components/time.rb +65 -0
  59. data/opal/fron-ui/components/title.rb +34 -0
  60. data/opal/fron-ui/examples/blog/index.rb +289 -0
  61. data/opal/fron-ui/examples/comments/components/comment.rb +75 -0
  62. data/opal/fron-ui/examples/comments/components/comments.rb +93 -0
  63. data/opal/fron-ui/examples/comments/components/footer.rb +36 -0
  64. data/opal/fron-ui/examples/comments/components/header.rb +35 -0
  65. data/opal/fron-ui/examples/comments/components/list.rb +12 -0
  66. data/opal/fron-ui/examples/comments/index.rb +6 -0
  67. data/opal/fron-ui/examples/contacts/components/contacts.rb +100 -0
  68. data/opal/fron-ui/examples/contacts/components/details.rb +92 -0
  69. data/opal/fron-ui/examples/contacts/components/item.rb +46 -0
  70. data/opal/fron-ui/examples/contacts/components/list.rb +10 -0
  71. data/opal/fron-ui/examples/contacts/components/sidebar.rb +30 -0
  72. data/opal/fron-ui/examples/contacts/index.rb +6 -0
  73. data/opal/fron-ui/examples/editor/index.rb +164 -0
  74. data/opal/fron-ui/examples/kitchensink/index.rb +193 -0
  75. data/opal/fron-ui/examples/todos/components/item.rb +84 -0
  76. data/opal/fron-ui/examples/todos/components/options.rb +26 -0
  77. data/opal/fron-ui/examples/todos/components/todos.rb +145 -0
  78. data/opal/fron-ui/examples/todos/index.rb +6 -0
  79. data/opal/fron-ui/examples/webshop/index.rb +0 -0
  80. data/opal/fron-ui/fonts/ionicons.rb +2954 -0
  81. data/opal/fron-ui/fonts/open_sans.rb +19 -0
  82. data/opal/fron-ui/lib/collection.rb +138 -0
  83. data/opal/fron-ui/lib/date.rb +23 -0
  84. data/opal/fron-ui/lib/debounce.rb +14 -0
  85. data/opal/fron-ui/lib/image_loader.rb +13 -0
  86. data/opal/fron-ui/lib/lorem.rb +93 -0
  87. data/opal/fron-ui/lib/nil.rb +29 -0
  88. data/opal/fron-ui/lib/record.rb +23 -0
  89. data/opal/fron-ui/lib/state_serializer.rb +129 -0
  90. data/opal/fron-ui/lib/storage.rb +57 -0
  91. data/opal/fron-ui/spec/setup.rb +40 -0
  92. data/opal/fron-ui/ui.rb +40 -0
  93. data/opal/fron-ui/utils/theme_roller.rb +63 -0
  94. data/opal/fron-ui/vendor/autoprefixer.js +21114 -0
  95. data/opal/fron-ui/vendor/marked.js +1291 -0
  96. data/opal/fron-ui/vendor/md5.js +274 -0
  97. data/opal/fron-ui/vendor/moment.js +3083 -0
  98. data/opal/fron-ui/vendor/uuid.js +92 -0
  99. data/opal/fron_ui.rb +13 -0
  100. data/spec/behaviors/action_spec.rb +34 -0
  101. data/spec/behaviors/actions_spec.rb +38 -0
  102. data/spec/behaviors/confirmation_spec.rb +23 -0
  103. data/spec/behaviors/dropdown_spec.rb +32 -0
  104. data/spec/behaviors/render_spec.rb +20 -0
  105. data/spec/behaviors/rest_spec.rb +70 -0
  106. data/spec/behaviors/selectable_children_spec.rb +40 -0
  107. data/spec/behaviors/serialize_spec.rb +34 -0
  108. data/spec/components/action_spec.rb +7 -0
  109. data/spec/components/base_spec.rb +19 -0
  110. data/spec/components/box_spec.rb +7 -0
  111. data/spec/components/button_spec.rb +9 -0
  112. data/spec/components/calendar_spec.rb +58 -0
  113. data/spec/components/checkbox_spec.rb +20 -0
  114. data/spec/components/chooser_spec.rb +75 -0
  115. data/spec/components/color_panel_spec.rb +49 -0
  116. data/spec/components/color_picker_spec.rb +41 -0
  117. data/spec/components/container_spec.rb +23 -0
  118. data/spec/components/date_picker_spec.rb +71 -0
  119. data/spec/components/drag_spec.rb +20 -0
  120. data/spec/components/dropdown_spec.rb +33 -0
  121. data/spec/components/image_spec.rb +33 -0
  122. data/spec/components/input_spec.rb +8 -0
  123. data/spec/components/list_spec.rb +10 -0
  124. data/spec/components/loader_spec.rb +9 -0
  125. data/spec/components/notifications_spec.rb +17 -0
  126. data/spec/components/number_spec.rb +64 -0
  127. data/spec/components/progress_spec.rb +23 -0
  128. data/spec/components/slider_spec.rb +25 -0
  129. data/spec/components/tabs_spec.rb +50 -0
  130. data/spec/components/textarea_spec.rb +7 -0
  131. data/spec/components/time_spec.rb +37 -0
  132. data/spec/components/title_spec.rb +11 -0
  133. data/spec/examples/comments_spec.rb +72 -0
  134. data/spec/examples/todos_spec.rb +39 -0
  135. data/spec/lib/collection_spec.rb +38 -0
  136. data/spec/lib/lorem_spec.rb +55 -0
  137. data/spec/lib/state_serializer_spec.rb +58 -0
  138. data/spec/lib/storage_spec.rb +39 -0
  139. data/spec/spec_helper.rb +1 -0
  140. metadata +223 -0
@@ -0,0 +1,29 @@
1
+ module UI
2
+ # Simple Icon component
3
+ #
4
+ # @author Gusztáv Szikszai
5
+ # @since 0.1.0
6
+ class Icon < UI::Base
7
+ tag 'ui-icon'
8
+
9
+ style justifyContent: :center,
10
+ display: 'inline-flex',
11
+ alignItems: :center,
12
+ fontWeight: :normal,
13
+ '&:not([clickable])' => { pointerEvents: :none },
14
+ '&[clickable]' => { cursor: :pointer,
15
+ '&:hover' => { color: -> { colors.focus } } }
16
+
17
+ # Sets the glyph
18
+ #
19
+ # @param value [String] The glyph
20
+ def glyph=(value)
21
+ self[:glyph] = value
22
+ self[:class] = "ion-#{value}"
23
+ end
24
+
25
+ def glyph
26
+ self[:glyph]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,77 @@
1
+ require 'fron-ui/components/loader'
2
+
3
+ module UI
4
+ # Component for displaying an image, with
5
+ # a transition after it loads.
6
+ #
7
+ # @author Gusztáv Szikszai
8
+ # @since 0.1.0
9
+ class Image < Fron::Component
10
+ tag 'ui-image'
11
+
12
+ component :img, :img
13
+ component :loader, UI::Loader
14
+
15
+ style borderRadius: -> { (theme.border_radius * 2).em },
16
+ background: -> { dampen colors.background, 0.05 },
17
+ display: 'inline-block',
18
+ position: :relative,
19
+ 'ui-loader' => { color: -> { dampen colors.background, 0.2 },
20
+ position: :absolute,
21
+ bottom: 0,
22
+ right: 0,
23
+ left: 0,
24
+ top: 0 },
25
+ img: { transition: 'opacity 320ms',
26
+ borderRadius: :inherit,
27
+ height: :inherit,
28
+ width: :inherit,
29
+ opacity: 0,
30
+ '&.loaded' => { opacity: 1 } }
31
+
32
+ # Initializes the component
33
+ # and listens on the load event
34
+ # because it doesn't bubble.
35
+ def initialize
36
+ super
37
+ @img.on(:load) { loaded }
38
+ end
39
+
40
+ # Adds the loaded class
41
+ def loaded
42
+ @img.add_class :loaded
43
+ @loader.loading = false
44
+ end
45
+
46
+ # Sets the width of the image
47
+ #
48
+ # @param value [Numeric] The width
49
+ def width=(value)
50
+ @style.width = value
51
+ end
52
+
53
+ # Sets the height of the image
54
+ #
55
+ # @param value [Numeric] The height
56
+ def height=(value)
57
+ @style.height = value
58
+ end
59
+
60
+ # Returns the src attribute of the image
61
+ #
62
+ # @return [String] The attribute
63
+ def src
64
+ @img[:src]
65
+ end
66
+
67
+ # Sets the src of the image
68
+ #
69
+ # @param value [String] The URL
70
+ def src=(value)
71
+ return if !value || @img[:src] == value
72
+ @img.remove_class :loaded
73
+ @loader.loading = true
74
+ timeout(320) { @img[:src] = value }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,30 @@
1
+ module UI
2
+ # Input component, basically the input element wrapped
3
+ # and styled.
4
+ #
5
+ # @author Gusztáv Szikszai
6
+ # @since 0.1.0
7
+ class Input < Base
8
+ tag 'input'
9
+
10
+ defaults type: 'text'
11
+
12
+ attribute_accessor :placeholder
13
+ attribute_accessor :readonly, default: false
14
+
15
+ style borderRadius: -> { theme.border_radius.em },
16
+ color: -> { readable_color(colors.input) },
17
+ padding: -> { "0 #{theme.spacing.em}" },
18
+ fontFamily: -> { theme.font_family },
19
+ lineHeight: -> { theme.size.em },
20
+ background: -> { colors.input },
21
+ height: -> { theme.size.em },
22
+ fontSize: :inherit,
23
+ border: 0,
24
+ '&:focus' => {
25
+ boxShadow: -> { theme.focus_box_shadow.call },
26
+ borderColor: :transparent,
27
+ outline: :none
28
+ }
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ module UI
2
+ # Simple label component
3
+ #
4
+ # @author Gusztáv Szikszai
5
+ # @since 0.1.0
6
+ class Label < UI::Base
7
+ tag 'ui-label'
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ module UI
2
+ # List component
3
+ #
4
+ # Features:
5
+ # * Empty message display in an :after element
6
+ # * Striped backgrounds for items
7
+ # * Overflow auto
8
+ #
9
+ # @author Gusztáv Szikszai
10
+ # @since 0.1.0
11
+ class List < Collection
12
+ tag 'ui-list'
13
+
14
+ style overflow: :auto,
15
+ display: :block,
16
+ '> *' => { display: :block,
17
+ '& + *' => { borderTop: -> { "1px solid #{dampen colors.background, 0.025}" } } },
18
+ '&:empty' => { padding: -> { theme.spacing.em },
19
+ justifyContent: :center,
20
+ alignItems: :center,
21
+ textAlign: :center,
22
+ display: :flex },
23
+ '&:empty:after' => { content: 'attr(empty_message)',
24
+ fontSize: 2.em,
25
+ opacity: 0.25 }
26
+
27
+ # Sets the flex value
28
+ #
29
+ # @param value [Numeric] The value
30
+ def flex=(value)
31
+ @style.flex = value
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,63 @@
1
+ # rubocop:disable DoubleNegation
2
+
3
+ module UI
4
+ # Loader component
5
+ #
6
+ # @author Gusztáv Szikszai
7
+ # @since 0.1.0
8
+ class Loader < Base
9
+ tag 'ui-loader'
10
+
11
+ component :div, 'ui-loader-div'
12
+
13
+ keyframes 'ui-loader', '0%' => { transform: 'rotate(0deg)' },
14
+ '50%' => { transform: 'rotate(179.9deg)' },
15
+ '100%' => { transform: 'rotate(359.9deg)' }
16
+
17
+ style transition: 'opacity 320ms',
18
+ justifyContent: :center,
19
+ alignItems: :center,
20
+ minHeight: 2.em,
21
+ minWidth: 2.em,
22
+ display: :flex,
23
+ color: -> { colors.primary },
24
+ opacity: 0,
25
+ pointerEvents: :none,
26
+ '&.loading' => {
27
+ opacity: 1
28
+ },
29
+ 'ui-loader-div' => {
30
+ animation: 'ui-loader 1.2s infinite linear',
31
+ border: '0.15em solid currentColor',
32
+ borderTop: '0.15em solid transparent',
33
+ borderBottom: '0.15em solid transparent',
34
+ display: :flex,
35
+ justifyContent: :center,
36
+ alignItems: :center,
37
+ borderRadius: '50%',
38
+ height: 2.em,
39
+ width: 2.em,
40
+ '&:before' => {
41
+ content: '""',
42
+ border: '0.15em solid currentColor',
43
+ borderRadius: '50%',
44
+ height: 1.em,
45
+ width: 1.em
46
+ }
47
+ }
48
+
49
+ # Sets the loading flag
50
+ #
51
+ # @param value [Boolean] The value
52
+ def loading=(value)
53
+ toggle_class :loading, !!value
54
+ end
55
+
56
+ # Returns the loading flag
57
+ #
58
+ # @return [Boolean] The value
59
+ def loading
60
+ has_class(:loading)
61
+ end
62
+ end
63
+ end
File without changes
@@ -0,0 +1,73 @@
1
+ module UI
2
+ # Component for displaying notifications.
3
+ #
4
+ # @author Gusztáv Szikszai
5
+ # @since 0.1.0
6
+ class Notifications < Base
7
+ # Notification component-
8
+ #
9
+ # @author Gusztáv Szikszai
10
+ # @since 0.1.0
11
+ class Notification < Base
12
+ include UI::Behaviors::Transition
13
+
14
+ tag 'ui-notification'
15
+
16
+ style background: -> { rgba colors.primary, 0.85 },
17
+ borderRadius: -> { theme.border_radius.em },
18
+ color: -> { readable_color colors.primary },
19
+ fontSize: 1.2.em,
20
+ fontWeight: 600,
21
+ display: :block,
22
+ lineHeight: 1,
23
+ span: {
24
+ display: :block,
25
+ padding: -> { theme.spacing.em },
26
+ paddingBottom: -> { (theme.spacing * 1.2).em }
27
+ }
28
+
29
+ component :span, :span
30
+
31
+ transition :show, duration: '500ms',
32
+ frames: { '0%' => { opacity: 0 },
33
+ '100%' => { opacity: 1 } },
34
+ callback: :hide
35
+
36
+ transition :hide, duration: '500ms',
37
+ delay: '3s',
38
+ frames: { '0%' => { opacity: 1 },
39
+ '100%' => { opacity: 0 } },
40
+ callback: :remove!
41
+
42
+ # Initializes the component, starting
43
+ # the show transition.
44
+ def initialize
45
+ super
46
+ transition! :show
47
+ end
48
+
49
+ # Hides the component with the hide transition.
50
+ def hide
51
+ transition! :hide
52
+ end
53
+ end
54
+
55
+ tag 'ui-notifications'
56
+
57
+ style position: :absolute,
58
+ bottom: 1.5.em,
59
+ left: 1.5.em,
60
+ '> * + *' => { marginTop: -> { (theme.spacing / 1.5).em } }
61
+
62
+ # Pushes a new notification with the given
63
+ # message into the queue.
64
+ #
65
+ # @param message [String] The message
66
+ def push(message)
67
+ noti = Notification.new
68
+ noti.span.text = message
69
+ noti >> self
70
+ noti
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,202 @@
1
+ require 'fron/utils/drag'
2
+
3
+ module UI
4
+ # Range input element. This element is editable just like a normal
5
+ # input element can, the difference is that this element is draggable.
6
+ # When dragging the value is incremeted or decremented depending on the
7
+ # direction of the drag. The element can be limited to an upper and a lower value.
8
+ #
9
+ # @attr_reader drag [Fron::Drag] The drag instance
10
+ # @attr affix [String] The affix (px, %, em, ...)
11
+ # @attr label [String] The label to be displayed
12
+ # @attr step [Float] The step modifier to apply to the step, default to 1
13
+ # @attr min [Float] The minimal possible value, defaults to -infinity
14
+ # @attr max [Float] The maximum possible value, defaults to infinity
15
+ # @attr round [Float] The rounding value, defaults to 2
16
+ #
17
+ # @author Gusztáv Szikszai
18
+ # @since 0.1.0
19
+ class NumberRange < Base
20
+ # Input component
21
+ class Input < Fron::Component
22
+ tag 'ui-number-range-input'
23
+
24
+ attribute_accessor :label
25
+ attribute_accessor :affix
26
+
27
+ style borderRadius: -> { theme.border_radius.em },
28
+ lineHeight: -> { theme.size.em },
29
+ background: -> { colors.input },
30
+ height: -> { theme.size.em },
31
+ textAlign: :center,
32
+ display: :block,
33
+ fontWeight: 600,
34
+ '&:before' => { content: 'attr(label)',
35
+ marginRight: 0.2.em,
36
+ fontWeight: :normal },
37
+ '&:after' => { content: 'attr(affix)' },
38
+ '&:focus' => { boxShadow: -> { theme.focus_box_shadow.call },
39
+ outline: :none }
40
+ end
41
+
42
+ extend Forwardable
43
+
44
+ attr_reader :drag
45
+
46
+ tag 'ui-number-range'
47
+
48
+ component :input, Input, contenteditable: true
49
+
50
+ def_delegators :@input, :affix=, :affix, :label=, :label
51
+
52
+ on :keydown, :keydown
53
+ on :input, :input
54
+ on :mousemove, :on_mouse_move
55
+ on :mousedown, :on_mouse_down
56
+
57
+ attribute_accessor :step, default: 1, coerce: :to_f
58
+ attribute_accessor :round, default: 1, coerce: :to_f
59
+ attribute_accessor :max, default: Float::INFINITY, coerce: :to_f
60
+ attribute_accessor :min, default: -Float::INFINITY, coerce: :to_f
61
+
62
+ style color: -> { readable_color(colors.input) },
63
+ minWidth: -> { (theme.size * 5).em },
64
+ display: 'inline-block',
65
+ position: :relative,
66
+ '&:after, &:before' => { borderStyle: :solid,
67
+ position: :absolute,
68
+ marginTop: -0.3.em,
69
+ content: "''",
70
+ opacity: 0.5,
71
+ top: '50%',
72
+ height: 0,
73
+ width: 0 },
74
+ '&:after' => { borderColor: 'transparent currentColor transparent transparent',
75
+ borderWidth: '0.35em 0.4em 0.35em 0',
76
+ left: 0.75.em },
77
+ '&:before' => { borderColor: 'transparent transparent transparent currentColor',
78
+ borderWidth: '0.35em 0 0.35em 0.4em',
79
+ right: 0.75.em }
80
+
81
+ # Creates a new instance
82
+ def initialize
83
+ super
84
+ @input.on(:blur) { blur }
85
+ self.value = 0
86
+ setup_drag
87
+ end
88
+
89
+ def _attribute_changed
90
+ reset_value
91
+ end
92
+
93
+ # Returns the value of the field
94
+ #
95
+ # @return [Float] The value of the field
96
+ def value
97
+ @value.to_f
98
+ end
99
+
100
+ def _value(value)
101
+ value = value.to_f.clamp(min, max)
102
+ return if @value == value
103
+ @value = value
104
+ end
105
+
106
+ # Sets the value of the field
107
+ #
108
+ # @param value [Float] The value
109
+ def value=(value)
110
+ _value value
111
+ @input.text = format "%.#{round}f", @value
112
+ trigger 'change'
113
+ end
114
+
115
+ private
116
+
117
+ # Resets the value when attribute changes
118
+ def reset_value
119
+ self.value = value
120
+ end
121
+
122
+ # Sets up dragging.
123
+ def setup_drag
124
+ @drag = Fron::Drag.new self, 0
125
+
126
+ @drag.on('start') { @start_value = value }
127
+ @drag.on('move') { on_drag_move }
128
+ @drag.on('end') { on_drag_end }
129
+ end
130
+
131
+ # Runs when drag end
132
+ def on_drag_end
133
+ DOM::Document.body.style.cursor = ''
134
+ blur
135
+ end
136
+
137
+ # Runs when drag moves
138
+ def on_drag_move
139
+ DOM::Document.body.style.cursor = 'move'
140
+ value = (@start_value - @drag.diff.x * step).round(round)
141
+ self.value = value if @value != value
142
+ end
143
+
144
+ # Runs when input changes. It sets the value if the emelement
145
+ # is not empty, otherwise it inserts a non-width space to prevent
146
+ # caret jumping in chrome.
147
+ def input
148
+ @input.html = '&#xfeff;' if text.strip == ''
149
+ _value @input.html
150
+ end
151
+
152
+ # Runs when key is pressed. Prevents hitting the enter key.
153
+ #
154
+ # :reek:FeatureEnvy
155
+ #
156
+ # @param event [Event] The event
157
+ def keydown(event)
158
+ return unless event.key == :enter
159
+ event.prevent_default
160
+ @input.blur
161
+ end
162
+
163
+ # Runs when the element is blurred. Sets the value form
164
+ # the elements text.
165
+ def blur
166
+ self.value = text
167
+ end
168
+
169
+ # Runs on pointer move. Sets the cursor to move when not
170
+ # in the center of the element
171
+ #
172
+ # @param event [Event] The event
173
+ def on_mouse_move(event)
174
+ @style.cursor = in_select_region?(event.page_x) ? '' : 'move'
175
+ end
176
+
177
+ # Runs on pointer down. Prevents propagation so dragging
178
+ # cannot start.
179
+ #
180
+ # :reek:FeatureEnvy
181
+ #
182
+ # @param event [Event] The event
183
+ def on_mouse_down(event)
184
+ @input.focus
185
+ if in_select_region?(event.page_x)
186
+ event.stop_immediate_propagation
187
+ else
188
+ event.prevent_default
189
+ end
190
+ end
191
+
192
+ # Returns form to position if it is in the region that
193
+ # allow selection.
194
+ #
195
+ # @param position [type] The position (horizontal) to be checked
196
+ #
197
+ # @return [Boolean] True if the position is in the region otherwise false.
198
+ def in_select_region?(position)
199
+ (left + width / 2 - position).abs <= width / 4.5
200
+ end
201
+ end
202
+ end